Browse Source

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

flowchartTest
Alex de Mulder 9 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