From 3733976b35810f531ba4198600c5f8913796241d Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Sun, 13 Sep 2015 19:06:30 +0200 Subject: [PATCH] - Fixed deletion of options by settings them to null. --- HISTORY.md | 1 + dist/vis.js | 68 +++++++------ lib/network/modules/components/Edge.js | 32 +++--- lib/network/modules/components/Node.js | 15 ++- lib/util.js | 26 +++-- test/networkTest.html | 133 +++++++------------------ 6 files changed, 115 insertions(+), 160 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 3e3884cc..2f515fe4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,7 @@ http://visjs.org - Fixed setting font to null so the network won't crash anymore. - Fixed stabilized event not firing if layout algorithm does very well. - Fixed arrows with some shapes when they are selected. #1292 +- Fixed deletion of options by settings them to null. ## 2015-09-07, version 4.8.1 diff --git a/dist/vis.js b/dist/vis.js index 2b0ce38c..599e2874 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -388,7 +388,11 @@ return /******/ (function(modules) { // webpackBootstrap } else if (Array.isArray(b[prop])) { throw new TypeError('Arrays are not supported by deepExtend'); } else { - a[prop] = b[prop]; + if (b[prop] === null && a[prop] !== undefined && allowDeletion === true) { + delete a[prop]; + } else { + a[prop] = b[prop]; + } } } } @@ -433,7 +437,11 @@ return /******/ (function(modules) { // webpackBootstrap a[prop].push(b[prop][i]); } } else { - a[prop] = b[prop]; + if (b[prop] === null && a[prop] !== undefined && allowDeletion === true) { + delete a[prop]; + } else { + a[prop] = b[prop]; + } } } } @@ -472,7 +480,11 @@ return /******/ (function(modules) { // webpackBootstrap a[prop].push(b[prop][i]); } } else { - a[prop] = b[prop]; + if (b[prop] === null && a[prop] !== undefined && allowDeletion === true) { + delete a[prop]; + } else { + a[prop] = b[prop]; + } } } } @@ -1357,10 +1369,10 @@ return /******/ (function(modules) { // webpackBootstrap */ exports.mergeOptions = function (mergeTarget, options, option) { var allowDeletion = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; + var globalOptions = arguments.length <= 4 || arguments[4] === undefined ? {} : arguments[4]; if (options[option] === null) { - mergeTarget[option] = undefined; - delete mergeTarget[option]; + mergeTarget[option] = Object.create(globalOptions[option]); } else { if (options[option] !== undefined) { if (typeof options[option] === 'boolean') { @@ -28193,6 +28205,7 @@ return /******/ (function(modules) { // webpackBootstrap _classCallCheck(this, Node); this.options = util.bridgeObject(globalOptions); + this.globalOptions = globalOptions; this.body = body; this.edges = []; // all edges connected to this node @@ -28294,7 +28307,7 @@ return /******/ (function(modules) { // webpackBootstrap } // this transforms all shorthands into fully defined options - Node.parseOptions(this.options, options, true); + Node.parseOptions(this.options, options, true, this.globalOptions); // load the images if (this.options.image !== undefined) { @@ -28552,20 +28565,20 @@ return /******/ (function(modules) { // webpackBootstrap key: 'parseOptions', value: function parseOptions(parentOptions, newOptions) { var allowDeletion = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; + var globalOptions = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; var fields = ['color', 'font', 'fixed', 'shadow']; util.selectiveNotDeepExtend(fields, parentOptions, newOptions, allowDeletion); // merge the shadow options into the parent. - util.mergeOptions(parentOptions, newOptions, 'shadow'); + util.mergeOptions(parentOptions, newOptions, 'shadow', allowDeletion, globalOptions); // individual shape newOptions if (newOptions.color !== undefined && newOptions.color !== null) { var parsedColor = util.parseColor(newOptions.color); util.fillIfDefined(parentOptions.color, parsedColor); } else if (allowDeletion === true && newOptions.color === null) { - parentOptions.color = undefined; - delete parentOptions.color; + parentOptions.color = Object.create(globalOptions.color); // this sets the pointer of the option back to the global option. } // handle the fixed options @@ -28587,13 +28600,12 @@ return /******/ (function(modules) { // webpackBootstrap if (newOptions.font !== undefined && newOptions.font !== null) { _sharedLabel2['default'].parseOptions(parentOptions.font, newOptions); } else if (allowDeletion === true && newOptions.font === null) { - parentOptions.font = undefined; - delete parentOptions.font; + parentOptions.font = Object.create(globalOptions.font); // this sets the pointer of the option back to the global option. } // handle the scaling options, specifically the label part if (newOptions.scaling !== undefined) { - util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', allowDeletion); + util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', allowDeletion, globalOptions.scaling); } } }]); @@ -30961,6 +30973,7 @@ return /******/ (function(modules) { // webpackBootstrap throw "No body provided"; } this.options = util.bridgeObject(globalOptions); + this.globalOptions = globalOptions; this.body = body; // initialize variables @@ -31001,7 +31014,7 @@ return /******/ (function(modules) { // webpackBootstrap } this.colorDirty = true; - Edge.parseOptions(this.options, options, true); + Edge.parseOptions(this.options, options, true, this.globalOptions); if (options.id !== undefined) { this.id = options.id; @@ -31038,6 +31051,7 @@ return /******/ (function(modules) { // webpackBootstrap } }, { key: 'updateLabelModule', + // this sets the pointer of the option back to the global option. /** * update the options in the label module @@ -31370,20 +31384,20 @@ return /******/ (function(modules) { // webpackBootstrap key: 'parseOptions', value: function parseOptions(parentOptions, newOptions) { var allowDeletion = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; + var globalOptions = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; var fields = ['id', 'from', 'hidden', 'hoverWidth', 'label', 'labelHighlightBold', 'length', 'line', 'opacity', 'physics', 'scaling', 'selectionWidth', 'selfReferenceSize', 'to', 'title', 'value', 'width']; // only deep extend the items in the field array. These do not have shorthand. util.selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion); - util.mergeOptions(parentOptions, newOptions, 'smooth'); - util.mergeOptions(parentOptions, newOptions, 'shadow'); + util.mergeOptions(parentOptions, newOptions, 'smooth', allowDeletion, globalOptions); + util.mergeOptions(parentOptions, newOptions, 'shadow', allowDeletion, globalOptions); if (newOptions.dashes !== undefined && newOptions.dashes !== null) { parentOptions.dashes = newOptions.dashes; } else if (allowDeletion === true && newOptions.dashes === null) { - parentOptions.dashes = undefined; - delete parentOptions.dashes; + parentOptions.dashes = Object.create(globalOptions.dashes); // this sets the pointer of the option back to the global option. } // set the scaling newOptions @@ -31394,10 +31408,9 @@ return /******/ (function(modules) { // webpackBootstrap 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', allowDeletion, globalOptions.scaling); } else if (allowDeletion === true && newOptions.scaling === null) { - parentOptions.scaling = undefined; - delete parentOptions.scaling; + parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option. } // hanlde multiple input cases for arrows @@ -31414,15 +31427,14 @@ return /******/ (function(modules) { // webpackBootstrap parentOptions.arrows.from.enabled = true; } } else if (typeof newOptions.arrows === 'object') { - util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'to'); - util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle'); - util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'from'); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'to', allowDeletion, globalOptions.arrows); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle', allowDeletion, globalOptions.arrows); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'from', allowDeletion, globalOptions.arrows); } else { 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 && newOptions.arrows === null) { - parentOptions.arrows = undefined; - delete parentOptions.arrows; + parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option. } // hanlde multiple input cases for color @@ -31455,16 +31467,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } else if (allowDeletion === true && newOptions.color === null) { - parentOptions.color = undefined; - delete parentOptions.color; + parentOptions.color = Object.create(globalOptions.color); // this sets the pointer of the option back to the global option. } // handle the font settings if (newOptions.font !== undefined && newOptions.font !== null) { _sharedLabel2['default'].parseOptions(parentOptions.font, newOptions); } else if (allowDeletion === true && newOptions.font === null) { - parentOptions.font = undefined; - delete parentOptions.font; + parentOptions.font = Object.create(globalOptions.font); } } }]); diff --git a/lib/network/modules/components/Edge.js b/lib/network/modules/components/Edge.js index 72bbccf2..236e10de 100644 --- a/lib/network/modules/components/Edge.js +++ b/lib/network/modules/components/Edge.js @@ -27,6 +27,7 @@ class Edge { throw "No body provided"; } this.options = util.bridgeObject(globalOptions); + this.globalOptions = globalOptions; this.body = body; // initialize variables @@ -65,7 +66,7 @@ class Edge { } this.colorDirty = true; - Edge.parseOptions(this.options, options, true); + Edge.parseOptions(this.options, options, true, this.globalOptions); if (options.id !== undefined) {this.id = options.id;} if (options.from !== undefined) {this.fromId = options.from;} @@ -92,7 +93,7 @@ class Edge { return dataChanged; } - static parseOptions(parentOptions, newOptions, allowDeletion = false) { + static parseOptions(parentOptions, newOptions, allowDeletion = false, globalOptions = {}) { var fields = [ 'id', 'from', @@ -116,26 +117,24 @@ class Edge { // only deep extend the items in the field array. These do not have shorthand. util.selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion); - util.mergeOptions(parentOptions, newOptions, 'smooth'); - util.mergeOptions(parentOptions, newOptions, 'shadow'); + util.mergeOptions(parentOptions, newOptions, 'smooth', allowDeletion, globalOptions); + util.mergeOptions(parentOptions, newOptions, 'shadow', allowDeletion, globalOptions); if (newOptions.dashes !== undefined && newOptions.dashes !== null) { parentOptions.dashes = newOptions.dashes; } else if (allowDeletion === true && newOptions.dashes === null) { - parentOptions.dashes = undefined; - delete parentOptions.dashes; + parentOptions.dashes = Object.create(globalOptions.dashes); // this sets the pointer of the option back to the global option. } // set the scaling newOptions if (newOptions.scaling !== undefined && newOptions.scaling !== null) { if (newOptions.scaling.min !== undefined) {parentOptions.scaling.min = newOptions.scaling.min;} 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', allowDeletion, globalOptions.scaling); } else if (allowDeletion === true && newOptions.scaling === null) { - parentOptions.scaling = undefined; - delete parentOptions.scaling; + parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option. } // hanlde multiple input cases for arrows @@ -147,17 +146,16 @@ class Edge { if (arrows.indexOf("from") != -1) {parentOptions.arrows.from.enabled = true;} } else if (typeof newOptions.arrows === 'object') { - util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'to'); - util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle'); - util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'from'); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'to', allowDeletion, globalOptions.arrows); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle', allowDeletion, globalOptions.arrows); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'from', allowDeletion, globalOptions.arrows); } else { 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 && newOptions.arrows === null) { - parentOptions.arrows = undefined; - delete parentOptions.arrows; + parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option. } // hanlde multiple input cases for color @@ -182,8 +180,7 @@ class Edge { } } else if (allowDeletion === true && newOptions.color === null) { - parentOptions.color = undefined; - delete parentOptions.color; + parentOptions.color = Object.create(globalOptions.color); // this sets the pointer of the option back to the global option. } // handle the font settings @@ -191,8 +188,7 @@ class Edge { Label.parseOptions(parentOptions.font, newOptions); } else if (allowDeletion === true && newOptions.font === null) { - parentOptions.font = undefined; - delete parentOptions.font; + parentOptions.font = Object.create(globalOptions.font); // this sets the pointer of the option back to the global option. } } diff --git a/lib/network/modules/components/Node.js b/lib/network/modules/components/Node.js index a16424e1..89152195 100644 --- a/lib/network/modules/components/Node.js +++ b/lib/network/modules/components/Node.js @@ -48,6 +48,7 @@ import {printStyle} from "../../../shared/Validator"; class Node { constructor(options, body, imagelist, grouplist, globalOptions) { this.options = util.bridgeObject(globalOptions); + this.globalOptions = globalOptions; this.body = body; this.edges = []; // all edges connected to this node @@ -135,7 +136,7 @@ class Node { } // this transforms all shorthands into fully defined options - Node.parseOptions(this.options, options, true); + Node.parseOptions(this.options, options, true, this.globalOptions); // load the images if (this.options.image !== undefined) { @@ -164,7 +165,7 @@ class Node { * @param parentOptions * @param newOptions */ - static parseOptions(parentOptions, newOptions, allowDeletion = false) { + static parseOptions(parentOptions, newOptions, allowDeletion = false, globalOptions = {}) { var fields = [ 'color', 'font', @@ -174,7 +175,7 @@ class Node { util.selectiveNotDeepExtend(fields, parentOptions, newOptions, allowDeletion); // merge the shadow options into the parent. - util.mergeOptions(parentOptions, newOptions, 'shadow'); + util.mergeOptions(parentOptions, newOptions, 'shadow', allowDeletion, globalOptions); // individual shape newOptions if (newOptions.color !== undefined && newOptions.color !== null) { @@ -182,8 +183,7 @@ class Node { util.fillIfDefined(parentOptions.color, parsedColor); } else if (allowDeletion === true && newOptions.color === null) { - parentOptions.color = undefined; - delete parentOptions.color; + parentOptions.color = Object.create(globalOptions.color); // this sets the pointer of the option back to the global option. } // handle the fixed options @@ -207,13 +207,12 @@ class Node { Label.parseOptions(parentOptions.font, newOptions); } else if (allowDeletion === true && newOptions.font === null) { - parentOptions.font = undefined; - delete parentOptions.font; + parentOptions.font = Object.create(globalOptions.font); // this sets the pointer of the option back to the global option. } // handle the scaling options, specifically the label part if (newOptions.scaling !== undefined) { - util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', allowDeletion); + util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', allowDeletion, globalOptions.scaling); } } diff --git a/lib/util.js b/lib/util.js index 46b2760f..9b1999f0 100644 --- a/lib/util.js +++ b/lib/util.js @@ -232,7 +232,12 @@ exports.selectiveDeepExtend = function (props, a, b, allowDeletion = false) { } else if (Array.isArray(b[prop])) { throw new TypeError('Arrays are not supported by deepExtend'); } else { - a[prop] = b[prop]; + if ((b[prop] === null) && a[prop] !== undefined && allowDeletion === true) { + delete a[prop]; + } + else { + a[prop] = b[prop]; + } } } @@ -278,7 +283,12 @@ exports.selectiveNotDeepExtend = function (props, a, b, allowDeletion = false) { a[prop].push(b[prop][i]); } } else { - a[prop] = b[prop]; + if ((b[prop] === null) && a[prop] !== undefined && allowDeletion === true) { + delete a[prop]; + } + else { + a[prop] = b[prop]; + } } } } @@ -319,7 +329,12 @@ exports.deepExtend = function (a, b, protoExtend, allowDeletion) { a[prop].push(b[prop][i]); } } else { - a[prop] = b[prop]; + if ((b[prop] === null) && a[prop] !== undefined && allowDeletion === true) { + delete a[prop]; + } + else { + a[prop] = b[prop]; + } } } } @@ -1248,10 +1263,9 @@ exports.bridgeObject = function (referenceObject) { * @param [String] option | this is the option key in the options argument * @private */ -exports.mergeOptions = function (mergeTarget, options, option, allowDeletion = false) { +exports.mergeOptions = function (mergeTarget, options, option, allowDeletion = false, globalOptions = {}) { if (options[option] === null) { - mergeTarget[option] = undefined; - delete mergeTarget[option]; + mergeTarget[option] = Object.create(globalOptions[option]); } else { if (options[option] !== undefined) { diff --git a/test/networkTest.html b/test/networkTest.html index 4b335579..2046ae84 100644 --- a/test/networkTest.html +++ b/test/networkTest.html @@ -1,122 +1,57 @@ - - - Network | Static smooth curves - World Cup Network + Network | Basic usage - - + - - -

Performance - World Cup Network

- -
- This example shows the performance of vis with a larger network. The edges in - particular (~9200) are very computationally intensive - to draw. Drag and hold the graph to see the performance difference if the - edges are hidden. -

- We use the following physics configuration:
- {barnesHut: {gravitationalConstant: -80000, springConstant: 0.001, - springLength: 200}} -

-
+

+ Create a simple network with some nodes and edges. +

+