Browse Source

allowed deleting values with null and undefined. Fix for global variables, fix for edge color strings

flowchartTest
Alex de Mulder 10 years ago
parent
commit
357853e2ce
10 changed files with 1965 additions and 1875 deletions
  1. +1883
    -1836
      dist/vis.js
  2. +7
    -5
      examples/network/01_basic_usage.html
  3. +1
    -1
      lib/network/modules/EdgesHandler.js
  4. +1
    -1
      lib/network/modules/InteractionHandler.js
  5. +1
    -1
      lib/network/modules/NodesHandler.js
  6. +1
    -1
      lib/network/modules/components/AllOptions.js
  7. +19
    -7
      lib/network/modules/components/Edge.js
  8. +13
    -5
      lib/network/modules/components/Node.js
  9. +4
    -4
      lib/network/modules/components/shared/Label.js
  10. +35
    -14
      lib/util.js

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


+ 7
- 5
examples/network/01_basic_usage.html View File

@ -19,8 +19,10 @@
<script type="text/javascript"> <script type="text/javascript">
// create an array with nodes // create an array with nodes
var nodesDS = new vis.DataSet();
var nodes = [ var nodes = [
{id: 1, label: 'Node 1', value:3, title:'hello world'},
{id: 1, label: 'Node 1', value:3, title:'hello world', color:'red'},
{id: 2, label: 'Node 2', value:1, group:'bla'}, {id: 2, label: 'Node 2', value:1, group:'bla'},
{id: 3, label: 'Node 3', value:5}, {id: 3, label: 'Node 3', value:5},
{id: 4, value:3}, {id: 4, value:3},
@ -38,17 +40,17 @@
// create a network // create a network
var container = document.getElementById('mynetwork'); var container = document.getElementById('mynetwork');
nodesDS.add(nodes);
var data = { var data = {
nodes: nodes,
nodes: nodesDS,
edges: edges edges: edges
}; };
var options = { var options = {
// physics:{barnesHut:{gravitationslPull:34}, solver:'banana'},
edges:{color:'red'}
} }
var network = new vis.Network(container, data, options); var network = new vis.Network(container, data, options);
// network.setOptions({nodes:{color:'red'}}) // network.setOptions({nodes:{color:'red'}})
network.on("rightClick",function(e){console.log(e)})
nodesDS.update({id:1, color:undefined,label:'hi'});
</script> </script>
<pre> <pre>
var options = { var options = {

+ 1
- 1
lib/network/modules/EdgesHandler.js View File

@ -170,7 +170,7 @@ class EdgesHandler {
// update fonts in all edges // update fonts in all edges
if (options.font !== undefined) { if (options.font !== undefined) {
// use the parser from the Label class to fill in all shorthand notations // use the parser from the Label class to fill in all shorthand notations
Label.parseOptions(this.options,options);
Label.parseOptions(this.options, options);
for (let edgeId in this.body.edges) { for (let edgeId in this.body.edges) {
if (this.body.edges.hasOwnProperty(edgeId)) { if (this.body.edges.hasOwnProperty(edgeId)) {
this.body.edges[edgeId].updateLabelModule(); this.body.edges[edgeId].updateLabelModule();

+ 1
- 1
lib/network/modules/InteractionHandler.js View File

@ -64,7 +64,7 @@ class InteractionHandler {
if (options !== undefined) { if (options !== undefined) {
// extend all but the values in fields // extend all but the values in fields
let fields = ['keyboard']; let fields = ['keyboard'];
util.selectiveNotDeepExtend(fields,this.options, options);
util.selectiveNotDeepExtend(fields, this.options, options);
// merge the keyboard options in. // merge the keyboard options in.
util.mergeOptions(this.options, options, 'keyboard'); util.mergeOptions(this.options, options, 'keyboard');

+ 1
- 1
lib/network/modules/NodesHandler.js View File

@ -130,7 +130,7 @@ class NodesHandler {
// update the shape size in all nodes // update the shape size in all nodes
if (options.font !== undefined) { if (options.font !== undefined) {
Label.parseOptions(this.options.font,options);
Label.parseOptions(this.options.font, options);
for (let nodeId in this.body.nodes) { for (let nodeId in this.body.nodes) {
if (this.body.nodes.hasOwnProperty(nodeId)) { if (this.body.nodes.hasOwnProperty(nodeId)) {
this.body.nodes[nodeId].updateLabelModule(); this.body.nodes[nodeId].updateLabelModule();

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

@ -47,7 +47,7 @@ let allOptions = {
hover: {string}, hover: {string},
inherit: {string:['from','to','both'],boolean}, inherit: {string:['from','to','both'],boolean},
opacity: {number}, opacity: {number},
__type__: {object}
__type__: {object, string}
}, },
dashes: { dashes: {
enabled: {boolean}, enabled: {boolean},

+ 19
- 7
lib/network/modules/components/Edge.js View File

@ -64,7 +64,7 @@ class Edge {
} }
this.colorDirty = true; this.colorDirty = true;
Edge.parseOptions(this.options, options);
Edge.parseOptions(this.options, options, true);
if (options.id !== undefined) {this.id = options.id;} if (options.id !== undefined) {this.id = options.id;}
if (options.from !== undefined) {this.fromId = options.from;} if (options.from !== undefined) {this.fromId = options.from;}
@ -87,7 +87,7 @@ class Edge {
return dataChanged; return dataChanged;
} }
static parseOptions(parentOptions, newOptions) {
static parseOptions(parentOptions, newOptions, allowDeletion = false) {
var fields = [ var fields = [
'id', 'id',
'font', 'font',
@ -108,21 +108,25 @@ class Edge {
]; ];
// only deep extend the items in the field array. These do not have shorthand. // only deep extend the items in the field array. These do not have shorthand.
util.selectiveDeepExtend(fields, parentOptions, newOptions);
util.selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion);
util.mergeOptions(parentOptions, newOptions, 'smooth'); util.mergeOptions(parentOptions, newOptions, 'smooth');
util.mergeOptions(parentOptions, newOptions, 'dashes'); util.mergeOptions(parentOptions, newOptions, 'dashes');
util.mergeOptions(parentOptions, newOptions, 'shadow'); util.mergeOptions(parentOptions, newOptions, 'shadow');
// set the scaling newOptions // set the scaling newOptions
if (newOptions.scaling !== undefined) {
if (newOptions.scaling !== undefined && newOptions.scaling !== null) {
if (newOptions.scaling.min !== undefined) {parentOptions.scaling.min = newOptions.scaling.min;} if (newOptions.scaling.min !== undefined) {parentOptions.scaling.min = newOptions.scaling.min;}
if (newOptions.scaling.max !== undefined) {parentOptions.scaling.max = newOptions.scaling.max;} if (newOptions.scaling.max !== undefined) {parentOptions.scaling.max = newOptions.scaling.max;}
util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label'); util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label');
} }
else if (allowDeletion === true) {
parentOptions.scaling = undefined;
delete parentOptions.scaling;
}
// hanlde multiple input cases for arrows // hanlde multiple input cases for arrows
if (newOptions.arrows !== undefined) {
if (newOptions.arrows !== undefined && newOptions.arrows !== null) {
if (typeof newOptions.arrows === 'string') { if (typeof newOptions.arrows === 'string') {
let arrows = newOptions.arrows.toLowerCase(); let arrows = newOptions.arrows.toLowerCase();
if (arrows.indexOf("to") != -1) {parentOptions.arrows.to.enabled = true;} if (arrows.indexOf("to") != -1) {parentOptions.arrows.to.enabled = true;}
@ -138,9 +142,13 @@ class Edge {
throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + JSON.stringify(newOptions.arrows)); throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + JSON.stringify(newOptions.arrows));
} }
} }
else if (allowDeletion === true) {
parentOptions.arrows = undefined;
delete parentOptions.arrows;
}
// hanlde multiple input cases for color // hanlde multiple input cases for color
if (newOptions.color !== undefined) {
if (newOptions.color !== undefined && newOptions.color !== null) {
if (util.isString(newOptions.color)) { if (util.isString(newOptions.color)) {
parentOptions.color.color = newOptions.color; parentOptions.color.color = newOptions.color;
parentOptions.color.highlight = newOptions.color; parentOptions.color.highlight = newOptions.color;
@ -160,6 +168,10 @@ class Edge {
} }
} }
} }
else if (allowDeletion === true) {
parentOptions.color = undefined;
delete parentOptions.color;
}
} }
@ -167,7 +179,7 @@ class Edge {
* update the options in the label module * update the options in the label module
*/ */
updateLabelModule() { updateLabelModule() {
this.labelModule.setOptions(this.options);
this.labelModule.setOptions(this.options, true);
if (this.labelModule.baseSize !== undefined) { if (this.labelModule.baseSize !== undefined) {
this.baseFontSize = this.labelModule.baseSize; this.baseFontSize = this.labelModule.baseSize;
} }

+ 13
- 5
lib/network/modules/components/Node.js View File

@ -125,7 +125,7 @@ class Node {
if (options.value !== undefined) {options.value = parseInt(options.value);} if (options.value !== undefined) {options.value = parseInt(options.value);}
// this transforms all shorthands into fully defined options // this transforms all shorthands into fully defined options
Node.parseOptions(this.options,options);
Node.parseOptions(this.options, options, true);
// copy group options // copy group options
if (typeof options.group === 'number' || (typeof options.group === 'string' && options.group != '')) { if (typeof options.group === 'number' || (typeof options.group === 'string' && options.group != '')) {
@ -159,7 +159,7 @@ class Node {
* @param parentOptions * @param parentOptions
* @param newOptions * @param newOptions
*/ */
static parseOptions(parentOptions, newOptions) {
static parseOptions(parentOptions, newOptions, allowDeletion = false) {
var fields = [ var fields = [
'color', 'color',
'fixed', 'fixed',
@ -172,12 +172,16 @@ class Node {
util.mergeOptions(parentOptions, newOptions, 'shadow'); util.mergeOptions(parentOptions, newOptions, 'shadow');
// individual shape newOptions // individual shape newOptions
if (newOptions.color !== undefined) {
if (newOptions.color !== undefined && newOptions.color !== null) {
let parsedColor = util.parseColor(newOptions.color); let parsedColor = util.parseColor(newOptions.color);
util.fillIfDefined(parentOptions.color, parsedColor); util.fillIfDefined(parentOptions.color, parsedColor);
} }
else if (allowDeletion === true) {
parentOptions.color = undefined;
delete parentOptions.color;
}
if (newOptions.fixed !== undefined) {
if (newOptions.fixed !== undefined && newOptions.fixed !== null) {
if (typeof newOptions.fixed === 'boolean') { if (typeof newOptions.fixed === 'boolean') {
parentOptions.fixed.x = newOptions.fixed; parentOptions.fixed.x = newOptions.fixed;
parentOptions.fixed.y = newOptions.fixed; parentOptions.fixed.y = newOptions.fixed;
@ -191,13 +195,17 @@ class Node {
} }
} }
} }
else if (allowDeletion === true) {
parentOptions.fixed = undefined;
delete parentOptions.fixed;
}
} }
updateLabelModule() { updateLabelModule() {
if (this.options.label === undefined || this.options.label === null) { if (this.options.label === undefined || this.options.label === null) {
this.options.label = ''; this.options.label = '';
} }
this.labelModule.setOptions(this.options);
this.labelModule.setOptions(this.options, true);
if (this.labelModule.baseSize !== undefined) { if (this.labelModule.baseSize !== undefined) {
this.baseFontSize = this.labelModule.baseSize; this.baseFontSize = this.labelModule.baseSize;
} }

+ 4
- 4
lib/network/modules/components/shared/Label.js View File

@ -9,7 +9,7 @@ class Label {
this.size = {top: 0, left: 0, width: 0, height: 0, yLine: 0}; // could be cached this.size = {top: 0, left: 0, width: 0, height: 0, yLine: 0}; // could be cached
} }
setOptions(options) {
setOptions(options, allowDeletion = false) {
this.options = options; this.options = options;
if (options.label !== undefined) { if (options.label !== undefined) {
@ -17,7 +17,7 @@ class Label {
} }
if (options.font !== undefined) { if (options.font !== undefined) {
Label.parseOptions(this.options.font,options);
Label.parseOptions(this.options.font, options, allowDeletion);
if (typeof options.font === 'string') { if (typeof options.font === 'string') {
this.baseSize = this.options.font.size; this.baseSize = this.options.font.size;
} }
@ -29,7 +29,7 @@ class Label {
} }
} }
static parseOptions(parentOptions, newOptions) {
static parseOptions(parentOptions, newOptions, allowDeletion = false) {
if (typeof newOptions.font === 'string') { if (typeof newOptions.font === 'string') {
let newOptionsArray = newOptions.font.split(" "); let newOptionsArray = newOptions.font.split(" ");
parentOptions.size = newOptionsArray[0].replace("px",''); parentOptions.size = newOptionsArray[0].replace("px",'');
@ -37,7 +37,7 @@ class Label {
parentOptions.color = newOptionsArray[2]; parentOptions.color = newOptionsArray[2];
} }
else if (typeof newOptions.font === 'object') { else if (typeof newOptions.font === 'object') {
util.fillIfDefined(parentOptions, newOptions.font);
util.fillIfDefined(parentOptions, newOptions.font, global);
} }
parentOptions.size = Number(parentOptions.size); parentOptions.size = Number(parentOptions.size);
} }

+ 35
- 14
lib/util.js View File

@ -118,11 +118,16 @@ exports.assignAllKeys = function (obj, value) {
* @param obj * @param obj
* @param value * @param value
*/ */
exports.fillIfDefined = function (parentObj, newObj) {
for (var prop in parentObj) {
if (newObj[prop] !== undefined) {
if (typeof newObj[prop] !== 'object') {
parentObj[prop] = newObj[prop];
exports.fillIfDefined = function (a, b, allowDeletion = false) {
for (var prop in a) {
if (b[prop] !== undefined) {
if (typeof b[prop] !== 'object') {
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
a[prop] = b[prop];
}
else {
a[prop] = b[prop];
}
} }
} }
} }
@ -169,7 +174,7 @@ exports.extend = function (a, b) {
* Only properties with defined values are copied * Only properties with defined values are copied
* @param {Array.<String>} props * @param {Array.<String>} props
* @param {Object} a * @param {Object} a
* @param {... Object} b
* @param {Object} b
* @return {Object} a * @return {Object} a
*/ */
exports.selectiveExtend = function (props, a, b) { exports.selectiveExtend = function (props, a, b) {
@ -195,10 +200,10 @@ exports.selectiveExtend = function (props, a, b) {
* Only properties with defined values are copied * Only properties with defined values are copied
* @param {Array.<String>} props * @param {Array.<String>} props
* @param {Object} a * @param {Object} a
* @param {... Object} b
* @param {Object} b
* @return {Object} a * @return {Object} a
*/ */
exports.selectiveDeepExtend = function (props, a, b) {
exports.selectiveDeepExtend = function (props, a, b, allowDeletion = false) {
// TODO: add support for Arrays to deepExtend // TODO: add support for Arrays to deepExtend
if (Array.isArray(b)) { if (Array.isArray(b)) {
throw new TypeError('Arrays are not supported by deepExtend'); throw new TypeError('Arrays are not supported by deepExtend');
@ -216,7 +221,12 @@ exports.selectiveDeepExtend = function (props, a, b) {
exports.deepExtend(a[prop], b[prop]); exports.deepExtend(a[prop], b[prop]);
} }
else { else {
a[prop] = b[prop];
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
delete a[prop];
}
else {
a[prop] = b[prop];
}
} }
} else if (Array.isArray(b[prop])) { } else if (Array.isArray(b[prop])) {
throw new TypeError('Arrays are not supported by deepExtend'); throw new TypeError('Arrays are not supported by deepExtend');
@ -235,10 +245,10 @@ exports.selectiveDeepExtend = function (props, a, b) {
* Only properties with defined values are copied * Only properties with defined values are copied
* @param {Array.<String>} props * @param {Array.<String>} props
* @param {Object} a * @param {Object} a
* @param {... Object} b
* @param {Object} b
* @return {Object} a * @return {Object} a
*/ */
exports.selectiveNotDeepExtend = function (props, a, b) {
exports.selectiveNotDeepExtend = function (props, a, b, allowDeletion = false) {
// TODO: add support for Arrays to deepExtend // TODO: add support for Arrays to deepExtend
if (Array.isArray(b)) { if (Array.isArray(b)) {
throw new TypeError('Arrays are not supported by deepExtend'); throw new TypeError('Arrays are not supported by deepExtend');
@ -254,7 +264,12 @@ exports.selectiveNotDeepExtend = function (props, a, b) {
exports.deepExtend(a[prop], b[prop]); exports.deepExtend(a[prop], b[prop]);
} }
else { else {
a[prop] = b[prop];
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
delete a[prop];
}
else {
a[prop] = b[prop];
}
} }
} else if (Array.isArray(b[prop])) { } else if (Array.isArray(b[prop])) {
throw new TypeError('Arrays are not supported by deepExtend'); throw new TypeError('Arrays are not supported by deepExtend');
@ -273,9 +288,10 @@ exports.selectiveNotDeepExtend = function (props, a, b) {
* @param {Object} b * @param {Object} b
* @param [Boolean] protoExtend --> optional parameter. If true, the prototype values will also be extended. * @param [Boolean] protoExtend --> optional parameter. If true, the prototype values will also be extended.
* (ie. the options objects that inherit from others will also get the inherited options) * (ie. the options objects that inherit from others will also get the inherited options)
* @param [Boolean] global --> optional parameter. If true, the values of fields that are undefined or null will not deleted
* @returns {Object} * @returns {Object}
*/ */
exports.deepExtend = function(a, b, protoExtend) {
exports.deepExtend = function(a, b, protoExtend, allowDeletion) {
for (var prop in b) { for (var prop in b) {
if (b.hasOwnProperty(prop) || protoExtend === true) { if (b.hasOwnProperty(prop) || protoExtend === true) {
if (b[prop] && b[prop].constructor === Object) { if (b[prop] && b[prop].constructor === Object) {
@ -286,7 +302,12 @@ exports.deepExtend = function(a, b, protoExtend) {
exports.deepExtend(a[prop], b[prop], protoExtend); exports.deepExtend(a[prop], b[prop], protoExtend);
} }
else { else {
a[prop] = b[prop];
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
delete a[prop];
}
else {
a[prop] = b[prop];
}
} }
} else if (Array.isArray(b[prop])) { } else if (Array.isArray(b[prop])) {
a[prop] = []; a[prop] = [];

Loading…
Cancel
Save