diff --git a/lib/network/Network.js b/lib/network/Network.js index 5e1c8d2610..4b83ad40e7 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -124,6 +124,12 @@ export function Network(container, data, options) { }, }; + //zindex body properties if needed. Must be set before bindEventListeners() and NodesHandler construction: zindex events will only be bound if necessary + if(options.zIndexField){ + this.body.zIndexField = options.zIndexField; // needed in Node.setOption(), has to know which field is the zIndex field, if any. + this.body.zIndexCompare = options.zIndexCompare || ((a,b)=>(parseInt(a)||0)-(parseInt(b)||0)); // defaults to integer comparison if nothing else given, any invalid int worth zero + } + // bind the event listeners this.bindEventListeners(); @@ -362,6 +368,10 @@ Network.prototype.bindEventListeners = function () { this.clustering._updateState(); this._updateVisibleIndices(); + if(this.body.zIndexField && this.body.zIndexCompare){//currently tested both before calling and in function, maybe not useful + this.nodesHandler.zindexSortNodeIndices(); + } + this._updateValueRange(this.body.nodes); this._updateValueRange(this.body.edges); // start simulation (can be called safely, even if already running) diff --git a/lib/network/modules/NodesHandler.js b/lib/network/modules/NodesHandler.js index c948b9fd96..19e8028fa4 100644 --- a/lib/network/modules/NodesHandler.js +++ b/lib/network/modules/NodesHandler.js @@ -166,6 +166,10 @@ class NodesHandler { // refresh the nodes. Used when reverting from hierarchical layout this.body.emitter.on("refreshNodes", this.refresh.bind(this)); this.body.emitter.on("refresh", this.refresh.bind(this)); + if(this.body.zIndexField && this.body.zIndexCompare){// after refreshing, also zindex-sort if a zindex is configured + this.body.emitter.on("refresh", this.zindexSortNodeIndices.bind(this)); + this.body.emitter.on("refreshNodes", this.zindexSortNodeIndices.bind(this)); + } this.body.emitter.on("destroy", () => { forEach(this.nodesListeners, (callback, event) => { if (this.body.data.nodes) this.body.data.nodes.off(event, callback); @@ -405,6 +409,15 @@ class NodesHandler { } }); } + + zindexSortNodeIndices(){ + const zindex = this.body.zIndexField; + const comp = this.body.zIndexCompare; + if(zindex && comp){//test not really necessary if previously tested before adding an Emitter event handler + const nodes = this.body.nodes; + this.body.nodeIndices.sort((a,b)=>comp(nodes[a].options[zindex], nodes[b].options[zindex])); + } + } /** * Returns the positions of the nodes. diff --git a/lib/network/modules/components/Node.js b/lib/network/modules/components/Node.js index 6611111bc6..19512400e1 100644 --- a/lib/network/modules/components/Node.js +++ b/lib/network/modules/components/Node.js @@ -114,12 +114,12 @@ class Node { * @returns {null|boolean} */ setOptions(options) { - const currentShape = this.options.shape; - if (!options) { return; // Note that the return value will be 'undefined'! This is OK. } + const currentShape = this.options.shape; + const zIdField = this.body.zIndexField; // Save the color for later. // This is necessary in order to prevent local color from being overwritten by group color. // TODO: To prevent such workarounds the way options are handled should be rewritten from scratch. @@ -127,6 +127,10 @@ class Node { if (typeof options.color !== "undefined") { this._localColor = options.color; } + //same logic and same comment as above. Thanks for the workaround. + if (zIdField && typeof options[zIdField] !== "undefined") { + this._zindex = options[zIdField]; + } // basic options if (options.id !== undefined) { @@ -185,6 +189,9 @@ class Node { if (options.opacity !== undefined && Node.checkOpacity(options.opacity)) { this.options.opacity = options.opacity; } + // Need to set local zindex after `Node.parseOptions(...);` and `this.updateLabelModule(options)` otherwise it's overwritten with group's zindex + this.options[zIdField] = this._zindex ?? this.grouplist.get(this.options.group)[zIdField] ?? this.globalOptions[zIdField] ?? undefined; // we want new option's zindex if given, otherwise previous own zindex, NOT group's zindex + //notice: using ?? and not || because 0 IS a valid zindex, only null or undefined are not this.updateShape(currentShape); @@ -492,12 +499,13 @@ class Node { if (this.options.label === undefined || this.options.label === null) { this.options.label = ""; } - + const zIdField = this.body.zIndexField; Node.updateGroupOptions( this.options, { ...options, color: (options && options.color) || this._localColor || undefined, + zindex: (options && options[zIdField]) || this._zindex || undefined }, this.grouplist, ); diff --git a/lib/network/options.ts b/lib/network/options.ts index 070de61f49..e79800d476 100644 --- a/lib/network/options.ts +++ b/lib/network/options.ts @@ -545,6 +545,8 @@ const allOptions: OptionsConfig = { }, height: { string }, width: { string }, + zIndexField: { string }, + zIndexCompare : { function: "function" }, __type__: { object }, }; /* eslint-enable @typescript-eslint/naming-convention */