From fe99e6edfd04f2c36df6f300f5d1d4bdc1f51d11 Mon Sep 17 00:00:00 2001 From: dee077 Date: Fri, 7 Mar 2025 18:11:39 +0530 Subject: [PATCH 1/4] [refactor] Improve code structure #347 Refactored src/js/netjsongraph.js Fixes #347 --- src/js/netjsongraph.js | 264 ++++++++++++++++++++++------------------- 1 file changed, 139 insertions(+), 125 deletions(-) diff --git a/src/js/netjsongraph.js b/src/js/netjsongraph.js index 56eba025..64f7973f 100644 --- a/src/js/netjsongraph.js +++ b/src/js/netjsongraph.js @@ -7,147 +7,159 @@ const colorTool = require("zrender/lib/tool/color"); const {each} = require("zrender/lib/core/util"); const env = require("zrender/lib/core/env"); +/** + * @class + * Class NetJSONGraph is entry point for NetJSONGraph library. + * Used as a global object in all examples located in `/public/examples_templates/`. + */ class NetJSONGraph { /** * @constructor + * Initializes a new NetJSONGraph instance. * - * @param {string} JSONParam The NetJSON file param - * @param {Object} config + * @param {string} JSONParam - The NetJSON file parameter. + * @param {Object} [config={}] - Configuration options for the graph. */ + constructor(JSONParam, config = {}) { + this.graph = new NetJSONGraphCore(JSONParam); + this.config = this.initializeConfig(config); + this.graph.setConfig(this.config); + this.setupGraph(); + this.config.onInit.call(this.graph); + this.initializeECharts(); + // eslint-disable-next-line no-constructor-return + return this.graph; + } - constructor(JSONParam, config) { - if (config && config.render === "map") { - config.render = NetJSONGraphRender.prototype.mapRender; - } else if (!config || !config.render || config.render === "graph") { - config = config || {}; - config.render = NetJSONGraphRender.prototype.graphRender; - } + /** + * Initializes the configuration with values and set render to map or graph. + * + * @param {Object} config - The user-defined configuration. + * @returns {Object} - The final configuration object. + */ + initializeConfig(config) { + return { + ...config, + render: + config.render === "map" + ? NetJSONGraphRender.prototype.mapRender + : NetJSONGraphRender.prototype.graphRender, + onInit: this.onInit, + onRender: this.onRender, + onUpdate: this.onUpdate, + afterUpdate: this.afterUpdate, + onLoad: this.onLoad, + setupModeSwitching: this.setupModeSwitching, + }; + } - const graph = new NetJSONGraphCore(JSONParam); + /** + * Sets up rendering utilities, GUI, and event handling. Used in constructor + */ + setupGraph() { + Object.setPrototypeOf(NetJSONGraphRender.prototype, this.graph.utils); + this.graph.gui = new NetJSONGraphGUI(this.graph); + this.graph.utils = new NetJSONGraphRender(); + this.graph.setUtils(); + this.graph.event = this.graph.utils.createEvent(); + } - Object.setPrototypeOf(NetJSONGraphRender.prototype, graph.utils); - graph.gui = new NetJSONGraphGUI(graph); - graph.utils = new NetJSONGraphRender(); - graph.setUtils(); + /** + * Initializes the ECharts rendering engine. Used in constructor + */ + initializeECharts() { + this.graph.echarts = echarts.init(this.graph.el, null, { + renderer: this.graph.config.svgRender ? "svg" : "canvas", + }); + } - graph.event = graph.utils.createEvent(); + // ──────────── Lifecycle Methods ──────────── - graph.setConfig({ - /** - * @function - * @name onInit - * Callback function executed on initialization - * - * @this {object} The instantiated object of NetJSONGraph - * - * @return {object} this.config - */ - onInit() { - return this.config; - }, + /** + * Callback function executed during initialization. + * + * @this {NetJSONGraph} + * @returns {Object} - The graph configuration. + */ + onInit() { + return this.config; + } - /** - * @function - * @name onRender - * Callback function executed on render start - * - * @this {object} The instantiated object of NetJSONGraph - * - * @return {object} this.config - */ - onRender() { - this.utils.showLoading.call(this); - this.gui.init(); - return this.config; - }, + /** + * Callback function executed when rendering starts. + * + * @this {NetJSONGraph} + * @returns {Object} - The graph configuration. + */ + onRender() { + this.utils.showLoading.call(this); + this.gui.init(); + return this.config; + } - /** - * @function - * @name onUpdate - * Callback function executed when data update. - * - * @this {object} The instantiated object of NetJSONGraph - * - * @return {object} this.config - */ - onUpdate() { - return this.config; - }, + /** + * Callback function executed when data updates. + * + * @this {NetJSONGraph} + * @returns {Object} - The graph configuration. + */ + onUpdate() { + return this.config; + } - /** - * @function - * @name afterUpdate - * Callback function executed after data update. - * - * @this {object} The instantiated object of NetJSONGraph - * - * @return {object} this.config - */ - afterUpdate() { - return this.config; - }, + /** + * Callback function executed after data updates. + * + * @this {NetJSONGraph} + * @returns {Object} - The graph configuration. + */ + afterUpdate() { + return this.config; + } - /** - * @function - * @name onLoad - * Callback function executed when first rendered. - * - * @this {object} The instantiated object of NetJSONGraph - * - * @return {object} this.config - */ - onLoad() { - if (this.config.metadata && this.type === "netjson") { - this.gui.createMetaInfoContainer(graph); - this.utils.updateMetadata.call(this); - } else { - this.gui.nodeLinkInfoContainer = - this.gui.createNodeLinkInfoContainer(); - } + /** + * Callback function executed when the graph is first rendered. + * + * @this {NetJSONGraph} + * @returns {Object} - The graph configuration. + */ + onLoad() { + if (this.config.metadata && this.type === "netjson") { + this.gui.createMetaInfoContainer(this.graph); + this.utils.updateMetadata.call(this); + } else { + this.gui.nodeLinkInfoContainer = this.gui.createNodeLinkInfoContainer(); + } - if (this.config.switchMode && this.type === "netjson") { - this.gui.renderModeSelector.onclick = () => { - if (this.config.render === this.utils.mapRender) { - this.config.render = this.utils.graphRender; - const canvasContainer = this.echarts - .getZr() - .painter.getViewportRoot().parentNode; - this.echarts.clear(); - this.utils.graphRender(this.data, this); - canvasContainer.style.background = - // eslint-disable-next-line no-underscore-dangle - this.echarts.getZr()._backgroundColor; - document.querySelector( - ".leaflet-control-attribution", - ).style.display = "none"; - document.querySelector(".leaflet-control-zoom").style.display = - "none"; - } else { - this.echarts.clear(); - this.config.render = this.utils.mapRender; - this.utils.mapRender(this.data, this); - document.querySelector( - ".leaflet-control-attribution", - ).style.display = "block"; - document.querySelector(".leaflet-control-zoom").style.display = - "block"; - } - }; + if (this.config.switchMode && this.type === "netjson") { + this.gui.renderModeSelector.onclick = () => { + if (this.config.render === this.utils.mapRender) { + this.config.render = this.utils.graphRender; + const canvasContainer = this.echarts + .getZr() + .painter.getViewportRoot().parentNode; + this.echarts.clear(); + this.utils.graphRender(this.data, this); + canvasContainer.style.background = + // eslint-disable-next-line no-underscore-dangle + this.echarts.getZr()._backgroundColor; + document.querySelector(".leaflet-control-attribution").style.display = + "none"; + document.querySelector(".leaflet-control-zoom").style.display = + "none"; + } else { + this.echarts.clear(); + this.config.render = this.utils.mapRender; + this.utils.mapRender(this.data, this); + document.querySelector(".leaflet-control-attribution").style.display = + "block"; + document.querySelector(".leaflet-control-zoom").style.display = + "block"; } - - this.utils.hideLoading.call(this); - return this.config; - }, - ...config, - }); - graph.echarts = echarts.init(graph.el, null, { - renderer: graph.config.svgRender ? "svg" : "canvas", - }); - - graph.config.onInit.call(graph); - - // eslint-disable-next-line no-constructor-return - return graph; + }; + } + this.utils.hideLoading.call(this); + return this.config; } } @@ -157,6 +169,8 @@ registerLeafletSystem(echarts, L, { env, }); +// Expose objects globally + window.NetJSONGraph = NetJSONGraph; window.echarts = echarts; window.L = L; From 5df12de2a4146a9baa1d7e555759e2a3eae0572c Mon Sep 17 00:00:00 2001 From: dee077 Date: Sat, 15 Mar 2025 00:24:13 +0530 Subject: [PATCH 2/4] [refactor] Added more comments --- src/js/netjsongraph.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/js/netjsongraph.js b/src/js/netjsongraph.js index 64f7973f..dc764737 100644 --- a/src/js/netjsongraph.js +++ b/src/js/netjsongraph.js @@ -49,7 +49,6 @@ class NetJSONGraph { onUpdate: this.onUpdate, afterUpdate: this.afterUpdate, onLoad: this.onLoad, - setupModeSwitching: this.setupModeSwitching, }; } @@ -131,8 +130,10 @@ class NetJSONGraph { this.gui.nodeLinkInfoContainer = this.gui.createNodeLinkInfoContainer(); } + // If mode switching is enabled and the type is 'netjson', set up the mode switch event if (this.config.switchMode && this.type === "netjson") { this.gui.renderModeSelector.onclick = () => { + // Switch from map to graph mode, first clear canvasContainer and then render if (this.config.render === this.utils.mapRender) { this.config.render = this.utils.graphRender; const canvasContainer = this.echarts @@ -143,14 +144,19 @@ class NetJSONGraph { canvasContainer.style.background = // eslint-disable-next-line no-underscore-dangle this.echarts.getZr()._backgroundColor; + + // Hide Leaflet UI elements when in graph mode document.querySelector(".leaflet-control-attribution").style.display = "none"; document.querySelector(".leaflet-control-zoom").style.display = "none"; } else { + // Switch from graph to map mode similarly this.echarts.clear(); this.config.render = this.utils.mapRender; this.utils.mapRender(this.data, this); + + // Show Leaflet UI elements when back in map mode document.querySelector(".leaflet-control-attribution").style.display = "block"; document.querySelector(".leaflet-control-zoom").style.display = From 9556a4ea1f49a0af1ccd58576a3ab4d1e8bf6d26 Mon Sep 17 00:00:00 2001 From: dee077 Date: Thu, 20 Mar 2025 03:07:58 +0530 Subject: [PATCH 3/4] [refactor] Improved comments --- src/js/netjsongraph.js | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/js/netjsongraph.js b/src/js/netjsongraph.js index dc764737..eb436a8f 100644 --- a/src/js/netjsongraph.js +++ b/src/js/netjsongraph.js @@ -10,12 +10,11 @@ const env = require("zrender/lib/core/env"); /** * @class * Class NetJSONGraph is entry point for NetJSONGraph library. - * Used as a global object in all examples located in `/public/examples_templates/`. + * Used as a global object in the examples_templates. */ class NetJSONGraph { /** * @constructor - * Initializes a new NetJSONGraph instance. * * @param {string} JSONParam - The NetJSON file parameter. * @param {Object} [config={}] - Configuration options for the graph. @@ -32,12 +31,10 @@ class NetJSONGraph { } /** - * Initializes the configuration with values and set render to map or graph. - * * @param {Object} config - The user-defined configuration. * @returns {Object} - The final configuration object. */ - initializeConfig(config) { + initializeConfig(config = {}) { return { ...config, render: @@ -52,9 +49,6 @@ class NetJSONGraph { }; } - /** - * Sets up rendering utilities, GUI, and event handling. Used in constructor - */ setupGraph() { Object.setPrototypeOf(NetJSONGraphRender.prototype, this.graph.utils); this.graph.gui = new NetJSONGraphGUI(this.graph); @@ -64,7 +58,7 @@ class NetJSONGraph { } /** - * Initializes the ECharts rendering engine. Used in constructor + * Used in example Switch render mode */ initializeECharts() { this.graph.echarts = echarts.init(this.graph.el, null, { @@ -72,11 +66,7 @@ class NetJSONGraph { }); } - // ──────────── Lifecycle Methods ──────────── - /** - * Callback function executed during initialization. - * * @this {NetJSONGraph} * @returns {Object} - The graph configuration. */ @@ -85,8 +75,6 @@ class NetJSONGraph { } /** - * Callback function executed when rendering starts. - * * @this {NetJSONGraph} * @returns {Object} - The graph configuration. */ @@ -97,8 +85,6 @@ class NetJSONGraph { } /** - * Callback function executed when data updates. - * * @this {NetJSONGraph} * @returns {Object} - The graph configuration. */ @@ -107,8 +93,6 @@ class NetJSONGraph { } /** - * Callback function executed after data updates. - * * @this {NetJSONGraph} * @returns {Object} - The graph configuration. */ @@ -117,7 +101,12 @@ class NetJSONGraph { } /** - * Callback function executed when the graph is first rendered. + * In map mode, two canvas elements are used: + * - One canvas displays the map tiles (background). + * - The other canvas renders the nodes and links on top of the map. + * + * When switching to graph mode, the map canvas remains in the DOM, + * but its container's background color is updated to match the graph rendering, * * @this {NetJSONGraph} * @returns {Object} - The graph configuration. @@ -129,11 +118,8 @@ class NetJSONGraph { } else { this.gui.nodeLinkInfoContainer = this.gui.createNodeLinkInfoContainer(); } - - // If mode switching is enabled and the type is 'netjson', set up the mode switch event if (this.config.switchMode && this.type === "netjson") { this.gui.renderModeSelector.onclick = () => { - // Switch from map to graph mode, first clear canvasContainer and then render if (this.config.render === this.utils.mapRender) { this.config.render = this.utils.graphRender; const canvasContainer = this.echarts @@ -145,18 +131,17 @@ class NetJSONGraph { // eslint-disable-next-line no-underscore-dangle this.echarts.getZr()._backgroundColor; - // Hide Leaflet UI elements when in graph mode + // Hide Openstreetmap credits in the bottom right corner document.querySelector(".leaflet-control-attribution").style.display = "none"; + // Hide zoom control buttons in top right corner document.querySelector(".leaflet-control-zoom").style.display = "none"; } else { - // Switch from graph to map mode similarly this.echarts.clear(); this.config.render = this.utils.mapRender; this.utils.mapRender(this.data, this); - // Show Leaflet UI elements when back in map mode document.querySelector(".leaflet-control-attribution").style.display = "block"; document.querySelector(".leaflet-control-zoom").style.display = @@ -175,8 +160,6 @@ registerLeafletSystem(echarts, L, { env, }); -// Expose objects globally - window.NetJSONGraph = NetJSONGraph; window.echarts = echarts; window.L = L; From 892fe051feca851b4b720ec28c7eafbb54bcaa43 Mon Sep 17 00:00:00 2001 From: dee077 Date: Thu, 20 Mar 2025 09:31:59 +0530 Subject: [PATCH 4/4] [refactor] Improved comments --- src/js/netjsongraph.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/js/netjsongraph.js b/src/js/netjsongraph.js index eb436a8f..b48c8514 100644 --- a/src/js/netjsongraph.js +++ b/src/js/netjsongraph.js @@ -49,6 +49,9 @@ class NetJSONGraph { }; } + /** + * Sets up rendering utilities, GUI, and event handling. Used in constructor + */ setupGraph() { Object.setPrototypeOf(NetJSONGraphRender.prototype, this.graph.utils); this.graph.gui = new NetJSONGraphGUI(this.graph); @@ -58,7 +61,7 @@ class NetJSONGraph { } /** - * Used in example Switch render mode + * Initializes the ECharts rendering engine. Used in constructor */ initializeECharts() { this.graph.echarts = echarts.init(this.graph.el, null, { @@ -120,6 +123,7 @@ class NetJSONGraph { } if (this.config.switchMode && this.type === "netjson") { this.gui.renderModeSelector.onclick = () => { + // Switch from map to graph mode, first clear canvasContainer and then render if (this.config.render === this.utils.mapRender) { this.config.render = this.utils.graphRender; const canvasContainer = this.echarts @@ -141,7 +145,7 @@ class NetJSONGraph { this.echarts.clear(); this.config.render = this.utils.mapRender; this.utils.mapRender(this.data, this); - + // Show OpenStreetMap credits and zoom control buttons in map mode document.querySelector(".leaflet-control-attribution").style.display = "block"; document.querySelector(".leaflet-control-zoom").style.display =