diff --git a/HISTORY.md b/HISTORY.md index 60308f08..1e133a0e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -16,6 +16,7 @@ http://visjs.org - Fixed #1343: Connected edges are now deselected too when deselecting a node. - Fixed #1398: Support nodes start with the correct positions. - Fixed #1324: Labels now scale again. +- Fixed #1362: Layout of hierarchicaly systems no longer overlaps NODES. ### Timeline diff --git a/dist/img/network/acceptDeleteIcon.png b/dist/img/network/acceptDeleteIcon.png deleted file mode 100644 index 02a06285..00000000 Binary files a/dist/img/network/acceptDeleteIcon.png and /dev/null differ diff --git a/dist/img/network/addNodeIcon.png b/dist/img/network/addNodeIcon.png deleted file mode 100644 index 6fa30613..00000000 Binary files a/dist/img/network/addNodeIcon.png and /dev/null differ diff --git a/dist/img/network/backIcon.png b/dist/img/network/backIcon.png deleted file mode 100644 index e2f99126..00000000 Binary files a/dist/img/network/backIcon.png and /dev/null differ diff --git a/dist/img/network/connectIcon.png b/dist/img/network/connectIcon.png deleted file mode 100644 index 4164da1f..00000000 Binary files a/dist/img/network/connectIcon.png and /dev/null differ diff --git a/dist/img/network/cross.png b/dist/img/network/cross.png deleted file mode 100644 index 9cbd189a..00000000 Binary files a/dist/img/network/cross.png and /dev/null differ diff --git a/dist/img/network/cross2.png b/dist/img/network/cross2.png deleted file mode 100644 index 9fc4b95c..00000000 Binary files a/dist/img/network/cross2.png and /dev/null differ diff --git a/dist/img/network/deleteIcon.png b/dist/img/network/deleteIcon.png deleted file mode 100644 index 54025647..00000000 Binary files a/dist/img/network/deleteIcon.png and /dev/null differ diff --git a/dist/img/network/downArrow.png b/dist/img/network/downArrow.png deleted file mode 100644 index e77d5e6d..00000000 Binary files a/dist/img/network/downArrow.png and /dev/null differ diff --git a/dist/img/network/editIcon.png b/dist/img/network/editIcon.png deleted file mode 100644 index 494d0f00..00000000 Binary files a/dist/img/network/editIcon.png and /dev/null differ diff --git a/dist/img/network/leftArrow.png b/dist/img/network/leftArrow.png deleted file mode 100644 index 3823536e..00000000 Binary files a/dist/img/network/leftArrow.png and /dev/null differ diff --git a/dist/img/network/minus.png b/dist/img/network/minus.png deleted file mode 100644 index 30698076..00000000 Binary files a/dist/img/network/minus.png and /dev/null differ diff --git a/dist/img/network/plus.png b/dist/img/network/plus.png deleted file mode 100644 index f7ab2a33..00000000 Binary files a/dist/img/network/plus.png and /dev/null differ diff --git a/dist/img/network/rightArrow.png b/dist/img/network/rightArrow.png deleted file mode 100644 index c3a209d8..00000000 Binary files a/dist/img/network/rightArrow.png and /dev/null differ diff --git a/dist/img/network/upArrow.png b/dist/img/network/upArrow.png deleted file mode 100644 index 8aedced7..00000000 Binary files a/dist/img/network/upArrow.png and /dev/null differ diff --git a/dist/img/network/zoomExtends.png b/dist/img/network/zoomExtends.png deleted file mode 100644 index 74595c63..00000000 Binary files a/dist/img/network/zoomExtends.png and /dev/null differ diff --git a/dist/img/timeline/delete.png b/dist/img/timeline/delete.png deleted file mode 100644 index d54d0e06..00000000 Binary files a/dist/img/timeline/delete.png and /dev/null differ diff --git a/dist/vis.js b/dist/vis.js index 691cda96..cc03042d 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 4.9.1-SNAPSHOT - * @date 2015-11-02 + * @date 2015-11-16 * * @license * Copyright (C) 2011-2015 Almende B.V, http://almende.com @@ -107,8 +107,9 @@ return /******/ (function(modules) { // webpackBootstrap exports.Timeline = __webpack_require__(19); exports.Graph2d = __webpack_require__(49); exports.timeline = { - DateUtil: __webpack_require__(27), + Core: __webpack_require__(28), DataStep: __webpack_require__(52), + DateUtil: __webpack_require__(27), Range: __webpack_require__(24), stack: __webpack_require__(32), TimeStep: __webpack_require__(30), @@ -122,13 +123,13 @@ return /******/ (function(modules) { // webpackBootstrap RangeItem: __webpack_require__(33) }, + BackgroundGroup: __webpack_require__(35), Component: __webpack_require__(26), CurrentTime: __webpack_require__(44), CustomTime: __webpack_require__(42), DataAxis: __webpack_require__(51), GraphGroup: __webpack_require__(53), Group: __webpack_require__(31), - BackgroundGroup: __webpack_require__(35), ItemSet: __webpack_require__(29), Legend: __webpack_require__(57), LineGraph: __webpack_require__(50), @@ -5451,10 +5452,11 @@ return /******/ (function(modules) { // webpackBootstrap var addOrUpdate = function addOrUpdate(item) { var id = item[fieldId]; if (me._data[id]) { + var oldData = util.extend({}, me._data[id]); // update item id = me._updateItem(item); updatedIds.push(id); - updatedData.push(item); + updatedData.push(oldData); } else { // add new item id = me._addItem(item); @@ -5478,7 +5480,15 @@ return /******/ (function(modules) { // webpackBootstrap this._trigger('add', { items: addedIds }, senderId); } if (updatedIds.length) { - this._trigger('update', { items: updatedIds, data: updatedData }, senderId); + var props = { items: updatedIds, oldData: updatedData }; + // TODO: remove deprecated property 'data' some day + Object.defineProperty(props, 'data', { + 'get': (function () { + console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data'); + return this.get(updatedIds); + }).bind(this) + }); + this._trigger('update', props, senderId); } return addedIds.concat(updatedIds); @@ -5712,7 +5722,7 @@ return /******/ (function(modules) { // webpackBootstrap var filter = options && options.filter, type = options && options.type || this._options.type, data = this._data, - itemIds = Object.key(data), + itemIds = Object.keys(data), i, len, item, @@ -15658,6 +15668,7 @@ return /******/ (function(modules) { // webpackBootstrap selectable: true, multiselect: false, + itemsAlwaysDraggable: false, editable: { updateTime: false, @@ -15922,7 +15933,7 @@ return /******/ (function(modules) { // webpackBootstrap ItemSet.prototype.setOptions = function (options) { if (options) { // copy all options that we know - var fields = ['type', 'align', 'order', 'stack', 'selectable', 'multiselect', 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', 'groupOrderSwap']; + var fields = ['type', 'align', 'order', 'stack', 'selectable', 'multiselect', 'itemsAlwaysDraggable', 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', 'groupOrderSwap']; util.selectiveExtend(fields, this.options, options); if ('orientation' in options) { @@ -16766,7 +16777,7 @@ return /******/ (function(modules) { // webpackBootstrap var me = this; var props; - if (item && item.selected) { + if (item && (item.selected || this.options.itemsAlwaysDraggable)) { if (!this.options.editable.updateTime && !this.options.editable.updateGroup && !item.editable) { return; @@ -16803,7 +16814,9 @@ return /******/ (function(modules) { // webpackBootstrap var baseGroupIndex = this._getGroupIndex(item.data.group); - this.touchParams.itemProps = this.getSelection().map((function (id) { + var itemsToDrag = this.options.itemsAlwaysDraggable && !item.selected ? [item.id] : this.getSelection(); + + this.touchParams.itemProps = itemsToDrag.map((function (id) { var item = me.items[id]; var groupIndex = me._getGroupIndex(item.data.group); return { @@ -21479,7 +21492,7 @@ return /******/ (function(modules) { // webpackBootstrap var locale = this.options.locales[this.options.locale]; if (!locale) { if (!this.warned) { - console.log('WARNING: options.locales[\'' + this.options.locale + '\'] not found. See http://visjs.org/docs/timeline.html#Localization'); + console.log('WARNING: options.locales[\'' + this.options.locale + '\'] not found. See http://visjs.org/docs/timeline/#Localization'); this.warned = true; } locale = this.options.locales['en']; // fall back on english when not available @@ -23342,6 +23355,7 @@ return /******/ (function(modules) { // webpackBootstrap repeat: { string: string }, __type__: { object: object, array: array } }, + itemsAlwaysDraggable: { boolean: boolean }, locale: { string: string }, locales: { __any__: { any: any }, @@ -39159,62 +39173,77 @@ return /******/ (function(modules) { // webpackBootstrap } /** - * select zero or more nodes with the option to highlight edges - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. - * @param {boolean} [highlightEdges] + * Updates the current selection + * @param {{nodes: Array., edges: Array.}} Selection + * @param {Object} options Options */ }, { - key: "selectNodes", - value: function selectNodes(selection) { - var highlightEdges = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; + key: "setSelection", + value: function setSelection(selection) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var i = undefined, id = undefined; - if (!selection || selection.length === undefined) throw 'Selection must be an array with ids'; + if (!selection || !selection.nodes && !selection.edges) throw 'Selection must be an object with nodes and/or edges properties'; + // first unselect any selected node, if option is true or undefined + if (options.unselectAll || options.unselectAll === undefined) { + this.unselectAll(); + } + if (selection.nodes) { + for (i = 0; i < selection.nodes.length; i++) { + id = selection.nodes[i]; - // first unselect any selected node - this.unselectAll(); + var node = this.body.nodes[id]; + if (!node) { + throw new RangeError('Node with id "' + id + '" not found'); + } + // don't select edges with it + this.selectObject(node, options.highlightEdges); + } + } - for (i = 0; i < selection.length; i++) { - id = selection[i]; + if (selection.edges) { + for (i = 0; i < selection.edges.length; i++) { + id = selection.edges[i]; - var node = this.body.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); + var edge = this.body.edges[id]; + if (!edge) { + throw new RangeError('Edge with id "' + id + '" not found'); + } + this.selectObject(edge); } - this.selectObject(node, highlightEdges); } this.body.emitter.emit('_requestRedraw'); } /** - * select zero or more edges + * select zero or more nodes with the option to highlight edges * @param {Number[] | String[]} selection An array with the ids of the * selected nodes. + * @param {boolean} [highlightEdges] */ }, { - key: "selectEdges", - value: function selectEdges(selection) { - var i = undefined, - id = undefined; + key: "selectNodes", + value: function selectNodes(selection) { + var highlightEdges = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; if (!selection || selection.length === undefined) throw 'Selection must be an array with ids'; - // first unselect any selected objects - this.unselectAll(); + this.setSelection({ nodes: selection }, { highlightEdges: highlightEdges }); + } - for (i = 0; i < selection.length; i++) { - id = selection[i]; + /** + * select zero or more edges + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. + */ + }, { + key: "selectEdges", + value: function selectEdges(selection) { + if (!selection || selection.length === undefined) throw 'Selection must be an array with ids'; - var edge = this.body.edges[id]; - if (!edge) { - throw new RangeError('Edge with id "' + id + '" not found'); - } - this.selectObject(edge); - } - this.body.emitter.emit('_requestRedraw'); + this.setSelection({ edges: selection }); } /** @@ -39629,12 +39658,14 @@ return /******/ (function(modules) { // webpackBootstrap if (node.x === undefined) { node.x = distribution[level].distance; } - distribution[level].distance = node.x + this.nodeSpacing; + // since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance. + distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.x + this.nodeSpacing); } else { if (node.y === undefined) { node.y = distribution[level].distance; } - distribution[level].distance = node.y + this.nodeSpacing; + // since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance. + distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.y + this.nodeSpacing); } this.positionedNodes[nodeId] = true; diff --git a/lib/network/modules/LayoutEngine.js b/lib/network/modules/LayoutEngine.js index b38bc393..12de04fd 100644 --- a/lib/network/modules/LayoutEngine.js +++ b/lib/network/modules/LayoutEngine.js @@ -350,11 +350,13 @@ class LayoutEngine { if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') { if (node.x === undefined) {node.x = distribution[level].distance;} - distribution[level].distance = node.x + this.nodeSpacing; + // since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance. + distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.x + this.nodeSpacing); } else { if (node.y === undefined) {node.y = distribution[level].distance;} - distribution[level].distance = node.y + this.nodeSpacing; + // since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance. + distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.y + this.nodeSpacing); } this.positionedNodes[nodeId] = true; diff --git a/lib/network/modules/ManipulationSystem.js b/lib/network/modules/ManipulationSystem.js index 28a62752..2e8bf75e 100644 --- a/lib/network/modules/ManipulationSystem.js +++ b/lib/network/modules/ManipulationSystem.js @@ -376,15 +376,12 @@ class ManipulationSystem { // temporarily overload UI functions, cleaned up automatically because of _temporaryBindUI this._temporaryBindUI('onTouch', this._controlNodeTouch.bind(this)); // used to get the position - this._temporaryBindUI('onTap', () => { - }); // disabled - this._temporaryBindUI('onHold', () => { - }); // disabled + this._temporaryBindUI('onTap', () => {}); // disabled + this._temporaryBindUI('onHold', () => {}); // disabled this._temporaryBindUI('onDragStart', this._controlNodeDragStart.bind(this));// used to select control node this._temporaryBindUI('onDrag', this._controlNodeDrag.bind(this)); // used to drag control node this._temporaryBindUI('onDragEnd', this._controlNodeDragEnd.bind(this)); // used to connect or revert control nodes - this._temporaryBindUI('onMouseMove', () => { - }); // disabled + this._temporaryBindUI('onMouseMove', () => {}); // disabled // create function to position control nodes correctly on movement // automatically cleaned up because we use the temporary bind diff --git a/test/networkTest.html b/test/networkTest.html index 11d09d98..aac4bc99 100644 --- a/test/networkTest.html +++ b/test/networkTest.html @@ -12,82 +12,67 @@ } - +