Browse Source

made config system fully independent of the network.

flowchartTest
Alex de Mulder 9 years ago
parent
commit
676250fd31
5 changed files with 2102 additions and 2093 deletions
  1. +1837
    -1840
      dist/vis.js
  2. +7
    -0
      docs/network/configure.html
  3. +19
    -4
      lib/network/Network.js
  4. +56
    -246
      lib/network/modules/ConfigurationSystem.js
  5. +183
    -3
      lib/network/modules/components/AllOptions.js

+ 1837
- 1840
dist/vis.js
File diff suppressed because it is too large
View File


+ 7
- 0
docs/network/configure.html View File

@ -118,6 +118,13 @@ network.setOptions(options);
<td class="default">default</td>
<td class="description">description</td>
</tr>
<tr>
<td>enabled</td>
<td class="mid">Boolean</td>
<td class="mid"><code>true</code></td>
<td>
</td>
</tr>
<tr>
<td>filter</td>
<td class="mid">String or Array or Boolean</td>

+ 19
- 4
lib/network/Network.js View File

@ -26,7 +26,7 @@ import ManipulationSystem from "./modules/ManipulationSystem";
import ConfigurationSystem from "./modules/ConfigurationSystem";
import Validator from "./modules/Validator";
import {printStyle} from "./modules/Validator";
import allOptions from './modules/components/AllOptions.js';
import {allOptions, configureOptions} from './modules/components/AllOptions.js';
/**
* @constructor Network
@ -112,11 +112,12 @@ function Network(container, data, options) {
this.nodesHandler = new NodesHandler(this.body, this.images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options
this.edgesHandler = new EdgesHandler(this.body, this.images, this.groups); // Handle adding, deleting and updating of edges as well as global options
this.configurationSystem = new ConfigurationSystem(this);
// create the DOM elements
this.canvas._create();
// setup configuration system
this.configurationSystem = new ConfigurationSystem(this, this.body.container, configureOptions, this.canvas.pixelRatio);
// apply options
this.setOptions(options);
@ -158,7 +159,21 @@ Network.prototype.setOptions = function (options) {
this.clustering.setOptions(options.clustering);
this.manipulation.setOptions(options.manipulation);
this.configurationSystem.setOptions(options);
this.configurationSystem.setOptions(options.configure);
// if the configuration system is enabled, copy all options and put them into the config system
if (this.configurationSystem.options.enabled === true) {
let networkOptions = {nodes:{},edges:{},layout:{},interaction:{},manipulation:{},physics:{},selection:{},rendering:{}};
util.deepExtend(networkOptions.nodes, this.nodesHandler.options);
util.deepExtend(networkOptions.edges, this.edgesHandler.options);
util.deepExtend(networkOptions.layout, this.layoutEngine.options);
util.deepExtend(networkOptions.interaction, this.interactionHandler.options);
util.deepExtend(networkOptions.manipulation, this.manipulation.options);
util.deepExtend(networkOptions.physics, this.physics.options);
util.deepExtend(networkOptions.selection, this.selectionHandler.options);
util.deepExtend(networkOptions.rendering, this.renderer.options);
this.configurationSystem.setModuleOptions(networkOptions);
}
// handle network global options
if (options.clickToUse !== undefined) {

+ 56
- 246
lib/network/modules/ConfigurationSystem.js View File

@ -1,6 +1,6 @@
var util = require('../../util');
import ColorPicker from './components/ColorPicker'
import ColorPicker from './components/ColorPicker'
/**
* The way this works is for all properties of this.possible options, you can supply the property name in any form to list the options.
@ -11,203 +11,29 @@ import ColorPicker from './components/ColorPicker'
*
* The options are matched with their counterparts in each of the modules and the values used in the configuration are
*
* @param parentModule | the location where parentModule.setOptions() can be called
* @param defaultContainer | the default container of the module
* @param configureOptions | the fully configured and predefined options set found in allOptions.js
* @param pixelRatio | canvas pixel ratio
*/
class ConfigurationSystem {
constructor(network) {
this.network = network;
constructor(parentModule, defaultContainer, configureOptions, pixelRatio = 1) {
this.parent = parentModule;
this.changedOptions = [];
this.container = defaultContainer;
this.possibleOptions = {
nodes: {
borderWidth: [1, 0, 10, 1],
borderWidthSelected: [2, 0, 10, 1],
color: {
border: ['color','#2B7CE9'],
background: ['color','#97C2FC'],
highlight: {
border: ['color','#2B7CE9'],
background: ['color','#D2E5FF']
},
hover: {
border: ['color','#2B7CE9'],
background: ['color','#D2E5FF']
}
},
fixed: {
x: false,
y: false
},
font: {
color: ['color','#343434'],
size: [14, 0, 100, 1], // px
face: ['arial', 'verdana', 'tahoma'],
background: ['color','none'],
stroke: [0, 0, 50, 1], // px
strokeColor: ['color','#ffffff']
},
//group: 'string',
hidden: false,
//icon: {
// face: 'string', //'FontAwesome',
// code: 'string', //'\uf007',
// size: [50, 0, 200, 1], //50,
// color: ['color','#2B7CE9'] //'#aa00ff'
//},
//image: 'string', // --> URL
physics: true,
scaling: {
min: [10, 0, 200, 1],
max: [30, 0, 200, 1],
label: {
enabled: true,
min: [14, 0, 200, 1],
max: [30, 0, 200, 1],
maxVisible: [30, 0, 200, 1],
drawThreshold: [3, 0, 20, 1]
}
},
shadow:{
enabled: false,
size:[10, 0, 20, 1],
x:[5, -30, 30, 1],
y:[5, -30, 30, 1]
},
shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'],
size: [25, 0, 200, 1]
},
edges: {
arrows: {
to: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1}
middle: {enabled: false, scaleFactor: [1, 0, 3, 0.05]},
from: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}
},
color: {
color: ['color','#848484'],
highlight: ['color','#848484'],
hover: ['color','#848484'],
inherit: ['from','to','both',true, false],
opacity: [1, 0, 1, 0.05]
},
dashes: false,
font: {
color: ['color','#343434'],
size: [14, 0, 100, 1], // px
face: ['arial', 'verdana', 'tahoma'],
background: ['color','none'],
stroke: [1, 0, 50, 1], // px
strokeColor: ['color','#ffffff'],
align: ['horizontal', 'top', 'middle', 'bottom']
},
hidden: false,
hoverWidth: [2, 0, 5, 0.1],
physics: true,
scaling: {
min: [1, 0, 100, 1],
max: [15, 0, 100, 1],
label: {
enabled: true,
min: [14, 0, 200, 1],
max: [30, 0, 200, 1],
maxVisible: [30, 0, 200, 1],
drawThreshold: [3, 0, 20, 1]
}
},
selectionWidth: [1.5, 0, 5, 0.1],
selfReferenceSize: [20, 0, 200, 1],
shadow:{
enabled: false,
size:[10, 0, 20, 1],
x:[5, -30, 30, 1],
y:[5, -30, 30, 1]
},
smooth: {
enabled: true,
dynamic: true,
type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'],
roundness: [0.5, 0, 1, 0.05]
},
width: [1, 0, 30, 1]
},
layout: {
randomSeed: [0, 0, 500, 1],
hierarchical: {
enabled: false,
levelSeparation: [150, 20, 500, 5],
direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL
sortMethod: ['hubsize', 'directed'] // hubsize, directed
}
},
interaction: {
dragNodes: true,
dragView: true,
zoomView: true,
hoverEnabled: false,
navigationButtons: false,
tooltipDelay: [300, 0, 1000, 25],
keyboard: {
enabled: false,
speed: {x: [10, 0, 40, 1], y: [10, 0, 40, 1], zoom: [0.02, 0, 0.1, 0.005]},
bindToWindow: true
}
},
manipulation: {
enabled: false,
initiallyActive: false,
locale: ['en', 'nl']
},
physics: {
barnesHut: {
//theta: [0.5, 0.1, 1, 0.05],
gravitationalConstant: [-2000, -30000, 0, 50],
centralGravity: [0.3, 0, 10, 0.05],
springLength: [95, 0, 500, 5],
springConstant: [0.04, 0, 5, 0.005],
damping: [0.09, 0, 1, 0.01]
},
repulsion: {
centralGravity: [0.2, 0, 10, 0.05],
springLength: [200, 0, 500, 5],
springConstant: [0.05, 0, 5, 0.005],
nodeDistance: [100, 0, 500, 5],
damping: [0.09, 0, 1, 0.01]
},
hierarchicalRepulsion: {
centralGravity: [0.2, 0, 10, 0.05],
springLength: [100, 0, 500, 5],
springConstant: [0.01, 0, 5, 0.005],
nodeDistance: [120, 0, 500, 5],
damping: [0.09, 0, 1, 0.01]
},
maxVelocity: [50, 0, 150, 1],
minVelocity: [0.1, 0.01, 0.5, 0.01],
solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'],
timestep: [0.5, 0, 1, 0.05]
},
selection: {
selectable: true,
selectConnectedEdges: true
},
rendering: {
hideEdgesOnDrag: false,
hideNodesOnDrag: false
}
};
this.actualOptions = {
nodes:{},
edges:{},
layout:{},
interaction:{},
manipulation:{},
physics:{},
selection:{},
rendering:{},
configure: false,
configureContainer: undefined
};
this.options = {};
this.defaultOptions = {
enabled: false,
filter: true,
container: undefined
}
util.extend(this.options, this.defaultOptions);
this.configureOptions = configureOptions;
this.moduleOptions = {};
this.domElements = [];
this.colorPicker = new ColorPicker(this.network.canvas.pixelRatio);
this.colorPicker = new ColorPicker(pixelRatio);
this.wrapper;
}
@ -220,45 +46,42 @@ class ConfigurationSystem {
*/
setOptions(options) {
if (options !== undefined) {
util.extend(this.actualOptions, options);
}
this._clean();
if (this.actualOptions.configure !== undefined && this.actualOptions.configure !== false) {
util.deepExtend(this.actualOptions.nodes, this.network.nodesHandler.options, true);
util.deepExtend(this.actualOptions.edges, this.network.edgesHandler.options, true);
util.deepExtend(this.actualOptions.layout, this.network.layoutEngine.options, true);
util.deepExtend(this.actualOptions.interaction, this.network.interactionHandler.options, true);
util.deepExtend(this.actualOptions.manipulation, this.network.manipulation.options, true);
util.deepExtend(this.actualOptions.physics, this.network.physics.options, true);
util.deepExtend(this.actualOptions.selection, this.network.selectionHandler.selection, true);
util.deepExtend(this.actualOptions.rendering, this.network.renderer.selection, true);
this.container = this.network.body.container;
let config = true;
if (typeof this.actualOptions.configure === 'string') {
config = this.actualOptions.configure;
let enabled = true;
if (typeof options === 'string') {
this.options.filter = options;
}
else if (this.actualOptions.configure instanceof Array) {
config = this.actualOptions.configure.join();
else if (options instanceof Array) {
this.options.filter = options.join();
}
else if (typeof this.actualOptions.configure === 'object') {
if (this.actualOptions.configure.container !== undefined) {
this.container = this.actualOptions.configure.container;
else if (typeof options === 'object') {
if (options.container !== undefined) {
this.options.container = options.container;
}
if (this.actualOptions.configure.filter !== undefined) {
config = this.actualOptions.configure.filter;
if (options.filter !== undefined) {
this.options.filter = options.filter;
}
if (options.enabled !== undefined) {
enabled = options.enabled;
}
}
else if (typeof this.actualOptions.configure === 'boolean') {
config = this.actualOptions.configure;
else if (typeof options === 'boolean') {
this.options.filter = true;
enabled = options;
}
this.options.enabled = enabled;
}
this._clean();
}
if (config !== false) {
this._create(config);
setModuleOptions(moduleOptions) {
this.moduleOptions = moduleOptions;
if (this.options.enabled === true) {
this._clean();
if (this.options.container !== undefined) {
this.container = this.options.container;
}
this._create(this.options.filter);
}
}
@ -272,10 +95,10 @@ class ConfigurationSystem {
this.changedOptions = [];
let counter = 0;
for (let option in this.possibleOptions) {
if (this.possibleOptions.hasOwnProperty(option)) {
for (let option in this.configureOptions) {
if (this.configureOptions.hasOwnProperty(option)) {
if (config === true || config.indexOf(option) !== -1) {
let optionObj = this.possibleOptions[option];
let optionObj = this.configureOptions[option];
// linebreak between categories
if (counter > 0) {
@ -322,6 +145,7 @@ class ConfigurationSystem {
}
}
/**
* delete all DOM elements
* @private
@ -338,6 +162,7 @@ class ConfigurationSystem {
this.domElements = [];
}
/**
* get the value from the actualOptions if it exists
* @param {array} path | where to look for the actual option
@ -345,7 +170,7 @@ class ConfigurationSystem {
* @private
*/
_getValue(path) {
let base = this.actualOptions;
let base = this.moduleOptions;
for (let i = 0; i < path.length; i++) {
if (base[path[i]] !== undefined) {
base = base[path[i]];
@ -359,22 +184,6 @@ class ConfigurationSystem {
}
/**
* Copy the path and add a step. It needs to copy because the path will keep stacking otherwise.
* @param path
* @param newValue
* @returns {Array}
* @private
*/
_addToPath(path, newValue) {
let newPath = [];
for (let i = 0; i < path.length; i++) {
newPath.push(path[i]);
}
newPath.push(newValue);
return newPath;
}
/**
* all option elements are wrapped in an item
* @param path
@ -390,6 +199,7 @@ class ConfigurationSystem {
this.domElements.push(item);
}
/**
* header for major subjects
* @param name
@ -402,6 +212,7 @@ class ConfigurationSystem {
this._makeItem([],div);
}
/**
* make a label, if it is an object label, it gets different styling.
* @param name
@ -616,7 +427,7 @@ class ConfigurationSystem {
// collapse the physics options that are not enabled
let draw = true;
if (path.indexOf('physics') !== -1) {
if (this.actualOptions.physics.solver !== subObj) {
if (this.moduleOptions.physics.solver !== subObj) {
draw = false;
}
}
@ -683,7 +494,7 @@ class ConfigurationSystem {
*/
_update(value, path) {
let options = this._constructOptions(value,path);
this.network.setOptions(options);
this.parent.setOptions(options);
}
_constructOptions(value, path, optionsObj = {}) {
@ -704,7 +515,6 @@ class ConfigurationSystem {
pointer[path[i]] = value;
}
}
console.log(optionsObj)
return optionsObj;
}

+ 183
- 3
lib/network/modules/components/AllOptions.js View File

@ -29,9 +29,10 @@ let allOptions = {
},
clustering: {},
configure: {
enabled: {boolean},
filter: {boolean,string:['nodes','edges','layout','physics','manipulation','interaction','selection','rendering'],array},
container: {dom},
__type__: {object,string,array,boolean}
__type__: {object,boolean,string:['nodes','edges','layout','physics','manipulation','interaction','selection','rendering'],array}
},
edges: {
arrows: {
@ -273,8 +274,187 @@ let allOptions = {
__type__: {object}
};
allOptions.groups.__any__ = allOptions.nodes;
allOptions.manipulation.controlNodeStyle = allOptions.nodes;
export default allOptions;
let configureOptions = {
nodes: {
borderWidth: [1, 0, 10, 1],
borderWidthSelected: [2, 0, 10, 1],
color: {
border: ['color','#2B7CE9'],
background: ['color','#97C2FC'],
highlight: {
border: ['color','#2B7CE9'],
background: ['color','#D2E5FF']
},
hover: {
border: ['color','#2B7CE9'],
background: ['color','#D2E5FF']
}
},
fixed: {
x: false,
y: false
},
font: {
color: ['color','#343434'],
size: [14, 0, 100, 1], // px
face: ['arial', 'verdana', 'tahoma'],
background: ['color','none'],
stroke: [0, 0, 50, 1], // px
strokeColor: ['color','#ffffff']
},
//group: 'string',
hidden: false,
//icon: {
// face: 'string', //'FontAwesome',
// code: 'string', //'\uf007',
// size: [50, 0, 200, 1], //50,
// color: ['color','#2B7CE9'] //'#aa00ff'
//},
//image: 'string', // --> URL
physics: true,
scaling: {
min: [10, 0, 200, 1],
max: [30, 0, 200, 1],
label: {
enabled: true,
min: [14, 0, 200, 1],
max: [30, 0, 200, 1],
maxVisible: [30, 0, 200, 1],
drawThreshold: [3, 0, 20, 1]
}
},
shadow:{
enabled: false,
size:[10, 0, 20, 1],
x:[5, -30, 30, 1],
y:[5, -30, 30, 1]
},
shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'],
size: [25, 0, 200, 1]
},
edges: {
arrows: {
to: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1}
middle: {enabled: false, scaleFactor: [1, 0, 3, 0.05]},
from: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}
},
color: {
color: ['color','#848484'],
highlight: ['color','#848484'],
hover: ['color','#848484'],
inherit: ['from','to','both',true, false],
opacity: [1, 0, 1, 0.05]
},
dashes: false,
font: {
color: ['color','#343434'],
size: [14, 0, 100, 1], // px
face: ['arial', 'verdana', 'tahoma'],
background: ['color','none'],
stroke: [1, 0, 50, 1], // px
strokeColor: ['color','#ffffff'],
align: ['horizontal', 'top', 'middle', 'bottom']
},
hidden: false,
hoverWidth: [2, 0, 5, 0.1],
physics: true,
scaling: {
min: [1, 0, 100, 1],
max: [15, 0, 100, 1],
label: {
enabled: true,
min: [14, 0, 200, 1],
max: [30, 0, 200, 1],
maxVisible: [30, 0, 200, 1],
drawThreshold: [3, 0, 20, 1]
}
},
selectionWidth: [1.5, 0, 5, 0.1],
selfReferenceSize: [20, 0, 200, 1],
shadow:{
enabled: false,
size:[10, 0, 20, 1],
x:[5, -30, 30, 1],
y:[5, -30, 30, 1]
},
smooth: {
enabled: true,
dynamic: true,
type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'],
roundness: [0.5, 0, 1, 0.05]
},
width: [1, 0, 30, 1]
},
layout: {
randomSeed: [0, 0, 500, 1],
hierarchical: {
enabled: false,
levelSeparation: [150, 20, 500, 5],
direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL
sortMethod: ['hubsize', 'directed'] // hubsize, directed
}
},
interaction: {
dragNodes: true,
dragView: true,
zoomView: true,
hoverEnabled: false,
navigationButtons: false,
tooltipDelay: [300, 0, 1000, 25],
keyboard: {
enabled: false,
speed: {x: [10, 0, 40, 1], y: [10, 0, 40, 1], zoom: [0.02, 0, 0.1, 0.005]},
bindToWindow: true
}
},
manipulation: {
enabled: false,
initiallyActive: false,
locale: ['en', 'nl']
},
physics: {
barnesHut: {
//theta: [0.5, 0.1, 1, 0.05],
gravitationalConstant: [-2000, -30000, 0, 50],
centralGravity: [0.3, 0, 10, 0.05],
springLength: [95, 0, 500, 5],
springConstant: [0.04, 0, 5, 0.005],
damping: [0.09, 0, 1, 0.01]
},
repulsion: {
centralGravity: [0.2, 0, 10, 0.05],
springLength: [200, 0, 500, 5],
springConstant: [0.05, 0, 5, 0.005],
nodeDistance: [100, 0, 500, 5],
damping: [0.09, 0, 1, 0.01]
},
hierarchicalRepulsion: {
centralGravity: [0.2, 0, 10, 0.05],
springLength: [100, 0, 500, 5],
springConstant: [0.01, 0, 5, 0.005],
nodeDistance: [120, 0, 500, 5],
damping: [0.09, 0, 1, 0.01]
},
maxVelocity: [50, 0, 150, 1],
minVelocity: [0.1, 0.01, 0.5, 0.01],
solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'],
timestep: [0.5, 0, 1, 0.05]
},
selection: {
selectable: true,
selectConnectedEdges: true
},
rendering: {
hideEdgesOnDrag: false,
hideNodesOnDrag: false
}
};
export {allOptions, configureOptions};

Loading…
Cancel
Save