@umbraci/jsmind 0.10.13 → 0.10.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -24
- package/README.md +116 -116
- package/dist/jsmind.copy-paste.js +9 -0
- package/dist/jsmind.copy-paste.js.map +1 -0
- package/dist/jsmind.draggable-node.js +1 -1
- package/dist/jsmind.draggable-node.js.map +1 -1
- package/dist/jsmind.history.js +1 -1
- package/dist/jsmind.history.js.map +1 -1
- package/dist/jsmind.js +1 -1
- package/dist/jsmind.js.map +1 -1
- package/dist/jsmind.multi-select.js +9 -0
- package/dist/jsmind.multi-select.js.map +1 -0
- package/dist/jsmind.multiline-text.js +1 -1
- package/dist/jsmind.multiline-text.js.map +1 -1
- package/dist/jsmind.screenshot.js +1 -1
- package/dist/jsmind.screenshot.js.map +1 -1
- package/es/jsmind.copy-paste.js +9 -0
- package/es/jsmind.copy-paste.js.map +1 -0
- package/es/jsmind.draggable-node.js +1 -1
- package/es/jsmind.draggable-node.js.map +1 -1
- package/es/jsmind.history.js +1 -1
- package/es/jsmind.history.js.map +1 -1
- package/es/jsmind.js +1 -1
- package/es/jsmind.js.map +1 -1
- package/es/jsmind.multi-select.js +9 -0
- package/es/jsmind.multi-select.js.map +1 -0
- package/es/jsmind.multiline-text.js +1 -1
- package/es/jsmind.multiline-text.js.map +1 -1
- package/es/jsmind.screenshot.js +1 -1
- package/es/jsmind.screenshot.js.map +1 -1
- package/lib/jsmind.copy-paste.js +9 -0
- package/lib/jsmind.copy-paste.js.map +1 -0
- package/lib/jsmind.draggable-node.js +1 -1
- package/lib/jsmind.draggable-node.js.map +1 -1
- package/lib/jsmind.history.js +1 -1
- package/lib/jsmind.history.js.map +1 -1
- package/lib/jsmind.js +1 -1
- package/lib/jsmind.js.map +1 -1
- package/lib/jsmind.multi-select.js +9 -0
- package/lib/jsmind.multi-select.js.map +1 -0
- package/lib/jsmind.multiline-text.js +1 -1
- package/lib/jsmind.multiline-text.js.map +1 -1
- package/lib/jsmind.screenshot.js +1 -1
- package/lib/jsmind.screenshot.js.map +1 -1
- package/package.json +115 -111
- package/style/jsmind.css +408 -408
- package/types/generated/jsmind.option.d.ts +0 -1
- package/types/tsconfig.declaration.json +19 -19
package/es/jsmind.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.js","sources":["../src/jsmind.common.js","../src/jsmind.dom.js","../src/jsmind.util.js","../src/jsmind.option.js","../src/jsmind.node.js","../src/jsmind.mind.js","../src/jsmind.format.js","../src/jsmind.data_provider.js","../src/jsmind.layout_provider.js","../src/jsmind.graph.js","../src/jsmind.view_provider.js","../src/jsmind.shortcut_provider.js","../src/jsmind.plugin.js","../src/jsmind.enhanced-plugin.js","../src/jsmind.js"],"sourcesContent":["/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\n/**\r\n * Library version string.\r\n * @type {string}\r\n */\r\nexport const __version__ = '0.9.0';\r\n/**\r\n * Library author.\r\n * @type {string}\r\n */\r\nexport const __author__ = 'UmbraCi';\r\n\r\nif (typeof String.prototype.startsWith != 'function') {\r\n String.prototype.startsWith = function (p) {\r\n return this.slice(0, p.length) === p;\r\n };\r\n}\r\n\r\n/**\r\n * Direction constants and parser.\r\n * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType\r\n */\r\n/** @type {DirectionType} */\r\nexport const Direction = {\r\n left: -1,\r\n center: 0,\r\n right: 1,\r\n of: function (dir) {\r\n if (!dir || dir === -1 || dir === 0 || dir === 1) {\r\n return dir;\r\n }\r\n if (dir === '-1' || dir === '0' || dir === '1') {\r\n return parseInt(dir);\r\n }\r\n if (dir.toLowerCase() === 'left') {\r\n return this.left;\r\n }\r\n if (dir.toLowerCase() === 'right') {\r\n return this.right;\r\n }\r\n if (dir.toLowerCase() === 'center') {\r\n return this.center;\r\n }\r\n },\r\n};\r\n/** @enum {number} */\r\nexport const EventType = { show: 1, resize: 2, edit: 3, select: 4, reset: 5, history_change: 6 };\r\n/** @enum {number} */\r\nexport const Key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };\r\n/** @enum {number} */\r\nexport const LogLevel = { debug: 1, info: 2, warn: 3, error: 4, disable: 9 };\r\n\r\n// an noop function define\r\nvar _noop = function () {};\r\n/**\r\n * Logger facade with dynamic level.\r\n * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}\r\n */\r\nexport let logger =\r\n typeof console === 'undefined'\r\n ? {\r\n level: _noop,\r\n log: _noop,\r\n debug: _noop,\r\n info: _noop,\r\n warn: _noop,\r\n error: _noop,\r\n }\r\n : {\r\n level: setup_logger_level,\r\n log: console.log,\r\n debug: console.debug,\r\n info: console.info,\r\n warn: console.warn,\r\n error: console.error,\r\n };\r\n\r\n/**\r\n * Set logger level.\r\n * @param {number} log_level\r\n */\r\nfunction setup_logger_level(log_level) {\r\n if (log_level > LogLevel.debug) {\r\n logger.debug = _noop;\r\n } else {\r\n logger.debug = console.debug;\r\n }\r\n if (log_level > LogLevel.info) {\r\n logger.info = _noop;\r\n } else {\r\n logger.info = console.info;\r\n }\r\n if (log_level > LogLevel.warn) {\r\n logger.warn = _noop;\r\n } else {\r\n logger.warn = console.warn;\r\n }\r\n if (log_level > LogLevel.error) {\r\n logger.error = _noop;\r\n } else {\r\n logger.error = console.error;\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\n/**\r\n * Lightweight DOM helpers bound to a window.\r\n */\r\nclass Dom {\r\n /**\r\n * @param {Window} w\r\n */\r\n constructor(w) {\r\n /** @type {Window} */\r\n this.w = w;\r\n /** @type {Document} */\r\n this.d = w.document;\r\n /**\r\n * Get element by id.\r\n * @param {string} id\r\n * @returns {HTMLElement|null}\r\n */\r\n this.g = function (id) {\r\n return this.d.getElementById(id);\r\n };\r\n /**\r\n * Create element with given tag.\r\n * @param {string} tag\r\n * @returns {HTMLElement}\r\n */\r\n this.c = function (tag) {\r\n return this.d.createElement(tag);\r\n };\r\n /**\r\n * Set text content for element.\r\n * @param {HTMLElement} n\r\n * @param {string} t\r\n */\r\n this.t = function (n, t) {\r\n if (n.hasChildNodes()) {\r\n n.firstChild.nodeValue = t;\r\n } else {\r\n n.appendChild(this.d.createTextNode(t));\r\n }\r\n };\r\n\r\n /**\r\n * Set inner HTML or append element.\r\n * @param {HTMLElement} n\r\n * @param {string|HTMLElement} t\r\n */\r\n this.h = function (n, t) {\r\n if (t instanceof HTMLElement) {\r\n n.innerHTML = '';\r\n n.appendChild(t);\r\n } else {\r\n n.innerHTML = t;\r\n }\r\n };\r\n // detect isElement\r\n /**\r\n * Runtime check for HTMLElement.\r\n * @param {unknown} el\r\n * @returns {el is HTMLElement}\r\n */\r\n this.i = function (el) {\r\n return (\r\n !!el &&\r\n typeof el === 'object' &&\r\n el.nodeType === 1 &&\r\n typeof el.style === 'object' &&\r\n typeof el.ownerDocument === 'object'\r\n );\r\n };\r\n\r\n //target,eventType,handler\r\n /**\r\n * Add event listener with legacy fallback.\r\n * @param {HTMLElement} t\r\n * @param {string} e\r\n * @param {(ev:Event)=>void} h\r\n */\r\n this.on = function (t, e, h) {\r\n if (!!t.addEventListener) {\r\n t.addEventListener(e, h, false);\r\n } else {\r\n t.attachEvent('on' + e, h);\r\n }\r\n };\r\n }\r\n}\r\n\r\nexport const $ = new Dom(window);\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { $ } from './jsmind.dom.js';\r\n\r\n/**\r\n * Misc utility collection.\r\n * @type {{\r\n * file: { read: (file: File, cb:(result:string,name:string)=>void)=>void, save:(data:string,type:string,name:string)=>void},\r\n * json: { json2string:(v:unknown)=>string, string2json:(s:string)=>unknown, merge:(b:object,a:object)=>object },\r\n * uuid: { newid:()=>string },\r\n * text: { is_empty:(s?:string)=>boolean }\r\n * }}\r\n */\r\nexport const util = {\r\n file: {\r\n read: function (file_data, fn_callback) {\r\n var reader = new FileReader();\r\n reader.onload = function () {\r\n if (typeof fn_callback === 'function') {\r\n fn_callback(this.result, file_data.name);\r\n }\r\n };\r\n reader.readAsText(file_data);\r\n },\r\n\r\n save: function (file_data, type, name) {\r\n var blob;\r\n if (typeof $.w.Blob === 'function') {\r\n blob = new Blob([file_data], { type: type });\r\n } else {\r\n var BlobBuilder =\r\n $.w.BlobBuilder ||\r\n $.w.MozBlobBuilder ||\r\n $.w.WebKitBlobBuilder ||\r\n $.w.MSBlobBuilder;\r\n var bb = new BlobBuilder();\r\n bb.append(file_data);\r\n blob = bb.getBlob(type);\r\n }\r\n if (navigator.msSaveBlob) {\r\n navigator.msSaveBlob(blob, name);\r\n } else {\r\n var URL = $.w.URL || $.w.webkitURL;\r\n var blob_url = URL.createObjectURL(blob);\r\n var anchor = $.c('a');\r\n if ('download' in anchor) {\r\n anchor.style.visibility = 'hidden';\r\n anchor.href = blob_url;\r\n anchor.download = name;\r\n $.d.body.appendChild(anchor);\r\n var evt = $.d.createEvent('MouseEvents');\r\n evt.initEvent('click', true, true);\r\n anchor.dispatchEvent(evt);\r\n $.d.body.removeChild(anchor);\r\n } else {\r\n location.href = blob_url;\r\n }\r\n }\r\n },\r\n },\r\n\r\n json: {\r\n json2string: function (json) {\r\n return JSON.stringify(json);\r\n },\r\n string2json: function (json_str) {\r\n return JSON.parse(json_str);\r\n },\r\n merge: function (b, a) {\r\n for (var o in a) {\r\n if (o in b) {\r\n if (\r\n typeof b[o] === 'object' &&\r\n Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&\r\n !b[o].length\r\n ) {\r\n util.json.merge(b[o], a[o]);\r\n } else {\r\n b[o] = a[o];\r\n }\r\n } else {\r\n b[o] = a[o];\r\n }\r\n }\r\n return b;\r\n },\r\n },\r\n\r\n uuid: {\r\n newid: function () {\r\n return (\r\n new Date().getTime().toString(16) + Math.random().toString(16).substring(2)\r\n ).substring(2, 18);\r\n },\r\n },\r\n\r\n text: {\r\n is_empty: function (s) {\r\n if (!s) {\r\n return true;\r\n }\r\n return s.replace(/\\s*/, '').length == 0;\r\n },\r\n },\r\n};\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { util } from './jsmind.util.js';\r\n\r\n/**\r\n * @typedef {{\r\n * container: string|HTMLElement,\r\n * editable?: boolean,\r\n * theme?: (string|null),\r\n * mode?: ('full'|'side'),\r\n * support_html?: boolean,\r\n * log_level?: 'debug'|'info'|'warn'|'error'|'disable',\r\n * view?: {\r\n * engine?: 'canvas'|'svg',\r\n * enable_device_pixel_ratio?: boolean,\r\n * hmargin?: number,\r\n * vmargin?: number,\r\n * line_width?: number,\r\n * line_color?: string,\r\n * line_style?: 'curved'|'straight',\r\n * custom_line_render?: (this: object, arg:{ ctx: CanvasRenderingContext2D|SVGPathElement, start_point:{x:number,y:number}, end_point:{x:number,y:number} })=>void,\r\n * draggable?: boolean,\r\n * hide_scrollbars_when_draggable?: boolean,\r\n * node_overflow?: 'hidden'|'wrap'|'visible',\r\n * zoom?: { min?:number, max?:number, step?:number, mask_key?:number },\r\n * custom_node_render?: (null|((jm: import('./jsmind.js').default, ele: HTMLElement, node: import('./jsmind.node.js').Node)=>void)),\r\n * expander_style?: 'char'|'number'\r\n * },\r\n * layout?: { hspace?:number, vspace?:number, pspace?:number, cousin_space?:number },\r\n * default_event_handle?: { enable_mousedown_handle?:boolean, enable_click_handle?:boolean, enable_dblclick_handle?:boolean, enable_mousewheel_handle?:boolean },\r\n * shortcut?: { enable?:boolean, handles?: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping?: Record<string, number|number[]>, id_generator?: ()=>string },\r\n * selection?: { enable_multi_select?: boolean, include_descendants?: boolean, shift_simple_mode?: boolean, filter?: (node: import('./jsmind.node.js').Node)=>boolean },\r\n * fieldNames?: { id?:string, topic?:string, children?:string, parentid?:string, isroot?:string, direction?:string, expanded?:string },\r\n * plugin?: Record<string, object>\r\n * }} JsMindRuntimeOptions\r\n */\r\n/** @type {JsMindRuntimeOptions} */\r\nconst default_options = {\r\n container: '', // id of the container\r\n editable: false, // you can change it in your options\r\n theme: null,\r\n mode: 'full', // full or side\r\n support_html: true,\r\n log_level: 'info',\r\n\r\n view: {\r\n engine: 'canvas',\r\n enable_device_pixel_ratio: false,\r\n hmargin: 100,\r\n vmargin: 50,\r\n line_width: 2,\r\n line_color: '#555',\r\n line_style: 'curved', // [straight | curved]\r\n draggable: false, // drag the mind map with your mouse, when it's larger that the container\r\n hide_scrollbars_when_draggable: false, // hide container scrollbars, when mind map is larger than container and draggable option is true.\r\n node_overflow: 'hidden', // [hidden | wrap]\r\n zoom: {\r\n min: 0.5,\r\n max: 2.1,\r\n step: 0.1,\r\n mask_key: 4096,\r\n },\r\n custom_node_render: null,\r\n expander_style: 'char', // [char | number]\r\n },\r\n layout: {\r\n hspace: 30,\r\n vspace: 20,\r\n pspace: 13,\r\n cousin_space: 0,\r\n },\r\n default_event_handle: {\r\n enable_mousedown_handle: true,\r\n enable_click_handle: true,\r\n enable_dblclick_handle: true,\r\n enable_mousewheel_handle: true,\r\n },\r\n shortcut: {\r\n enable: true,\r\n handles: {},\r\n mapping: {\r\n addchild: [45, 4096 + 13], // Insert, Ctrl+Enter\r\n addbrother: 13, // Enter\r\n editnode: 113, // F2\r\n delnode: 46, // Delete\r\n toggle: 32, // Space\r\n left: 37, // Left\r\n up: 38, // Up\r\n right: 39, // Right\r\n down: 40, // Down\r\n },\r\n },\r\n selection: {\r\n enable_multi_select: false,\r\n include_descendants: false,\r\n shift_simple_mode: false,\r\n filter: null,\r\n },\r\n // Field names mapping for custom data structure\r\n // Similar to Ant Design's fieldNames prop\r\n fieldNames: {\r\n id: 'id',\r\n topic: 'topic',\r\n children: 'children',\r\n parentid: 'parentid',\r\n isroot: 'isroot',\r\n direction: 'direction',\r\n expanded: 'expanded',\r\n },\r\n plugin: {},\r\n};\r\n\r\n/**\r\n * Merge user options with defaults. Throws if container missing.\r\n * @param {JsMindRuntimeOptions} options\r\n * @returns {JsMindRuntimeOptions}\r\n */\r\nexport function merge_option(options) {\r\n var opts = {};\r\n util.json.merge(opts, default_options);\r\n util.json.merge(opts, options);\r\n\r\n if (!opts.container) {\r\n throw new Error('the options.container should not be null or empty.');\r\n }\r\n return opts;\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { logger } from './jsmind.common.js';\r\nexport class Node {\r\n /**\r\n * Create a Node instance.\r\n * @param {string} sId - Node id\r\n * @param {number} iIndex - Node index (order among siblings). Use -1 for tail\r\n * @param {string} sTopic - Node topic text\r\n * @param {Record<string, any>=} oData - Arbitrary node data\r\n * @param {boolean=} bIsRoot - Whether it is the root node\r\n * @param {Node | null=} oParent - Parent node\r\n * @param {number=} eDirection - Direction for children under root (-1 left, 0 center, 1 right)\r\n * @param {boolean=} bExpanded - Expanded state\r\n */\r\n constructor(sId, iIndex, sTopic, oData, bIsRoot, oParent, eDirection, bExpanded) {\r\n if (!sId) {\r\n logger.error('invalid node id');\r\n return;\r\n }\r\n if (typeof iIndex != 'number') {\r\n logger.error('invalid node index');\r\n return;\r\n }\r\n if (typeof bExpanded === 'undefined') {\r\n bExpanded = true;\r\n }\r\n this.id = sId;\r\n this.index = iIndex;\r\n this.topic = sTopic;\r\n /** @type {Record<string, any>} */\r\n this.data = oData || {};\r\n this.isroot = bIsRoot;\r\n this.parent = oParent;\r\n this.direction = eDirection;\r\n this.expanded = !!bExpanded;\r\n /** @type {Node[]} */\r\n this.children = [];\r\n this._data = {};\r\n }\r\n\r\n /**\r\n * Get absolute location of this node in view coordinates.\r\n * @returns {{x:number,y:number}}\r\n */\r\n get_location() {\r\n var vd = this._data.view;\r\n return {\r\n x: vd.abs_x,\r\n y: vd.abs_y,\r\n };\r\n }\r\n /**\r\n * Get rendered size of this node.\r\n * @returns {{w:number,h:number}}\r\n */\r\n get_size() {\r\n var vd = this._data.view;\r\n return {\r\n w: vd.width,\r\n h: vd.height,\r\n };\r\n }\r\n\r\n /**\r\n * Compare two nodes by index for ordering.\r\n * @param {Node} node1\r\n * @param {Node} node2\r\n * @returns {number}\r\n */\r\n static compare(node1, node2) {\r\n // '-1' is always the latest\r\n var r = 0;\r\n var i1 = node1.index;\r\n var i2 = node2.index;\r\n if (i1 >= 0 && i2 >= 0) {\r\n r = i1 - i2;\r\n } else if (i1 == -1 && i2 == -1) {\r\n r = 0;\r\n } else if (i1 == -1) {\r\n r = 1;\r\n } else if (i2 == -1) {\r\n r = -1;\r\n } else {\r\n r = 0;\r\n }\r\n return r;\r\n }\r\n /**\r\n * Check if node is the same as or a descendant of parent_node.\r\n * @param {Node} parent_node\r\n * @param {Node} node\r\n * @returns {boolean}\r\n */\r\n static inherited(parent_node, node) {\r\n if (!!parent_node && !!node) {\r\n if (parent_node.id === node.id) {\r\n return true;\r\n }\r\n if (parent_node.isroot) {\r\n return true;\r\n }\r\n var pid = parent_node.id;\r\n var p = node;\r\n while (!p.isroot) {\r\n p = p.parent;\r\n if (p.id === pid) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n /**\r\n * Runtime check for Node instance.\r\n * @param {unknown} n\r\n * @returns {n is Node}\r\n */\r\n static is_node(n) {\r\n return !!n && n instanceof Node;\r\n }\r\n\r\n /**\r\n * Convert node to plain object with custom field names.\r\n * @param {Record<string,string>=} fieldNames - Field names mapping\r\n * @param {boolean=} includeChildren - Whether to include children nodes (default: false)\r\n * @returns {Record<string, any>} Plain object representation of node\r\n */\r\n toObject(fieldNames, includeChildren = false) {\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var childrenKey = fn.children || 'children';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var obj = {};\r\n obj[idKey] = this.id;\r\n obj[topicKey] = this.topic;\r\n obj[expandedKey] = this.expanded;\r\n\r\n // Add direction for nodes under root\r\n if (!!this.parent && this.parent.isroot) {\r\n obj[directionKey] = this.direction === -1 ? 'left' : 'right';\r\n }\r\n\r\n // Add custom data properties\r\n if (this.data != null) {\r\n for (var k in this.data) {\r\n obj[k] = this.data[k];\r\n }\r\n }\r\n\r\n // Add children if requested\r\n if (includeChildren && this.children.length > 0) {\r\n obj[childrenKey] = this.children.map(child => child.toObject(fieldNames, true));\r\n }\r\n\r\n return obj;\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { Node } from './jsmind.node.js';\r\nimport { logger, Direction } from './jsmind.common.js';\r\n\r\nexport class Mind {\r\n /**\r\n * Mind model: holds nodes and selection.\r\n */\r\n constructor() {\r\n /** @type {string | null} */\r\n this.name = null;\r\n /** @type {string | null} */\r\n this.author = null;\r\n /** @type {string | null} */\r\n this.version = null;\r\n /** @type {Node | null} */\r\n this.root = null;\r\n /** @type {Node | null} */\r\n this.selected = null;\r\n /** @type {Set<Node>} */\r\n this.selected_nodes = new Set();\r\n /** @type {Record<string, Node>} */\r\n this.nodes = {};\r\n }\r\n /**\r\n * Get a node by id.\r\n * @param {string} node_id\r\n * @returns {Node | null}\r\n */\r\n get_node(node_id) {\r\n if (node_id in this.nodes) {\r\n return this.nodes[node_id];\r\n } else {\r\n logger.warn('the node[id=' + node_id + '] can not be found');\r\n return null;\r\n }\r\n }\r\n /**\r\n * Set the root node, only once.\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @returns {Node | null}\r\n */\r\n set_root(node_id, topic, data) {\r\n if (this.root == null) {\r\n this.root = new Node(node_id, 0, topic, data, true);\r\n this._put_node(this.root);\r\n return this.root;\r\n } else {\r\n logger.error('root node is already exist');\r\n return null;\r\n }\r\n }\r\n /**\r\n * Add a child node under parent.\r\n * @param {Node} parent_node\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @param {boolean=} expanded\r\n * @param {number=} idx\r\n * @returns {Node | null}\r\n */\r\n add_node(parent_node, node_id, topic, data, direction, expanded, idx) {\r\n if (!Node.is_node(parent_node)) {\r\n logger.error('the parent_node ' + parent_node + ' is not a node.');\r\n return null;\r\n }\r\n var node_index = idx || -1;\r\n var node = new Node(\r\n node_id,\r\n node_index,\r\n topic,\r\n data,\r\n false,\r\n parent_node,\r\n parent_node.direction,\r\n expanded\r\n );\r\n if (parent_node.isroot) {\r\n node.direction = direction || Direction.right;\r\n }\r\n if (this._put_node(node)) {\r\n parent_node.children.push(node);\r\n this._update_index(parent_node);\r\n } else {\r\n logger.error(\"fail, the node id '\" + node.id + \"' has been already exist.\");\r\n node = null;\r\n }\r\n return node;\r\n }\r\n /**\r\n * Insert a node before target node.\r\n * @param {Node} node_before\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {Node | null}\r\n */\r\n insert_node_before(node_before, node_id, topic, data, direction) {\r\n if (!Node.is_node(node_before)) {\r\n logger.error('the node_before ' + node_before + ' is not a node.');\r\n return null;\r\n }\r\n var node_index = node_before.index - 0.5;\r\n return this.add_node(node_before.parent, node_id, topic, data, direction, true, node_index);\r\n }\r\n /**\r\n * Get previous sibling of a node or node id.\r\n * @param {string | Node} node\r\n * @returns {Node | null}\r\n */\r\n get_node_before(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return null;\r\n } else {\r\n return this.get_node_before(the_node);\r\n }\r\n }\r\n if (node.isroot) {\r\n return null;\r\n }\r\n var idx = node.index - 2;\r\n if (idx >= 0) {\r\n return node.parent.children[idx];\r\n } else {\r\n return null;\r\n }\r\n }\r\n /**\r\n * Insert a node after target node.\r\n * @param {Node} node_after\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {Node | null}\r\n */\r\n insert_node_after(node_after, node_id, topic, data, direction) {\r\n if (!Node.is_node(node_after)) {\r\n logger.error('the node_after ' + node_after + ' is not a node.');\r\n return null;\r\n }\r\n var node_index = node_after.index + 0.5;\r\n return this.add_node(node_after.parent, node_id, topic, data, direction, true, node_index);\r\n }\r\n /**\r\n * Get next sibling of a node or node id.\r\n * @param {string | Node} node\r\n * @returns {Node | null}\r\n */\r\n get_node_after(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return null;\r\n } else {\r\n return this.get_node_after(the_node);\r\n }\r\n }\r\n if (node.isroot) {\r\n return null;\r\n }\r\n var idx = node.index;\r\n var brothers = node.parent.children;\r\n if (brothers.length > idx) {\r\n return node.parent.children[idx];\r\n } else {\r\n return null;\r\n }\r\n }\r\n /**\r\n * Move a node to new parent/position.\r\n * @param {Node} node\r\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\r\n * @param {string=} parent_id\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {Node | null}\r\n */\r\n move_node(node, before_id, parent_id, direction) {\r\n if (!Node.is_node(node)) {\r\n logger.error('the parameter node ' + node + ' is not a node.');\r\n return null;\r\n }\r\n if (!parent_id) {\r\n parent_id = node.parent.id;\r\n }\r\n return this._move_node(node, before_id, parent_id, direction);\r\n }\r\n /**\r\n * Propagate direction to descendants.\r\n * @param {Node} node\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n */\r\n _flow_node_direction(node, direction) {\r\n if (typeof direction === 'undefined') {\r\n direction = node.direction;\r\n } else {\r\n node.direction = direction;\r\n }\r\n var len = node.children.length;\r\n while (len--) {\r\n this._flow_node_direction(node.children[len], direction);\r\n }\r\n }\r\n /**\r\n * Re-index node among siblings based on before_id marker.\r\n * @param {Node} node\r\n * @param {string} before_id\r\n * @returns {Node}\r\n */\r\n _move_node_internal(node, before_id) {\r\n if (!!node && !!before_id) {\r\n if (before_id == '_last_') {\r\n node.index = -1;\r\n this._update_index(node.parent);\r\n } else if (before_id == '_first_') {\r\n node.index = 0;\r\n this._update_index(node.parent);\r\n } else {\r\n var node_before = !!before_id ? this.get_node(before_id) : null;\r\n if (\r\n node_before != null &&\r\n node_before.parent != null &&\r\n node_before.parent.id == node.parent.id\r\n ) {\r\n node.index = node_before.index - 0.5;\r\n this._update_index(node.parent);\r\n }\r\n }\r\n }\r\n return node;\r\n }\r\n /**\r\n * Internal move implementation.\r\n * @param {Node} node\r\n * @param {string} before_id\r\n * @param {string} parent_id\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {Node | null}\r\n */\r\n _move_node(node, before_id, parent_id, direction) {\r\n if (!!node && !!parent_id) {\r\n var parent_node = this.get_node(parent_id);\r\n if (Node.inherited(node, parent_node)) {\r\n logger.error('can not move a node to its children');\r\n return null;\r\n }\r\n if (node.parent.id != parent_id) {\r\n // remove from parent's children\r\n var sibling = node.parent.children;\r\n var si = sibling.length;\r\n while (si--) {\r\n if (sibling[si].id == node.id) {\r\n sibling.splice(si, 1);\r\n break;\r\n }\r\n }\r\n let origin_parent = node.parent;\r\n node.parent = parent_node;\r\n parent_node.children.push(node);\r\n this._update_index(origin_parent);\r\n }\r\n\r\n if (node.parent.isroot) {\r\n if (direction == Direction.left) {\r\n node.direction = direction;\r\n } else {\r\n node.direction = Direction.right;\r\n }\r\n } else {\r\n node.direction = node.parent.direction;\r\n }\r\n this._move_node_internal(node, before_id);\r\n this._flow_node_direction(node);\r\n }\r\n return node;\r\n }\r\n /**\r\n * Remove a node from the mind.\r\n * @param {Node} node\r\n * @returns {boolean}\r\n */\r\n remove_node(node) {\r\n if (!Node.is_node(node)) {\r\n logger.error('the parameter node ' + node + ' is not a node.');\r\n return false;\r\n }\r\n if (node.isroot) {\r\n logger.error('fail, can not remove root node');\r\n return false;\r\n }\r\n if (this.selected != null && this.selected.id == node.id) {\r\n this.selected = null;\r\n }\r\n this._purge_selection(node);\r\n // clean all subordinate nodes\r\n var children = node.children;\r\n var ci = children.length;\r\n while (ci--) {\r\n this.remove_node(children[ci]);\r\n }\r\n // clean all children\r\n children.length = 0;\r\n var node_parent = node.parent;\r\n // remove from parent's children\r\n var sibling = node_parent.children;\r\n var si = sibling.length;\r\n while (si--) {\r\n if (sibling[si].id == node.id) {\r\n sibling.splice(si, 1);\r\n break;\r\n }\r\n }\r\n // remove from global nodes\r\n delete this.nodes[node.id];\r\n // clean all properties\r\n for (var k in node) {\r\n delete node[k];\r\n }\r\n // remove it's self\r\n node = null;\r\n this._update_index(node_parent);\r\n return true;\r\n }\r\n\r\n /**\r\n * Remove a node and its subtree from the cached selection set.\r\n * @param {Node} node\r\n * @private\r\n */\r\n _purge_selection(node) {\r\n if (this.selected_nodes.has(node)) {\r\n this.selected_nodes.delete(node);\r\n }\r\n var children = node.children || [];\r\n for (var i = 0; i < children.length; i++) {\r\n this._purge_selection(children[i]);\r\n }\r\n }\r\n /**\r\n * Put node into the map if id is not taken.\r\n * @param {Node} node\r\n * @returns {boolean}\r\n */\r\n _put_node(node) {\r\n if (node.id in this.nodes) {\r\n logger.warn(\"the node_id '\" + node.id + \"' has been already exist.\");\r\n return false;\r\n } else {\r\n this.nodes[node.id] = node;\r\n return true;\r\n }\r\n }\r\n /**\r\n * Re-index children by Node.compare.\r\n * @param {Node} node\r\n */\r\n _update_index(node) {\r\n if (node instanceof Node) {\r\n node.children.sort(Node.compare);\r\n for (var i = 0; i < node.children.length; i++) {\r\n node.children[i].index = i + 1;\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { __author__, __version__, logger, Direction } from './jsmind.common.js';\r\nimport { Mind } from './jsmind.mind.js';\r\nimport { Node } from './jsmind.node.js';\r\nimport { util } from './jsmind.util.js';\r\n\r\n/** @typedef {{name:string,author:string,version:string}} MindMapMeta */\r\n/**\r\n * Node tree data item\r\n *\r\n * Note: When using custom fieldNames configuration, the actual property names\r\n * in your data may differ from these type definitions. For example, if you\r\n * configure `fieldNames: { topic: 'name' }`, your data should use 'name'\r\n * instead of 'topic'. The types shown here represent the default field names.\r\n *\r\n * @typedef {{\r\n * id?: string,\r\n * topic?: string,\r\n * data?: Record<string, any>,\r\n * direction?: (number|string),\r\n * expanded?: boolean,\r\n * children?: NodeTreeData[],\r\n * [key: string]: any\r\n * }} NodeTreeData\r\n */\r\n/**\r\n * Node tree formatted payload\r\n * @typedef {{\r\n * meta?: MindMapMeta,\r\n * format: 'node_tree',\r\n * data: NodeTreeData\r\n * }} NodeTreeFormat\r\n */\r\n/**\r\n * Node array data item\r\n *\r\n * Note: When using custom fieldNames configuration, the actual property names\r\n * in your data may differ from these type definitions. For example, if you\r\n * configure `fieldNames: { topic: 'name', parentid: 'parent' }`, your data\r\n * should use 'name' and 'parent' instead of 'topic' and 'parentid'. The types\r\n * shown here represent the default field names.\r\n *\r\n * @typedef {{\r\n * id?: string,\r\n * topic?: string,\r\n * parentid?: string,\r\n * data?: Record<string, any>,\r\n * direction?: (number|string),\r\n * expanded?: boolean,\r\n * isroot?: boolean,\r\n * [key: string]: any\r\n * }} NodeArrayItem\r\n */\r\n/**\r\n * Node array formatted payload\r\n * @typedef {{\r\n * meta?: MindMapMeta,\r\n * format: 'node_array',\r\n * data: NodeArrayItem[]\r\n * }} NodeArrayFormat\r\n */\r\n/** @type {MindMapMeta} */\r\nconst DEFAULT_META = { name: 'jsMind', author: __author__, version: __version__ };\r\n\r\n/**\r\n * Mind data format handlers.\r\n * @type {{\r\n * node_tree: { example:NodeTreeFormat, get_mind:(src:NodeTreeFormat)=>Mind, get_data:(mind:Mind)=>NodeTreeFormat },\r\n * node_array: { example:NodeArrayFormat, get_mind:(src:NodeArrayFormat)=>Mind, get_data:(mind:Mind)=>NodeArrayFormat },\r\n * freemind: { example:{meta:MindMapMeta,format:'freemind',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'freemind',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'freemind',data:string} },\r\n * text: { example:{meta:MindMapMeta,format:'text',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'text',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'text',data:string} }\r\n * }}\r\n */\r\nexport const format = {\r\n node_tree: {\r\n example: {\r\n meta: DEFAULT_META,\r\n format: 'node_tree',\r\n data: { id: 'root', topic: 'jsMind node_tree example' },\r\n },\r\n /** @param {NodeTreeFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\r\n get_mind: function (source, fieldNames) {\r\n var df = format.node_tree;\r\n var mind = new Mind();\r\n mind.name = source.meta.name;\r\n mind.author = source.meta.author;\r\n mind.version = source.meta.version;\r\n df._parse(mind, source.data, fieldNames);\r\n return mind;\r\n },\r\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\r\n get_data: function (mind, fieldNames) {\r\n var df = format.node_tree;\r\n var json = {};\r\n json.meta = {\r\n name: mind.name,\r\n author: mind.author,\r\n version: mind.version,\r\n };\r\n json.format = 'node_tree';\r\n json.data = df._build_node(mind.root, fieldNames);\r\n return json;\r\n },\r\n\r\n /** @param {Mind} mind @param {NodeTreeData} node_root @param {Record<string,string>=} fieldNames */\r\n _parse: function (mind, node_root, fieldNames) {\r\n var df = format.node_tree;\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var childrenKey = fn.children || 'children';\r\n\r\n var data = df._extract_data(node_root, fieldNames);\r\n mind.set_root(node_root[idKey], node_root[topicKey], data);\r\n if (childrenKey in node_root) {\r\n var children = node_root[childrenKey];\r\n for (var i = 0; i < children.length; i++) {\r\n df._extract_subnode(mind, mind.root, children[i], fieldNames);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Extract custom data from node JSON, excluding standard properties.\r\n * @private\r\n * @param {Record<string, unknown>} node_json - Node JSON object\r\n * @param {Record<string,string>=} fieldNames - Field names mapping\r\n * @returns {Record<string,any>} Custom data object\r\n */\r\n _extract_data: function (node_json, fieldNames) {\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var childrenKey = fn.children || 'children';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var data = {};\r\n for (var k in node_json) {\r\n if (\r\n k == idKey ||\r\n k == topicKey ||\r\n k == childrenKey ||\r\n k == directionKey ||\r\n k == expandedKey\r\n ) {\r\n continue;\r\n }\r\n data[k] = node_json[k];\r\n }\r\n return data;\r\n },\r\n\r\n /** @param {Mind} mind @param {Node} node_parent @param {NodeTreeData} node_json @param {Record<string,string>=} fieldNames */\r\n _extract_subnode: function (mind, node_parent, node_json, fieldNames) {\r\n var df = format.node_tree;\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var childrenKey = fn.children || 'children';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var data = df._extract_data(node_json, fieldNames);\r\n var d = null;\r\n if (node_parent.isroot) {\r\n d = node_json[directionKey] == 'left' ? Direction.left : Direction.right;\r\n }\r\n var node = mind.add_node(\r\n node_parent,\r\n node_json[idKey],\r\n node_json[topicKey],\r\n data,\r\n d,\r\n node_json[expandedKey]\r\n );\r\n if (!!node_json[childrenKey]) {\r\n var children = node_json[childrenKey];\r\n for (var i = 0; i < children.length; i++) {\r\n df._extract_subnode(mind, node, children[i], fieldNames);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Build JSON object from a node.\r\n * @private\r\n * @param {Node} node - Node to convert\r\n * @param {Record<string,string>=} fieldNames - Field names mapping\r\n * @returns {NodeTreeData} JSON representation of node\r\n */\r\n _build_node: function (node, fieldNames) {\r\n var df = format.node_tree;\r\n if (!(node instanceof Node)) {\r\n return;\r\n }\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var childrenKey = fn.children || 'children';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var o = {};\r\n o[idKey] = node.id;\r\n o[topicKey] = node.topic;\r\n o[expandedKey] = node.expanded;\r\n\r\n if (!!node.parent && node.parent.isroot) {\r\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\r\n }\r\n if (node.data != null) {\r\n var node_data = node.data;\r\n for (var k in node_data) {\r\n o[k] = node_data[k];\r\n }\r\n }\r\n var children = node.children;\r\n if (children.length > 0) {\r\n o[childrenKey] = [];\r\n for (var i = 0; i < children.length; i++) {\r\n o[childrenKey].push(df._build_node(children[i], fieldNames));\r\n }\r\n }\r\n return o;\r\n },\r\n },\r\n\r\n node_array: {\r\n example: {\r\n meta: DEFAULT_META,\r\n format: 'node_array',\r\n data: [{ id: 'root', topic: 'jsMind node_array example', isroot: true }],\r\n },\r\n\r\n /** @param {NodeArrayFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\r\n get_mind: function (source, fieldNames) {\r\n var df = format.node_array;\r\n var mind = new Mind();\r\n mind.name = source.meta.name;\r\n mind.author = source.meta.author;\r\n mind.version = source.meta.version;\r\n df._parse(mind, source.data, fieldNames);\r\n return mind;\r\n },\r\n\r\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\r\n get_data: function (mind, fieldNames) {\r\n var df = format.node_array;\r\n var json = {};\r\n json.meta = {\r\n name: mind.name,\r\n author: mind.author,\r\n version: mind.version,\r\n };\r\n json.format = 'node_array';\r\n json.data = [];\r\n df._array(mind, json.data, fieldNames);\r\n return json;\r\n },\r\n\r\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\r\n _parse: function (mind, node_array, fieldNames) {\r\n var df = format.node_array;\r\n var nodes = node_array.slice(0);\r\n // reverse array for improving looping performance\r\n nodes.reverse();\r\n var root_node = df._extract_root(mind, nodes, fieldNames);\r\n if (!!root_node) {\r\n df._extract_subnode(mind, root_node, nodes, fieldNames);\r\n } else {\r\n logger.error('root node can not be found');\r\n }\r\n },\r\n\r\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\r\n _extract_root: function (mind, node_array, fieldNames) {\r\n var df = format.node_array;\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var isrootKey = fn.isroot || 'isroot';\r\n\r\n var i = node_array.length;\r\n while (i--) {\r\n if (isrootKey in node_array[i] && node_array[i][isrootKey]) {\r\n var root_json = node_array[i];\r\n var data = df._extract_data(root_json, fieldNames);\r\n var node = mind.set_root(root_json[idKey], root_json[topicKey], data);\r\n node_array.splice(i, 1);\r\n return node;\r\n }\r\n }\r\n return null;\r\n },\r\n\r\n /** @param {Mind} mind @param {Node} parent_node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\r\n _extract_subnode: function (mind, parent_node, node_array, fieldNames) {\r\n var df = format.node_array;\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var parentidKey = fn.parentid || 'parentid';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var i = node_array.length;\r\n var node_json = null;\r\n var data = null;\r\n var extract_count = 0;\r\n while (i--) {\r\n node_json = node_array[i];\r\n if (node_json[parentidKey] == parent_node.id) {\r\n data = df._extract_data(node_json, fieldNames);\r\n var d = null;\r\n var node_direction = node_json[directionKey];\r\n if (!!node_direction) {\r\n d = node_direction == 'left' ? Direction.left : Direction.right;\r\n }\r\n var node = mind.add_node(\r\n parent_node,\r\n node_json[idKey],\r\n node_json[topicKey],\r\n data,\r\n d,\r\n node_json[expandedKey]\r\n );\r\n node_array.splice(i, 1);\r\n extract_count++;\r\n var sub_extract_count = df._extract_subnode(mind, node, node_array, fieldNames);\r\n if (sub_extract_count > 0) {\r\n // reset loop index after extract subordinate node\r\n i = node_array.length;\r\n extract_count += sub_extract_count;\r\n }\r\n }\r\n }\r\n return extract_count;\r\n },\r\n\r\n /** @param {Record<string, unknown>} node_json @param {Record<string,string>=} fieldNames */\r\n _extract_data: function (node_json, fieldNames) {\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var parentidKey = fn.parentid || 'parentid';\r\n var isrootKey = fn.isroot || 'isroot';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var data = {};\r\n for (var k in node_json) {\r\n if (\r\n k == idKey ||\r\n k == topicKey ||\r\n k == parentidKey ||\r\n k == isrootKey ||\r\n k == directionKey ||\r\n k == expandedKey\r\n ) {\r\n continue;\r\n }\r\n data[k] = node_json[k];\r\n }\r\n return data;\r\n },\r\n\r\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\r\n _array: function (mind, node_array, fieldNames) {\r\n var df = format.node_array;\r\n df._array_node(mind.root, node_array, fieldNames);\r\n },\r\n\r\n /** @param {Node} node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\r\n _array_node: function (node, node_array, fieldNames) {\r\n var df = format.node_array;\r\n if (!(node instanceof Node)) {\r\n return;\r\n }\r\n var fn = fieldNames || {};\r\n var idKey = fn.id || 'id';\r\n var topicKey = fn.topic || 'topic';\r\n var parentidKey = fn.parentid || 'parentid';\r\n var isrootKey = fn.isroot || 'isroot';\r\n var directionKey = fn.direction || 'direction';\r\n var expandedKey = fn.expanded || 'expanded';\r\n\r\n var o = {};\r\n o[idKey] = node.id;\r\n o[topicKey] = node.topic;\r\n o[expandedKey] = node.expanded;\r\n\r\n if (!!node.parent) {\r\n o[parentidKey] = node.parent.id;\r\n }\r\n if (node.isroot) {\r\n o[isrootKey] = true;\r\n }\r\n if (!!node.parent && node.parent.isroot) {\r\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\r\n }\r\n if (node.data != null) {\r\n var node_data = node.data;\r\n for (var k in node_data) {\r\n o[k] = node_data[k];\r\n }\r\n }\r\n node_array.push(o);\r\n var ci = node.children.length;\r\n for (var i = 0; i < ci; i++) {\r\n df._array_node(node.children[i], node_array, fieldNames);\r\n }\r\n },\r\n },\r\n\r\n freemind: {\r\n example: {\r\n meta: DEFAULT_META,\r\n format: 'freemind',\r\n data: '<map version=\"1.0.1\"><node ID=\"root\" TEXT=\"jsMind freemind example\"/></map>',\r\n },\r\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\r\n get_mind: function (source, fieldNames) {\r\n var df = format.freemind;\r\n var mind = new Mind();\r\n mind.name = source.meta.name;\r\n mind.author = source.meta.author;\r\n mind.version = source.meta.version;\r\n var xml = source.data;\r\n var xml_doc = df._parse_xml(xml);\r\n var xml_root = df._find_root(xml_doc);\r\n // freemind format uses fixed XML attributes (ID, TEXT), fieldNames not applicable\r\n df._load_node(mind, null, xml_root);\r\n return mind;\r\n },\r\n\r\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\r\n get_data: function (mind, fieldNames) {\r\n var df = format.freemind;\r\n var json = {};\r\n json.meta = {\r\n name: mind.name,\r\n author: mind.author,\r\n version: mind.version,\r\n };\r\n json.format = 'freemind';\r\n var xml_lines = [];\r\n xml_lines.push('<map version=\"1.0.1\">');\r\n // freemind format uses fixed XML attributes, fieldNames not applicable\r\n df._build_map(mind.root, xml_lines);\r\n xml_lines.push('</map>');\r\n json.data = xml_lines.join('');\r\n return json;\r\n },\r\n\r\n /** @param {string} xml */\r\n _parse_xml: function (xml) {\r\n var xml_doc = null;\r\n if (window.DOMParser) {\r\n var parser = new DOMParser();\r\n xml_doc = parser.parseFromString(xml, 'text/xml');\r\n } else {\r\n // Internet Explorer\r\n xml_doc = new ActiveXObject('Microsoft.XMLDOM');\r\n xml_doc.async = false;\r\n xml_doc.loadXML(xml);\r\n }\r\n return xml_doc;\r\n },\r\n\r\n /** @param {Document} xml_doc */\r\n _find_root: function (xml_doc) {\r\n var nodes = xml_doc.childNodes;\r\n var node = null;\r\n var root = null;\r\n var n = null;\r\n for (var i = 0; i < nodes.length; i++) {\r\n n = nodes[i];\r\n if (n.nodeType == 1 && n.tagName == 'map') {\r\n node = n;\r\n break;\r\n }\r\n }\r\n if (!!node) {\r\n var ns = node.childNodes;\r\n node = null;\r\n for (var i = 0; i < ns.length; i++) {\r\n n = ns[i];\r\n if (n.nodeType == 1 && n.tagName == 'node') {\r\n node = n;\r\n break;\r\n }\r\n }\r\n }\r\n return node;\r\n },\r\n\r\n /** @param {Mind} mind @param {Node|null} parent_node @param {Element} xml_node */\r\n _load_node: function (mind, parent_node, xml_node) {\r\n var df = format.freemind;\r\n var node_id = xml_node.getAttribute('ID');\r\n var node_topic = xml_node.getAttribute('TEXT');\r\n var node_folded = xml_node.getAttribute('FOLDED');\r\n // look for richcontent\r\n if (node_topic == null) {\r\n var topic_children = xml_node.childNodes;\r\n var topic_child = null;\r\n for (var i = 0; i < topic_children.length; i++) {\r\n topic_child = topic_children[i];\r\n if (topic_child.nodeType == 1 && topic_child.tagName === 'richcontent') {\r\n node_topic = topic_child.textContent;\r\n break;\r\n }\r\n }\r\n }\r\n var node_data = df._load_attributes(xml_node);\r\n var node_expanded =\r\n 'expanded' in node_data ? node_data.expanded == 'true' : node_folded != 'true';\r\n delete node_data.expanded;\r\n\r\n var node_foreground_color = xml_node.getAttribute('COLOR');\r\n if (!!node_foreground_color) {\r\n node_data['foreground-color'] = node_foreground_color;\r\n }\r\n\r\n var node_background_color = xml_node.getAttribute('BACKGROUND_COLOR');\r\n if (!!node_background_color) {\r\n node_data['background-color'] = node_background_color;\r\n }\r\n\r\n var node_position = xml_node.getAttribute('POSITION');\r\n var node_direction = null;\r\n if (!!node_position) {\r\n node_direction = node_position == 'left' ? Direction.left : Direction.right;\r\n }\r\n var node = null;\r\n if (!!parent_node) {\r\n node = mind.add_node(\r\n parent_node,\r\n node_id,\r\n node_topic,\r\n node_data,\r\n node_direction,\r\n node_expanded\r\n );\r\n } else {\r\n node = mind.set_root(node_id, node_topic, node_data);\r\n }\r\n var children = xml_node.childNodes;\r\n var child = null;\r\n for (var i = 0; i < children.length; i++) {\r\n child = children[i];\r\n if (child.nodeType == 1 && child.tagName == 'node') {\r\n df._load_node(mind, node, child);\r\n }\r\n }\r\n },\r\n\r\n /** @param {Element} xml_node */\r\n _load_attributes: function (xml_node) {\r\n var children = xml_node.childNodes;\r\n var attr = null;\r\n var attr_data = {};\r\n for (var i = 0; i < children.length; i++) {\r\n attr = children[i];\r\n if (attr.nodeType == 1 && attr.tagName === 'attribute') {\r\n attr_data[attr.getAttribute('NAME')] = attr.getAttribute('VALUE');\r\n }\r\n }\r\n return attr_data;\r\n },\r\n\r\n /** @param {Node} node @param {string[]} xml_lines */\r\n _build_map: function (node, xml_lines) {\r\n var df = format.freemind;\r\n var pos = null;\r\n var node_data = node.data;\r\n\r\n if (!!node.parent && node.parent.isroot) {\r\n pos = node.direction === Direction.left ? 'left' : 'right';\r\n }\r\n xml_lines.push('<node');\r\n xml_lines.push(' ID=\"' + node.id + '\"');\r\n if (!!pos) {\r\n xml_lines.push(' POSITION=\"' + pos + '\"');\r\n }\r\n if (!node.expanded) {\r\n xml_lines.push(' FOLDED=\"true\"');\r\n }\r\n if (!!node_data['foreground-color']) {\r\n xml_lines.push(' COLOR=\"' + node_data['foreground-color'] + '\"');\r\n }\r\n if (!!node_data['background-color']) {\r\n xml_lines.push(' BACKGROUND_COLOR=\"' + node_data['background-color'] + '\"');\r\n }\r\n xml_lines.push(' TEXT=\"' + df._escape(node.topic) + '\">');\r\n\r\n // for attributes\r\n if (node_data != null) {\r\n for (var k in node_data) {\r\n if (k === 'foreground-color' || k === 'background-color') {\r\n continue;\r\n }\r\n xml_lines.push('<attribute NAME=\"' + k + '\" VALUE=\"' + node_data[k] + '\"/>');\r\n }\r\n }\r\n\r\n // for children\r\n var children = node.children;\r\n for (var i = 0; i < children.length; i++) {\r\n df._build_map(children[i], xml_lines);\r\n }\r\n\r\n xml_lines.push('</node>');\r\n },\r\n\r\n /** @param {string} text */\r\n _escape: function (text) {\r\n return text\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/'/g, ''')\r\n .replace(/\"/g, '"');\r\n },\r\n },\r\n text: {\r\n example: {\r\n meta: DEFAULT_META,\r\n format: 'text',\r\n data: 'jsMind text example\\n node1\\n node1-sub\\n node1-sub\\n node2',\r\n },\r\n _line_regex: /\\s*/,\r\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\r\n get_mind: function (source, fieldNames) {\r\n var df = format.text;\r\n var mind = new Mind();\r\n mind.name = source.meta.name;\r\n mind.author = source.meta.author;\r\n mind.version = source.meta.version;\r\n var lines = source.data.split(/\\n|\\r/);\r\n // text format uses indentation-based structure, fieldNames not applicable\r\n df._fill_nodes(mind, lines, 0, 0);\r\n return mind;\r\n },\r\n\r\n /** @param {Mind} mind @param {string[]} lines */\r\n _fill_nodes: function (mind, lines) {\r\n let node_path = [];\r\n let i = 0;\r\n while (i < lines.length) {\r\n let line = lines[i];\r\n let level = line.match(/\\s*/)[0].length;\r\n let topic = line.substr(level);\r\n\r\n if (level == 0 && node_path.length > 0) {\r\n log.error('more than 1 root node was found: ' + topic);\r\n return;\r\n }\r\n if (level > node_path.length) {\r\n log.error('a suspended node was found: ' + topic);\r\n return;\r\n }\r\n let diff = node_path.length - level;\r\n while (diff--) {\r\n node_path.pop();\r\n }\r\n\r\n if (level == 0 && node_path.length == 0) {\r\n let node = mind.set_root(util.uuid.newid(), topic);\r\n node_path.push(node);\r\n } else {\r\n let node = mind.add_node(\r\n node_path[level - 1],\r\n util.uuid.newid(),\r\n topic,\r\n {},\r\n null\r\n );\r\n node_path.push(node);\r\n }\r\n i++;\r\n }\r\n node_path.length = 0;\r\n },\r\n\r\n /** @param {Mind} mind */\r\n get_data: function (mind) {\r\n var df = format.text;\r\n var json = {};\r\n json.meta = {\r\n name: mind.name,\r\n author: mind.author,\r\n version: mind.version,\r\n };\r\n json.format = 'text';\r\n let lines = [];\r\n df._build_lines(lines, [mind.root], 0);\r\n json.data = lines.join('\\n');\r\n return json;\r\n },\r\n\r\n /** @param {string[]} lines @param {Node[]} nodes @param {number} level */\r\n _build_lines: function (lines, nodes, level) {\r\n let prefix = new Array(level + 1).join(' ');\r\n for (let node of nodes) {\r\n lines.push(prefix + node.topic);\r\n if (!!node.children) {\r\n format.text._build_lines(lines, node.children, level + 1);\r\n }\r\n }\r\n },\r\n },\r\n};\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { logger } from './jsmind.common.js';\r\nimport { format } from './jsmind.format.js';\r\n\r\nexport class DataProvider {\r\n /**\r\n * Data provider: loads and serializes mind data by format.\r\n * @param {import('./jsmind.js').default} jm - jsMind instance\r\n */\r\n constructor(jm) {\r\n this.jm = jm;\r\n }\r\n\r\n /** Initialize data provider. */\r\n init() {\r\n logger.debug('data.init');\r\n }\r\n /** Reset data provider state. */\r\n reset() {\r\n logger.debug('data.reset');\r\n }\r\n /**\r\n * Load a Mind from mixed source.\r\n * @param {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta?:{name:string,author:string,version:string},format:'freemind',data:string}|{meta?:{name:string,author:string,version:string},format:'text',data:string}} mind_data - object with {format,data} or a format-specific payload\r\n * @returns {import('./jsmind.mind.js').Mind|null}\r\n */\r\n load(mind_data) {\r\n var df = null;\r\n var mind = null;\r\n if (typeof mind_data === 'object') {\r\n if (!!mind_data.format) {\r\n df = mind_data.format;\r\n } else {\r\n df = 'node_tree';\r\n }\r\n } else {\r\n df = 'freemind';\r\n }\r\n\r\n var fieldNames = this.jm.options.fieldNames;\r\n if (df == 'node_array') {\r\n mind = format.node_array.get_mind(mind_data, fieldNames);\r\n } else if (df == 'node_tree') {\r\n mind = format.node_tree.get_mind(mind_data, fieldNames);\r\n } else if (df == 'freemind') {\r\n mind = format.freemind.get_mind(mind_data, fieldNames);\r\n } else if (df == 'text') {\r\n mind = format.text.get_mind(mind_data, fieldNames);\r\n } else {\r\n logger.warn('unsupported format');\r\n }\r\n return mind;\r\n }\r\n /**\r\n * Serialize current mind to target format.\r\n * @param {'node_tree'|'node_array'|'freemind'|'text'} data_format\r\n * @returns {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta:{name:string,author:string,version:string},format:'freemind',data:string}|{meta:{name:string,author:string,version:string},format:'text',data:string}}\r\n */\r\n get_data(data_format) {\r\n var data = null;\r\n var fieldNames = this.jm.options.fieldNames;\r\n if (data_format == 'node_array') {\r\n data = format.node_array.get_data(this.jm.mind, fieldNames);\r\n } else if (data_format == 'node_tree') {\r\n data = format.node_tree.get_data(this.jm.mind, fieldNames);\r\n } else if (data_format == 'freemind') {\r\n data = format.freemind.get_data(this.jm.mind);\r\n } else if (data_format == 'text') {\r\n data = format.text.get_data(this.jm.mind);\r\n } else {\r\n logger.error('unsupported ' + data_format + ' format');\r\n }\r\n return data;\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\nimport { logger, Direction, EventType } from './jsmind.common.js';\r\n\r\nexport class LayoutProvider {\r\n /**\r\n * Layout engine for positioning nodes and lines.\r\n * @param {import('./jsmind.js').default} jm - jsMind instance\r\n * @param {{mode:'full'|'side', hspace:number, vspace:number, pspace:number, cousin_space:number}} options - Layout configuration options\r\n */\r\n constructor(jm, options) {\r\n this.opts = options;\r\n this.jm = jm;\r\n this.isside = this.opts.mode == 'side';\r\n this.bounds = null;\r\n\r\n this.cache_valid = false;\r\n }\r\n /** Initialize layout provider. */\r\n init() {\r\n logger.debug('layout.init');\r\n }\r\n /** Reset layout state and bounds. */\r\n reset() {\r\n logger.debug('layout.reset');\r\n this.bounds = { n: 0, s: 0, w: 0, e: 0 };\r\n }\r\n /**\r\n * Decide the next child's direction for a parent node.\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @returns {number}\r\n */\r\n calculate_next_child_direction(node) {\r\n if (this.isside) {\r\n return Direction.right;\r\n }\r\n var children = node.children || [];\r\n var children_len = children.length;\r\n var r = 0;\r\n for (var i = 0; i < children_len; i++) {\r\n if (children[i].direction === Direction.left) {\r\n r--;\r\n } else {\r\n r++;\r\n }\r\n }\r\n return children_len > 1 && r > 0 ? Direction.left : Direction.right;\r\n }\r\n /** Perform layout and offsets recalculation. */\r\n layout() {\r\n logger.debug('layout.layout');\r\n this.layout_direction();\r\n this.layout_offset();\r\n }\r\n /** Calculate and set direction for all nodes. */\r\n layout_direction() {\r\n this._layout_direction_root();\r\n }\r\n /**\r\n * Set direction layout for root node and its children.\r\n * @private\r\n */\r\n _layout_direction_root() {\r\n var node = this.jm.mind.root;\r\n var layout_data = null;\r\n if ('layout' in node._data) {\r\n layout_data = node._data.layout;\r\n } else {\r\n layout_data = {};\r\n node._data.layout = layout_data;\r\n }\r\n var children = node.children;\r\n var children_count = children.length;\r\n layout_data.direction = Direction.center;\r\n layout_data.side_index = 0;\r\n if (this.isside) {\r\n var i = children_count;\r\n while (i--) {\r\n this._layout_direction_side(children[i], Direction.right, i);\r\n }\r\n } else {\r\n var i = children_count;\r\n var subnode = null;\r\n while (i--) {\r\n subnode = children[i];\r\n if (subnode.direction == Direction.left) {\r\n this._layout_direction_side(subnode, Direction.left, i);\r\n } else {\r\n this._layout_direction_side(subnode, Direction.right, i);\r\n }\r\n }\r\n }\r\n }\r\n /**\r\n * Set direction layout for a node and its descendants.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @param {number} direction - Direction constant (-1, 0, 1)\r\n * @param {number} side_index - Index among siblings\r\n */\r\n _layout_direction_side(node, direction, side_index) {\r\n var layout_data = null;\r\n if ('layout' in node._data) {\r\n layout_data = node._data.layout;\r\n } else {\r\n layout_data = {};\r\n node._data.layout = layout_data;\r\n }\r\n var children = node.children;\r\n var children_count = children.length;\r\n\r\n layout_data.direction = direction;\r\n layout_data.side_index = side_index;\r\n var i = children_count;\r\n while (i--) {\r\n this._layout_direction_side(children[i], direction, i);\r\n }\r\n }\r\n /** Calculate and set position offsets for all nodes. */\r\n layout_offset() {\r\n var node = this.jm.mind.root;\r\n var layout_data = node._data.layout;\r\n layout_data.offset_x = 0;\r\n layout_data.offset_y = 0;\r\n layout_data.outer_height = 0;\r\n var children = node.children;\r\n var i = children.length;\r\n var left_nodes = [];\r\n var right_nodes = [];\r\n var subnode = null;\r\n while (i--) {\r\n subnode = children[i];\r\n if (subnode._data.layout.direction == Direction.right) {\r\n right_nodes.unshift(subnode);\r\n } else {\r\n left_nodes.unshift(subnode);\r\n }\r\n }\r\n layout_data.left_nodes = left_nodes;\r\n layout_data.right_nodes = right_nodes;\r\n layout_data.outer_height_left = this._layout_offset_subnodes(left_nodes);\r\n layout_data.outer_height_right = this._layout_offset_subnodes(right_nodes);\r\n this.bounds.e = node._data.view.width / 2;\r\n this.bounds.w = 0 - this.bounds.e;\r\n this.bounds.n = 0;\r\n this.bounds.s = Math.max(layout_data.outer_height_left, layout_data.outer_height_right);\r\n }\r\n /**\r\n * Layout both the x and y axis for subnodes.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\r\n * @returns {number} Total height of all nodes\r\n */\r\n _layout_offset_subnodes(nodes) {\r\n var total_height = 0;\r\n var nodes_count = nodes.length;\r\n var i = nodes_count;\r\n var node = null;\r\n var node_outer_height = 0;\r\n var layout_data = null;\r\n var base_y = 0;\r\n var pd = null; // parent._data\r\n while (i--) {\r\n node = nodes[i];\r\n layout_data = node._data.layout;\r\n if (pd == null) {\r\n pd = node.parent._data;\r\n }\r\n\r\n node_outer_height = this._layout_offset_subnodes(node.children);\r\n if (!node.expanded) {\r\n node_outer_height = 0;\r\n this.set_visible(node.children, false);\r\n }\r\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\r\n\r\n if (this._should_reserve_cousin_space(node)) {\r\n node_outer_height += this.opts.cousin_space;\r\n }\r\n\r\n layout_data.outer_height = node_outer_height;\r\n layout_data.offset_y = base_y - node_outer_height / 2;\r\n layout_data.offset_x =\r\n this.opts.hspace * layout_data.direction +\r\n (pd.view.width * (pd.layout.direction + layout_data.direction)) / 2;\r\n if (!node.parent.isroot) {\r\n layout_data.offset_x += this.opts.pspace * layout_data.direction;\r\n }\r\n\r\n base_y = base_y - node_outer_height - this.opts.vspace;\r\n total_height += node_outer_height;\r\n }\r\n if (nodes_count > 1) {\r\n total_height += this.opts.vspace * (nodes_count - 1);\r\n }\r\n i = nodes_count;\r\n var middle_height = total_height / 2;\r\n while (i--) {\r\n node = nodes[i];\r\n node._data.layout.offset_y += middle_height;\r\n }\r\n return total_height;\r\n }\r\n /**\r\n * Layout the y axis only, for collapse/expand a node.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\r\n * @returns {number} Total height of all nodes\r\n */\r\n _layout_offset_subnodes_height(nodes) {\r\n var total_height = 0;\r\n var nodes_count = nodes.length;\r\n var i = nodes_count;\r\n var node = null;\r\n var node_outer_height = 0;\r\n var layout_data = null;\r\n var base_y = 0;\r\n var pd = null; // parent._data\r\n while (i--) {\r\n node = nodes[i];\r\n layout_data = node._data.layout;\r\n if (pd == null) {\r\n pd = node.parent._data;\r\n }\r\n\r\n node_outer_height = this._layout_offset_subnodes_height(node.children);\r\n if (!node.expanded) {\r\n node_outer_height = 0;\r\n }\r\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\r\n if (this._should_reserve_cousin_space(node)) {\r\n node_outer_height += this.opts.cousin_space;\r\n }\r\n\r\n layout_data.outer_height = node_outer_height;\r\n layout_data.offset_y = base_y - node_outer_height / 2;\r\n base_y = base_y - node_outer_height - this.opts.vspace;\r\n total_height += node_outer_height;\r\n }\r\n if (nodes_count > 1) {\r\n total_height += this.opts.vspace * (nodes_count - 1);\r\n }\r\n i = nodes_count;\r\n var middle_height = total_height / 2;\r\n while (i--) {\r\n node = nodes[i];\r\n node._data.layout.offset_y += middle_height;\r\n }\r\n return total_height;\r\n }\r\n /**\r\n * Check if node should reserve cousin space.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node} node - Node to check\r\n * @returns {boolean} True if cousin space should be reserved\r\n */\r\n _should_reserve_cousin_space(node) {\r\n return node.children.length > 0 && node.parent.children.length > 1;\r\n }\r\n /**\r\n * Get absolute offset for a node.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {{x:number, y:number}} Absolute position offset\r\n */\r\n get_node_offset(node) {\r\n var layout_data = node._data.layout;\r\n var offset_cache = null;\r\n if ('_offset_' in layout_data && this.cache_valid) {\r\n offset_cache = layout_data._offset_;\r\n } else {\r\n offset_cache = { x: -1, y: -1 };\r\n layout_data._offset_ = offset_cache;\r\n }\r\n if (offset_cache.x == -1 || offset_cache.y == -1) {\r\n var x = layout_data.offset_x;\r\n var y = layout_data.offset_y;\r\n if (!node.isroot) {\r\n var offset_p = this.get_node_offset(node.parent);\r\n x += offset_p.x;\r\n y += offset_p.y;\r\n }\r\n offset_cache.x = x;\r\n offset_cache.y = y;\r\n }\r\n return offset_cache;\r\n }\r\n /**\r\n * Get anchor point for lines on a node.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {{x:number, y:number}} Anchor point coordinates\r\n */\r\n get_node_point(node) {\r\n var view_data = node._data.view;\r\n var offset_p = this.get_node_offset(node);\r\n var p = {};\r\n p.x = offset_p.x + (view_data.width * (node._data.layout.direction - 1)) / 2;\r\n p.y = offset_p.y - view_data.height / 2;\r\n return p;\r\n }\r\n /**\r\n * Get input point for lines on a node.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {{x:number, y:number}} Input point coordinates\r\n */\r\n get_node_point_in(node) {\r\n var p = this.get_node_offset(node);\r\n return p;\r\n }\r\n /**\r\n * Get output point for lines on a node.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {{x:number, y:number}} Output point coordinates\r\n */\r\n get_node_point_out(node) {\r\n var layout_data = node._data.layout;\r\n var pout_cache = null;\r\n if ('_pout_' in layout_data && this.cache_valid) {\r\n pout_cache = layout_data._pout_;\r\n } else {\r\n pout_cache = { x: -1, y: -1 };\r\n layout_data._pout_ = pout_cache;\r\n }\r\n if (pout_cache.x == -1 || pout_cache.y == -1) {\r\n if (node.isroot) {\r\n pout_cache.x = 0;\r\n pout_cache.y = 0;\r\n } else {\r\n var view_data = node._data.view;\r\n var offset_p = this.get_node_offset(node);\r\n pout_cache.x =\r\n offset_p.x + (view_data.width + this.opts.pspace) * node._data.layout.direction;\r\n pout_cache.y = offset_p.y;\r\n }\r\n }\r\n return pout_cache;\r\n }\r\n /**\r\n * Get expander point for a node.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {{x:number, y:number}} Expander point coordinates\r\n */\r\n get_expander_point(node) {\r\n var p = this.get_node_point_out(node);\r\n var ex_p = {};\r\n if (node._data.layout.direction == Direction.right) {\r\n ex_p.x = p.x - this.opts.pspace;\r\n } else {\r\n ex_p.x = p.x;\r\n }\r\n ex_p.y = p.y - Math.ceil(this.opts.pspace / 2);\r\n return ex_p;\r\n }\r\n /**\r\n * Get minimal canvas size to contain all nodes.\r\n * @returns {{w:number, h:number}} Minimum size required\r\n */\r\n get_min_size() {\r\n var nodes = this.jm.mind.nodes;\r\n var node = null;\r\n var pout = null;\r\n for (var node_id in nodes) {\r\n node = nodes[node_id];\r\n pout = this.get_node_point_out(node);\r\n if (pout.x > this.bounds.e) {\r\n this.bounds.e = pout.x;\r\n }\r\n if (pout.x < this.bounds.w) {\r\n this.bounds.w = pout.x;\r\n }\r\n }\r\n return {\r\n w: this.bounds.e - this.bounds.w,\r\n h: this.bounds.s - this.bounds.n,\r\n };\r\n }\r\n /**\r\n * Toggle node expanded/collapsed state.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n */\r\n toggle_node(node) {\r\n if (node.isroot) {\r\n return;\r\n }\r\n if (node.expanded) {\r\n this.collapse_node(node);\r\n } else {\r\n this.expand_node(node);\r\n }\r\n }\r\n /**\r\n * Expand a node and show its children.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n */\r\n expand_node(node) {\r\n node.expanded = true;\r\n this.part_layout(node);\r\n this.set_visible(node.children, true);\r\n this.jm.invoke_event_handle(EventType.show, {\r\n evt: 'expand_node',\r\n data: [],\r\n node: node.id,\r\n });\r\n }\r\n /**\r\n * Collapse a node and hide its children.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n */\r\n collapse_node(node) {\r\n node.expanded = false;\r\n this.part_layout(node);\r\n this.set_visible(node.children, false);\r\n this.jm.invoke_event_handle(EventType.show, {\r\n evt: 'collapse_node',\r\n data: [],\r\n node: node.id,\r\n });\r\n }\r\n /** Expand all nodes in the mind map. */\r\n expand_all() {\r\n var nodes = this.jm.mind.nodes;\r\n var c = 0;\r\n var node;\r\n for (var node_id in nodes) {\r\n node = nodes[node_id];\r\n if (!node.expanded) {\r\n node.expanded = true;\r\n c++;\r\n }\r\n }\r\n if (c > 0) {\r\n var root = this.jm.mind.root;\r\n this.part_layout(root);\r\n this.set_visible(root.children, true);\r\n }\r\n }\r\n /** Collapse all nodes in the mind map. */\r\n collapse_all() {\r\n var nodes = this.jm.mind.nodes;\r\n var c = 0;\r\n var node;\r\n for (var node_id in nodes) {\r\n node = nodes[node_id];\r\n if (node.expanded && !node.isroot) {\r\n node.expanded = false;\r\n c++;\r\n }\r\n }\r\n if (c > 0) {\r\n var root = this.jm.mind.root;\r\n this.part_layout(root);\r\n this.set_visible(root.children, true);\r\n }\r\n }\r\n /**\r\n * Expand nodes to a specific depth level.\r\n * @param {number} target_depth - Target depth level\r\n * @param {import('./jsmind.node.js').Node[]=} curr_nodes - Current nodes to process\r\n * @param {number=} curr_depth - Current depth level\r\n */\r\n expand_to_depth(target_depth, curr_nodes, curr_depth) {\r\n if (target_depth < 1) {\r\n return;\r\n }\r\n var nodes = curr_nodes || this.jm.mind.root.children;\r\n var depth = curr_depth || 1;\r\n var i = nodes.length;\r\n var node = null;\r\n while (i--) {\r\n node = nodes[i];\r\n if (depth < target_depth) {\r\n if (!node.expanded) {\r\n this.expand_node(node);\r\n }\r\n this.expand_to_depth(target_depth, node.children, depth + 1);\r\n }\r\n if (depth == target_depth) {\r\n if (node.expanded) {\r\n this.collapse_node(node);\r\n }\r\n }\r\n }\r\n }\r\n /**\r\n * Perform partial layout for a node and its subtree.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n */\r\n part_layout(node) {\r\n var root = this.jm.mind.root;\r\n if (!!root) {\r\n var root_layout_data = root._data.layout;\r\n if (node.isroot) {\r\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\r\n root_layout_data.right_nodes\r\n );\r\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\r\n root_layout_data.left_nodes\r\n );\r\n } else {\r\n if (node._data.layout.direction == Direction.right) {\r\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\r\n root_layout_data.right_nodes\r\n );\r\n } else {\r\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\r\n root_layout_data.left_nodes\r\n );\r\n }\r\n }\r\n this.bounds.s = Math.max(\r\n root_layout_data.outer_height_left,\r\n root_layout_data.outer_height_right\r\n );\r\n this.cache_valid = false;\r\n } else {\r\n logger.warn('can not found root node');\r\n }\r\n }\r\n /**\r\n * Set visibility for nodes and their children.\r\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes\r\n * @param {boolean} visible - Visibility state\r\n */\r\n set_visible(nodes, visible) {\r\n var i = nodes.length;\r\n var node = null;\r\n var layout_data = null;\r\n while (i--) {\r\n node = nodes[i];\r\n layout_data = node._data.layout;\r\n if (node.expanded) {\r\n this.set_visible(node.children, visible);\r\n } else {\r\n this.set_visible(node.children, false);\r\n }\r\n if (!node.isroot) {\r\n node._data.layout.visible = visible;\r\n }\r\n }\r\n }\r\n /**\r\n * Check if a node is expanded.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {boolean} True if node is expanded\r\n */\r\n is_expand(node) {\r\n return node.expanded;\r\n }\r\n /**\r\n * Check if a node is visible.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n * @returns {boolean} True if node is visible\r\n */\r\n is_visible(node) {\r\n var layout_data = node._data.layout;\r\n if ('visible' in layout_data && !layout_data.visible) {\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { $ } from './jsmind.dom.js';\r\nimport { logger } from './jsmind.common.js';\r\n\r\n/**\r\n * SVG-based graph renderer.\r\n */\r\nclass SvgGraph {\r\n /**\r\n * Create SVG graph renderer.\r\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\r\n */\r\n constructor(view) {\r\n this.view = view;\r\n this.opts = view.opts;\r\n this.e_svg = SvgGraph.c('svg');\r\n this.e_svg.setAttribute('class', 'jsmind');\r\n this.size = { w: 0, h: 0 };\r\n /** @type {SVGPathElement[]} */\r\n this.lines = [];\r\n this.line_drawing = {\r\n straight: this._line_to,\r\n curved: this._bezier_to,\r\n };\r\n this.init_line_render();\r\n }\r\n /** @param {string} tag */\r\n static c(tag) {\r\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\r\n }\r\n /** Choose line drawing renderer. */\r\n init_line_render() {\r\n if (typeof this.opts.custom_line_render === 'function') {\r\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\r\n this.drawing = (path, x1, y1, x2, y2) => {\r\n try {\r\n this.opts.custom_line_render.call(this, {\r\n ctx: path,\r\n start_point: { x: x1, y: y1 },\r\n end_point: { x: x2, y: y2 },\r\n });\r\n } catch (e) {\r\n logger.error('custom line renderer error: ', e);\r\n }\r\n };\r\n } else {\r\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\r\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\r\n }\r\n }\r\n /** @returns {SVGSVGElement} */\r\n element() {\r\n return this.e_svg;\r\n }\r\n /** @param {number} w @param {number} h */\r\n set_size(w, h) {\r\n this.size.w = w;\r\n this.size.h = h;\r\n this.e_svg.setAttribute('width', w);\r\n this.e_svg.setAttribute('height', h);\r\n }\r\n clear() {\r\n var len = this.lines.length;\r\n while (len--) {\r\n this.e_svg.removeChild(this.lines[len]);\r\n }\r\n this.lines.length = 0;\r\n }\r\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\r\n draw_line(pout, pin, offset, color) {\r\n var line = SvgGraph.c('path');\r\n line.setAttribute('stroke', color || this.opts.line_color);\r\n line.setAttribute('stroke-width', this.opts.line_width);\r\n line.setAttribute('fill', 'transparent');\r\n this.lines.push(line);\r\n this.e_svg.appendChild(line);\r\n this.drawing(\r\n line,\r\n pin.x + offset.x,\r\n pin.y + offset.y,\r\n pout.x + offset.x,\r\n pout.y + offset.y\r\n );\r\n }\r\n\r\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\r\n copy_to(dest_canvas_ctx, callback) {\r\n var img = new Image();\r\n img.onload = function () {\r\n dest_canvas_ctx.drawImage(img, 0, 0);\r\n !!callback && callback();\r\n };\r\n img.src =\r\n 'data:image/svg+xml;base64,' + btoa(new XMLSerializer().serializeToString(this.e_svg));\r\n }\r\n /**\r\n * Draw bezier curve to SVG path.\r\n * @internal\r\n * @param {SVGPathElement} path - SVG path element\r\n * @param {number} x1 - Start x coordinate\r\n * @param {number} y1 - Start y coordinate\r\n * @param {number} x2 - End x coordinate\r\n * @param {number} y2 - End y coordinate\r\n */\r\n _bezier_to(path, x1, y1, x2, y2) {\r\n path.setAttribute(\r\n 'd',\r\n 'M ' +\r\n x1 +\r\n ' ' +\r\n y1 +\r\n ' C ' +\r\n (x1 + ((x2 - x1) * 2) / 3) +\r\n ' ' +\r\n y1 +\r\n ', ' +\r\n x1 +\r\n ' ' +\r\n y2 +\r\n ', ' +\r\n x2 +\r\n ' ' +\r\n y2\r\n );\r\n }\r\n /**\r\n * Draw straight line to SVG path.\r\n * @internal\r\n * @param {SVGPathElement} path - SVG path element\r\n * @param {number} x1 - Start x coordinate\r\n * @param {number} y1 - Start y coordinate\r\n * @param {number} x2 - End x coordinate\r\n * @param {number} y2 - End y coordinate\r\n */\r\n _line_to(path, x1, y1, x2, y2) {\r\n path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2);\r\n }\r\n}\r\n\r\n/**\r\n * Canvas-based graph renderer.\r\n */\r\nclass CanvasGraph {\r\n /**\r\n * Create canvas graph renderer.\r\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\r\n */\r\n constructor(view) {\r\n this.opts = view.opts;\r\n this.e_canvas = $.c('canvas');\r\n this.e_canvas.className = 'jsmind';\r\n this.canvas_ctx = /** @type {CanvasRenderingContext2D} */ (this.e_canvas.getContext('2d'));\r\n this.size = { w: 0, h: 0 };\r\n this.line_drawing = {\r\n straight: this._line_to,\r\n curved: this._bezier_to,\r\n };\r\n this.dpr = view.device_pixel_ratio;\r\n this.init_line_render();\r\n }\r\n /** Choose line drawing renderer. */\r\n init_line_render() {\r\n if (typeof this.opts.custom_line_render === 'function') {\r\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\r\n this.drawing = (ctx, x1, y1, x2, y2) => {\r\n try {\r\n this.opts.custom_line_render.call(this, {\r\n ctx,\r\n start_point: { x: x1, y: y1 },\r\n end_point: { x: x2, y: y2 },\r\n });\r\n } catch (e) {\r\n logger.error('custom line render error: ', e);\r\n }\r\n };\r\n } else {\r\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\r\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\r\n }\r\n }\r\n /** @returns {HTMLCanvasElement} */\r\n element() {\r\n return this.e_canvas;\r\n }\r\n /** @param {number} w @param {number} h */\r\n set_size(w, h) {\r\n this.size.w = w;\r\n this.size.h = h;\r\n if (this.e_canvas.width && this.e_canvas.height && this.canvas_ctx.scale) {\r\n this.e_canvas.width = w * this.dpr;\r\n this.e_canvas.height = h * this.dpr;\r\n\r\n this.e_canvas.style.width = w + 'px';\r\n this.e_canvas.style.height = h + 'px';\r\n this.canvas_ctx.scale(this.dpr, this.dpr);\r\n } else {\r\n this.e_canvas.width = w;\r\n this.e_canvas.height = h;\r\n }\r\n }\r\n\r\n /** Clear the canvas. */\r\n clear() {\r\n this.canvas_ctx.clearRect(0, 0, this.size.w, this.size.h);\r\n }\r\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\r\n draw_line(pout, pin, offset, color) {\r\n var ctx = this.canvas_ctx;\r\n ctx.strokeStyle = color || this.opts.line_color;\r\n ctx.lineWidth = this.opts.line_width;\r\n ctx.lineCap = 'round';\r\n this.drawing(ctx, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y);\r\n }\r\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\r\n copy_to(dest_canvas_ctx, callback) {\r\n dest_canvas_ctx.drawImage(this.e_canvas, 0, 0, this.size.w, this.size.h);\r\n !!callback && callback();\r\n }\r\n /**\r\n * Draw bezier curve on canvas.\r\n * @internal\r\n * @param {CanvasRenderingContext2D} ctx - Canvas context\r\n * @param {number} x1 - Start x coordinate\r\n * @param {number} y1 - Start y coordinate\r\n * @param {number} x2 - End x coordinate\r\n * @param {number} y2 - End y coordinate\r\n */\r\n _bezier_to(ctx, x1, y1, x2, y2) {\r\n ctx.beginPath();\r\n ctx.moveTo(x1, y1);\r\n ctx.bezierCurveTo(x1 + ((x2 - x1) * 2) / 3, y1, x1, y2, x2, y2);\r\n ctx.stroke();\r\n }\r\n /**\r\n * Draw straight line on canvas.\r\n * @internal\r\n * @param {CanvasRenderingContext2D} ctx - Canvas context\r\n * @param {number} x1 - Start x coordinate\r\n * @param {number} y1 - Start y coordinate\r\n * @param {number} x2 - End x coordinate\r\n * @param {number} y2 - End y coordinate\r\n */\r\n _line_to(ctx, x1, y1, x2, y2) {\r\n ctx.beginPath();\r\n ctx.moveTo(x1, y1);\r\n ctx.lineTo(x2, y2);\r\n ctx.stroke();\r\n }\r\n}\r\n\r\n/**\r\n * Initialize graph renderer based on engine type.\r\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\r\n * @param {'canvas'|'svg'} engine - Rendering engine type\r\n * @returns {SvgGraph|CanvasGraph} Graph renderer instance\r\n */\r\nexport function init_graph(view, engine) {\r\n return engine.toLowerCase() === 'svg' ? new SvgGraph(view) : new CanvasGraph(view);\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\nimport { logger, EventType } from './jsmind.common.js';\r\nimport { $ } from './jsmind.dom.js';\r\nimport { init_graph } from './jsmind.graph.js';\r\nimport { util } from './jsmind.util.js';\r\n\r\nexport class ViewProvider {\r\n /**\r\n * View layer: DOM nodes, editor, graph and zoom.\r\n * @param {import('./jsmind.js').default} jm - jsMind instance\r\n * @param {{\r\n * engine: 'canvas'|'svg',\r\n * enable_device_pixel_ratio: boolean,\r\n * hmargin: number,\r\n * vmargin: number,\r\n * line_width: number,\r\n * line_color: string,\r\n * line_style: 'curved'|'straight',\r\n * custom_line_render?: Function,\r\n * draggable: boolean,\r\n * hide_scrollbars_when_draggable: boolean,\r\n * node_overflow: 'hidden'|'wrap',\r\n * zoom: {min:number, max:number, step:number, mask_key:number},\r\n * custom_node_render?: Function,\r\n * expander_style: 'char'|'number'\r\n * }} options - View configuration options\r\n */\r\n constructor(jm, options) {\r\n this.opts = options;\r\n this.jm = jm;\r\n this.layout = jm.layout;\r\n\r\n this.container = null;\r\n this.e_panel = null;\r\n this.e_nodes = null;\r\n\r\n this.size = { w: 0, h: 0 };\r\n\r\n this.selected_node = null;\r\n /** @type {Map<string, import('./jsmind.node.js').Node>} */\r\n this.multi_selected_nodes = new Map();\r\n this.editing_node = null;\r\n\r\n this.graph = null;\r\n this.render_node = !!options.custom_node_render\r\n ? this._custom_node_render\r\n : this._default_node_render;\r\n this.zoom_current = 1;\r\n this.device_pixel_ratio = this.opts.enable_device_pixel_ratio\r\n ? $.w.devicePixelRatio || 1\r\n : 1;\r\n this._initialized = false;\r\n }\r\n /** Initialize DOM structure, graph and editor. */\r\n init() {\r\n logger.debug(this.opts);\r\n logger.debug('view.init');\r\n\r\n this.container = $.i(this.opts.container)\r\n ? /** @type {HTMLElement} */ (this.opts.container)\r\n : /** @type {HTMLElement} */ ($.g(this.opts.container));\r\n if (!this.container) {\r\n logger.error('the options.view.container was not be found in dom');\r\n return;\r\n }\r\n this.graph = init_graph(this, this.opts.engine);\r\n\r\n this.e_panel = $.c('div');\r\n this.e_nodes = $.c('jmnodes');\r\n this.e_editor = $.c('input');\r\n this.e_panel.className = 'jsmind-inner jmnode-overflow-' + this.opts.node_overflow;\r\n this.e_panel.tabIndex = 1;\r\n this.e_panel.appendChild(this.graph.element());\r\n this.e_panel.appendChild(this.e_nodes);\r\n\r\n this.e_editor.className = 'jsmind-editor';\r\n this.e_editor.type = 'text';\r\n\r\n var v = this;\r\n $.on(this.e_editor, 'keydown', function (e) {\r\n var evt = e || event;\r\n if (evt.keyCode == 13) {\r\n v.edit_node_end();\r\n evt.stopPropagation();\r\n }\r\n });\r\n $.on(this.e_editor, 'blur', function (e) {\r\n v.edit_node_end();\r\n });\r\n\r\n this.container.appendChild(this.e_panel);\r\n\r\n if (!this.container.offsetParent) {\r\n new IntersectionObserver((entities, observer) => {\r\n if (entities[0].isIntersecting) {\r\n observer.unobserve(this.e_panel);\r\n this.resize();\r\n }\r\n }).observe(this.e_panel);\r\n }\r\n }\r\n\r\n /**\r\n * Add a delegated event handler.\r\n * @param {import('./jsmind.js').default} obj\r\n * @param {string} event_name\r\n * @param {(e:Event)=>void} event_handle\r\n * @param {boolean=} capture_by_panel\r\n */\r\n add_event(obj, event_name, event_handle, capture_by_panel) {\r\n let target = !!capture_by_panel ? this.e_panel : this.e_nodes;\r\n $.on(target, event_name, function (e) {\r\n var evt = e || event;\r\n event_handle.call(obj, evt);\r\n });\r\n }\r\n /**\r\n * @param {HTMLElement|null} element\r\n * @returns {string|null}\r\n */\r\n get_binded_nodeid(element) {\r\n if (element == null) {\r\n return null;\r\n }\r\n var tagName = element.tagName.toLowerCase();\r\n if (tagName == 'jmnode' || tagName == 'jmexpander') {\r\n return element.getAttribute('nodeid');\r\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\r\n return null;\r\n } else {\r\n return this.get_binded_nodeid(element.parentElement);\r\n }\r\n }\r\n /**\r\n * @param {HTMLElement|null} element\r\n * @returns {boolean}\r\n */\r\n is_node(element) {\r\n if (element == null) {\r\n return false;\r\n }\r\n var tagName = element.tagName.toLowerCase();\r\n if (tagName == 'jmnode') {\r\n return true;\r\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\r\n return false;\r\n } else {\r\n return this.is_node(element.parentElement);\r\n }\r\n }\r\n /**\r\n * @param {HTMLElement} element\r\n * @returns {boolean}\r\n */\r\n is_expander(element) {\r\n return element.tagName.toLowerCase() == 'jmexpander';\r\n }\r\n reset() {\r\n logger.debug('view.reset');\r\n this.selected_node = null;\r\n this.multi_selected_nodes.clear();\r\n this.clear_lines();\r\n this.clear_nodes();\r\n this.reset_theme();\r\n }\r\n reset_theme() {\r\n var theme_name = this.jm.options.theme;\r\n if (!!theme_name) {\r\n this.e_nodes.className = 'theme-' + theme_name;\r\n } else {\r\n this.e_nodes.className = '';\r\n }\r\n }\r\n /** Reset custom styles for all nodes. */\r\n reset_custom_style() {\r\n var nodes = this.jm.mind.nodes;\r\n for (var nodeid in nodes) {\r\n this.reset_node_custom_style(nodes[nodeid]);\r\n }\r\n }\r\n /** Load and initialize the view. */\r\n load() {\r\n logger.debug('view.load');\r\n this.setup_canvas_draggable(this.opts.draggable);\r\n this.init_nodes();\r\n this._initialized = true;\r\n }\r\n /** Calculate and set the expanded canvas size. */\r\n expand_size() {\r\n var min_size = this.layout.get_min_size();\r\n var min_width = min_size.w + this.opts.hmargin * 2;\r\n var min_height = min_size.h + this.opts.vmargin * 2;\r\n var client_w = this.e_panel.clientWidth;\r\n var client_h = this.e_panel.clientHeight;\r\n if (client_w < min_width) {\r\n client_w = min_width;\r\n }\r\n if (client_h < min_height) {\r\n client_h = min_height;\r\n }\r\n this.size.w = client_w;\r\n this.size.h = client_h;\r\n }\r\n /**\r\n * Initialize size data for a node.\r\n * @param {import('./jsmind.node.js').Node} node - Target node\r\n */\r\n init_nodes_size(node) {\r\n var view_data = node._data.view;\r\n view_data.width = view_data.element.clientWidth;\r\n view_data.height = view_data.element.clientHeight;\r\n }\r\n /** Initialize DOM elements for all nodes. */\r\n init_nodes() {\r\n var nodes = this.jm.mind.nodes;\r\n var doc_frag = $.d.createDocumentFragment();\r\n for (var nodeid in nodes) {\r\n this.create_node_element(nodes[nodeid], doc_frag);\r\n }\r\n this.e_nodes.appendChild(doc_frag);\r\n\r\n this.run_in_c11y_mode_if_needed(() => {\r\n for (var nodeid in nodes) {\r\n this.init_nodes_size(nodes[nodeid]);\r\n }\r\n });\r\n }\r\n /**\r\n * Add a new node to the view.\r\n * @param {import('./jsmind.node.js').Node} node - Node to add\r\n */\r\n add_node(node) {\r\n this.create_node_element(node, this.e_nodes);\r\n this.run_in_c11y_mode_if_needed(() => {\r\n this.init_nodes_size(node);\r\n });\r\n }\r\n /**\r\n * Run function in compatibility mode if container is not visible.\r\n * @param {Function} func - Function to execute\r\n */\r\n run_in_c11y_mode_if_needed(func) {\r\n if (!!this.container.offsetParent) {\r\n func();\r\n return;\r\n }\r\n logger.warn(\r\n 'init nodes in compatibility mode. because the container or its parent has style {display:none}. '\r\n );\r\n this.e_panel.style.position = 'absolute';\r\n this.e_panel.style.top = '-100000';\r\n $.d.body.appendChild(this.e_panel);\r\n func();\r\n this.container.appendChild(this.e_panel);\r\n this.e_panel.style.position = null;\r\n this.e_panel.style.top = null;\r\n }\r\n /**\r\n * Create a DOM element for a node and append to parent container.\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @param {HTMLElement} parent_node\r\n */\r\n create_node_element(node, parent_node) {\r\n var view_data = null;\r\n if ('view' in node._data) {\r\n view_data = node._data.view;\r\n } else {\r\n view_data = {};\r\n node._data.view = view_data;\r\n }\r\n\r\n var d = $.c('jmnode');\r\n if (node.isroot) {\r\n d.className = 'root';\r\n } else {\r\n var d_e = $.c('jmexpander');\r\n $.t(d_e, '-');\r\n d_e.setAttribute('nodeid', node.id);\r\n d_e.style.visibility = 'hidden';\r\n parent_node.appendChild(d_e);\r\n view_data.expander = d_e;\r\n }\r\n if (!!node.topic) {\r\n this.render_node(d, node);\r\n }\r\n d.setAttribute('nodeid', node.id);\r\n d.style.visibility = 'hidden';\r\n this._reset_node_custom_style(d, node.data);\r\n\r\n parent_node.appendChild(d);\r\n view_data.element = d;\r\n }\r\n /**\r\n * Remove a node from the view.\r\n * @param {import('./jsmind.node.js').Node} node - Node to remove\r\n */\r\n remove_node(node) {\r\n this._unmark_node_selected(node);\r\n if (this.editing_node != null && this.editing_node.id == node.id) {\r\n node._data.view.element.removeChild(this.e_editor);\r\n this.editing_node = null;\r\n }\r\n var children = node.children;\r\n var i = children.length;\r\n while (i--) {\r\n this.remove_node(children[i]);\r\n }\r\n if (node._data.view) {\r\n var element = node._data.view.element;\r\n var expander = node._data.view.expander;\r\n this.e_nodes.removeChild(element);\r\n this.e_nodes.removeChild(expander);\r\n node._data.view.element = null;\r\n node._data.view.expander = null;\r\n }\r\n }\r\n /**\r\n * Update a node's display.\r\n * @param {import('./jsmind.node.js').Node} node - Node to update\r\n */\r\n update_node(node) {\r\n var view_data = node._data.view;\r\n var element = view_data.element;\r\n if (!!node.topic) {\r\n this.render_node(element, node);\r\n }\r\n if (this.layout.is_visible(node)) {\r\n view_data.width = element.clientWidth;\r\n view_data.height = element.clientHeight;\r\n } else {\r\n let origin_style = element.getAttribute('style');\r\n element.style = 'visibility: visible; left:0; top:0;';\r\n view_data.width = element.clientWidth;\r\n view_data.height = element.clientHeight;\r\n element.style = origin_style;\r\n }\r\n }\r\n /**\r\n * Select a node visually.\r\n * @param {import('./jsmind.node.js').Node|null} node - Node to select\r\n */\r\n select_node(node) {\r\n this.clear_all_selected_nodes();\r\n if (!!node) {\r\n this.selected_node = node;\r\n this._mark_node_selected(node);\r\n }\r\n }\r\n /** Clear node selection. */\r\n select_clear() {\r\n this.clear_all_selected_nodes();\r\n }\r\n /**\r\n * Append nodes to the current selection without clearing existing ones.\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @param {import('./jsmind.node.js').Node=} focus_node\r\n */\r\n append_selected_nodes(nodes, focus_node) {\r\n if (!nodes || !nodes.length) {\r\n return;\r\n }\r\n for (var i = 0; i < nodes.length; i++) {\r\n this._mark_node_selected(nodes[i]);\r\n }\r\n if (focus_node) {\r\n this.selected_node = focus_node;\r\n } else {\r\n this.selected_node = nodes[nodes.length - 1];\r\n }\r\n }\r\n /**\r\n * Remove the provided nodes from selection state.\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n */\r\n remove_selected_nodes(nodes) {\r\n if (!nodes || !nodes.length) {\r\n return;\r\n }\r\n for (var i = 0; i < nodes.length; i++) {\r\n this._unmark_node_selected(nodes[i]);\r\n }\r\n }\r\n /** Clear all selections at once. */\r\n clear_all_selected_nodes() {\r\n if (!this.multi_selected_nodes.size) {\r\n this.selected_node = null;\r\n return;\r\n }\r\n var nodes = Array.from(this.multi_selected_nodes.values());\r\n for (var i = 0; i < nodes.length; i++) {\r\n this._unmark_node_selected(nodes[i]);\r\n }\r\n this.selected_node = null;\r\n }\r\n /**\r\n * Get currently editing node.\r\n * @returns {import('./jsmind.node.js').Node|null} Currently editing node\r\n */\r\n get_editing_node() {\r\n return this.editing_node;\r\n }\r\n /**\r\n * Check if any node is being edited.\r\n * @returns {boolean} True if editing\r\n */\r\n is_editing() {\r\n return !!this.editing_node;\r\n }\r\n /**\r\n * Begin editing a node.\r\n * @param {import('./jsmind.node.js').Node} node - Node to edit\r\n */\r\n edit_node_begin(node) {\r\n if (!node.topic) {\r\n logger.warn(\"don't edit image nodes\");\r\n return;\r\n }\r\n if (this.editing_node != null) {\r\n this.edit_node_end();\r\n }\r\n this.editing_node = node;\r\n var view_data = node._data.view;\r\n var element = view_data.element;\r\n var topic = node.topic;\r\n var ncs = getComputedStyle(element);\r\n this.e_editor.value = topic;\r\n this.e_editor.style.width =\r\n element.clientWidth -\r\n parseInt(ncs.getPropertyValue('padding-left')) -\r\n parseInt(ncs.getPropertyValue('padding-right')) +\r\n 'px';\r\n element.innerHTML = '';\r\n element.appendChild(this.e_editor);\r\n element.style.zIndex = 5;\r\n this.e_editor.focus();\r\n this.e_editor.select();\r\n }\r\n /** End editing current node. */\r\n edit_node_end() {\r\n if (this.editing_node != null) {\r\n var node = this.editing_node;\r\n this.editing_node = null;\r\n var view_data = node._data.view;\r\n var element = view_data.element;\r\n var topic = this.e_editor.value;\r\n element.style.zIndex = 'auto';\r\n element.removeChild(this.e_editor);\r\n if (util.text.is_empty(topic) || node.topic === topic) {\r\n this.render_node(element, node);\r\n } else {\r\n this.jm.update_node(node.id, topic);\r\n }\r\n }\r\n this.e_panel.focus();\r\n }\r\n /** @returns {{x:number,y:number}} */\r\n get_view_offset() {\r\n var bounds = this.layout.bounds;\r\n var _x = (this.size.w - bounds.e - bounds.w) / 2;\r\n var _y = this.size.h / 2;\r\n return { x: _x, y: _y };\r\n }\r\n /** Resize the view to fit container. */\r\n resize() {\r\n this.graph.set_size(1, 1);\r\n this.e_nodes.style.width = '1px';\r\n this.e_nodes.style.height = '1px';\r\n\r\n this.expand_size();\r\n this._show();\r\n }\r\n /**\r\n * Internal show implementation.\r\n * @private\r\n */\r\n _show() {\r\n this.graph.set_size(this.size.w, this.size.h);\r\n this.e_nodes.style.width = this.size.w + 'px';\r\n this.e_nodes.style.height = this.size.h + 'px';\r\n this.show_nodes();\r\n this.show_lines();\r\n //this.layout.cache_valid = true;\r\n this.jm.invoke_event_handle(EventType.resize, { data: [] });\r\n }\r\n /**\r\n * Zoom in the view.\r\n * @param {MouseEvent=} e - Mouse event for zoom center\r\n * @returns {boolean} True if zoom succeeded\r\n */\r\n zoom_in(e) {\r\n return this.set_zoom(this.zoom_current + this.opts.zoom.step, e);\r\n }\r\n /**\r\n * Zoom out the view.\r\n * @param {MouseEvent=} e - Mouse event for zoom center\r\n * @returns {boolean} True if zoom succeeded\r\n */\r\n zoom_out(e) {\r\n return this.set_zoom(this.zoom_current - this.opts.zoom.step, e);\r\n }\r\n /**\r\n * Set zoom level and keep scroll around zoom center.\r\n * @param {number} zoom\r\n * @param {MouseEvent=} e\r\n */\r\n set_zoom(zoom, e) {\r\n if (zoom < this.opts.zoom.min || zoom > this.opts.zoom.max) {\r\n return false;\r\n }\r\n let e_panel_rect = this.e_panel.getBoundingClientRect();\r\n if (\r\n zoom < 1 &&\r\n zoom < this.zoom_current &&\r\n this.size.w * zoom < e_panel_rect.width &&\r\n this.size.h * zoom < e_panel_rect.height\r\n ) {\r\n return false;\r\n }\r\n let zoom_center = !!e\r\n ? { x: e.x - e_panel_rect.x, y: e.y - e_panel_rect.y }\r\n : { x: e_panel_rect.width / 2, y: e_panel_rect.height / 2 };\r\n let panel_scroll_x =\r\n ((this.e_panel.scrollLeft + zoom_center.x) * zoom) / this.zoom_current - zoom_center.x;\r\n let panel_scroll_y =\r\n ((this.e_panel.scrollTop + zoom_center.y) * zoom) / this.zoom_current - zoom_center.y;\r\n\r\n this.zoom_current = zoom;\r\n for (var i = 0; i < this.e_panel.children.length; i++) {\r\n this.e_panel.children[i].style.zoom = zoom;\r\n }\r\n this._show();\r\n this.e_panel.scrollLeft = panel_scroll_x;\r\n this.e_panel.scrollTop = panel_scroll_y;\r\n return true;\r\n }\r\n /** @param {boolean=} keep_center */\r\n show(keep_center) {\r\n logger.debug(`view.show: {keep_center: ${keep_center}}`);\r\n this.expand_size();\r\n this._show();\r\n if (!!keep_center) {\r\n this.center_node(this.jm.mind.root);\r\n }\r\n }\r\n relayout() {\r\n this.expand_size();\r\n this._show();\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n save_location(node) {\r\n var vd = node._data.view;\r\n vd._saved_location = {\r\n x: parseInt(vd.element.style.left) - this.e_panel.scrollLeft,\r\n y: parseInt(vd.element.style.top) - this.e_panel.scrollTop,\r\n };\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n restore_location(node) {\r\n var vd = node._data.view;\r\n this.e_panel.scrollLeft = parseInt(vd.element.style.left) - vd._saved_location.x;\r\n this.e_panel.scrollTop = parseInt(vd.element.style.top) - vd._saved_location.y;\r\n }\r\n clear_nodes() {\r\n var mind = this.jm.mind;\r\n if (mind == null) {\r\n return;\r\n }\r\n var nodes = mind.nodes;\r\n var node = null;\r\n for (var nodeid in nodes) {\r\n node = nodes[nodeid];\r\n node._data.view.element = null;\r\n node._data.view.expander = null;\r\n }\r\n this.e_nodes.innerHTML = '';\r\n }\r\n /** Render node elements and expanders to screen. */\r\n show_nodes() {\r\n var nodes = this.jm.mind.nodes;\r\n var node = null;\r\n var node_element = null;\r\n var p = null;\r\n var view_data = null;\r\n var view_offset = this.get_view_offset();\r\n for (var nodeid in nodes) {\r\n node = nodes[nodeid];\r\n view_data = node._data.view;\r\n node_element = view_data.element;\r\n if (!this.layout.is_visible(node)) {\r\n node_element.style.display = 'none';\r\n view_data.expander.style.display = 'none';\r\n continue;\r\n }\r\n this.reset_node_custom_style(node);\r\n p = this.layout.get_node_point(node);\r\n view_data.abs_x = view_offset.x + p.x;\r\n view_data.abs_y = view_offset.y + p.y;\r\n node_element.style.left = view_offset.x + p.x + 'px';\r\n node_element.style.top = view_offset.y + p.y + 'px';\r\n node_element.style.display = '';\r\n node_element.style.visibility = 'visible';\r\n this._show_expander(node, view_offset);\r\n }\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node @param {{x:number,y:number}} view_offset */\r\n _show_expander(node, view_offset) {\r\n if (node.isroot) {\r\n return;\r\n }\r\n\r\n var expander = node._data.view.expander;\r\n if (node.children.length == 0) {\r\n expander.style.display = 'none';\r\n expander.style.visibility = 'hidden';\r\n return;\r\n }\r\n\r\n let expander_text = this._get_expander_text(node);\r\n $.t(expander, expander_text);\r\n\r\n let p_expander = this.layout.get_expander_point(node);\r\n expander.style.left = view_offset.x + p_expander.x + 'px';\r\n expander.style.top = view_offset.y + p_expander.y + 'px';\r\n expander.style.display = '';\r\n expander.style.visibility = 'visible';\r\n }\r\n\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n _get_expander_text(node) {\r\n let style = !!this.opts.expander_style ? this.opts.expander_style.toLowerCase() : 'char';\r\n if (style === 'number') {\r\n return node.children.length > 99 ? '...' : node.children.length;\r\n }\r\n if (style === 'char') {\r\n return node.expanded ? '-' : '+';\r\n }\r\n }\r\n\r\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\r\n _default_node_render(ele, node) {\r\n if (this.opts.support_html) {\r\n $.h(ele, node.topic);\r\n } else {\r\n $.t(ele, node.topic);\r\n }\r\n }\r\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\r\n _custom_node_render(ele, node) {\r\n let rendered = this.opts.custom_node_render(this.jm, ele, node);\r\n if (!rendered) {\r\n this._default_node_render(ele, node);\r\n }\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n reset_node_custom_style(node) {\r\n this._reset_node_custom_style(node._data.view.element, node.data);\r\n }\r\n /** @param {HTMLElement} node_element @param {Record<string,string|number>} node_data */\r\n _reset_node_custom_style(node_element, node_data) {\r\n if ('background-color' in node_data) {\r\n node_element.style.backgroundColor = node_data['background-color'];\r\n }\r\n if ('foreground-color' in node_data) {\r\n node_element.style.color = node_data['foreground-color'];\r\n }\r\n if ('width' in node_data) {\r\n node_element.style.width = node_data['width'] + 'px';\r\n }\r\n if ('height' in node_data) {\r\n node_element.style.height = node_data['height'] + 'px';\r\n }\r\n if ('font-size' in node_data) {\r\n node_element.style.fontSize = node_data['font-size'] + 'px';\r\n }\r\n if ('font-weight' in node_data) {\r\n node_element.style.fontWeight = node_data['font-weight'];\r\n }\r\n if ('font-style' in node_data) {\r\n node_element.style.fontStyle = node_data['font-style'];\r\n }\r\n if ('background-image' in node_data) {\r\n var backgroundImage = node_data['background-image'];\r\n if (backgroundImage.startsWith('data') && node_data['width'] && node_data['height']) {\r\n var img = new Image();\r\n\r\n img.onload = function () {\r\n var c = $.c('canvas');\r\n c.width = node_element.clientWidth;\r\n c.height = node_element.clientHeight;\r\n var img = this;\r\n if (c.getContext) {\r\n var ctx = c.getContext('2d');\r\n ctx.drawImage(\r\n img,\r\n 2,\r\n 2,\r\n node_element.clientWidth,\r\n node_element.clientHeight\r\n );\r\n var scaledImageData = c.toDataURL();\r\n node_element.style.backgroundImage = 'url(' + scaledImageData + ')';\r\n }\r\n };\r\n img.src = backgroundImage;\r\n } else {\r\n node_element.style.backgroundImage = 'url(' + backgroundImage + ')';\r\n }\r\n node_element.style.backgroundSize = '99%';\r\n\r\n if ('background-rotation' in node_data) {\r\n node_element.style.transform =\r\n 'rotate(' + node_data['background-rotation'] + 'deg)';\r\n }\r\n }\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n restore_selected_node_custom_style(node) {\r\n var node_element = node._data.view.element;\r\n var node_data = node.data;\r\n if ('background-color' in node_data) {\r\n node_element.style.backgroundColor = node_data['background-color'];\r\n }\r\n if ('foreground-color' in node_data) {\r\n node_element.style.color = node_data['foreground-color'];\r\n }\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n clear_selected_node_custom_style(node) {\r\n var node_element = node._data.view.element;\r\n node_element.style.backgroundColor = '';\r\n node_element.style.color = '';\r\n }\r\n /**\r\n * Mark the DOM/state for a selected node.\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @private\r\n */\r\n _mark_node_selected(node) {\r\n if (!node || this.multi_selected_nodes.has(node.id)) {\r\n return;\r\n }\r\n var element = node._data.view.element;\r\n if (!element) {\r\n return;\r\n }\r\n if (!/(\\s|^)selected(\\s|$)/.test(element.className)) {\r\n element.className += ' selected';\r\n }\r\n this.clear_selected_node_custom_style(node);\r\n this.multi_selected_nodes.set(node.id, node);\r\n }\r\n /**\r\n * Remove DOM/state selection for a node.\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @private\r\n */\r\n _unmark_node_selected(node) {\r\n if (!node) {\r\n return;\r\n }\r\n if (this.multi_selected_nodes.has(node.id)) {\r\n var element = node._data.view.element;\r\n if (!!element) {\r\n element.className = element.className.replace(/\\s*selected\\b/i, '');\r\n }\r\n this.restore_selected_node_custom_style(node);\r\n this.multi_selected_nodes.delete(node.id);\r\n }\r\n if (!!this.selected_node && this.selected_node.id == node.id) {\r\n this.selected_node = null;\r\n }\r\n }\r\n clear_lines() {\r\n this.graph.clear();\r\n }\r\n show_lines() {\r\n this.clear_lines();\r\n var nodes = this.jm.mind.nodes;\r\n var node = null;\r\n var pin = null;\r\n var pout = null;\r\n var color = null;\r\n var _offset = this.get_view_offset();\r\n for (var nodeid in nodes) {\r\n node = nodes[nodeid];\r\n if (!!node.isroot) {\r\n continue;\r\n }\r\n if (!this.layout.is_visible(node)) {\r\n continue;\r\n }\r\n pin = this.layout.get_node_point_in(node);\r\n pout = this.layout.get_node_point_out(node.parent);\r\n color = node.data['leading-line-color'];\r\n this.graph.draw_line(pout, pin, _offset, color);\r\n }\r\n }\r\n // Drag the whole mind map with your mouse, when it's larger that the container\r\n /**\r\n * Enable/disable dragging the whole canvas with mouse.\r\n * @param {boolean} enabled\r\n */\r\n setup_canvas_draggable(enabled) {\r\n this.opts.draggable = enabled;\r\n if (!this._initialized) {\r\n let dragging = false;\r\n let x, y;\r\n if (this.opts.hide_scrollbars_when_draggable) {\r\n // Avoid scrollbars when mind map is larger than the container (e_panel = id jsmind-inner)\r\n this.e_panel.style = 'overflow: hidden';\r\n }\r\n // Move the whole mind map with mouse moves, while button is down.\r\n $.on(this.container, 'mousedown', eventDown => {\r\n if (this.opts.draggable) {\r\n dragging = true;\r\n // Record current mouse position.\r\n x = eventDown.clientX;\r\n y = eventDown.clientY;\r\n }\r\n });\r\n // Stop moving mind map once mouse button is released.\r\n $.on(this.container, 'mouseup', () => {\r\n dragging = false;\r\n });\r\n // Follow current mouse position and move mind map accordingly.\r\n $.on(this.container, 'mousemove', eventMove => {\r\n if (this.opts.draggable) {\r\n if (dragging) {\r\n this.e_panel.scrollBy(x - eventMove.clientX, y - eventMove.clientY);\r\n // Record new current position.\r\n x = eventMove.clientX;\r\n y = eventMove.clientY;\r\n }\r\n }\r\n });\r\n }\r\n }\r\n /** @param {import('./jsmind.node.js').Node} node */\r\n center_node(node) {\r\n if (!this.layout.is_visible(node)) {\r\n logger.warn('can not scroll to the node, because it is invisible');\r\n return false;\r\n }\r\n let view_data = node._data.view;\r\n let e_panel_rect = this.e_panel.getBoundingClientRect();\r\n let node_center_point = {\r\n x: view_data.abs_x + view_data.width / 2,\r\n y: view_data.abs_y + view_data.height / 2,\r\n };\r\n this.e_panel.scrollTo(\r\n node_center_point.x * this.zoom_current - e_panel_rect.width / 2,\r\n node_center_point.y * this.zoom_current - e_panel_rect.height / 2\r\n );\r\n return true;\r\n }\r\n\r\n /** @param {MouseEvent=} e */\r\n zoomIn(e) {\r\n logger.warn('please use zoom_in instead');\r\n return this.zoom_in(e);\r\n }\r\n /** @param {MouseEvent=} e */\r\n zoomOut(e) {\r\n logger.warn('please use zoom_out instead');\r\n return this.zoom_out(e);\r\n }\r\n /** @param {number} zoom @param {MouseEvent=} e */\r\n setZoom(zoom, e) {\r\n logger.warn('please use set_zoom instead');\r\n return this.set_zoom(zoom, e);\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { $ } from './jsmind.dom.js';\r\nimport { util } from './jsmind.util.js';\r\nimport { Direction } from './jsmind.common.js';\r\n\r\nexport class ShortcutProvider {\r\n /**\r\n * @param {import('./jsmind.js').default} jm\r\n * @param {{ enable:boolean, handles: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping: Record<string, number|number[]>, id_generator?: ()=>string }} options\r\n */\r\n constructor(jm, options) {\r\n this.jm = jm;\r\n this.opts = options;\r\n /** @type {Record<string, number|number[]>} */\r\n this.mapping = options.mapping;\r\n /** @type {Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\r\n this.handles = options.handles;\r\n /** @type {()=>string|null} */\r\n this._newid = null;\r\n /** @type {Record<number,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\r\n this._mapping = {};\r\n }\r\n init() {\r\n $.on(this.jm.view.e_panel, 'keydown', this.handler.bind(this));\r\n\r\n this.handles['addchild'] = this.handle_addchild;\r\n this.handles['addbrother'] = this.handle_addbrother;\r\n this.handles['editnode'] = this.handle_editnode;\r\n this.handles['delnode'] = this.handle_delnode;\r\n this.handles['toggle'] = this.handle_toggle;\r\n this.handles['up'] = this.handle_up;\r\n this.handles['down'] = this.handle_down;\r\n this.handles['left'] = this.handle_left;\r\n this.handles['right'] = this.handle_right;\r\n\r\n for (var handle in this.mapping) {\r\n if (!!this.mapping[handle] && handle in this.handles) {\r\n let keys = this.mapping[handle];\r\n if (!Array.isArray(keys)) {\r\n keys = [keys];\r\n }\r\n for (let key of keys) {\r\n this._mapping[key] = this.handles[handle];\r\n }\r\n }\r\n }\r\n\r\n if (typeof this.opts.id_generator === 'function') {\r\n this._newid = this.opts.id_generator;\r\n } else {\r\n this._newid = util.uuid.newid;\r\n }\r\n }\r\n enable_shortcut() {\r\n this.opts.enable = true;\r\n }\r\n disable_shortcut() {\r\n this.opts.enable = false;\r\n }\r\n /** @param {KeyboardEvent} e */\r\n handler(e) {\r\n if (e.which == 9) {\r\n e.preventDefault();\r\n } //prevent tab to change focus in browser\r\n if (this.jm.view.is_editing()) {\r\n return;\r\n }\r\n var evt = e || event;\r\n if (!this.opts.enable) {\r\n return true;\r\n }\r\n var kc =\r\n evt.keyCode +\r\n (evt.metaKey << 13) +\r\n (evt.ctrlKey << 12) +\r\n (evt.altKey << 11) +\r\n (evt.shiftKey << 10);\r\n if (kc in this._mapping) {\r\n this._mapping[kc].call(this, this.jm, e);\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_addchild(_jm, e) {\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node) {\r\n var node_id = this._newid();\r\n var node = _jm.add_node(selected_node, node_id, 'New Node');\r\n if (!!node) {\r\n _jm.select_node(node_id);\r\n _jm.begin_edit(node_id);\r\n }\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_addbrother(_jm, e) {\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node && !selected_node.isroot) {\r\n var node_id = this._newid();\r\n var node = _jm.insert_node_after(selected_node, node_id, 'New Node');\r\n if (!!node) {\r\n _jm.select_node(node_id);\r\n _jm.begin_edit(node_id);\r\n }\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_editnode(_jm, e) {\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node) {\r\n _jm.begin_edit(selected_node);\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_delnode(_jm, e) {\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node && !selected_node.isroot) {\r\n _jm.select_node(selected_node.parent);\r\n _jm.remove_node(selected_node);\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_toggle(_jm, e) {\r\n var evt = e || event;\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node) {\r\n _jm.toggle_node(selected_node.id);\r\n evt.stopPropagation();\r\n evt.preventDefault();\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_up(_jm, e) {\r\n var evt = e || event;\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node) {\r\n var up_node = _jm.find_node_before(selected_node);\r\n if (!up_node) {\r\n var np = _jm.find_node_before(selected_node.parent);\r\n if (!!np && np.children.length > 0) {\r\n up_node = np.children[np.children.length - 1];\r\n }\r\n }\r\n if (!!up_node) {\r\n _jm.select_node(up_node);\r\n }\r\n evt.stopPropagation();\r\n evt.preventDefault();\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_down(_jm, e) {\r\n var evt = e || event;\r\n var selected_node = _jm.get_selected_node();\r\n if (!!selected_node) {\r\n var down_node = _jm.find_node_after(selected_node);\r\n if (!down_node) {\r\n var np = _jm.find_node_after(selected_node.parent);\r\n if (!!np && np.children.length > 0) {\r\n down_node = np.children[0];\r\n }\r\n }\r\n if (!!down_node) {\r\n _jm.select_node(down_node);\r\n }\r\n evt.stopPropagation();\r\n evt.preventDefault();\r\n }\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_left(_jm, e) {\r\n this._handle_direction(_jm, e, Direction.left);\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\r\n handle_right(_jm, e) {\r\n this._handle_direction(_jm, e, Direction.right);\r\n }\r\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e @param {number} d */\r\n _handle_direction(_jm, e, d) {\r\n var evt = e || event;\r\n var selected_node = _jm.get_selected_node();\r\n var node = null;\r\n if (!!selected_node) {\r\n if (selected_node.isroot) {\r\n var c = selected_node.children;\r\n var children = [];\r\n for (var i = 0; i < c.length; i++) {\r\n if (c[i].direction === d) {\r\n children.push(i);\r\n }\r\n }\r\n node = c[children[Math.floor((children.length - 1) / 2)]];\r\n } else if (selected_node.direction === d) {\r\n var children = selected_node.children;\r\n var children_count = children.length;\r\n if (children_count > 0) {\r\n node = children[Math.floor((children_count - 1) / 2)];\r\n }\r\n } else {\r\n node = selected_node.parent;\r\n }\r\n if (!!node) {\r\n _jm.select_node(node);\r\n }\r\n evt.stopPropagation();\r\n evt.preventDefault();\r\n }\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { $ } from './jsmind.dom.js';\r\n\r\n/** @type {{ plugins: Array<Plugin<object>> }} */\r\nconst plugin_data = {\r\n plugins: [],\r\n};\r\n\r\n/**\r\n * Register a plugin instance.\r\n * @param {Plugin<object>} plugin\r\n */\r\nexport function register(plugin) {\r\n if (!(plugin instanceof Plugin)) {\r\n throw new Error('can not register plugin, it is not an instance of Plugin');\r\n }\r\n if (plugin_data.plugins.map(p => p.name).includes(plugin.name)) {\r\n throw new Error('can not register plugin ' + plugin.name + ': plugin name already exist');\r\n }\r\n plugin_data.plugins.push(plugin);\r\n}\r\n\r\n/**\r\n * Apply registered plugins asynchronously.\r\n * @param {import('./jsmind.js').default} jm\r\n * @param {Record<string, object>} options\r\n */\r\nexport function apply(jm, options) {\r\n $.w.setTimeout(function () {\r\n _apply(jm, options);\r\n }, 0);\r\n}\r\n\r\n/**\r\n * @param {import('./jsmind.js').default} jm\r\n * @param {Record<string, object>} options */\r\nfunction _apply(jm, options) {\r\n plugin_data.plugins.forEach(p => p.fn_init(jm, options[p.name]));\r\n}\r\n\r\nexport class Plugin {\r\n /**\r\n * @template [TOptions=object]\r\n * @param {string} name\r\n * @param {(jm: import('./jsmind.js').default, options: TOptions)=>void} fn_init\r\n */\r\n constructor(name, fn_init) {\r\n if (!name) {\r\n throw new Error('plugin must has a name');\r\n }\r\n if (!fn_init || typeof fn_init !== 'function') {\r\n throw new Error('plugin must has an init function');\r\n }\r\n this.name = name;\r\n this.fn_init = fn_init;\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { logger } from './jsmind.common.js';\r\n\r\n/**\r\n * Enhanced Plugin Manager\r\n * Manages the lifecycle of enhanced plugins with synchronous initialization,\r\n * preload support, and lifecycle hooks.\r\n */\r\nexport class EnhancedPluginManager {\r\n /**\r\n * @param {import('./jsmind.js').default} jm - jsMind instance\r\n */\r\n constructor(jm) {\r\n this.jm = jm;\r\n /** @type {Map<string, EnhancedPlugin>} */\r\n this.plugins = new Map();\r\n }\r\n\r\n /**\r\n * Initialize preload plugins (before core modules)\r\n */\r\n initPreloadPlugins() {\r\n const preloadPlugins = this.jm.constructor.enhancedPluginList.filter(d => d.preload);\r\n logger.info('Initializing ' + preloadPlugins.length + ' preload plugins');\r\n preloadPlugins.forEach(descriptor => {\r\n this._initPlugin(descriptor);\r\n });\r\n }\r\n\r\n /**\r\n * Initialize normal plugins (after core modules)\r\n */\r\n initNormalPlugins() {\r\n const normalPlugins = this.jm.constructor.enhancedPluginList.filter(d => !d.preload);\r\n logger.info('Initializing ' + normalPlugins.length + ' normal plugins');\r\n normalPlugins.forEach(descriptor => {\r\n this._initPlugin(descriptor);\r\n });\r\n }\r\n\r\n /**\r\n * Internal method: Initialize a single plugin\r\n * @param {PluginDescriptor} descriptor\r\n * @private\r\n */\r\n _initPlugin(descriptor) {\r\n try {\r\n const { PluginClass, pluginOpt } = descriptor;\r\n\r\n // Check instanceName\r\n if (!PluginClass.instanceName) {\r\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\r\n }\r\n\r\n // Check naming conflict\r\n if (this.plugins.has(PluginClass.instanceName)) {\r\n logger.warn(\r\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\r\n );\r\n }\r\n\r\n // Instantiate plugin\r\n const instance = new PluginClass({\r\n jm: this.jm,\r\n pluginOpt: pluginOpt || {},\r\n });\r\n\r\n // Save instance\r\n this.plugins.set(PluginClass.instanceName, instance);\r\n this.jm[PluginClass.instanceName] = instance;\r\n descriptor.instance = instance;\r\n\r\n logger.info('Enhanced plugin ' + PluginClass.instanceName + ' initialized');\r\n } catch (error) {\r\n logger.error('Failed to initialize plugin ' + descriptor.PluginClass.name + ':', error);\r\n }\r\n }\r\n\r\n /**\r\n * Remove a plugin\r\n * @param {typeof EnhancedPlugin} PluginClass\r\n */\r\n removePlugin(PluginClass) {\r\n const instanceName = PluginClass.instanceName;\r\n if (!instanceName) {\r\n return;\r\n }\r\n\r\n const instance = this.plugins.get(instanceName);\r\n if (!instance) {\r\n return;\r\n }\r\n\r\n try {\r\n // Call lifecycle hook\r\n if (typeof instance.beforePluginRemove === 'function') {\r\n instance.beforePluginRemove();\r\n }\r\n\r\n // Remove from Map\r\n this.plugins.delete(instanceName);\r\n\r\n // Remove from jsMind instance\r\n delete this.jm[instanceName];\r\n\r\n // Remove from plugin list\r\n const list = this.jm.constructor.enhancedPluginList;\r\n const index = list.findIndex(d => d.PluginClass === PluginClass);\r\n if (index !== -1) {\r\n list.splice(index, 1);\r\n }\r\n\r\n logger.info('Enhanced plugin ' + instanceName + ' removed');\r\n } catch (error) {\r\n logger.error('Failed to remove plugin ' + instanceName + ':', error);\r\n }\r\n }\r\n\r\n /**\r\n * Destroy all plugins\r\n */\r\n destroyAllPlugins() {\r\n this.plugins.forEach((instance, instanceName) => {\r\n try {\r\n // Call lifecycle hook\r\n if (typeof instance.beforePluginDestroy === 'function') {\r\n instance.beforePluginDestroy();\r\n }\r\n } catch (error) {\r\n logger.error('Failed to destroy plugin ' + instanceName + ':', error);\r\n }\r\n });\r\n\r\n this.plugins.clear();\r\n }\r\n\r\n /**\r\n * Get plugin instance by name\r\n * @param {string} instanceName\r\n * @returns {EnhancedPlugin | undefined}\r\n */\r\n getPlugin(instanceName) {\r\n return this.plugins.get(instanceName);\r\n }\r\n}\r\n\r\n/**\r\n * Enhanced Plugin Base Class\r\n * Provides standard interface for enhanced plugins\r\n */\r\nexport class EnhancedPlugin {\r\n /**\r\n * Plugin instance name (must be defined by subclass)\r\n * @type {string}\r\n */\r\n static instanceName = '';\r\n\r\n /**\r\n * Whether to initialize before core modules\r\n * @type {boolean}\r\n */\r\n static preload = false;\r\n\r\n /**\r\n * @param {{ jm: import('./jsmind.js').default, pluginOpt: object }} params\r\n */\r\n constructor({ jm, pluginOpt }) {\r\n this.jm = jm;\r\n this.options = pluginOpt || {};\r\n }\r\n\r\n /**\r\n * Called before plugin is removed\r\n * Override this method to clean up resources\r\n */\r\n beforePluginRemove() {\r\n // Default implementation: do nothing\r\n }\r\n\r\n /**\r\n * Called before jsMind instance is destroyed\r\n * Override this method to clean up resources\r\n */\r\n beforePluginDestroy() {\r\n // Default implementation: call beforePluginRemove\r\n this.beforePluginRemove();\r\n }\r\n}\r\n\r\n/**\r\n * Plugin descriptor\r\n * @typedef {object} PluginDescriptor\r\n * @property {typeof EnhancedPlugin} PluginClass - Plugin class\r\n * @property {string} instanceName - Plugin instance name\r\n * @property {boolean} preload - Whether to preload\r\n * @property {object} pluginOpt - Plugin options\r\n * @property {EnhancedPlugin | null} instance - Plugin instance (after initialization)\r\n */\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { __version__, logger, EventType, Direction, LogLevel } from './jsmind.common.js';\r\nimport { merge_option } from './jsmind.option.js';\r\nimport { Mind } from './jsmind.mind.js';\r\nimport { Node } from './jsmind.node.js';\r\nimport { DataProvider } from './jsmind.data_provider.js';\r\nimport { LayoutProvider } from './jsmind.layout_provider.js';\r\nimport { ViewProvider } from './jsmind.view_provider.js';\r\nimport { ShortcutProvider } from './jsmind.shortcut_provider.js';\r\nimport { Plugin, register as _register_plugin, apply as apply_plugins } from './jsmind.plugin.js';\r\nimport { EnhancedPluginManager, EnhancedPlugin } from './jsmind.enhanced-plugin.js';\r\nimport { format } from './jsmind.format.js';\r\nimport { $ } from './jsmind.dom.js';\r\nimport { util as _util } from './jsmind.util.js';\r\n\r\n/**\r\n * Event callback payload\r\n * @typedef {{ evt?: string, data?: unknown[], node?: string }} EventData\r\n */\r\n\r\n/**\r\n * jsMind runtime: orchestrates data/layout/view/shortcut and exposes public API.\r\n */\r\nexport default class jsMind {\r\n static mind = Mind;\r\n static node = Node;\r\n static direction = Direction;\r\n static event_type = EventType;\r\n static $ = $;\r\n static plugin = Plugin;\r\n static register_plugin = _register_plugin;\r\n static util = _util;\r\n static enhanced_plugin = EnhancedPlugin;\r\n\r\n /** @type {Array<import('./jsmind.enhanced-plugin.js').PluginDescriptor>} */\r\n static enhancedPluginList = [];\r\n\r\n /**\r\n * Register an enhanced plugin\r\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\r\n * @param {object} [options={}] - Plugin options\r\n * @returns {typeof jsMind}\r\n */\r\n static usePlugin(PluginClass, options = {}) {\r\n // Check if already registered\r\n const exists = jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\r\n if (exists) {\r\n logger.warn('Plugin ' + PluginClass.name + ' already registered');\r\n return jsMind;\r\n }\r\n\r\n // Check instanceName\r\n if (!PluginClass.instanceName) {\r\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\r\n }\r\n\r\n // Add to plugin list\r\n jsMind.enhancedPluginList.push({\r\n PluginClass,\r\n instanceName: PluginClass.instanceName,\r\n preload: PluginClass.preload || false,\r\n pluginOpt: options,\r\n instance: null,\r\n });\r\n\r\n return jsMind;\r\n }\r\n\r\n /**\r\n * Check if an enhanced plugin is registered\r\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\r\n * @returns {boolean}\r\n */\r\n static hasEnhancedPlugin(PluginClass) {\r\n return jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\r\n }\r\n\r\n /**\r\n * Create a jsMind instance.\r\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\r\n */\r\n constructor(options) {\r\n jsMind.current = this;\r\n this.options = merge_option(options);\r\n logger.level(LogLevel[this.options.log_level]);\r\n this.version = __version__;\r\n this.initialized = false;\r\n this.mind = null;\r\n /** @type {'single'|'multi'|null} */\r\n this._selection_mode = null;\r\n /** @type {import('./jsmind.node.js').Node|null} */\r\n this._last_selected_node = null;\r\n /** @type {Array<(type: number, data: EventData) => void>} */\r\n this.event_handles = [];\r\n this.init();\r\n }\r\n\r\n /** Initialize sub-systems and plugins. */\r\n init() {\r\n if (!!this.initialized) {\r\n return;\r\n }\r\n this.initialized = true;\r\n\r\n // Initialize enhanced plugin manager\r\n this.enhancedPluginManager = new EnhancedPluginManager(this);\r\n\r\n // Initialize preload plugins (before core modules)\r\n this.enhancedPluginManager.initPreloadPlugins();\r\n\r\n var opts_layout = {\r\n mode: this.options.mode,\r\n hspace: this.options.layout.hspace,\r\n vspace: this.options.layout.vspace,\r\n pspace: this.options.layout.pspace,\r\n cousin_space: this.options.layout.cousin_space,\r\n };\r\n var opts_view = {\r\n container: this.options.container,\r\n support_html: this.options.support_html,\r\n engine: this.options.view.engine,\r\n enable_device_pixel_ratio: this.options.view.enable_device_pixel_ratio,\r\n hmargin: this.options.view.hmargin,\r\n vmargin: this.options.view.vmargin,\r\n line_width: this.options.view.line_width,\r\n line_color: this.options.view.line_color,\r\n line_style: this.options.view.line_style,\r\n custom_line_render: this.options.view.custom_line_render,\r\n draggable: this.options.view.draggable,\r\n hide_scrollbars_when_draggable: this.options.view.hide_scrollbars_when_draggable,\r\n node_overflow: this.options.view.node_overflow,\r\n zoom: this.options.view.zoom,\r\n custom_node_render: this.options.view.custom_node_render,\r\n expander_style: this.options.view.expander_style,\r\n };\r\n // create instance of function provider\r\n this.data = new DataProvider(this);\r\n this.layout = new LayoutProvider(this, opts_layout);\r\n this.view = new ViewProvider(this, opts_view);\r\n this.shortcut = new ShortcutProvider(this, this.options.shortcut);\r\n\r\n this.data.init();\r\n this.layout.init();\r\n this.view.init();\r\n this.shortcut.init();\r\n\r\n this._event_bind();\r\n\r\n // Initialize normal plugins (after core modules)\r\n this.enhancedPluginManager.initNormalPlugins();\r\n\r\n // Apply old plugins (asynchronously)\r\n apply_plugins(this, this.options.plugin);\r\n }\r\n /** @returns {boolean} whether current mind map is editable */\r\n get_editable() {\r\n return this.options.editable;\r\n }\r\n /** enable editing */\r\n enable_edit() {\r\n this.options.editable = true;\r\n }\r\n /** disable editing */\r\n disable_edit() {\r\n this.options.editable = false;\r\n }\r\n /** @returns {boolean} whether view is draggable */\r\n get_view_draggable() {\r\n return this.options.view.draggable;\r\n }\r\n /** enable view dragging */\r\n enable_view_draggable() {\r\n this.options.view.draggable = true;\r\n this.view.setup_canvas_draggable(true);\r\n }\r\n /** disable view dragging */\r\n disable_view_draggable() {\r\n this.options.view.draggable = false;\r\n this.view.setup_canvas_draggable(false);\r\n }\r\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\r\n /**\r\n * Enable default event handle.\r\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\r\n */\r\n enable_event_handle(event_handle) {\r\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = true;\r\n }\r\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\r\n /**\r\n * Disable default event handle.\r\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\r\n */\r\n disable_event_handle(event_handle) {\r\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = false;\r\n }\r\n /**\r\n * Set theme name.\r\n * @param {string|null=} theme\r\n */\r\n set_theme(theme) {\r\n var theme_old = this.options.theme;\r\n this.options.theme = !!theme ? theme : null;\r\n if (theme_old != this.options.theme) {\r\n this.view.reset_theme();\r\n this.view.reset_custom_style();\r\n }\r\n }\r\n /** bind internal DOM events */\r\n _event_bind() {\r\n this.view.add_event(this, 'mousedown', this.mousedown_handle);\r\n this.view.add_event(this, 'click', this.click_handle);\r\n this.view.add_event(this, 'dblclick', this.dblclick_handle);\r\n this.view.add_event(this, 'wheel', this.mousewheel_handle, true);\r\n }\r\n /** @param {MouseEvent} e */\r\n mousedown_handle(e) {\r\n if (!this.options.default_event_handle['enable_mousedown_handle']) {\r\n return;\r\n }\r\n var element = e.target || event.srcElement;\r\n var node_id = this.view.get_binded_nodeid(element);\r\n var mode = this._get_multi_select_mode(e);\r\n if (!!node_id) {\r\n if (this.view.is_node(element)) {\r\n if (mode === 'ctrl') {\r\n // Ctrl/Cmd + Click: toggle single node (add/remove only this node)\r\n this._toggle_node_selection(node_id);\r\n } else if (mode === 'shift') {\r\n // Shift+Click behavior:\r\n // - Default (shift_simple_mode=false): select ONLY the clicked node and ALL its descendants (no siblings)\r\n // - When shift_simple_mode=true: enable range mode (may include sibling branches per anchor..target)\r\n if (this.options.selection && this.options.selection.shift_simple_mode) {\r\n // Range mode\r\n if (this.is_node_selected(node_id)) {\r\n this._deselect_subtree(node_id);\r\n } else {\r\n this._range_select_nodes(node_id);\r\n }\r\n } else {\r\n // Simple subtree mode (default)\r\n var base = this.get_node(node_id);\r\n if (base) {\r\n if (this.is_node_selected(node_id)) {\r\n this._deselect_subtree(node_id);\r\n } else {\r\n var nodes_to_add = this._collect_subtree_nodes(base, {\r\n includeChildren: true,\r\n respectFilter: true,\r\n skipRootFilter: true,\r\n });\r\n if (!nodes_to_add.length) {\r\n nodes_to_add = [base];\r\n }\r\n var added = this._append_selection(nodes_to_add, { focusNode: base });\r\n if (added.length) {\r\n this.mind.selected = base;\r\n this._last_selected_node = base;\r\n this._selection_mode = this._derive_selection_mode();\r\n var addedIds = added.map(function (n) { return n.id; });\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_select',\r\n data: addedIds,\r\n node: base.id,\r\n nodes: addedIds,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Single click: clear all and select this node only\r\n this.select_node(node_id);\r\n }\r\n }\r\n } else if (mode === null) {\r\n // Only clear selection if no modifier keys\r\n this.select_clear();\r\n }\r\n }\r\n /** @param {MouseEvent} e */\r\n click_handle(e) {\r\n if (!this.options.default_event_handle['enable_click_handle']) {\r\n return;\r\n }\r\n var element = e.target || event.srcElement;\r\n var is_expander = this.view.is_expander(element);\r\n if (is_expander) {\r\n var node_id = this.view.get_binded_nodeid(element);\r\n if (!!node_id) {\r\n this.toggle_node(node_id);\r\n }\r\n }\r\n }\r\n /** @param {MouseEvent} e */\r\n dblclick_handle(e) {\r\n if (!this.options.default_event_handle['enable_dblclick_handle']) {\r\n return;\r\n }\r\n if (this.get_editable()) {\r\n var element = e.target || event.srcElement;\r\n var is_node = this.view.is_node(element);\r\n if (is_node) {\r\n var node_id = this.view.get_binded_nodeid(element);\r\n if (!!node_id) {\r\n this.begin_edit(node_id);\r\n }\r\n }\r\n }\r\n }\r\n // Use [Ctrl] + Mousewheel, to zoom in/out.\r\n /** @param {WheelEvent} e */\r\n mousewheel_handle(e) {\r\n // Test if mousewheel option is enabled and Ctrl key is pressed.\r\n var kc = (e.metaKey << 13) + (e.ctrlKey << 12) + (e.altKey << 11) + (e.shiftKey << 10);\r\n if (\r\n !this.options.default_event_handle['enable_mousewheel_handle'] ||\r\n this.options.view.zoom.mask_key !== kc\r\n ) {\r\n return;\r\n }\r\n var evt = e || event;\r\n // Avoid default page scrolling behavior.\r\n evt.preventDefault();\r\n\r\n if (evt.deltaY < 0) {\r\n this.view.zoom_in(evt); // wheel down\r\n } else {\r\n this.view.zoom_out(evt);\r\n }\r\n }\r\n /**\r\n * Begin editing a node.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {boolean|void}\r\n */\r\n begin_edit(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return false;\r\n } else {\r\n return this.begin_edit(the_node);\r\n }\r\n }\r\n if (this.get_editable()) {\r\n this.view.edit_node_begin(node);\r\n } else {\r\n logger.error('fail, this mind map is not editable.');\r\n return;\r\n }\r\n }\r\n /** End editing */\r\n end_edit() {\r\n this.view.edit_node_end();\r\n }\r\n /**\r\n * Toggle a node's expanded state.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {void}\r\n */\r\n toggle_node(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n this.toggle_node(the_node);\r\n return;\r\n }\r\n }\r\n if (node.isroot) {\r\n return;\r\n }\r\n this.view.save_location(node);\r\n this.layout.toggle_node(node);\r\n this.view.relayout();\r\n this.view.restore_location(node);\r\n }\r\n /**\r\n * Expand a node.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {void}\r\n */\r\n expand_node(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n this.expand_node(the_node);\r\n return;\r\n }\r\n }\r\n if (node.isroot) {\r\n return;\r\n }\r\n this.view.save_location(node);\r\n this.layout.expand_node(node);\r\n this.view.relayout();\r\n this.view.restore_location(node);\r\n }\r\n /**\r\n * Collapse a node.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {void}\r\n */\r\n collapse_node(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n this.collapse_node(the_node);\r\n return;\r\n }\r\n }\r\n if (node.isroot) {\r\n return;\r\n }\r\n this.view.save_location(node);\r\n this.layout.collapse_node(node);\r\n this.view.relayout();\r\n this.view.restore_location(node);\r\n }\r\n /** Expand all nodes */\r\n expand_all() {\r\n this.layout.expand_all();\r\n this.view.relayout();\r\n }\r\n /** Collapse all nodes */\r\n collapse_all() {\r\n this.layout.collapse_all();\r\n this.view.relayout();\r\n }\r\n /**\r\n * Expand nodes up to a specified depth level.\r\n * @param {number} depth\r\n */\r\n expand_to_depth(depth) {\r\n this.layout.expand_to_depth(depth);\r\n this.view.relayout();\r\n }\r\n /** reset view/layout/data */\r\n _reset() {\r\n this.invoke_event_handle(EventType.reset, { data: [] });\r\n this.view.reset();\r\n this.layout.reset();\r\n this.data.reset();\r\n }\r\n /**\r\n * Internal show flow.\r\n * @param {object | null} mind\r\n * @param {boolean=} skip_centering\r\n */\r\n _show(mind, skip_centering) {\r\n var m = mind || format.node_array.example;\r\n this.mind = this.data.load(m);\r\n if (!this.mind) {\r\n logger.error('data.load error');\r\n return;\r\n } else {\r\n logger.debug('data.load ok');\r\n }\r\n\r\n this.view.load();\r\n logger.debug('view.load ok');\r\n\r\n this.layout.layout();\r\n logger.debug('layout.layout ok');\r\n\r\n this.view.show(!skip_centering);\r\n logger.debug('view.show ok');\r\n\r\n this.invoke_event_handle(EventType.show, { data: [mind] });\r\n }\r\n /**\r\n * Show a mind (or example) on the canvas.\r\n * @param {object | null} mind\r\n * @param {boolean=} skip_centering\r\n */\r\n show(mind, skip_centering) {\r\n this._reset();\r\n this._show(mind, skip_centering);\r\n }\r\n /** @returns {{name:string,author:string,version:string}} */\r\n get_meta() {\r\n return {\r\n name: this.mind.name,\r\n author: this.mind.author,\r\n version: this.mind.version,\r\n };\r\n }\r\n /**\r\n * Serialize current mind to given format.\r\n * @param {'node_tree'|'node_array'|'freemind'|'text'} [data_format]\r\n * @returns {object}\r\n */\r\n get_data(data_format) {\r\n var df = data_format || 'node_tree';\r\n return this.data.get_data(df);\r\n }\r\n /** @returns {import('./jsmind.node.js').Node} */\r\n get_root() {\r\n return this.mind.root;\r\n }\r\n /**\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {import('./jsmind.node.js').Node}\r\n */\r\n get_node(node) {\r\n if (Node.is_node(node)) {\r\n return node;\r\n }\r\n return this.mind.get_node(node);\r\n }\r\n /**\r\n * Get the level/depth of a node in the mind map.\r\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\r\n * @returns {number} Node level (root node is 0, its children are 1, etc.)\r\n */\r\n get_node_level(node) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.warn('the node[id=' + node + '] can not be found.');\r\n return -1;\r\n }\r\n\r\n // Root node is at level 0\r\n if (the_node.isroot) {\r\n return 0;\r\n }\r\n\r\n var level = 0;\r\n var current = the_node;\r\n\r\n // Traverse up to root node, counting levels\r\n while (current.parent && !current.parent.isroot) {\r\n level++;\r\n current = current.parent;\r\n }\r\n\r\n // Add 1 for children of root node\r\n return level + 1;\r\n }\r\n /**\r\n * Add node data to the mind map without triggering UI refresh.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node} parent_node\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n */\r\n _add_node_data(parent_node, node_id, topic, data, direction) {\r\n var dir = Direction.of(direction);\r\n if (dir === undefined) {\r\n dir = this.layout.calculate_next_child_direction(parent_node);\r\n }\r\n\r\n var node = this.mind.add_node(parent_node, node_id, topic, data, dir);\r\n if (!!node) {\r\n this.view.add_node(node);\r\n this.view.reset_node_custom_style(node);\r\n }\r\n return node;\r\n }\r\n\r\n /**\r\n * Refresh UI after node changes.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node} parent_node\r\n */\r\n _refresh_node_ui(parent_node) {\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.expand_node(parent_node);\r\n }\r\n\r\n /**\r\n * Add a new node to the mind map.\r\n * @param {string | import('./jsmind.node.js').Node} parent_node\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n */\r\n add_node(parent_node, node_id, topic, data, direction) {\r\n if (!this.get_editable()) {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n\r\n var the_parent_node = this.get_node(parent_node);\r\n if (!the_parent_node) {\r\n logger.error('parent node not found');\r\n return null;\r\n }\r\n\r\n var node = this._add_node_data(the_parent_node, node_id, topic, data, direction);\r\n if (!!node) {\r\n this._refresh_node_ui(the_parent_node);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'add_node',\r\n data: [the_parent_node.id, node_id, topic, data, Direction.of(direction)],\r\n node: node_id,\r\n });\r\n }\r\n return node;\r\n }\r\n\r\n /**\r\n * Add multiple nodes in batch.\r\n *\r\n * This method provides atomic batch node creation with automatic rollback on failure.\r\n * All nodes are created in a single operation, and if any node fails to create,\r\n * all previously created nodes in this batch will be automatically removed.\r\n *\r\n * **Note**: This is a batch operation API that uses standard field names only.\r\n * For data import with custom fieldNames, use `show()` instead.\r\n *\r\n * @example\r\n * // Using standard field names\r\n * jm.add_nodes('parent_id', [\r\n * { id: 'node1', topic: 'Node 1', data: { color: 'red' }, children: [\r\n * { id: 'node1-1', topic: 'Child 1' }\r\n * ]}\r\n * ]);\r\n *\r\n * @param {string | import('./jsmind.node.js').Node} parent_node - Parent node for all new nodes\r\n * @param {Array<{id: string, topic: string, data?: Record<string, any>, direction?: ('left'|'center'|'right'|'-1'|'0'|'1'|number), children?: Array}>} nodes_data - Array of node data objects with standard field names (id, topic, children, data, direction)\r\n * @returns {Array<import('./jsmind.node.js').Node|null>} Array of created nodes (flattened from all levels)\r\n */\r\n add_nodes(parent_node, nodes_data) {\r\n if (!this.get_editable()) {\r\n logger.error('fail, this mind map is not editable');\r\n return [];\r\n }\r\n\r\n var the_parent_node = this.get_node(parent_node);\r\n if (!the_parent_node) {\r\n logger.error('parent node not found');\r\n return [];\r\n }\r\n\r\n if (!Array.isArray(nodes_data) || nodes_data.length === 0) {\r\n logger.warn('nodes_data should be a non-empty array');\r\n return [];\r\n }\r\n\r\n const expected_count = this._count_expected_nodes(nodes_data);\r\n let created_nodes = nodes_data\r\n .map(node_data => this._add_nodes_recursive(the_parent_node, node_data))\r\n .flat()\r\n .filter(n => n !== null);\r\n\r\n const actual_count = created_nodes.length;\r\n\r\n // Atomic operation: either all nodes succeed or cleanup all partial nodes\r\n if (actual_count === expected_count) {\r\n // All nodes created successfully, refresh UI\r\n this._refresh_node_ui(the_parent_node);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'add_nodes',\r\n data: [the_parent_node.id, nodes_data],\r\n nodes: created_nodes.map(node => node.id),\r\n });\r\n return created_nodes;\r\n } else {\r\n // Cleanup partially created nodes to ensure atomicity\r\n logger.warn(\r\n `Expected ${expected_count} nodes, but only created ${actual_count}. Cleaning up...`\r\n );\r\n this._cleanup_partial_nodes(created_nodes);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Recursively add nodes using standard field names.\r\n * This is a batch operation API that uses standard field names only.\r\n * For data import with custom fieldNames, use `show()` instead.\r\n * @private\r\n * @param {import('./jsmind.node.js').Node} parent_node\r\n * @param {object} node_data - Node data object with standard field names (id, topic, children, data, direction)\r\n * @returns {Array<import('./jsmind.node.js').Node|null>}\r\n */\r\n _add_nodes_recursive(parent_node, node_data) {\r\n var created_nodes = [];\r\n\r\n // Validate required fields (using standard field names only)\r\n if (!node_data.id || !node_data.topic) {\r\n logger.warn('invalid node data:', node_data);\r\n return [];\r\n }\r\n\r\n // Create the node using standard field names\r\n var new_node = this._add_node_data(\r\n parent_node,\r\n node_data.id,\r\n node_data.topic,\r\n node_data.data || {},\r\n node_data.direction\r\n );\r\n\r\n if (new_node) {\r\n created_nodes.push(new_node);\r\n // Process children using standard field name\r\n if (Array.isArray(node_data.children)) {\r\n const sub_nodes = node_data.children\r\n .map(child => this._add_nodes_recursive(new_node, child))\r\n .flat();\r\n created_nodes = created_nodes.concat(sub_nodes);\r\n }\r\n }\r\n\r\n return created_nodes;\r\n }\r\n\r\n /**\r\n * Count expected nodes recursively.\r\n * Supports custom field names via options.fieldNames configuration.\r\n * @private\r\n * @param {Array} nodes_data\r\n * @returns {number}\r\n */\r\n _count_expected_nodes(nodes_data) {\r\n if (!Array.isArray(nodes_data)) {\r\n return 0;\r\n }\r\n\r\n // Get field names from options (support custom field names)\r\n var fn = this.options.fieldNames || {};\r\n var childrenKey = fn.children || 'children';\r\n\r\n return nodes_data.reduce((count, node_data) => {\r\n count++; // Count current node\r\n // Use custom children field name\r\n count += this._count_expected_nodes(node_data && node_data[childrenKey]);\r\n return count;\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Clean up partially created nodes without triggering UI refresh for each node.\r\n * @private\r\n * @param {Array<import('./jsmind.node.js').Node>} created_nodes\r\n */\r\n _cleanup_partial_nodes(created_nodes) {\r\n if (created_nodes.length === 0) return;\r\n // Remove all created nodes in reverse order to avoid parent-child issues\r\n // Use direct view and mind operations without triggering layout/show\r\n [...created_nodes].reverse().forEach(node => {\r\n if (node && !node.isroot) {\r\n // Remove from view without triggering layout\r\n this.view.remove_node(node);\r\n // Remove from mind model without triggering layout\r\n this.mind.remove_node(node);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Insert a node before target node.\r\n * @param {string | import('./jsmind.node.js').Node} node_before\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n */\r\n insert_node_before(node_before, node_id, topic, data, direction) {\r\n if (this.get_editable()) {\r\n var the_node_before = this.get_node(node_before);\r\n var dir = Direction.of(direction);\r\n if (dir === undefined) {\r\n dir = this.layout.calculate_next_child_direction(the_node_before.parent);\r\n }\r\n var node = this.mind.insert_node_before(the_node_before, node_id, topic, data, dir);\r\n if (!!node) {\r\n this.view.add_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'insert_node_before',\r\n data: [the_node_before.id, node_id, topic, data, dir],\r\n node: node_id,\r\n });\r\n }\r\n return node;\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n }\r\n /**\r\n * Insert a node after target node.\r\n * @param {string | import('./jsmind.node.js').Node} node_after\r\n * @param {string} node_id\r\n * @param {string} topic\r\n * @param {Record<string, any>=} data\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n */\r\n insert_node_after(node_after, node_id, topic, data, direction) {\r\n if (this.get_editable()) {\r\n var the_node_after = this.get_node(node_after);\r\n var dir = Direction.of(direction);\r\n if (dir === undefined) {\r\n dir = this.layout.calculate_next_child_direction(the_node_after.parent);\r\n }\r\n var node = this.mind.insert_node_after(the_node_after, node_id, topic, data, dir);\r\n if (!!node) {\r\n this.view.add_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'insert_node_after',\r\n data: [the_node_after.id, node_id, topic, data, dir],\r\n node: node_id,\r\n });\r\n }\r\n return node;\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n }\r\n /**\r\n * Remove a node.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {boolean}\r\n */\r\n remove_node(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return false;\r\n } else {\r\n return this.remove_node(the_node);\r\n }\r\n }\r\n if (this.get_editable()) {\r\n if (node.isroot) {\r\n logger.error('fail, can not remove root node');\r\n return false;\r\n }\r\n var node_id = node.id;\r\n var parent_id = node.parent.id;\r\n var parent_node = this.get_node(parent_id);\r\n this.view.save_location(parent_node);\r\n this.view.remove_node(node);\r\n this.mind.remove_node(node);\r\n // Clear _last_selected_node if the removed node was the last selected\r\n if (this._last_selected_node && this._last_selected_node.id === node_id) {\r\n this._last_selected_node = null;\r\n }\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.view.restore_location(parent_node);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'remove_node',\r\n data: [node_id],\r\n node: parent_id,\r\n });\r\n return true;\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return false;\r\n }\r\n }\r\n /**\r\n * Update node topic text or multiple node properties.\r\n * @param {string} node_id - The ID of the node to update\r\n * @param {string|Partial<Pick<import('./jsmind.node.js').Node, 'topic' | 'data' | 'id' | 'index' | 'expanded' | 'direction'>>} topic_or_updates - Topic string for backward compatibility, or partial Node object for comprehensive updates\r\n */\r\n update_node(node_id, topic_or_updates) {\r\n if (!this.get_editable()) {\r\n logger.error('fail, this mind map is not editable');\r\n return;\r\n }\r\n\r\n var node = this.get_node(node_id);\r\n if (!!node) {\r\n // Handle backward compatibility: string parameter\r\n if (typeof topic_or_updates === 'string') {\r\n if (_util.text.is_empty(topic_or_updates)) {\r\n logger.warn('fail, topic can not be empty');\r\n return;\r\n }\r\n if (node.topic === topic_or_updates) {\r\n logger.info('nothing changed');\r\n this.view.update_node(node);\r\n return;\r\n }\r\n node.topic = topic_or_updates;\r\n this.view.update_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'update_node',\r\n data: [node_id, topic_or_updates],\r\n node: node_id,\r\n });\r\n return;\r\n }\r\n\r\n // Handle advanced updates with object parameter\r\n if (typeof topic_or_updates === 'object' && topic_or_updates !== null) {\r\n var originalId = node.id;\r\n var hasChanges = false;\r\n\r\n // Validate and apply topic change\r\n if (topic_or_updates.topic !== undefined) {\r\n if (_util.text.is_empty(topic_or_updates.topic)) {\r\n logger.warn('fail, topic can not be empty');\r\n return;\r\n }\r\n if (node.topic !== topic_or_updates.topic) {\r\n node.topic = topic_or_updates.topic;\r\n hasChanges = true;\r\n }\r\n }\r\n\r\n // Validate and apply data changes\r\n if (topic_or_updates.data && typeof topic_or_updates.data === 'object') {\r\n for (var key in topic_or_updates.data) {\r\n if (topic_or_updates.data.hasOwnProperty(key)) {\r\n if (node.data[key] !== topic_or_updates.data[key]) {\r\n node.data[key] = topic_or_updates.data[key];\r\n hasChanges = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Validate and apply ID change\r\n if (topic_or_updates.id !== undefined) {\r\n if (\r\n typeof topic_or_updates.id !== 'string' ||\r\n topic_or_updates.id.trim() === ''\r\n ) {\r\n logger.error('fail, new node id must be a non-empty string');\r\n return;\r\n }\r\n\r\n // Only proceed if there's an actual ID change\r\n if (node.id !== topic_or_updates.id) {\r\n // Validation checks\r\n if (node.isroot) {\r\n logger.error('fail, cannot change root node id');\r\n return;\r\n }\r\n\r\n if (topic_or_updates.id in this.mind.nodes) {\r\n logger.error(\r\n 'fail, new id \"' + topic_or_updates.id + '\" already exists'\r\n );\r\n return;\r\n }\r\n\r\n // Direct ID change implementation\r\n var oldId = node.id;\r\n\r\n // Remove from old mapping\r\n delete this.mind.nodes[oldId];\r\n\r\n // Update node ID\r\n node.id = topic_or_updates.id;\r\n\r\n // Add to new mapping\r\n this.mind.nodes[topic_or_updates.id] = node;\r\n\r\n // Update selected state if needed\r\n if (this.mind.selected && this.mind.selected.id === oldId) {\r\n this.mind.selected = node;\r\n }\r\n\r\n hasChanges = true;\r\n }\r\n }\r\n\r\n // Apply other Node properties\r\n ['index', 'expanded', 'direction'].forEach(function (prop) {\r\n if (\r\n topic_or_updates[prop] !== undefined &&\r\n node[prop] !== topic_or_updates[prop]\r\n ) {\r\n node[prop] = topic_or_updates[prop];\r\n hasChanges = true;\r\n }\r\n });\r\n\r\n if (!hasChanges) {\r\n logger.info('nothing changed');\r\n this.view.update_node(node);\r\n return;\r\n }\r\n\r\n this.view.update_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'update_node',\r\n data: [originalId, topic_or_updates],\r\n node: originalId,\r\n });\r\n }\r\n } else {\r\n logger.error('fail, node not found');\r\n return;\r\n }\r\n }\r\n /**\r\n * Move a node and optionally change direction.\r\n * @param {string} node_id\r\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\r\n * @param {string=} parent_id\r\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1). Only effective for second-level nodes (children of root). If not provided, direction will be determined automatically.\r\n */\r\n move_node(node_id, before_id, parent_id, direction) {\r\n if (this.get_editable()) {\r\n var node = this.get_node(node_id);\r\n var updated_node = this.mind.move_node(node, before_id, parent_id, direction);\r\n if (!!updated_node) {\r\n this.view.update_node(updated_node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n this.invoke_event_handle(EventType.edit, {\r\n evt: 'move_node',\r\n data: [node_id, before_id, parent_id, direction],\r\n node: node_id,\r\n });\r\n }\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return;\r\n }\r\n }\r\n /**\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {void}\r\n */\r\n select_node(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n this.select_node(the_node);\r\n return;\r\n }\r\n }\r\n if (!this.layout.is_visible(node)) {\r\n return;\r\n }\r\n this._clear_selection_state();\r\n this.mind.selected = node;\r\n this._last_selected_node = node;\r\n this._append_selection([node]);\r\n this._selection_mode = 'single';\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'select_node',\r\n data: [],\r\n node: node.id,\r\n nodes: [node.id],\r\n });\r\n }\r\n /**\r\n * Get the currently selected node.\r\n *\r\n * This is a query API that returns the internal Node instance.\r\n * For data export with custom fieldNames, use `get_data()` instead.\r\n *\r\n * @returns {import('./jsmind.node.js').Node|null} Node instance or null\r\n */\r\n get_selected_node() {\r\n if (!!this.mind) {\r\n return this.mind.selected;\r\n } else {\r\n return null;\r\n }\r\n }\r\n /**\r\n * Get all currently selected nodes.\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n */\r\n get_selected_nodes() {\r\n if (!!this.mind) {\r\n return Array.from(this.mind.selected_nodes);\r\n }\r\n return [];\r\n }\r\n /** clear selection */\r\n select_clear() {\r\n if (!!this.mind) {\r\n this.mind.selected = null;\r\n this._last_selected_node = null;\r\n this._clear_selection_state();\r\n }\r\n }\r\n /**\r\n * Toggle multi-selection for a node (and optionally descendants).\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n */\r\n toggle_subtree_selection(node) {\r\n if (!this.options.selection || !this.options.selection.enable_multi_select) {\r\n this.select_node(node);\r\n return;\r\n }\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n this.toggle_subtree_selection(the_node);\r\n return;\r\n }\r\n }\r\n if (!this.layout.is_visible(node)) {\r\n return;\r\n }\r\n var isSelected = this.mind.selected_nodes.has(node);\r\n var shouldExpandSelection = !isSelected || this._selection_mode !== 'multi';\r\n if (shouldExpandSelection) {\r\n this._selection_mode = 'multi';\r\n var includeDescendants = this.options.selection.include_descendants !== false;\r\n var nodes_to_add = this._collect_subtree_nodes(node, {\r\n includeChildren: includeDescendants,\r\n respectFilter: true,\r\n skipRootFilter: true,\r\n });\r\n if (!nodes_to_add.length) {\r\n nodes_to_add = [node];\r\n }\r\n var added = this._append_selection(nodes_to_add, { focusNode: node });\r\n var ancestorAdded =\r\n node.parent && !this.mind.selected_nodes.has(node.parent)\r\n ? this._ensure_ancestor_selection([node], node, {\r\n requireAncestorChainSelected: true,\r\n })\r\n : [];\r\n var totalAdded = added.concat(ancestorAdded);\r\n if (totalAdded.length) {\r\n this.mind.selected = node;\r\n var addedIds = totalAdded.map(n => n.id);\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_select',\r\n data: addedIds,\r\n node: node.id,\r\n nodes: addedIds,\r\n });\r\n }\r\n } else {\r\n var nodes_to_remove = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: false,\r\n });\r\n if (!nodes_to_remove.length) {\r\n nodes_to_remove = [node];\r\n }\r\n var removed = this._remove_selection(nodes_to_remove);\r\n if (removed.length) {\r\n if (this.mind.selected && this.mind.selected.id === node.id) {\r\n this.mind.selected = null;\r\n }\r\n var removedIds = removed.map(n => n.id);\r\n this._selection_mode = this._derive_selection_mode();\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_deselect',\r\n data: removedIds,\r\n node: node.id,\r\n nodes: removedIds,\r\n });\r\n }\r\n }\r\n }\r\n /**\r\n * Determine whether a node is currently selected.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {boolean}\r\n */\r\n is_node_selected(node) {\r\n var target = node;\r\n if (!Node.is_node(node)) {\r\n target = this.get_node(node);\r\n }\r\n if (!target || !this.mind) {\r\n return false;\r\n }\r\n return this.mind.selected_nodes.has(target);\r\n }\r\n /** @param {string | import('./jsmind.node.js').Node} node */\r\n is_node_visible(node) {\r\n return this.layout.is_visible(node);\r\n }\r\n /**\r\n * Scroll the mind map to center the specified node.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n */\r\n scroll_node_to_center(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n } else {\r\n this.scroll_node_to_center(the_node);\r\n }\r\n return;\r\n }\r\n this.view.center_node(node);\r\n }\r\n /**\r\n * Add nodes into the current selection set without clearing existing ones.\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n /**\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @param {{focusNode?: import('./jsmind.node.js').Node}=} options\r\n * @private\r\n */\r\n _append_selection(nodes, options) {\r\n if (!nodes || !nodes.length) {\r\n return [];\r\n }\r\n var added = [];\r\n for (var i = 0; i < nodes.length; i++) {\r\n var node = nodes[i];\r\n if (!this.mind.selected_nodes.has(node)) {\r\n this.mind.selected_nodes.add(node);\r\n added.push(node);\r\n }\r\n }\r\n if (added.length) {\r\n var focusNode = options && options.focusNode ? options.focusNode : null;\r\n this.view.append_selected_nodes(added, focusNode || added[added.length - 1]);\r\n }\r\n return added;\r\n }\r\n /**\r\n * Remove nodes from the current selection set.\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _remove_selection(nodes) {\r\n if (!nodes || !nodes.length) {\r\n return [];\r\n }\r\n var removed = [];\r\n for (var i = 0; i < nodes.length; i++) {\r\n var node = nodes[i];\r\n if (this.mind.selected_nodes.has(node)) {\r\n this.mind.selected_nodes.delete(node);\r\n removed.push(node);\r\n }\r\n }\r\n if (removed.length) {\r\n this.view.remove_selected_nodes(removed);\r\n }\r\n return removed;\r\n }\r\n /**\r\n * Deselect a node and all its descendants from the current selection.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @private\r\n */\r\n _deselect_subtree(node) {\r\n var the_node = Node.is_node(node) ? node : this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n }\r\n var nodes_to_remove = this._collect_subtree_nodes(the_node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: false,\r\n });\r\n if (!nodes_to_remove.length) {\r\n nodes_to_remove = [the_node];\r\n }\r\n var removed = this._remove_selection(nodes_to_remove);\r\n if (removed.length) {\r\n if (this.mind.selected && this.mind.selected.id === the_node.id) {\r\n this.mind.selected = null;\r\n }\r\n var removedIds = removed.map(function (n) { return n.id; });\r\n this._selection_mode = this._derive_selection_mode();\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_deselect',\r\n data: removedIds,\r\n node: the_node.id,\r\n nodes: removedIds,\r\n });\r\n }\r\n }\r\n /**\r\n * Clear all current selections and return the nodes that were cleared.\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _clear_selection_state() {\r\n this._selection_mode = null;\r\n if (!this.mind.selected_nodes.size) {\r\n this.view.clear_all_selected_nodes();\r\n return [];\r\n }\r\n var nodes = Array.from(this.mind.selected_nodes);\r\n this.mind.selected_nodes.clear();\r\n this.view.remove_selected_nodes(nodes);\r\n return nodes;\r\n }\r\n /**\r\n * Collect a node and optionally its descendants respecting filters.\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @param {{includeChildren?:boolean, respectFilter?:boolean, skipRootFilter?:boolean}=} config\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _collect_subtree_nodes(node, config) {\r\n var opts = config || {};\r\n var includeChildren = opts.includeChildren !== false;\r\n var respectFilter = !!opts.respectFilter;\r\n var skipRootFilter = !!opts.skipRootFilter;\r\n var filter = respectFilter ? this._get_selection_filter() : null;\r\n var collected = [];\r\n var traverse = function (current, isRoot) {\r\n var includeCurrent = true;\r\n if (filter && !(skipRootFilter && isRoot)) {\r\n includeCurrent = filter(current) !== false;\r\n }\r\n if (includeCurrent) {\r\n collected.push(current);\r\n }\r\n if (!includeChildren) {\r\n return;\r\n }\r\n var children = current.children || [];\r\n for (var i = 0; i < children.length; i++) {\r\n traverse(children[i], false);\r\n }\r\n };\r\n traverse(node, true);\r\n return collected;\r\n }\r\n /**\r\n * Ensure ancestors of provided nodes are also selected (up to first selected ancestor).\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @param {import('./jsmind.node.js').Node=} focusNode\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n /**\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @param {import('./jsmind.node.js').Node=} focusNode\r\n * @param {{requireAncestorChainSelected?: boolean}=} options\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _ensure_ancestor_selection(nodes, focusNode, options) {\r\n if (!nodes || !nodes.length) {\r\n return [];\r\n }\r\n var requireChain = !!(options && options.requireAncestorChainSelected);\r\n var ancestors = [];\r\n var seen = Object.create(null);\r\n for (var i = 0; i < nodes.length; i++) {\r\n var current = nodes[i].parent;\r\n if (!current) {\r\n continue;\r\n }\r\n var path = [];\r\n var chainValid = !requireChain;\r\n while (current) {\r\n if (this.mind.selected_nodes.has(current)) {\r\n chainValid = true;\r\n break;\r\n }\r\n path.push(current);\r\n current = current.parent;\r\n }\r\n if (!chainValid) {\r\n continue;\r\n }\r\n for (var p = 0; p < path.length; p++) {\r\n var ancestorNode = path[p];\r\n if (!this.mind.selected_nodes.has(ancestorNode) && !seen[ancestorNode.id]) {\r\n ancestors.push(ancestorNode);\r\n seen[ancestorNode.id] = true;\r\n }\r\n }\r\n }\r\n if (!ancestors.length) {\r\n return [];\r\n }\r\n var anchor = focusNode || nodes[nodes.length - 1];\r\n return this._append_selection(ancestors, { focusNode: anchor });\r\n }\r\n /**\r\n * Get the configured selection filter callback, if any.\r\n * @returns {((node: import('./jsmind.node.js').Node)=>boolean)|null}\r\n * @private\r\n */\r\n _get_selection_filter() {\r\n var selection = this.options.selection || {};\r\n if (selection && typeof selection.filter === 'function') {\r\n return selection.filter;\r\n }\r\n return null;\r\n }\r\n /**\r\n * Determine the multi-select mode based on event modifiers.\r\n * Returns: null (single select), 'ctrl' (add/remove), 'shift' (range select)\r\n * @param {MouseEvent} e\r\n * @returns {null|'ctrl'|'shift'}\r\n * @private\r\n */\r\n _get_multi_select_mode(e) {\r\n var selection = this.options.selection || {};\r\n if (!selection.enable_multi_select) {\r\n return null;\r\n }\r\n if (!e) {\r\n return null;\r\n }\r\n if (e.shiftKey) {\r\n return 'shift';\r\n }\r\n if (e.ctrlKey || e.metaKey) {\r\n return 'ctrl';\r\n }\r\n return null;\r\n }\r\n /**\r\n * Toggle selection of a single node (add if not selected, remove if selected).\r\n * Used for Ctrl+Click behavior.\r\n * @param {string | import('./jsmind.node.js').Node} node_id\r\n * @private\r\n */\r\n _toggle_node_selection(node_id) {\r\n var node = Node.is_node(node_id) ? node_id : this.get_node(node_id);\r\n if (!node || !this.layout.is_visible(node)) {\r\n return;\r\n }\r\n var isSelected = this.mind.selected_nodes.has(node);\r\n if (isSelected) {\r\n // Deselect this node and all its descendants\r\n this._deselect_subtree(node);\r\n } else {\r\n this._selection_mode = 'multi';\r\n var added = this._append_selection([node]);\r\n if (added.length) {\r\n this.mind.selected = node;\r\n this._last_selected_node = node;\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_select',\r\n data: [node.id],\r\n node: node.id,\r\n nodes: [node.id],\r\n });\r\n }\r\n }\r\n }\r\n /**\r\n * Range select nodes for Shift+Click behavior.\r\n * Logic:\r\n * - If no nodes are currently selected: select all nodes under the clicked node\r\n * - If nodes are already selected: select nodes in the range from first selected to clicked node\r\n * @param {string | import('./jsmind.node.js').Node} node_id\r\n * @private\r\n */\r\n _range_select_nodes(node_id) {\r\n var node = Node.is_node(node_id) ? node_id : this.get_node(node_id);\r\n if (!node || !this.layout.is_visible(node)) {\r\n return;\r\n }\r\n\r\n // If no nodes are currently selected, select all nodes under this node\r\n if (this.mind.selected_nodes.size === 0) {\r\n var descendantNodes = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: true,\r\n skipRootFilter: true,\r\n });\r\n if (!descendantNodes.length) {\r\n descendantNodes = [node];\r\n }\r\n var added = this._append_selection(descendantNodes);\r\n if (added.length) {\r\n this.mind.selected = node;\r\n this._last_selected_node = node;\r\n this._selection_mode = this._derive_selection_mode();\r\n var addedIds = added.map(n => n.id);\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_select',\r\n data: addedIds,\r\n node: node.id,\r\n nodes: addedIds,\r\n });\r\n }\r\n return;\r\n }\r\n\r\n // If nodes are already selected, select range from anchor (prefer last selected if still selected) to current node\r\n var selectedNodesArray = Array.from(this.mind.selected_nodes);\r\n var firstSelectedNode = selectedNodesArray[0];\r\n var anchorNode = (this._last_selected_node && this.mind.selected_nodes.has(this._last_selected_node))\r\n ? this._last_selected_node\r\n : firstSelectedNode;\r\n\r\n // Build base nodes from the linear range between anchor and current node\r\n var nodesBetween = this._find_nodes_between(anchorNode, node);\r\n if (!nodesBetween.length) {\r\n nodesBetween = [node];\r\n }\r\n\r\n // Special case: selecting another branch under the same ancestor\r\n var expandedSet = new Set();\r\n var expandedSetReady = false;\r\n var siblingBranches = !this._is_ancestor_of(anchorNode, node) && !this._is_ancestor_of(node, anchorNode);\r\n // Precompute LCA and the branch head under LCA on the path to target\r\n var lca = this._find_lca(anchorNode, node);\r\n var childOnPath = this._child_on_path(lca, node);\r\n var anchorChild = this._child_on_path(lca, anchorNode);\r\n // Branch-range under same LCA: select every sibling branch between anchor and target (inclusive), with full subtrees\r\n var anchorChild = this._child_on_path(lca, anchorNode);\r\n var targetChild = this._child_on_path(lca, node);\r\n if (lca && anchorChild && targetChild && anchorChild !== targetChild && anchorNode === anchorChild && node === targetChild && !expandedSetReady) {\r\n var lcaChildren = Array.isArray(lca.children) ? lca.children : [];\r\n var ai = lcaChildren.indexOf(anchorChild);\r\n var ti = lcaChildren.indexOf(targetChild);\r\n if (ai >= 0 && ti >= 0) {\r\n var sidx = Math.min(ai, ti);\r\n var eidx = Math.max(ai, ti);\r\n for (var xi = sidx; xi <= eidx; xi++) {\r\n var branchHead = lcaChildren[xi];\r\n var branchTree = this._collect_subtree_nodes(branchHead, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var bt = 0; bt < branchTree.length; bt++) {\r\n expandedSet.add(branchTree[bt]);\r\n }\r\n }\r\n expandedSetReady = true;\r\n }\r\n }\r\n if (siblingBranches && anchorChild && targetChild && anchorNode === anchorChild && node === targetChild) {\r\n // Use nodesBetween to gather intermediate top-level branches (excluding anchor subtree and node's ancestor chain)\r\n var midNodes = [];\r\n for (var mb = 0; mb < nodesBetween.length; mb++) {\r\n var m = nodesBetween[mb];\r\n if (m === anchorNode) continue;\r\n if (this._is_ancestor_of(anchorNode, m)) continue; // skip nodes under the anchor's branch\r\n if (this._is_ancestor_of(m, node)) continue; // skip ancestors of target branch (e.g., B when clicking B-2)\r\n midNodes.push(m);\r\n }\r\n var baseNodes = this._remove_descendant_nodes(midNodes);\r\n for (var bi = 0; bi < baseNodes.length; bi++) {\r\n var base = baseNodes[bi];\r\n var baseFull = this._collect_subtree_nodes(base, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var bfi = 0; bfi < baseFull.length; bfi++) {\r\n expandedSet.add(baseFull[bfi]);\r\n }\r\n }\r\n // Now handle the target branch itself\r\n if (childOnPath && node !== childOnPath) {\r\n // descendant in target branch: include siblings up to target, including their subtrees\r\n var p = node.parent;\r\n if (p && Array.isArray(p.children)) {\r\n var idx = p.children.indexOf(node);\r\n for (var si = 0; si <= idx; si++) {\r\n var sib = p.children[si];\r\n var sibSubtree = this._collect_subtree_nodes(sib, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var ssi = 0; ssi < sibSubtree.length; ssi++) {\r\n expandedSet.add(sibSubtree[ssi]);\r\n }\r\n }\r\n } else {\r\n expandedSet.add(node);\r\n }\r\n } else {\r\n // target is branch head: include its entire subtree (including the head)\r\n var full = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var fi = 0; fi < full.length; fi++) {\r\n expandedSet.add(full[fi]);\r\n }\r\n }\r\n expandedSetReady = true;\r\n }\r\n if (!expandedSetReady) {\r\n // Build selection within the target branch only\r\n if (childOnPath) {\r\n if (node === childOnPath) {\r\n // Branch head: include its entire subtree (including the head)\r\n var fullHead = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var hi = 0; hi < fullHead.length; hi++) {\r\n expandedSet.add(fullHead[hi]);\r\n }\r\n } else {\r\n // Descendant: include siblings up to target, including each sibling's subtree\r\n var p = node.parent;\r\n if (p && Array.isArray(p.children)) {\r\n var idx = p.children.indexOf(node);\r\n for (var si = 0; si <= idx; si++) {\r\n var sib = p.children[si];\r\n var sibTree = this._collect_subtree_nodes(sib, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var sti = 0; sti < sibTree.length; sti++) {\r\n expandedSet.add(sibTree[sti]);\r\n }\r\n }\r\n } else {\r\n var onlyTree = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var oti = 0; oti < onlyTree.length; oti++) {\r\n expandedSet.add(onlyTree[oti]);\r\n }\r\n }\r\n }\r\n } else {\r\n // Fallback: include siblings up to target under its immediate parent (and their subtrees)\r\n var p2 = node.parent;\r\n if (p2 && Array.isArray(p2.children)) {\r\n var idx2 = p2.children.indexOf(node);\r\n for (var sj = 0; sj <= idx2; sj++) {\r\n var s2 = p2.children[sj];\r\n var s2Tree = this._collect_subtree_nodes(s2, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var s2i = 0; s2i < s2Tree.length; s2i++) {\r\n expandedSet.add(s2Tree[s2i]);\r\n }\r\n }\r\n } else {\r\n expandedSet.add(node);\r\n }\r\n }\r\n }\r\n\r\n // Safety fallback: if nothing was inferred, include the target node and its entire subtree\r\n if (expandedSet.size === 0 && node) {\r\n var fallbackAll = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var fk = 0; fk < fallbackAll.length; fk++) {\r\n expandedSet.add(fallbackAll[fk]);\r\n }\r\n }\r\n\r\n // Post-filter: if selecting a descendant within a branch, remove later siblings and their subtrees\r\n if (childOnPath && node !== childOnPath && node.parent && Array.isArray(node.parent.children)) {\r\n var p = node.parent;\r\n var idx = p.children.indexOf(node);\r\n for (var ri = idx + 1; ri < p.children.length; ri++) {\r\n var rem = p.children[ri];\r\n // remove the sibling and its entire subtree if present in the expanded set\r\n var remNodes = this._collect_subtree_nodes(rem, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: true,\r\n });\r\n for (var rj = 0; rj < remNodes.length; rj++) {\r\n if (expandedSet.has(remNodes[rj])) {\r\n expandedSet.delete(remNodes[rj]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Always include the clicked node itself\r\n if (node) {\r\n expandedSet.add(node);\r\n }\r\n\r\n // Step 4: Add to current selection (do not clear existing Ctrl selections)\r\n var toAddArr = Array.from(expandedSet).filter(function (n) { return !this.mind.selected_nodes.has(n); }.bind(this));\r\n var added = this._append_selection(toAddArr);\r\n if (added.length) {\r\n this.mind.selected = node;\r\n this._last_selected_node = node;\r\n this._selection_mode = this._derive_selection_mode();\r\n var addedIds = added.map(function (n) { return n.id; });\r\n this.invoke_event_handle(EventType.select, {\r\n evt: 'multi_select',\r\n data: addedIds,\r\n node: node.id,\r\n nodes: addedIds,\r\n });\r\n }\r\n }\r\n /**\r\n * Find all nodes between two nodes (for range selection).\r\n * This includes both nodes and all nodes in between them in tree order.\r\n * @param {import('./jsmind.node.js').Node} node1\r\n * @param {import('./jsmind.node.js').Node} node2\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _find_nodes_between(node1, node2) {\r\n if (!node1 || !node2) {\r\n return [];\r\n }\r\n // Get all visible nodes in tree order\r\n var allNodes = [];\r\n var traverse = (node) => {\r\n if (this.layout.is_visible(node)) {\r\n allNodes.push(node);\r\n }\r\n if (node.children && node.children.length) {\r\n for (var i = 0; i < node.children.length; i++) {\r\n traverse(node.children[i]);\r\n }\r\n }\r\n };\r\n if (this.mind && this.mind.root) {\r\n traverse(this.mind.root);\r\n }\r\n // Find indices of both nodes\r\n var idx1 = -1, idx2 = -1;\r\n for (var i = 0; i < allNodes.length; i++) {\r\n if (allNodes[i].id === node1.id) idx1 = i;\r\n if (allNodes[i].id === node2.id) idx2 = i;\r\n }\r\n if (idx1 === -1 || idx2 === -1) {\r\n return [];\r\n }\r\n // Return nodes between (inclusive)\r\n var start = Math.min(idx1, idx2);\r\n var end = Math.max(idx1, idx2);\r\n return allNodes.slice(start, end + 1);\r\n }\r\n\r\n /**\r\n * Check whether ancestor is an ancestor of node.\r\n * @param {import('./jsmind.node.js').Node} ancestor\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @returns {boolean}\r\n * @private\r\n */\r\n _is_ancestor_of(ancestor, node) {\r\n if (!ancestor || !node) return false;\r\n var cur = node.parent;\r\n while (cur) {\r\n if (cur === ancestor) return true;\r\n cur = cur.parent;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Return nodes along the ancestor->descendant chain, inclusive. If 'ancestor' is not actually\r\n * an ancestor of 'descendant', returns empty array.\r\n * @param {import('./jsmind.node.js').Node} ancestor\r\n * @param {import('./jsmind.node.js').Node} descendant\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _get_path_nodes(ancestor, descendant) {\r\n if (!ancestor || !descendant) return [];\r\n var stack = [];\r\n var cur = descendant;\r\n while (cur) {\r\n stack.push(cur);\r\n if (cur === ancestor) break;\r\n cur = cur.parent;\r\n }\r\n if (!stack.length || stack[stack.length - 1] !== ancestor) {\r\n return [];\r\n }\r\n // stack is [descendant ... ancestor]; reverse to ancestor..descendant\r\n stack.reverse();\r\n return stack;\r\n }\r\n\r\n /**\r\n * Find nearest selected ancestor of the given node from current selection set.\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n * @private\r\n */\r\n _find_nearest_selected_ancestor(node) {\r\n if (!node || !this.mind || !this.mind.selected_nodes) return null;\r\n var cur = node.parent;\r\n while (cur) {\r\n if (this.mind.selected_nodes.has(cur)) return cur;\r\n cur = cur.parent;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Find lowest common ancestor of two nodes.\r\n * @param {import('./jsmind.node.js').Node} a\r\n * @param {import('./jsmind.node.js').Node} b\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n * @private\r\n */\r\n _find_lca(a, b) {\r\n if (!a || !b) return null;\r\n if (a === b) return a.parent || a; // trivial\r\n var ancestors = new Set();\r\n var cur = a;\r\n while (cur) {\r\n ancestors.add(cur);\r\n cur = cur.parent;\r\n }\r\n cur = b;\r\n while (cur) {\r\n if (ancestors.has(cur)) return cur;\r\n cur = cur.parent;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Given a lowest common ancestor 'lca' and a descendant 'node',\r\n * return the direct child of lca that lies on the path to node.\r\n * Returns null if node is not a descendant of lca or node === lca.\r\n * @param {import('./jsmind.node.js').Node} lca\r\n * @param {import('./jsmind.node.js').Node} node\r\n * @returns {import('./jsmind.node.js').Node|null}\r\n * @private\r\n */\r\n _child_on_path(lca, node) {\r\n if (!lca || !node) return null;\r\n if (lca === node) return null;\r\n var cur = node;\r\n while (cur && cur.parent && cur.parent !== lca) {\r\n cur = cur.parent;\r\n }\r\n if (cur && cur.parent === lca) return cur;\r\n return null;\r\n }\r\n\r\n /**\r\n * From a list of nodes, remove those that are ancestors of any other node in the same list.\r\n * Keeps only the deepest nodes so that we don't auto-select parents implicitly.\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _remove_ancestor_nodes(nodes, preserveSet) {\r\n if (!nodes || !nodes.length) return [];\r\n var preserve = preserveSet || new Set();\r\n var result = [];\r\n for (var i = 0; i < nodes.length; i++) {\r\n var n = nodes[i];\r\n if (preserve.has(n)) {\r\n result.push(n);\r\n continue;\r\n }\r\n var isAncestor = false;\r\n for (var j = 0; j < nodes.length; j++) {\r\n if (i === j) continue;\r\n if (this._is_ancestor_of(n, nodes[j])) {\r\n isAncestor = true;\r\n break;\r\n }\r\n }\r\n if (!isAncestor) result.push(n);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * From a list of nodes, remove those that are descendants of any other node in the same list.\r\n * Keeps only top-most nodes so that expanding subtrees covers full branches across siblings.\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @returns {import('./jsmind.node.js').Node[]}\r\n * @private\r\n */\r\n _remove_descendant_nodes(nodes) {\r\n if (!nodes || !nodes.length) return [];\r\n var result = [];\r\n for (var i = 0; i < nodes.length; i++) {\r\n var n = nodes[i];\r\n var isDescendant = false;\r\n for (var j = 0; j < nodes.length; j++) {\r\n if (i === j) continue;\r\n if (this._is_ancestor_of(nodes[j], n)) {\r\n isDescendant = true;\r\n break;\r\n }\r\n }\r\n if (!isDescendant) result.push(n);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Expand a set of base nodes with all their descendants (and themselves).\r\n * @param {import('./jsmind.node.js').Node[]} nodes\r\n * @param {{respectFilter?: boolean}=} opts\r\n * @returns {Set<import('./jsmind.node.js').Node>}\r\n * @private\r\n */\r\n _expand_with_descendants(nodes, opts) {\r\n var respectFilter = !!(opts && opts.respectFilter);\r\n var out = new Set();\r\n if (!nodes || !nodes.length) return out;\r\n for (var i = 0; i < nodes.length; i++) {\r\n var base = nodes[i];\r\n var list = this._collect_subtree_nodes(base, {\r\n includeChildren: true,\r\n respectFilter: respectFilter,\r\n skipRootFilter: true,\r\n });\r\n for (var k = 0; k < list.length; k++) {\r\n out.add(list[k]);\r\n }\r\n }\r\n return out;\r\n }\r\n\r\n /**\r\n * Promote parents into selection ONLY when all their direct children are selected\r\n * AND at least one ancestor of that parent is already selected (in previous selection set).\r\n * This avoids auto-selecting parents when only siblings are selected.\r\n * @param {Set<import('./jsmind.node.js').Node>} set\r\n * @returns {Set<import('./jsmind.node.js').Node>}\r\n * @private\r\n */\r\n _promote_parents_when_children_selected(set) {\r\n if (!set || !set.size) return set || new Set();\r\n var selectedSet = new Set(set);\r\n var prevSel = (this.mind && this.mind.selected_nodes) ? this.mind.selected_nodes : new Set();\r\n var changed = true;\r\n while (changed) {\r\n changed = false;\r\n var toAdd = [];\r\n selectedSet.forEach(function (node) {\r\n var p = node.parent;\r\n if (!p) return;\r\n if (selectedSet.has(p)) return;\r\n // require an ancestor of p to be in previous selection\r\n var ancestorSelected = false;\r\n var cur = p.parent;\r\n while (cur) {\r\n if (prevSel.has(cur)) {\r\n ancestorSelected = true;\r\n break;\r\n }\r\n cur = cur.parent;\r\n }\r\n if (ancestorSelected) toAdd.push(p);\r\n });\r\n if (toAdd.length) {\r\n for (var t = 0; t < toAdd.length; t++) {\r\n selectedSet.add(toAdd[t]);\r\n }\r\n changed = true;\r\n }\r\n }\r\n return selectedSet;\r\n }\r\n\r\n /**\r\n * Determine selection mode based on current selection size.\r\n * @returns {'single'|'multi'|null}\r\n * @private\r\n */\r\n _derive_selection_mode() {\r\n var size = this.mind.selected_nodes.size;\r\n if (size === 0) {\r\n return null;\r\n }\r\n return size > 1 ? 'multi' : 'single';\r\n }\r\n /**\r\n * Find the previous sibling node of the given node.\r\n *\r\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\r\n * @returns {import('./jsmind.node.js').Node | null}\r\n */\r\n find_node_before(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n return this.find_node_before(the_node);\r\n }\r\n }\r\n if (node.isroot) {\r\n return null;\r\n }\r\n var n = null;\r\n if (node.parent.isroot) {\r\n var c = node.parent.children;\r\n var prev = null;\r\n var ni = null;\r\n for (var i = 0; i < c.length; i++) {\r\n ni = c[i];\r\n if (node.direction === ni.direction) {\r\n if (node.id === ni.id) {\r\n n = prev;\r\n }\r\n prev = ni;\r\n }\r\n }\r\n } else {\r\n n = this.mind.get_node_before(node);\r\n }\r\n return n;\r\n }\r\n /**\r\n * Find the next sibling node of the given node.\r\n * @param {string | import('./jsmind.node.js').Node} node\r\n * @returns {import('./jsmind.node.js').Node | null}\r\n */\r\n find_node_after(node) {\r\n if (!Node.is_node(node)) {\r\n var the_node = this.get_node(node);\r\n if (!the_node) {\r\n logger.error('the node[id=' + node + '] can not be found.');\r\n return;\r\n } else {\r\n return this.find_node_after(the_node);\r\n }\r\n }\r\n if (node.isroot) {\r\n return null;\r\n }\r\n var n = null;\r\n if (node.parent.isroot) {\r\n var c = node.parent.children;\r\n var found = false;\r\n var ni = null;\r\n for (var i = 0; i < c.length; i++) {\r\n ni = c[i];\r\n if (node.direction === ni.direction) {\r\n if (found) {\r\n n = ni;\r\n break;\r\n }\r\n if (node.id === ni.id) {\r\n found = true;\r\n }\r\n }\r\n }\r\n } else {\r\n n = this.mind.get_node_after(node);\r\n }\r\n return n;\r\n }\r\n /**\r\n * Set background and foreground colors for a node.\r\n * @param {string} node_id\r\n * @param {string=} bg_color\r\n * @param {string=} fg_color\r\n * @returns {void}\r\n */\r\n set_node_color(node_id, bg_color, fg_color) {\r\n if (this.get_editable()) {\r\n var node = this.mind.get_node(node_id);\r\n if (!!node) {\r\n if (!!bg_color) {\r\n node.data['background-color'] = bg_color;\r\n }\r\n if (!!fg_color) {\r\n node.data['foreground-color'] = fg_color;\r\n }\r\n this.view.reset_node_custom_style(node);\r\n }\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n }\r\n /**\r\n * Set font style for a node.\r\n * @param {string} node_id\r\n * @param {number=} size\r\n * @param {string=} weight\r\n * @param {string=} style\r\n * @returns {void}\r\n */\r\n set_node_font_style(node_id, size, weight, style) {\r\n if (this.get_editable()) {\r\n var node = this.mind.get_node(node_id);\r\n if (!!node) {\r\n if (!!size) {\r\n node.data['font-size'] = size;\r\n }\r\n if (!!weight) {\r\n node.data['font-weight'] = weight;\r\n }\r\n if (!!style) {\r\n node.data['font-style'] = style;\r\n }\r\n this.view.reset_node_custom_style(node);\r\n this.view.update_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n }\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n }\r\n /**\r\n * Set background image for a node.\r\n * @param {string} node_id\r\n * @param {string=} image\r\n * @param {number=} width\r\n * @param {number=} height\r\n * @param {number=} rotation\r\n * @returns {void}\r\n */\r\n set_node_background_image(node_id, image, width, height, rotation) {\r\n if (this.get_editable()) {\r\n var node = this.mind.get_node(node_id);\r\n if (!!node) {\r\n if (!!image) {\r\n node.data['background-image'] = image;\r\n }\r\n if (!!width) {\r\n node.data['width'] = width;\r\n }\r\n if (!!height) {\r\n node.data['height'] = height;\r\n }\r\n if (!!rotation) {\r\n node.data['background-rotation'] = rotation;\r\n }\r\n this.view.reset_node_custom_style(node);\r\n this.view.update_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n }\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n }\r\n /**\r\n * @param {string} node_id\r\n * @param {number} rotation\r\n * @returns {void}\r\n */\r\n set_node_background_rotation(node_id, rotation) {\r\n if (this.get_editable()) {\r\n var node = this.mind.get_node(node_id);\r\n if (!!node) {\r\n if (!node.data['background-image']) {\r\n logger.error(\r\n 'fail, only can change rotation angle of node with background image'\r\n );\r\n return null;\r\n }\r\n node.data['background-rotation'] = rotation;\r\n this.view.reset_node_custom_style(node);\r\n this.view.update_node(node);\r\n this.layout.layout();\r\n this.view.show(false);\r\n }\r\n } else {\r\n logger.error('fail, this mind map is not editable');\r\n return null;\r\n }\r\n }\r\n /** trigger view resize */\r\n resize() {\r\n this.view.resize();\r\n }\r\n // callback(type ,data)\r\n /** @param {(type:number, data: EventData)=>void} callback */\r\n add_event_listener(callback) {\r\n if (typeof callback === 'function') {\r\n this.event_handles.push(callback);\r\n }\r\n }\r\n /** clear event listeners */\r\n clear_event_listener() {\r\n this.event_handles = [];\r\n }\r\n /** @param {number} type @param {EventData} data */\r\n invoke_event_handle(type, data) {\r\n var j = this;\r\n $.w.setTimeout(function () {\r\n j._invoke_event_handle(type, data);\r\n }, 0);\r\n }\r\n /** @param {number} type @param {EventData} data */\r\n _invoke_event_handle(type, data) {\r\n var l = this.event_handles.length;\r\n for (var i = 0; i < l; i++) {\r\n this.event_handles[i](type, data);\r\n }\r\n }\r\n\r\n /**\r\n * Remove an enhanced plugin\r\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\r\n */\r\n removePlugin(PluginClass) {\r\n if (this.enhancedPluginManager) {\r\n this.enhancedPluginManager.removePlugin(PluginClass);\r\n }\r\n }\r\n\r\n /**\r\n * Get an enhanced plugin instance\r\n * @param {string} instanceName - Plugin instance name\r\n * @returns {EnhancedPlugin | undefined}\r\n */\r\n getPlugin(instanceName) {\r\n if (this.enhancedPluginManager) {\r\n return this.enhancedPluginManager.getPlugin(instanceName);\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Destroy the jsMind instance and clean up resources\r\n */\r\n destroy() {\r\n // Destroy enhanced plugins\r\n if (this.enhancedPluginManager) {\r\n this.enhancedPluginManager.destroyAllPlugins();\r\n }\r\n\r\n // Clear event listeners\r\n this.clear_event_listener();\r\n\r\n // Clean up view\r\n if (this.view) {\r\n this.view.reset();\r\n }\r\n\r\n // Clear mind data\r\n this.mind = null;\r\n this.initialized = false;\r\n }\r\n\r\n /**\r\n * Deprecated: static show constructor helper.\r\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\r\n * @param {object | null} mind\r\n * @returns {jsMind}\r\n */\r\n static show(options, mind) {\r\n logger.warn(\r\n '`jsMind.show(options, mind)` is deprecated, please use `jm = new jsMind(options); jm.show(mind);` instead'\r\n );\r\n var _jm = new jsMind(options);\r\n _jm.show(mind);\r\n return _jm;\r\n }\r\n}\r\n"],"names":["__version__","String","prototype","startsWith","p","this","slice","length","Direction","left","center","right","of","dir","parseInt","toLowerCase","EventType","show","resize","edit","select","reset","history_change","LogLevel","debug","info","warn","error","disable","_noop","logger","console","level","log","log_level","$","constructor","w","d","document","g","id","getElementById","c","tag","createElement","t","n","hasChildNodes","firstChild","nodeValue","appendChild","createTextNode","h","HTMLElement","innerHTML","i","el","nodeType","style","ownerDocument","on","e","addEventListener","attachEvent","window","util","file","read","file_data","fn_callback","reader","FileReader","onload","result","name","readAsText","save","type","blob","Blob","bb","BlobBuilder","MozBlobBuilder","WebKitBlobBuilder","MSBlobBuilder","append","getBlob","navigator","msSaveBlob","blob_url","URL","webkitURL","createObjectURL","anchor","visibility","href","download","body","evt","createEvent","initEvent","dispatchEvent","removeChild","location","json","json2string","JSON","stringify","string2json","json_str","parse","merge","b","a","o","Object","toString","call","uuid","newid","Date","getTime","Math","random","substring","text","is_empty","s","replace","default_options","container","editable","theme","mode","support_html","view","engine","enable_device_pixel_ratio","hmargin","vmargin","line_width","line_color","line_style","draggable","hide_scrollbars_when_draggable","node_overflow","zoom","min","max","step","mask_key","custom_node_render","expander_style","layout","hspace","vspace","pspace","cousin_space","default_event_handle","enable_mousedown_handle","enable_click_handle","enable_dblclick_handle","enable_mousewheel_handle","shortcut","enable","handles","mapping","addchild","addbrother","editnode","delnode","toggle","up","down","selection","enable_multi_select","include_descendants","shift_simple_mode","filter","fieldNames","topic","children","parentid","isroot","direction","expanded","plugin","Node","sId","iIndex","sTopic","oData","bIsRoot","oParent","eDirection","bExpanded","index","data","parent","_data","get_location","vd","x","abs_x","y","abs_y","get_size","width","height","compare","node1","node2","i1","i2","inherited","parent_node","node","pid","is_node","toObject","includeChildren","fn","idKey","topicKey","childrenKey","directionKey","expandedKey","obj","k","map","child","Mind","author","version","root","selected","selected_nodes","Set","nodes","get_node","node_id","set_root","_put_node","add_node","idx","push","_update_index","insert_node_before","node_before","node_index","get_node_before","the_node","insert_node_after","node_after","get_node_after","move_node","before_id","parent_id","_move_node","_flow_node_direction","len","_move_node_internal","sibling","si","splice","origin_parent","remove_node","_purge_selection","ci","node_parent","has","delete","sort","DEFAULT_META","format","node_tree","example","meta","get_mind","source","df","mind","_parse","get_data","_build_node","node_root","_extract_data","_extract_subnode","node_json","node_data","node_array","_array","reverse","root_node","_extract_root","isrootKey","root_json","parentidKey","extract_count","node_direction","sub_extract_count","_array_node","freemind","xml","xml_doc","_parse_xml","xml_root","_find_root","_load_node","xml_lines","_build_map","join","DOMParser","parseFromString","ActiveXObject","async","loadXML","childNodes","tagName","ns","xml_node","getAttribute","node_topic","node_folded","topic_children","topic_child","textContent","_load_attributes","node_expanded","node_foreground_color","node_background_color","node_position","attr","attr_data","pos","_escape","_line_regex","lines","split","_fill_nodes","node_path","line","match","substr","diff","pop","_build_lines","prefix","Array","DataProvider","jm","init","load","mind_data","options","data_format","LayoutProvider","opts","isside","bounds","cache_valid","calculate_next_child_direction","children_len","r","layout_direction","layout_offset","_layout_direction_root","layout_data","children_count","side_index","_layout_direction_side","subnode","offset_x","offset_y","outer_height","left_nodes","right_nodes","unshift","outer_height_left","_layout_offset_subnodes","outer_height_right","total_height","nodes_count","node_outer_height","base_y","pd","set_visible","_should_reserve_cousin_space","middle_height","_layout_offset_subnodes_height","get_node_offset","offset_cache","_offset_","offset_p","get_node_point","view_data","get_node_point_in","get_node_point_out","pout_cache","_pout_","get_expander_point","ex_p","ceil","get_min_size","pout","toggle_node","collapse_node","expand_node","part_layout","invoke_event_handle","expand_all","collapse_all","expand_to_depth","target_depth","curr_nodes","curr_depth","depth","root_layout_data","visible","is_expand","is_visible","SvgGraph","e_svg","setAttribute","size","line_drawing","straight","_line_to","curved","_bezier_to","init_line_render","createElementNS","custom_line_render","drawing","path","x1","y1","x2","y2","ctx","start_point","end_point","element","set_size","clear","draw_line","pin","offset","color","copy_to","dest_canvas_ctx","callback","img","Image","drawImage","src","btoa","XMLSerializer","serializeToString","CanvasGraph","e_canvas","className","canvas_ctx","getContext","dpr","device_pixel_ratio","scale","clearRect","strokeStyle","lineWidth","lineCap","beginPath","moveTo","bezierCurveTo","stroke","lineTo","ViewProvider","e_panel","e_nodes","selected_node","multi_selected_nodes","Map","editing_node","graph","render_node","_custom_node_render","_default_node_render","zoom_current","devicePixelRatio","_initialized","e_editor","tabIndex","v","event","keyCode","edit_node_end","stopPropagation","offsetParent","IntersectionObserver","entities","observer","isIntersecting","unobserve","observe","add_event","event_name","event_handle","capture_by_panel","target","get_binded_nodeid","parentElement","is_expander","clear_lines","clear_nodes","reset_theme","theme_name","reset_custom_style","nodeid","reset_node_custom_style","setup_canvas_draggable","init_nodes","expand_size","min_size","min_width","min_height","client_w","clientWidth","client_h","clientHeight","init_nodes_size","doc_frag","createDocumentFragment","create_node_element","run_in_c11y_mode_if_needed","func","position","top","d_e","expander","_reset_node_custom_style","_unmark_node_selected","update_node","origin_style","select_node","clear_all_selected_nodes","_mark_node_selected","select_clear","append_selected_nodes","focus_node","remove_selected_nodes","from","values","get_editing_node","is_editing","edit_node_begin","ncs","getComputedStyle","value","getPropertyValue","zIndex","focus","get_view_offset","_show","show_nodes","show_lines","zoom_in","set_zoom","zoom_out","e_panel_rect","getBoundingClientRect","zoom_center","panel_scroll_x","scrollLeft","panel_scroll_y","scrollTop","keep_center","center_node","relayout","save_location","_saved_location","restore_location","node_element","view_offset","display","_show_expander","expander_text","_get_expander_text","p_expander","ele","backgroundColor","fontSize","fontWeight","fontStyle","backgroundImage","scaledImageData","toDataURL","backgroundSize","transform","restore_selected_node_custom_style","clear_selected_node_custom_style","test","set","_offset","enabled","dragging","eventDown","clientX","clientY","eventMove","scrollBy","node_center_point","scrollTo","zoomIn","zoomOut","setZoom","ShortcutProvider","_newid","_mapping","handle","handler","bind","handle_addchild","handle_addbrother","handle_editnode","handle_delnode","handle_toggle","handle_up","handle_down","handle_left","handle_right","keys","isArray","key","id_generator","enable_shortcut","disable_shortcut","which","preventDefault","kc","metaKey","ctrlKey","altKey","shiftKey","_jm","get_selected_node","begin_edit","up_node","find_node_before","np","down_node","find_node_after","_handle_direction","floor","plugin_data","plugins","register","Plugin","Error","includes","apply","setTimeout","forEach","fn_init","_apply","EnhancedPluginManager","initPreloadPlugins","preloadPlugins","enhancedPluginList","preload","descriptor","_initPlugin","initNormalPlugins","normalPlugins","PluginClass","pluginOpt","instanceName","instance","removePlugin","get","beforePluginRemove","list","findIndex","destroyAllPlugins","beforePluginDestroy","getPlugin","EnhancedPlugin","static","jsMind","_register_plugin","_util","usePlugin","some","hasEnhancedPlugin","current","merge_option","initialized","_selection_mode","_last_selected_node","event_handles","enhancedPluginManager","opts_layout","opts_view","_event_bind","apply_plugins","get_editable","enable_edit","disable_edit","get_view_draggable","enable_view_draggable","disable_view_draggable","enable_event_handle","disable_event_handle","set_theme","theme_old","mousedown_handle","click_handle","dblclick_handle","mousewheel_handle","srcElement","_get_multi_select_mode","_toggle_node_selection","is_node_selected","_deselect_subtree","_range_select_nodes","base","nodes_to_add","_collect_subtree_nodes","respectFilter","skipRootFilter","added","_append_selection","focusNode","_derive_selection_mode","addedIds","deltaY","end_edit","_reset","skip_centering","m","get_meta","get_root","get_node_level","_add_node_data","undefined","_refresh_node_ui","the_parent_node","add_nodes","nodes_data","expected_count","_count_expected_nodes","created_nodes","_add_nodes_recursive","flat","actual_count","_cleanup_partial_nodes","new_node","sub_nodes","concat","reduce","count","the_node_before","the_node_after","topic_or_updates","originalId","hasChanges","hasOwnProperty","trim","oldId","prop","updated_node","_clear_selection_state","get_selected_nodes","toggle_subtree_selection","includeDescendants","ancestorAdded","_ensure_ancestor_selection","requireAncestorChainSelected","totalAdded","nodes_to_remove","removed","_remove_selection","removedIds","is_node_visible","scroll_node_to_center","add","config","_get_selection_filter","collected","traverse","isRoot","includeCurrent","requireChain","ancestors","seen","create","chainValid","ancestorNode","firstSelectedNode","anchorNode","nodesBetween","_find_nodes_between","expandedSet","expandedSetReady","siblingBranches","_is_ancestor_of","lca","_find_lca","childOnPath","_child_on_path","anchorChild","targetChild","lcaChildren","ai","indexOf","ti","sidx","eidx","xi","branchHead","branchTree","bt","midNodes","mb","baseNodes","_remove_descendant_nodes","bi","baseFull","bfi","sib","sibSubtree","ssi","full","fi","fullHead","hi","sibTree","sti","onlyTree","oti","p2","idx2","sj","s2","s2Tree","s2i","fallbackAll","fk","ri","rem","remNodes","rj","toAddArr","descendantNodes","allNodes","idx1","start","end","ancestor","cur","_get_path_nodes","descendant","stack","_find_nearest_selected_ancestor","_remove_ancestor_nodes","preserveSet","preserve","isAncestor","j","isDescendant","_expand_with_descendants","out","_promote_parents_when_children_selected","selectedSet","prevSel","changed","toAdd","ancestorSelected","prev","ni","found","set_node_color","bg_color","fg_color","set_node_font_style","weight","set_node_background_image","image","rotation","set_node_background_rotation","add_event_listener","clear_event_listener","_invoke_event_handle","l","destroy"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"jsmind.js","sources":["../src/jsmind.common.js","../src/jsmind.dom.js","../src/jsmind.util.js","../src/jsmind.option.js","../src/jsmind.node.js","../src/jsmind.mind.js","../src/jsmind.format.js","../src/jsmind.data_provider.js","../src/jsmind.layout_provider.js","../src/jsmind.graph.js","../src/jsmind.view_provider.js","../src/jsmind.shortcut_provider.js","../src/jsmind.plugin.js","../src/jsmind.enhanced-plugin.js","../src/jsmind.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Library version string.\n * @type {string}\n */\nexport const __version__ = '0.9.0';\n/**\n * Library author.\n * @type {string}\n */\nexport const __author__ = 'UmbraCi';\n\nif (typeof String.prototype.startsWith != 'function') {\n String.prototype.startsWith = function (p) {\n return this.slice(0, p.length) === p;\n };\n}\n\n/**\n * Direction constants and parser.\n * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType\n */\n/** @type {DirectionType} */\nexport const Direction = {\n left: -1,\n center: 0,\n right: 1,\n of: function (dir) {\n if (!dir || dir === -1 || dir === 0 || dir === 1) {\n return dir;\n }\n if (dir === '-1' || dir === '0' || dir === '1') {\n return parseInt(dir);\n }\n if (dir.toLowerCase() === 'left') {\n return this.left;\n }\n if (dir.toLowerCase() === 'right') {\n return this.right;\n }\n if (dir.toLowerCase() === 'center') {\n return this.center;\n }\n },\n};\n/** @enum {number} */\nexport const EventType = { show: 1, resize: 2, edit: 3, select: 4, reset: 5, history_change: 6 };\n/** @enum {number} */\nexport const Key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };\n/** @enum {number} */\nexport const LogLevel = { debug: 1, info: 2, warn: 3, error: 4, disable: 9 };\n\n// an noop function define\nvar _noop = function () {};\n/**\n * Logger facade with dynamic level.\n * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}\n */\nexport let logger =\n typeof console === 'undefined'\n ? {\n level: _noop,\n log: _noop,\n debug: _noop,\n info: _noop,\n warn: _noop,\n error: _noop,\n }\n : {\n level: setup_logger_level,\n log: console.log,\n debug: console.debug,\n info: console.info,\n warn: console.warn,\n error: console.error,\n };\n\n/**\n * Set logger level.\n * @param {number} log_level\n */\nfunction setup_logger_level(log_level) {\n if (log_level > LogLevel.debug) {\n logger.debug = _noop;\n } else {\n logger.debug = console.debug;\n }\n if (log_level > LogLevel.info) {\n logger.info = _noop;\n } else {\n logger.info = console.info;\n }\n if (log_level > LogLevel.warn) {\n logger.warn = _noop;\n } else {\n logger.warn = console.warn;\n }\n if (log_level > LogLevel.error) {\n logger.error = _noop;\n } else {\n logger.error = console.error;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Lightweight DOM helpers bound to a window.\n */\nclass Dom {\n /**\n * @param {Window} w\n */\n constructor(w) {\n /** @type {Window} */\n this.w = w;\n /** @type {Document} */\n this.d = w.document;\n /**\n * Get element by id.\n * @param {string} id\n * @returns {HTMLElement|null}\n */\n this.g = function (id) {\n return this.d.getElementById(id);\n };\n /**\n * Create element with given tag.\n * @param {string} tag\n * @returns {HTMLElement}\n */\n this.c = function (tag) {\n return this.d.createElement(tag);\n };\n /**\n * Set text content for element.\n * @param {HTMLElement} n\n * @param {string} t\n */\n this.t = function (n, t) {\n if (n.hasChildNodes()) {\n n.firstChild.nodeValue = t;\n } else {\n n.appendChild(this.d.createTextNode(t));\n }\n };\n\n /**\n * Set inner HTML or append element.\n * @param {HTMLElement} n\n * @param {string|HTMLElement} t\n */\n this.h = function (n, t) {\n if (t instanceof HTMLElement) {\n n.innerHTML = '';\n n.appendChild(t);\n } else {\n n.innerHTML = t;\n }\n };\n // detect isElement\n /**\n * Runtime check for HTMLElement.\n * @param {unknown} el\n * @returns {el is HTMLElement}\n */\n this.i = function (el) {\n return (\n !!el &&\n typeof el === 'object' &&\n el.nodeType === 1 &&\n typeof el.style === 'object' &&\n typeof el.ownerDocument === 'object'\n );\n };\n\n //target,eventType,handler\n /**\n * Add event listener with legacy fallback.\n * @param {HTMLElement} t\n * @param {string} e\n * @param {(ev:Event)=>void} h\n */\n this.on = function (t, e, h) {\n if (!!t.addEventListener) {\n t.addEventListener(e, h, false);\n } else {\n t.attachEvent('on' + e, h);\n }\n };\n }\n}\n\nexport const $ = new Dom(window);\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/**\n * Misc utility collection.\n * @type {{\n * file: { read: (file: File, cb:(result:string,name:string)=>void)=>void, save:(data:string,type:string,name:string)=>void},\n * json: { json2string:(v:unknown)=>string, string2json:(s:string)=>unknown, merge:(b:object,a:object)=>object },\n * uuid: { newid:()=>string },\n * text: { is_empty:(s?:string)=>boolean }\n * }}\n */\nexport const util = {\n file: {\n read: function (file_data, fn_callback) {\n var reader = new FileReader();\n reader.onload = function () {\n if (typeof fn_callback === 'function') {\n fn_callback(this.result, file_data.name);\n }\n };\n reader.readAsText(file_data);\n },\n\n save: function (file_data, type, name) {\n var blob;\n if (typeof $.w.Blob === 'function') {\n blob = new Blob([file_data], { type: type });\n } else {\n var BlobBuilder =\n $.w.BlobBuilder ||\n $.w.MozBlobBuilder ||\n $.w.WebKitBlobBuilder ||\n $.w.MSBlobBuilder;\n var bb = new BlobBuilder();\n bb.append(file_data);\n blob = bb.getBlob(type);\n }\n if (navigator.msSaveBlob) {\n navigator.msSaveBlob(blob, name);\n } else {\n var URL = $.w.URL || $.w.webkitURL;\n var blob_url = URL.createObjectURL(blob);\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n },\n },\n\n json: {\n json2string: function (json) {\n return JSON.stringify(json);\n },\n string2json: function (json_str) {\n return JSON.parse(json_str);\n },\n merge: function (b, a) {\n for (var o in a) {\n if (o in b) {\n if (\n typeof b[o] === 'object' &&\n Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&\n !b[o].length\n ) {\n util.json.merge(b[o], a[o]);\n } else {\n b[o] = a[o];\n }\n } else {\n b[o] = a[o];\n }\n }\n return b;\n },\n },\n\n uuid: {\n newid: function () {\n return (\n new Date().getTime().toString(16) + Math.random().toString(16).substring(2)\n ).substring(2, 18);\n },\n },\n\n text: {\n is_empty: function (s) {\n if (!s) {\n return true;\n }\n return s.replace(/\\s*/, '').length == 0;\n },\n },\n};\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { util } from './jsmind.util.js';\n\n/**\n * @typedef {{\n * container: string|HTMLElement,\n * editable?: boolean,\n * theme?: (string|null),\n * mode?: ('full'|'side'),\n * support_html?: boolean,\n * log_level?: 'debug'|'info'|'warn'|'error'|'disable',\n * view?: {\n * engine?: 'canvas'|'svg',\n * enable_device_pixel_ratio?: boolean,\n * hmargin?: number,\n * vmargin?: number,\n * line_width?: number,\n * line_color?: string,\n * line_style?: 'curved'|'straight',\n * custom_line_render?: (this: object, arg:{ ctx: CanvasRenderingContext2D|SVGPathElement, start_point:{x:number,y:number}, end_point:{x:number,y:number} })=>void,\n * draggable?: boolean,\n * hide_scrollbars_when_draggable?: boolean,\n * node_overflow?: 'hidden'|'wrap'|'visible',\n * zoom?: { min?:number, max?:number, step?:number, mask_key?:number },\n * custom_node_render?: (null|((jm: import('./jsmind.js').default, ele: HTMLElement, node: import('./jsmind.node.js').Node)=>void)),\n * expander_style?: 'char'|'number'\n * },\n * layout?: { hspace?:number, vspace?:number, pspace?:number, cousin_space?:number },\n * default_event_handle?: { enable_mousedown_handle?:boolean, enable_click_handle?:boolean, enable_dblclick_handle?:boolean, enable_mousewheel_handle?:boolean },\n * shortcut?: { enable?:boolean, handles?: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping?: Record<string, number|number[]>, id_generator?: ()=>string },\n * fieldNames?: { id?:string, topic?:string, children?:string, parentid?:string, isroot?:string, direction?:string, expanded?:string },\n * plugin?: Record<string, object>\n * }} JsMindRuntimeOptions\n */\n/** @type {JsMindRuntimeOptions} */\nconst default_options = {\n container: '', // id of the container\n editable: false, // you can change it in your options\n theme: null,\n mode: 'full', // full or side\n support_html: true,\n log_level: 'info',\n\n view: {\n engine: 'canvas',\n enable_device_pixel_ratio: false,\n hmargin: 100,\n vmargin: 50,\n line_width: 2,\n line_color: '#555',\n line_style: 'curved', // [straight | curved]\n draggable: false, // drag the mind map with your mouse, when it's larger that the container\n hide_scrollbars_when_draggable: false, // hide container scrollbars, when mind map is larger than container and draggable option is true.\n node_overflow: 'hidden', // [hidden | wrap]\n zoom: {\n min: 0.5,\n max: 2.1,\n step: 0.1,\n mask_key: 4096,\n },\n custom_node_render: null,\n expander_style: 'char', // [char | number]\n },\n layout: {\n hspace: 30,\n vspace: 20,\n pspace: 13,\n cousin_space: 0,\n },\n default_event_handle: {\n enable_mousedown_handle: true,\n enable_click_handle: true,\n enable_dblclick_handle: true,\n enable_mousewheel_handle: true,\n },\n shortcut: {\n enable: true,\n handles: {},\n mapping: {\n addchild: [45, 4096 + 13], // Insert, Ctrl+Enter\n addbrother: 13, // Enter\n editnode: 113, // F2\n delnode: 46, // Delete\n toggle: 32, // Space\n left: 37, // Left\n up: 38, // Up\n right: 39, // Right\n down: 40, // Down\n },\n },\n // Field names mapping for custom data structure\n // Similar to Ant Design's fieldNames prop\n fieldNames: {\n id: 'id',\n topic: 'topic',\n children: 'children',\n parentid: 'parentid',\n isroot: 'isroot',\n direction: 'direction',\n expanded: 'expanded',\n },\n plugin: {},\n};\n\n/**\n * Merge user options with defaults. Throws if container missing.\n * @param {JsMindRuntimeOptions} options\n * @returns {JsMindRuntimeOptions}\n */\nexport function merge_option(options) {\n var opts = {};\n util.json.merge(opts, default_options);\n util.json.merge(opts, options);\n\n if (!opts.container) {\n throw new Error('the options.container should not be null or empty.');\n }\n return opts;\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\nexport class Node {\n /**\n * Create a Node instance.\n * @param {string} sId - Node id\n * @param {number} iIndex - Node index (order among siblings). Use -1 for tail\n * @param {string} sTopic - Node topic text\n * @param {Record<string, any>=} oData - Arbitrary node data\n * @param {boolean=} bIsRoot - Whether it is the root node\n * @param {Node | null=} oParent - Parent node\n * @param {number=} eDirection - Direction for children under root (-1 left, 0 center, 1 right)\n * @param {boolean=} bExpanded - Expanded state\n */\n constructor(sId, iIndex, sTopic, oData, bIsRoot, oParent, eDirection, bExpanded) {\n if (!sId) {\n logger.error('invalid node id');\n return;\n }\n if (typeof iIndex != 'number') {\n logger.error('invalid node index');\n return;\n }\n if (typeof bExpanded === 'undefined') {\n bExpanded = true;\n }\n this.id = sId;\n this.index = iIndex;\n this.topic = sTopic;\n /** @type {Record<string, any>} */\n this.data = oData || {};\n this.isroot = bIsRoot;\n this.parent = oParent;\n this.direction = eDirection;\n this.expanded = !!bExpanded;\n /** @type {Node[]} */\n this.children = [];\n this._data = {};\n }\n\n /**\n * Get absolute location of this node in view coordinates.\n * @returns {{x:number,y:number}}\n */\n get_location() {\n var vd = this._data.view;\n return {\n x: vd.abs_x,\n y: vd.abs_y,\n };\n }\n /**\n * Get rendered size of this node.\n * @returns {{w:number,h:number}}\n */\n get_size() {\n var vd = this._data.view;\n return {\n w: vd.width,\n h: vd.height,\n };\n }\n\n /**\n * Compare two nodes by index for ordering.\n * @param {Node} node1\n * @param {Node} node2\n * @returns {number}\n */\n static compare(node1, node2) {\n // '-1' is always the latest\n var r = 0;\n var i1 = node1.index;\n var i2 = node2.index;\n if (i1 >= 0 && i2 >= 0) {\n r = i1 - i2;\n } else if (i1 == -1 && i2 == -1) {\n r = 0;\n } else if (i1 == -1) {\n r = 1;\n } else if (i2 == -1) {\n r = -1;\n } else {\n r = 0;\n }\n return r;\n }\n /**\n * Check if node is the same as or a descendant of parent_node.\n * @param {Node} parent_node\n * @param {Node} node\n * @returns {boolean}\n */\n static inherited(parent_node, node) {\n if (!!parent_node && !!node) {\n if (parent_node.id === node.id) {\n return true;\n }\n if (parent_node.isroot) {\n return true;\n }\n var pid = parent_node.id;\n var p = node;\n while (!p.isroot) {\n p = p.parent;\n if (p.id === pid) {\n return true;\n }\n }\n }\n return false;\n }\n /**\n * Runtime check for Node instance.\n * @param {unknown} n\n * @returns {n is Node}\n */\n static is_node(n) {\n return !!n && n instanceof Node;\n }\n\n /**\n * Convert node to plain object with custom field names.\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @param {boolean=} includeChildren - Whether to include children nodes (default: false)\n * @returns {Record<string, any>} Plain object representation of node\n */\n toObject(fieldNames, includeChildren = false) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var obj = {};\n obj[idKey] = this.id;\n obj[topicKey] = this.topic;\n obj[expandedKey] = this.expanded;\n\n // Add direction for nodes under root\n if (!!this.parent && this.parent.isroot) {\n obj[directionKey] = this.direction === -1 ? 'left' : 'right';\n }\n\n // Add custom data properties\n if (this.data != null) {\n for (var k in this.data) {\n obj[k] = this.data[k];\n }\n }\n\n // Add children if requested\n if (includeChildren && this.children.length > 0) {\n obj[childrenKey] = this.children.map(child => child.toObject(fieldNames, true));\n }\n\n return obj;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { Node } from './jsmind.node.js';\nimport { logger, Direction } from './jsmind.common.js';\n\nexport class Mind {\n /**\n * Mind model: holds nodes and selection.\n */\n constructor() {\n /** @type {string | null} */\n this.name = null;\n /** @type {string | null} */\n this.author = null;\n /** @type {string | null} */\n this.version = null;\n /** @type {Node | null} */\n this.root = null;\n /** @type {Node | null} */\n this.selected = null;\n /** @type {Record<string, Node>} */\n this.nodes = {};\n }\n /**\n * Get a node by id.\n * @param {string} node_id\n * @returns {Node | null}\n */\n get_node(node_id) {\n if (node_id in this.nodes) {\n return this.nodes[node_id];\n } else {\n logger.warn('the node[id=' + node_id + '] can not be found');\n return null;\n }\n }\n /**\n * Set the root node, only once.\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @returns {Node | null}\n */\n set_root(node_id, topic, data) {\n if (this.root == null) {\n this.root = new Node(node_id, 0, topic, data, true);\n this._put_node(this.root);\n return this.root;\n } else {\n logger.error('root node is already exist');\n return null;\n }\n }\n /**\n * Add a child node under parent.\n * @param {Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @param {boolean=} expanded\n * @param {number=} idx\n * @returns {Node | null}\n */\n add_node(parent_node, node_id, topic, data, direction, expanded, idx) {\n if (!Node.is_node(parent_node)) {\n logger.error('the parent_node ' + parent_node + ' is not a node.');\n return null;\n }\n var node_index = idx || -1;\n var node = new Node(\n node_id,\n node_index,\n topic,\n data,\n false,\n parent_node,\n parent_node.direction,\n expanded\n );\n if (parent_node.isroot) {\n node.direction = direction || Direction.right;\n }\n if (this._put_node(node)) {\n parent_node.children.push(node);\n this._update_index(parent_node);\n } else {\n logger.error(\"fail, the node id '\" + node.id + \"' has been already exist.\");\n node = null;\n }\n return node;\n }\n /**\n * Insert a node before target node.\n * @param {Node} node_before\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n insert_node_before(node_before, node_id, topic, data, direction) {\n if (!Node.is_node(node_before)) {\n logger.error('the node_before ' + node_before + ' is not a node.');\n return null;\n }\n var node_index = node_before.index - 0.5;\n return this.add_node(node_before.parent, node_id, topic, data, direction, true, node_index);\n }\n /**\n * Get previous sibling of a node or node id.\n * @param {string | Node} node\n * @returns {Node | null}\n */\n get_node_before(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return null;\n } else {\n return this.get_node_before(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var idx = node.index - 2;\n if (idx >= 0) {\n return node.parent.children[idx];\n } else {\n return null;\n }\n }\n /**\n * Insert a node after target node.\n * @param {Node} node_after\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n insert_node_after(node_after, node_id, topic, data, direction) {\n if (!Node.is_node(node_after)) {\n logger.error('the node_after ' + node_after + ' is not a node.');\n return null;\n }\n var node_index = node_after.index + 0.5;\n return this.add_node(node_after.parent, node_id, topic, data, direction, true, node_index);\n }\n /**\n * Get next sibling of a node or node id.\n * @param {string | Node} node\n * @returns {Node | null}\n */\n get_node_after(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return null;\n } else {\n return this.get_node_after(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var idx = node.index;\n var brothers = node.parent.children;\n if (brothers.length > idx) {\n return node.parent.children[idx];\n } else {\n return null;\n }\n }\n /**\n * Move a node to new parent/position.\n * @param {Node} node\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\n * @param {string=} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n move_node(node, before_id, parent_id, direction) {\n if (!Node.is_node(node)) {\n logger.error('the parameter node ' + node + ' is not a node.');\n return null;\n }\n if (!parent_id) {\n parent_id = node.parent.id;\n }\n return this._move_node(node, before_id, parent_id, direction);\n }\n /**\n * Propagate direction to descendants.\n * @param {Node} node\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n */\n _flow_node_direction(node, direction) {\n if (typeof direction === 'undefined') {\n direction = node.direction;\n } else {\n node.direction = direction;\n }\n var len = node.children.length;\n while (len--) {\n this._flow_node_direction(node.children[len], direction);\n }\n }\n /**\n * Re-index node among siblings based on before_id marker.\n * @param {Node} node\n * @param {string} before_id\n * @returns {Node}\n */\n _move_node_internal(node, before_id) {\n if (!!node && !!before_id) {\n if (before_id == '_last_') {\n node.index = -1;\n this._update_index(node.parent);\n } else if (before_id == '_first_') {\n node.index = 0;\n this._update_index(node.parent);\n } else {\n var node_before = !!before_id ? this.get_node(before_id) : null;\n if (\n node_before != null &&\n node_before.parent != null &&\n node_before.parent.id == node.parent.id\n ) {\n node.index = node_before.index - 0.5;\n this._update_index(node.parent);\n }\n }\n }\n return node;\n }\n /**\n * Internal move implementation.\n * @param {Node} node\n * @param {string} before_id\n * @param {string} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n _move_node(node, before_id, parent_id, direction) {\n if (!!node && !!parent_id) {\n var parent_node = this.get_node(parent_id);\n if (Node.inherited(node, parent_node)) {\n logger.error('can not move a node to its children');\n return null;\n }\n if (node.parent.id != parent_id) {\n // remove from parent's children\n var sibling = node.parent.children;\n var si = sibling.length;\n while (si--) {\n if (sibling[si].id == node.id) {\n sibling.splice(si, 1);\n break;\n }\n }\n let origin_parent = node.parent;\n node.parent = parent_node;\n parent_node.children.push(node);\n this._update_index(origin_parent);\n }\n\n if (node.parent.isroot) {\n if (direction == Direction.left) {\n node.direction = direction;\n } else {\n node.direction = Direction.right;\n }\n } else {\n node.direction = node.parent.direction;\n }\n this._move_node_internal(node, before_id);\n this._flow_node_direction(node);\n }\n return node;\n }\n /**\n * Remove a node from the mind.\n * @param {Node} node\n * @returns {boolean}\n */\n remove_node(node) {\n if (!Node.is_node(node)) {\n logger.error('the parameter node ' + node + ' is not a node.');\n return false;\n }\n if (node.isroot) {\n logger.error('fail, can not remove root node');\n return false;\n }\n if (this.selected != null && this.selected.id == node.id) {\n this.selected = null;\n }\n // clean all subordinate nodes\n var children = node.children;\n var ci = children.length;\n while (ci--) {\n this.remove_node(children[ci]);\n }\n // clean all children\n children.length = 0;\n var node_parent = node.parent;\n // remove from parent's children\n var sibling = node_parent.children;\n var si = sibling.length;\n while (si--) {\n if (sibling[si].id == node.id) {\n sibling.splice(si, 1);\n break;\n }\n }\n // remove from global nodes\n delete this.nodes[node.id];\n // clean all properties\n for (var k in node) {\n delete node[k];\n }\n // remove it's self\n node = null;\n this._update_index(node_parent);\n return true;\n }\n /**\n * Put node into the map if id is not taken.\n * @param {Node} node\n * @returns {boolean}\n */\n _put_node(node) {\n if (node.id in this.nodes) {\n logger.warn(\"the node_id '\" + node.id + \"' has been already exist.\");\n return false;\n } else {\n this.nodes[node.id] = node;\n return true;\n }\n }\n /**\n * Re-index children by Node.compare.\n * @param {Node} node\n */\n _update_index(node) {\n if (node instanceof Node) {\n node.children.sort(Node.compare);\n for (var i = 0; i < node.children.length; i++) {\n node.children[i].index = i + 1;\n }\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { __author__, __version__, logger, Direction } from './jsmind.common.js';\nimport { Mind } from './jsmind.mind.js';\nimport { Node } from './jsmind.node.js';\nimport { util } from './jsmind.util.js';\n\n/** @typedef {{name:string,author:string,version:string}} MindMapMeta */\n/**\n * Node tree data item\n *\n * Note: When using custom fieldNames configuration, the actual property names\n * in your data may differ from these type definitions. For example, if you\n * configure `fieldNames: { topic: 'name' }`, your data should use 'name'\n * instead of 'topic'. The types shown here represent the default field names.\n *\n * @typedef {{\n * id?: string,\n * topic?: string,\n * data?: Record<string, any>,\n * direction?: (number|string),\n * expanded?: boolean,\n * children?: NodeTreeData[],\n * [key: string]: any\n * }} NodeTreeData\n */\n/**\n * Node tree formatted payload\n * @typedef {{\n * meta?: MindMapMeta,\n * format: 'node_tree',\n * data: NodeTreeData\n * }} NodeTreeFormat\n */\n/**\n * Node array data item\n *\n * Note: When using custom fieldNames configuration, the actual property names\n * in your data may differ from these type definitions. For example, if you\n * configure `fieldNames: { topic: 'name', parentid: 'parent' }`, your data\n * should use 'name' and 'parent' instead of 'topic' and 'parentid'. The types\n * shown here represent the default field names.\n *\n * @typedef {{\n * id?: string,\n * topic?: string,\n * parentid?: string,\n * data?: Record<string, any>,\n * direction?: (number|string),\n * expanded?: boolean,\n * isroot?: boolean,\n * [key: string]: any\n * }} NodeArrayItem\n */\n/**\n * Node array formatted payload\n * @typedef {{\n * meta?: MindMapMeta,\n * format: 'node_array',\n * data: NodeArrayItem[]\n * }} NodeArrayFormat\n */\n/** @type {MindMapMeta} */\nconst DEFAULT_META = { name: 'jsMind', author: __author__, version: __version__ };\n\n/**\n * Mind data format handlers.\n * @type {{\n * node_tree: { example:NodeTreeFormat, get_mind:(src:NodeTreeFormat)=>Mind, get_data:(mind:Mind)=>NodeTreeFormat },\n * node_array: { example:NodeArrayFormat, get_mind:(src:NodeArrayFormat)=>Mind, get_data:(mind:Mind)=>NodeArrayFormat },\n * freemind: { example:{meta:MindMapMeta,format:'freemind',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'freemind',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'freemind',data:string} },\n * text: { example:{meta:MindMapMeta,format:'text',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'text',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'text',data:string} }\n * }}\n */\nexport const format = {\n node_tree: {\n example: {\n meta: DEFAULT_META,\n format: 'node_tree',\n data: { id: 'root', topic: 'jsMind node_tree example' },\n },\n /** @param {NodeTreeFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.node_tree;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n df._parse(mind, source.data, fieldNames);\n return mind;\n },\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.node_tree;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'node_tree';\n json.data = df._build_node(mind.root, fieldNames);\n return json;\n },\n\n /** @param {Mind} mind @param {NodeTreeData} node_root @param {Record<string,string>=} fieldNames */\n _parse: function (mind, node_root, fieldNames) {\n var df = format.node_tree;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n\n var data = df._extract_data(node_root, fieldNames);\n mind.set_root(node_root[idKey], node_root[topicKey], data);\n if (childrenKey in node_root) {\n var children = node_root[childrenKey];\n for (var i = 0; i < children.length; i++) {\n df._extract_subnode(mind, mind.root, children[i], fieldNames);\n }\n }\n },\n\n /**\n * Extract custom data from node JSON, excluding standard properties.\n * @private\n * @param {Record<string, unknown>} node_json - Node JSON object\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @returns {Record<string,any>} Custom data object\n */\n _extract_data: function (node_json, fieldNames) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = {};\n for (var k in node_json) {\n if (\n k == idKey ||\n k == topicKey ||\n k == childrenKey ||\n k == directionKey ||\n k == expandedKey\n ) {\n continue;\n }\n data[k] = node_json[k];\n }\n return data;\n },\n\n /** @param {Mind} mind @param {Node} node_parent @param {NodeTreeData} node_json @param {Record<string,string>=} fieldNames */\n _extract_subnode: function (mind, node_parent, node_json, fieldNames) {\n var df = format.node_tree;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = df._extract_data(node_json, fieldNames);\n var d = null;\n if (node_parent.isroot) {\n d = node_json[directionKey] == 'left' ? Direction.left : Direction.right;\n }\n var node = mind.add_node(\n node_parent,\n node_json[idKey],\n node_json[topicKey],\n data,\n d,\n node_json[expandedKey]\n );\n if (!!node_json[childrenKey]) {\n var children = node_json[childrenKey];\n for (var i = 0; i < children.length; i++) {\n df._extract_subnode(mind, node, children[i], fieldNames);\n }\n }\n },\n\n /**\n * Build JSON object from a node.\n * @private\n * @param {Node} node - Node to convert\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @returns {NodeTreeData} JSON representation of node\n */\n _build_node: function (node, fieldNames) {\n var df = format.node_tree;\n if (!(node instanceof Node)) {\n return;\n }\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var o = {};\n o[idKey] = node.id;\n o[topicKey] = node.topic;\n o[expandedKey] = node.expanded;\n\n if (!!node.parent && node.parent.isroot) {\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\n }\n if (node.data != null) {\n var node_data = node.data;\n for (var k in node_data) {\n o[k] = node_data[k];\n }\n }\n var children = node.children;\n if (children.length > 0) {\n o[childrenKey] = [];\n for (var i = 0; i < children.length; i++) {\n o[childrenKey].push(df._build_node(children[i], fieldNames));\n }\n }\n return o;\n },\n },\n\n node_array: {\n example: {\n meta: DEFAULT_META,\n format: 'node_array',\n data: [{ id: 'root', topic: 'jsMind node_array example', isroot: true }],\n },\n\n /** @param {NodeArrayFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.node_array;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n df._parse(mind, source.data, fieldNames);\n return mind;\n },\n\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.node_array;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'node_array';\n json.data = [];\n df._array(mind, json.data, fieldNames);\n return json;\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _parse: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n var nodes = node_array.slice(0);\n // reverse array for improving looping performance\n nodes.reverse();\n var root_node = df._extract_root(mind, nodes, fieldNames);\n if (!!root_node) {\n df._extract_subnode(mind, root_node, nodes, fieldNames);\n } else {\n logger.error('root node can not be found');\n }\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _extract_root: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var isrootKey = fn.isroot || 'isroot';\n\n var i = node_array.length;\n while (i--) {\n if (isrootKey in node_array[i] && node_array[i][isrootKey]) {\n var root_json = node_array[i];\n var data = df._extract_data(root_json, fieldNames);\n var node = mind.set_root(root_json[idKey], root_json[topicKey], data);\n node_array.splice(i, 1);\n return node;\n }\n }\n return null;\n },\n\n /** @param {Mind} mind @param {Node} parent_node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _extract_subnode: function (mind, parent_node, node_array, fieldNames) {\n var df = format.node_array;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var i = node_array.length;\n var node_json = null;\n var data = null;\n var extract_count = 0;\n while (i--) {\n node_json = node_array[i];\n if (node_json[parentidKey] == parent_node.id) {\n data = df._extract_data(node_json, fieldNames);\n var d = null;\n var node_direction = node_json[directionKey];\n if (!!node_direction) {\n d = node_direction == 'left' ? Direction.left : Direction.right;\n }\n var node = mind.add_node(\n parent_node,\n node_json[idKey],\n node_json[topicKey],\n data,\n d,\n node_json[expandedKey]\n );\n node_array.splice(i, 1);\n extract_count++;\n var sub_extract_count = df._extract_subnode(mind, node, node_array, fieldNames);\n if (sub_extract_count > 0) {\n // reset loop index after extract subordinate node\n i = node_array.length;\n extract_count += sub_extract_count;\n }\n }\n }\n return extract_count;\n },\n\n /** @param {Record<string, unknown>} node_json @param {Record<string,string>=} fieldNames */\n _extract_data: function (node_json, fieldNames) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var isrootKey = fn.isroot || 'isroot';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = {};\n for (var k in node_json) {\n if (\n k == idKey ||\n k == topicKey ||\n k == parentidKey ||\n k == isrootKey ||\n k == directionKey ||\n k == expandedKey\n ) {\n continue;\n }\n data[k] = node_json[k];\n }\n return data;\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _array: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n df._array_node(mind.root, node_array, fieldNames);\n },\n\n /** @param {Node} node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _array_node: function (node, node_array, fieldNames) {\n var df = format.node_array;\n if (!(node instanceof Node)) {\n return;\n }\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var isrootKey = fn.isroot || 'isroot';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var o = {};\n o[idKey] = node.id;\n o[topicKey] = node.topic;\n o[expandedKey] = node.expanded;\n\n if (!!node.parent) {\n o[parentidKey] = node.parent.id;\n }\n if (node.isroot) {\n o[isrootKey] = true;\n }\n if (!!node.parent && node.parent.isroot) {\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\n }\n if (node.data != null) {\n var node_data = node.data;\n for (var k in node_data) {\n o[k] = node_data[k];\n }\n }\n node_array.push(o);\n var ci = node.children.length;\n for (var i = 0; i < ci; i++) {\n df._array_node(node.children[i], node_array, fieldNames);\n }\n },\n },\n\n freemind: {\n example: {\n meta: DEFAULT_META,\n format: 'freemind',\n data: '<map version=\"1.0.1\"><node ID=\"root\" TEXT=\"jsMind freemind example\"/></map>',\n },\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.freemind;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n var xml = source.data;\n var xml_doc = df._parse_xml(xml);\n var xml_root = df._find_root(xml_doc);\n // freemind format uses fixed XML attributes (ID, TEXT), fieldNames not applicable\n df._load_node(mind, null, xml_root);\n return mind;\n },\n\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.freemind;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'freemind';\n var xml_lines = [];\n xml_lines.push('<map version=\"1.0.1\">');\n // freemind format uses fixed XML attributes, fieldNames not applicable\n df._build_map(mind.root, xml_lines);\n xml_lines.push('</map>');\n json.data = xml_lines.join('');\n return json;\n },\n\n /** @param {string} xml */\n _parse_xml: function (xml) {\n var xml_doc = null;\n if (window.DOMParser) {\n var parser = new DOMParser();\n xml_doc = parser.parseFromString(xml, 'text/xml');\n } else {\n // Internet Explorer\n xml_doc = new ActiveXObject('Microsoft.XMLDOM');\n xml_doc.async = false;\n xml_doc.loadXML(xml);\n }\n return xml_doc;\n },\n\n /** @param {Document} xml_doc */\n _find_root: function (xml_doc) {\n var nodes = xml_doc.childNodes;\n var node = null;\n var root = null;\n var n = null;\n for (var i = 0; i < nodes.length; i++) {\n n = nodes[i];\n if (n.nodeType == 1 && n.tagName == 'map') {\n node = n;\n break;\n }\n }\n if (!!node) {\n var ns = node.childNodes;\n node = null;\n for (var i = 0; i < ns.length; i++) {\n n = ns[i];\n if (n.nodeType == 1 && n.tagName == 'node') {\n node = n;\n break;\n }\n }\n }\n return node;\n },\n\n /** @param {Mind} mind @param {Node|null} parent_node @param {Element} xml_node */\n _load_node: function (mind, parent_node, xml_node) {\n var df = format.freemind;\n var node_id = xml_node.getAttribute('ID');\n var node_topic = xml_node.getAttribute('TEXT');\n var node_folded = xml_node.getAttribute('FOLDED');\n // look for richcontent\n if (node_topic == null) {\n var topic_children = xml_node.childNodes;\n var topic_child = null;\n for (var i = 0; i < topic_children.length; i++) {\n topic_child = topic_children[i];\n if (topic_child.nodeType == 1 && topic_child.tagName === 'richcontent') {\n node_topic = topic_child.textContent;\n break;\n }\n }\n }\n var node_data = df._load_attributes(xml_node);\n var node_expanded =\n 'expanded' in node_data ? node_data.expanded == 'true' : node_folded != 'true';\n delete node_data.expanded;\n\n var node_foreground_color = xml_node.getAttribute('COLOR');\n if (!!node_foreground_color) {\n node_data['foreground-color'] = node_foreground_color;\n }\n\n var node_background_color = xml_node.getAttribute('BACKGROUND_COLOR');\n if (!!node_background_color) {\n node_data['background-color'] = node_background_color;\n }\n\n var node_position = xml_node.getAttribute('POSITION');\n var node_direction = null;\n if (!!node_position) {\n node_direction = node_position == 'left' ? Direction.left : Direction.right;\n }\n var node = null;\n if (!!parent_node) {\n node = mind.add_node(\n parent_node,\n node_id,\n node_topic,\n node_data,\n node_direction,\n node_expanded\n );\n } else {\n node = mind.set_root(node_id, node_topic, node_data);\n }\n var children = xml_node.childNodes;\n var child = null;\n for (var i = 0; i < children.length; i++) {\n child = children[i];\n if (child.nodeType == 1 && child.tagName == 'node') {\n df._load_node(mind, node, child);\n }\n }\n },\n\n /** @param {Element} xml_node */\n _load_attributes: function (xml_node) {\n var children = xml_node.childNodes;\n var attr = null;\n var attr_data = {};\n for (var i = 0; i < children.length; i++) {\n attr = children[i];\n if (attr.nodeType == 1 && attr.tagName === 'attribute') {\n attr_data[attr.getAttribute('NAME')] = attr.getAttribute('VALUE');\n }\n }\n return attr_data;\n },\n\n /** @param {Node} node @param {string[]} xml_lines */\n _build_map: function (node, xml_lines) {\n var df = format.freemind;\n var pos = null;\n var node_data = node.data;\n\n if (!!node.parent && node.parent.isroot) {\n pos = node.direction === Direction.left ? 'left' : 'right';\n }\n xml_lines.push('<node');\n xml_lines.push(' ID=\"' + node.id + '\"');\n if (!!pos) {\n xml_lines.push(' POSITION=\"' + pos + '\"');\n }\n if (!node.expanded) {\n xml_lines.push(' FOLDED=\"true\"');\n }\n if (!!node_data['foreground-color']) {\n xml_lines.push(' COLOR=\"' + node_data['foreground-color'] + '\"');\n }\n if (!!node_data['background-color']) {\n xml_lines.push(' BACKGROUND_COLOR=\"' + node_data['background-color'] + '\"');\n }\n xml_lines.push(' TEXT=\"' + df._escape(node.topic) + '\">');\n\n // for attributes\n if (node_data != null) {\n for (var k in node_data) {\n if (k === 'foreground-color' || k === 'background-color') {\n continue;\n }\n xml_lines.push('<attribute NAME=\"' + k + '\" VALUE=\"' + node_data[k] + '\"/>');\n }\n }\n\n // for children\n var children = node.children;\n for (var i = 0; i < children.length; i++) {\n df._build_map(children[i], xml_lines);\n }\n\n xml_lines.push('</node>');\n },\n\n /** @param {string} text */\n _escape: function (text) {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/'/g, ''')\n .replace(/\"/g, '"');\n },\n },\n text: {\n example: {\n meta: DEFAULT_META,\n format: 'text',\n data: 'jsMind text example\\n node1\\n node1-sub\\n node1-sub\\n node2',\n },\n _line_regex: /\\s*/,\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.text;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n var lines = source.data.split(/\\n|\\r/);\n // text format uses indentation-based structure, fieldNames not applicable\n df._fill_nodes(mind, lines, 0, 0);\n return mind;\n },\n\n /** @param {Mind} mind @param {string[]} lines */\n _fill_nodes: function (mind, lines) {\n let node_path = [];\n let i = 0;\n while (i < lines.length) {\n let line = lines[i];\n let level = line.match(/\\s*/)[0].length;\n let topic = line.substr(level);\n\n if (level == 0 && node_path.length > 0) {\n log.error('more than 1 root node was found: ' + topic);\n return;\n }\n if (level > node_path.length) {\n log.error('a suspended node was found: ' + topic);\n return;\n }\n let diff = node_path.length - level;\n while (diff--) {\n node_path.pop();\n }\n\n if (level == 0 && node_path.length == 0) {\n let node = mind.set_root(util.uuid.newid(), topic);\n node_path.push(node);\n } else {\n let node = mind.add_node(\n node_path[level - 1],\n util.uuid.newid(),\n topic,\n {},\n null\n );\n node_path.push(node);\n }\n i++;\n }\n node_path.length = 0;\n },\n\n /** @param {Mind} mind */\n get_data: function (mind) {\n var df = format.text;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'text';\n let lines = [];\n df._build_lines(lines, [mind.root], 0);\n json.data = lines.join('\\n');\n return json;\n },\n\n /** @param {string[]} lines @param {Node[]} nodes @param {number} level */\n _build_lines: function (lines, nodes, level) {\n let prefix = new Array(level + 1).join(' ');\n for (let node of nodes) {\n lines.push(prefix + node.topic);\n if (!!node.children) {\n format.text._build_lines(lines, node.children, level + 1);\n }\n }\n },\n },\n};\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\nimport { format } from './jsmind.format.js';\n\nexport class DataProvider {\n /**\n * Data provider: loads and serializes mind data by format.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n }\n\n /** Initialize data provider. */\n init() {\n logger.debug('data.init');\n }\n /** Reset data provider state. */\n reset() {\n logger.debug('data.reset');\n }\n /**\n * Load a Mind from mixed source.\n * @param {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta?:{name:string,author:string,version:string},format:'freemind',data:string}|{meta?:{name:string,author:string,version:string},format:'text',data:string}} mind_data - object with {format,data} or a format-specific payload\n * @returns {import('./jsmind.mind.js').Mind|null}\n */\n load(mind_data) {\n var df = null;\n var mind = null;\n if (typeof mind_data === 'object') {\n if (!!mind_data.format) {\n df = mind_data.format;\n } else {\n df = 'node_tree';\n }\n } else {\n df = 'freemind';\n }\n\n var fieldNames = this.jm.options.fieldNames;\n if (df == 'node_array') {\n mind = format.node_array.get_mind(mind_data, fieldNames);\n } else if (df == 'node_tree') {\n mind = format.node_tree.get_mind(mind_data, fieldNames);\n } else if (df == 'freemind') {\n mind = format.freemind.get_mind(mind_data, fieldNames);\n } else if (df == 'text') {\n mind = format.text.get_mind(mind_data, fieldNames);\n } else {\n logger.warn('unsupported format');\n }\n return mind;\n }\n /**\n * Serialize current mind to target format.\n * @param {'node_tree'|'node_array'|'freemind'|'text'} data_format\n * @returns {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta:{name:string,author:string,version:string},format:'freemind',data:string}|{meta:{name:string,author:string,version:string},format:'text',data:string}}\n */\n get_data(data_format) {\n var data = null;\n var fieldNames = this.jm.options.fieldNames;\n if (data_format == 'node_array') {\n data = format.node_array.get_data(this.jm.mind, fieldNames);\n } else if (data_format == 'node_tree') {\n data = format.node_tree.get_data(this.jm.mind, fieldNames);\n } else if (data_format == 'freemind') {\n data = format.freemind.get_data(this.jm.mind);\n } else if (data_format == 'text') {\n data = format.text.get_data(this.jm.mind);\n } else {\n logger.error('unsupported ' + data_format + ' format');\n }\n return data;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\nimport { logger, Direction, EventType } from './jsmind.common.js';\n\nexport class LayoutProvider {\n /**\n * Layout engine for positioning nodes and lines.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n * @param {{mode:'full'|'side', hspace:number, vspace:number, pspace:number, cousin_space:number}} options - Layout configuration options\n */\n constructor(jm, options) {\n this.opts = options;\n this.jm = jm;\n this.isside = this.opts.mode == 'side';\n this.bounds = null;\n\n this.cache_valid = false;\n }\n /** Initialize layout provider. */\n init() {\n logger.debug('layout.init');\n }\n /** Reset layout state and bounds. */\n reset() {\n logger.debug('layout.reset');\n this.bounds = { n: 0, s: 0, w: 0, e: 0 };\n }\n /**\n * Decide the next child's direction for a parent node.\n * @param {import('./jsmind.node.js').Node} node\n * @returns {number}\n */\n calculate_next_child_direction(node) {\n if (this.isside) {\n return Direction.right;\n }\n var children = node.children || [];\n var children_len = children.length;\n var r = 0;\n for (var i = 0; i < children_len; i++) {\n if (children[i].direction === Direction.left) {\n r--;\n } else {\n r++;\n }\n }\n return children_len > 1 && r > 0 ? Direction.left : Direction.right;\n }\n /** Perform layout and offsets recalculation. */\n layout() {\n logger.debug('layout.layout');\n this.layout_direction();\n this.layout_offset();\n }\n /** Calculate and set direction for all nodes. */\n layout_direction() {\n this._layout_direction_root();\n }\n /**\n * Set direction layout for root node and its children.\n * @private\n */\n _layout_direction_root() {\n var node = this.jm.mind.root;\n var layout_data = null;\n if ('layout' in node._data) {\n layout_data = node._data.layout;\n } else {\n layout_data = {};\n node._data.layout = layout_data;\n }\n var children = node.children;\n var children_count = children.length;\n layout_data.direction = Direction.center;\n layout_data.side_index = 0;\n if (this.isside) {\n var i = children_count;\n while (i--) {\n this._layout_direction_side(children[i], Direction.right, i);\n }\n } else {\n var i = children_count;\n var subnode = null;\n while (i--) {\n subnode = children[i];\n if (subnode.direction == Direction.left) {\n this._layout_direction_side(subnode, Direction.left, i);\n } else {\n this._layout_direction_side(subnode, Direction.right, i);\n }\n }\n }\n }\n /**\n * Set direction layout for a node and its descendants.\n * @private\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @param {number} direction - Direction constant (-1, 0, 1)\n * @param {number} side_index - Index among siblings\n */\n _layout_direction_side(node, direction, side_index) {\n var layout_data = null;\n if ('layout' in node._data) {\n layout_data = node._data.layout;\n } else {\n layout_data = {};\n node._data.layout = layout_data;\n }\n var children = node.children;\n var children_count = children.length;\n\n layout_data.direction = direction;\n layout_data.side_index = side_index;\n var i = children_count;\n while (i--) {\n this._layout_direction_side(children[i], direction, i);\n }\n }\n /** Calculate and set position offsets for all nodes. */\n layout_offset() {\n var node = this.jm.mind.root;\n var layout_data = node._data.layout;\n layout_data.offset_x = 0;\n layout_data.offset_y = 0;\n layout_data.outer_height = 0;\n var children = node.children;\n var i = children.length;\n var left_nodes = [];\n var right_nodes = [];\n var subnode = null;\n while (i--) {\n subnode = children[i];\n if (subnode._data.layout.direction == Direction.right) {\n right_nodes.unshift(subnode);\n } else {\n left_nodes.unshift(subnode);\n }\n }\n layout_data.left_nodes = left_nodes;\n layout_data.right_nodes = right_nodes;\n layout_data.outer_height_left = this._layout_offset_subnodes(left_nodes);\n layout_data.outer_height_right = this._layout_offset_subnodes(right_nodes);\n this.bounds.e = node._data.view.width / 2;\n this.bounds.w = 0 - this.bounds.e;\n this.bounds.n = 0;\n this.bounds.s = Math.max(layout_data.outer_height_left, layout_data.outer_height_right);\n }\n /**\n * Layout both the x and y axis for subnodes.\n * @private\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\n * @returns {number} Total height of all nodes\n */\n _layout_offset_subnodes(nodes) {\n var total_height = 0;\n var nodes_count = nodes.length;\n var i = nodes_count;\n var node = null;\n var node_outer_height = 0;\n var layout_data = null;\n var base_y = 0;\n var pd = null; // parent._data\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (pd == null) {\n pd = node.parent._data;\n }\n\n node_outer_height = this._layout_offset_subnodes(node.children);\n if (!node.expanded) {\n node_outer_height = 0;\n this.set_visible(node.children, false);\n }\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\n\n if (this._should_reserve_cousin_space(node)) {\n node_outer_height += this.opts.cousin_space;\n }\n\n layout_data.outer_height = node_outer_height;\n layout_data.offset_y = base_y - node_outer_height / 2;\n layout_data.offset_x =\n this.opts.hspace * layout_data.direction +\n (pd.view.width * (pd.layout.direction + layout_data.direction)) / 2;\n if (!node.parent.isroot) {\n layout_data.offset_x += this.opts.pspace * layout_data.direction;\n }\n\n base_y = base_y - node_outer_height - this.opts.vspace;\n total_height += node_outer_height;\n }\n if (nodes_count > 1) {\n total_height += this.opts.vspace * (nodes_count - 1);\n }\n i = nodes_count;\n var middle_height = total_height / 2;\n while (i--) {\n node = nodes[i];\n node._data.layout.offset_y += middle_height;\n }\n return total_height;\n }\n /**\n * Layout the y axis only, for collapse/expand a node.\n * @private\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\n * @returns {number} Total height of all nodes\n */\n _layout_offset_subnodes_height(nodes) {\n var total_height = 0;\n var nodes_count = nodes.length;\n var i = nodes_count;\n var node = null;\n var node_outer_height = 0;\n var layout_data = null;\n var base_y = 0;\n var pd = null; // parent._data\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (pd == null) {\n pd = node.parent._data;\n }\n\n node_outer_height = this._layout_offset_subnodes_height(node.children);\n if (!node.expanded) {\n node_outer_height = 0;\n }\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\n if (this._should_reserve_cousin_space(node)) {\n node_outer_height += this.opts.cousin_space;\n }\n\n layout_data.outer_height = node_outer_height;\n layout_data.offset_y = base_y - node_outer_height / 2;\n base_y = base_y - node_outer_height - this.opts.vspace;\n total_height += node_outer_height;\n }\n if (nodes_count > 1) {\n total_height += this.opts.vspace * (nodes_count - 1);\n }\n i = nodes_count;\n var middle_height = total_height / 2;\n while (i--) {\n node = nodes[i];\n node._data.layout.offset_y += middle_height;\n }\n return total_height;\n }\n /**\n * Check if node should reserve cousin space.\n * @private\n * @param {import('./jsmind.node.js').Node} node - Node to check\n * @returns {boolean} True if cousin space should be reserved\n */\n _should_reserve_cousin_space(node) {\n return node.children.length > 0 && node.parent.children.length > 1;\n }\n /**\n * Get absolute offset for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Absolute position offset\n */\n get_node_offset(node) {\n var layout_data = node._data.layout;\n var offset_cache = null;\n if ('_offset_' in layout_data && this.cache_valid) {\n offset_cache = layout_data._offset_;\n } else {\n offset_cache = { x: -1, y: -1 };\n layout_data._offset_ = offset_cache;\n }\n if (offset_cache.x == -1 || offset_cache.y == -1) {\n var x = layout_data.offset_x;\n var y = layout_data.offset_y;\n if (!node.isroot) {\n var offset_p = this.get_node_offset(node.parent);\n x += offset_p.x;\n y += offset_p.y;\n }\n offset_cache.x = x;\n offset_cache.y = y;\n }\n return offset_cache;\n }\n /**\n * Get anchor point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Anchor point coordinates\n */\n get_node_point(node) {\n var view_data = node._data.view;\n var offset_p = this.get_node_offset(node);\n var p = {};\n p.x = offset_p.x + (view_data.width * (node._data.layout.direction - 1)) / 2;\n p.y = offset_p.y - view_data.height / 2;\n return p;\n }\n /**\n * Get input point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Input point coordinates\n */\n get_node_point_in(node) {\n var p = this.get_node_offset(node);\n return p;\n }\n /**\n * Get output point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Output point coordinates\n */\n get_node_point_out(node) {\n var layout_data = node._data.layout;\n var pout_cache = null;\n if ('_pout_' in layout_data && this.cache_valid) {\n pout_cache = layout_data._pout_;\n } else {\n pout_cache = { x: -1, y: -1 };\n layout_data._pout_ = pout_cache;\n }\n if (pout_cache.x == -1 || pout_cache.y == -1) {\n if (node.isroot) {\n pout_cache.x = 0;\n pout_cache.y = 0;\n } else {\n var view_data = node._data.view;\n var offset_p = this.get_node_offset(node);\n pout_cache.x =\n offset_p.x + (view_data.width + this.opts.pspace) * node._data.layout.direction;\n pout_cache.y = offset_p.y;\n }\n }\n return pout_cache;\n }\n /**\n * Get expander point for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Expander point coordinates\n */\n get_expander_point(node) {\n var p = this.get_node_point_out(node);\n var ex_p = {};\n if (node._data.layout.direction == Direction.right) {\n ex_p.x = p.x - this.opts.pspace;\n } else {\n ex_p.x = p.x;\n }\n ex_p.y = p.y - Math.ceil(this.opts.pspace / 2);\n return ex_p;\n }\n /**\n * Get minimal canvas size to contain all nodes.\n * @returns {{w:number, h:number}} Minimum size required\n */\n get_min_size() {\n var nodes = this.jm.mind.nodes;\n var node = null;\n var pout = null;\n for (var node_id in nodes) {\n node = nodes[node_id];\n pout = this.get_node_point_out(node);\n if (pout.x > this.bounds.e) {\n this.bounds.e = pout.x;\n }\n if (pout.x < this.bounds.w) {\n this.bounds.w = pout.x;\n }\n }\n return {\n w: this.bounds.e - this.bounds.w,\n h: this.bounds.s - this.bounds.n,\n };\n }\n /**\n * Toggle node expanded/collapsed state.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n toggle_node(node) {\n if (node.isroot) {\n return;\n }\n if (node.expanded) {\n this.collapse_node(node);\n } else {\n this.expand_node(node);\n }\n }\n /**\n * Expand a node and show its children.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n expand_node(node) {\n node.expanded = true;\n this.part_layout(node);\n this.set_visible(node.children, true);\n this.jm.invoke_event_handle(EventType.show, {\n evt: 'expand_node',\n data: [],\n node: node.id,\n });\n }\n /**\n * Collapse a node and hide its children.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n collapse_node(node) {\n node.expanded = false;\n this.part_layout(node);\n this.set_visible(node.children, false);\n this.jm.invoke_event_handle(EventType.show, {\n evt: 'collapse_node',\n data: [],\n node: node.id,\n });\n }\n /** Expand all nodes in the mind map. */\n expand_all() {\n var nodes = this.jm.mind.nodes;\n var c = 0;\n var node;\n for (var node_id in nodes) {\n node = nodes[node_id];\n if (!node.expanded) {\n node.expanded = true;\n c++;\n }\n }\n if (c > 0) {\n var root = this.jm.mind.root;\n this.part_layout(root);\n this.set_visible(root.children, true);\n }\n }\n /** Collapse all nodes in the mind map. */\n collapse_all() {\n var nodes = this.jm.mind.nodes;\n var c = 0;\n var node;\n for (var node_id in nodes) {\n node = nodes[node_id];\n if (node.expanded && !node.isroot) {\n node.expanded = false;\n c++;\n }\n }\n if (c > 0) {\n var root = this.jm.mind.root;\n this.part_layout(root);\n this.set_visible(root.children, true);\n }\n }\n /**\n * Expand nodes to a specific depth level.\n * @param {number} target_depth - Target depth level\n * @param {import('./jsmind.node.js').Node[]=} curr_nodes - Current nodes to process\n * @param {number=} curr_depth - Current depth level\n */\n expand_to_depth(target_depth, curr_nodes, curr_depth) {\n if (target_depth < 1) {\n return;\n }\n var nodes = curr_nodes || this.jm.mind.root.children;\n var depth = curr_depth || 1;\n var i = nodes.length;\n var node = null;\n while (i--) {\n node = nodes[i];\n if (depth < target_depth) {\n if (!node.expanded) {\n this.expand_node(node);\n }\n this.expand_to_depth(target_depth, node.children, depth + 1);\n }\n if (depth == target_depth) {\n if (node.expanded) {\n this.collapse_node(node);\n }\n }\n }\n }\n /**\n * Perform partial layout for a node and its subtree.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n part_layout(node) {\n var root = this.jm.mind.root;\n if (!!root) {\n var root_layout_data = root._data.layout;\n if (node.isroot) {\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\n root_layout_data.right_nodes\n );\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\n root_layout_data.left_nodes\n );\n } else {\n if (node._data.layout.direction == Direction.right) {\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\n root_layout_data.right_nodes\n );\n } else {\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\n root_layout_data.left_nodes\n );\n }\n }\n this.bounds.s = Math.max(\n root_layout_data.outer_height_left,\n root_layout_data.outer_height_right\n );\n this.cache_valid = false;\n } else {\n logger.warn('can not found root node');\n }\n }\n /**\n * Set visibility for nodes and their children.\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes\n * @param {boolean} visible - Visibility state\n */\n set_visible(nodes, visible) {\n var i = nodes.length;\n var node = null;\n var layout_data = null;\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (node.expanded) {\n this.set_visible(node.children, visible);\n } else {\n this.set_visible(node.children, false);\n }\n if (!node.isroot) {\n node._data.layout.visible = visible;\n }\n }\n }\n /**\n * Check if a node is expanded.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {boolean} True if node is expanded\n */\n is_expand(node) {\n return node.expanded;\n }\n /**\n * Check if a node is visible.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {boolean} True if node is visible\n */\n is_visible(node) {\n var layout_data = node._data.layout;\n if ('visible' in layout_data && !layout_data.visible) {\n return false;\n } else {\n return true;\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\nimport { logger } from './jsmind.common.js';\n\n/**\n * SVG-based graph renderer.\n */\nclass SvgGraph {\n /**\n * Create SVG graph renderer.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n */\n constructor(view) {\n this.view = view;\n this.opts = view.opts;\n this.e_svg = SvgGraph.c('svg');\n this.e_svg.setAttribute('class', 'jsmind');\n this.size = { w: 0, h: 0 };\n /** @type {SVGPathElement[]} */\n this.lines = [];\n this.line_drawing = {\n straight: this._line_to,\n curved: this._bezier_to,\n };\n this.init_line_render();\n }\n /** @param {string} tag */\n static c(tag) {\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\n }\n /** Choose line drawing renderer. */\n init_line_render() {\n if (typeof this.opts.custom_line_render === 'function') {\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = (path, x1, y1, x2, y2) => {\n try {\n this.opts.custom_line_render.call(this, {\n ctx: path,\n start_point: { x: x1, y: y1 },\n end_point: { x: x2, y: y2 },\n });\n } catch (e) {\n logger.error('custom line renderer error: ', e);\n }\n };\n } else {\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\n }\n }\n /** @returns {SVGSVGElement} */\n element() {\n return this.e_svg;\n }\n /** @param {number} w @param {number} h */\n set_size(w, h) {\n this.size.w = w;\n this.size.h = h;\n this.e_svg.setAttribute('width', w);\n this.e_svg.setAttribute('height', h);\n }\n clear() {\n var len = this.lines.length;\n while (len--) {\n this.e_svg.removeChild(this.lines[len]);\n }\n this.lines.length = 0;\n }\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\n draw_line(pout, pin, offset, color) {\n var line = SvgGraph.c('path');\n line.setAttribute('stroke', color || this.opts.line_color);\n line.setAttribute('stroke-width', this.opts.line_width);\n line.setAttribute('fill', 'transparent');\n this.lines.push(line);\n this.e_svg.appendChild(line);\n this.drawing(\n line,\n pin.x + offset.x,\n pin.y + offset.y,\n pout.x + offset.x,\n pout.y + offset.y\n );\n }\n\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\n copy_to(dest_canvas_ctx, callback) {\n var img = new Image();\n img.onload = function () {\n dest_canvas_ctx.drawImage(img, 0, 0);\n !!callback && callback();\n };\n img.src =\n 'data:image/svg+xml;base64,' + btoa(new XMLSerializer().serializeToString(this.e_svg));\n }\n /**\n * Draw bezier curve to SVG path.\n * @internal\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _bezier_to(path, x1, y1, x2, y2) {\n path.setAttribute(\n 'd',\n 'M ' +\n x1 +\n ' ' +\n y1 +\n ' C ' +\n (x1 + ((x2 - x1) * 2) / 3) +\n ' ' +\n y1 +\n ', ' +\n x1 +\n ' ' +\n y2 +\n ', ' +\n x2 +\n ' ' +\n y2\n );\n }\n /**\n * Draw straight line to SVG path.\n * @internal\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _line_to(path, x1, y1, x2, y2) {\n path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2);\n }\n}\n\n/**\n * Canvas-based graph renderer.\n */\nclass CanvasGraph {\n /**\n * Create canvas graph renderer.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n */\n constructor(view) {\n this.opts = view.opts;\n this.e_canvas = $.c('canvas');\n this.e_canvas.className = 'jsmind';\n this.canvas_ctx = /** @type {CanvasRenderingContext2D} */ (this.e_canvas.getContext('2d'));\n this.size = { w: 0, h: 0 };\n this.line_drawing = {\n straight: this._line_to,\n curved: this._bezier_to,\n };\n this.dpr = view.device_pixel_ratio;\n this.init_line_render();\n }\n /** Choose line drawing renderer. */\n init_line_render() {\n if (typeof this.opts.custom_line_render === 'function') {\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = (ctx, x1, y1, x2, y2) => {\n try {\n this.opts.custom_line_render.call(this, {\n ctx,\n start_point: { x: x1, y: y1 },\n end_point: { x: x2, y: y2 },\n });\n } catch (e) {\n logger.error('custom line render error: ', e);\n }\n };\n } else {\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\n }\n }\n /** @returns {HTMLCanvasElement} */\n element() {\n return this.e_canvas;\n }\n /** @param {number} w @param {number} h */\n set_size(w, h) {\n this.size.w = w;\n this.size.h = h;\n if (this.e_canvas.width && this.e_canvas.height && this.canvas_ctx.scale) {\n this.e_canvas.width = w * this.dpr;\n this.e_canvas.height = h * this.dpr;\n\n this.e_canvas.style.width = w + 'px';\n this.e_canvas.style.height = h + 'px';\n this.canvas_ctx.scale(this.dpr, this.dpr);\n } else {\n this.e_canvas.width = w;\n this.e_canvas.height = h;\n }\n }\n\n /** Clear the canvas. */\n clear() {\n this.canvas_ctx.clearRect(0, 0, this.size.w, this.size.h);\n }\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\n draw_line(pout, pin, offset, color) {\n var ctx = this.canvas_ctx;\n ctx.strokeStyle = color || this.opts.line_color;\n ctx.lineWidth = this.opts.line_width;\n ctx.lineCap = 'round';\n this.drawing(ctx, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y);\n }\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\n copy_to(dest_canvas_ctx, callback) {\n dest_canvas_ctx.drawImage(this.e_canvas, 0, 0, this.size.w, this.size.h);\n !!callback && callback();\n }\n /**\n * Draw bezier curve on canvas.\n * @internal\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _bezier_to(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.bezierCurveTo(x1 + ((x2 - x1) * 2) / 3, y1, x1, y2, x2, y2);\n ctx.stroke();\n }\n /**\n * Draw straight line on canvas.\n * @internal\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _line_to(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n}\n\n/**\n * Initialize graph renderer based on engine type.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n * @param {'canvas'|'svg'} engine - Rendering engine type\n * @returns {SvgGraph|CanvasGraph} Graph renderer instance\n */\nexport function init_graph(view, engine) {\n return engine.toLowerCase() === 'svg' ? new SvgGraph(view) : new CanvasGraph(view);\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\nimport { logger, EventType } from './jsmind.common.js';\nimport { $ } from './jsmind.dom.js';\nimport { init_graph } from './jsmind.graph.js';\nimport { util } from './jsmind.util.js';\n\nexport class ViewProvider {\n /**\n * View layer: DOM nodes, editor, graph and zoom.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n * @param {{\n * engine: 'canvas'|'svg',\n * enable_device_pixel_ratio: boolean,\n * hmargin: number,\n * vmargin: number,\n * line_width: number,\n * line_color: string,\n * line_style: 'curved'|'straight',\n * custom_line_render?: Function,\n * draggable: boolean,\n * hide_scrollbars_when_draggable: boolean,\n * node_overflow: 'hidden'|'wrap',\n * zoom: {min:number, max:number, step:number, mask_key:number},\n * custom_node_render?: Function,\n * expander_style: 'char'|'number'\n * }} options - View configuration options\n */\n constructor(jm, options) {\n this.opts = options;\n this.jm = jm;\n this.layout = jm.layout;\n\n this.container = null;\n this.e_panel = null;\n this.e_nodes = null;\n\n this.size = { w: 0, h: 0 };\n\n this.selected_node = null;\n this.editing_node = null;\n\n this.graph = null;\n this.render_node = !!options.custom_node_render\n ? this._custom_node_render\n : this._default_node_render;\n this.zoom_current = 1;\n this.device_pixel_ratio = this.opts.enable_device_pixel_ratio\n ? $.w.devicePixelRatio || 1\n : 1;\n this._initialized = false;\n }\n /** Initialize DOM structure, graph and editor. */\n init() {\n logger.debug(this.opts);\n logger.debug('view.init');\n\n this.container = $.i(this.opts.container)\n ? /** @type {HTMLElement} */ (this.opts.container)\n : /** @type {HTMLElement} */ ($.g(this.opts.container));\n if (!this.container) {\n logger.error('the options.view.container was not be found in dom');\n return;\n }\n this.graph = init_graph(this, this.opts.engine);\n\n this.e_panel = $.c('div');\n this.e_nodes = $.c('jmnodes');\n this.e_editor = $.c('input');\n this.e_panel.className = 'jsmind-inner jmnode-overflow-' + this.opts.node_overflow;\n this.e_panel.tabIndex = 1;\n this.e_panel.appendChild(this.graph.element());\n this.e_panel.appendChild(this.e_nodes);\n\n this.e_editor.className = 'jsmind-editor';\n this.e_editor.type = 'text';\n\n var v = this;\n $.on(this.e_editor, 'keydown', function (e) {\n var evt = e || event;\n if (evt.keyCode == 13) {\n v.edit_node_end();\n evt.stopPropagation();\n }\n });\n $.on(this.e_editor, 'blur', function (e) {\n v.edit_node_end();\n });\n\n this.container.appendChild(this.e_panel);\n\n if (!this.container.offsetParent) {\n new IntersectionObserver((entities, observer) => {\n if (entities[0].isIntersecting) {\n observer.unobserve(this.e_panel);\n this.resize();\n }\n }).observe(this.e_panel);\n }\n }\n\n /**\n * Add a delegated event handler.\n * @param {import('./jsmind.js').default} obj\n * @param {string} event_name\n * @param {(e:Event)=>void} event_handle\n * @param {boolean=} capture_by_panel\n */\n add_event(obj, event_name, event_handle, capture_by_panel) {\n let target = !!capture_by_panel ? this.e_panel : this.e_nodes;\n $.on(target, event_name, function (e) {\n var evt = e || event;\n event_handle.call(obj, evt);\n });\n }\n /**\n * @param {HTMLElement|null} element\n * @returns {string|null}\n */\n get_binded_nodeid(element) {\n if (element == null) {\n return null;\n }\n var tagName = element.tagName.toLowerCase();\n if (tagName == 'jmnode' || tagName == 'jmexpander') {\n return element.getAttribute('nodeid');\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\n return null;\n } else {\n return this.get_binded_nodeid(element.parentElement);\n }\n }\n /**\n * @param {HTMLElement|null} element\n * @returns {boolean}\n */\n is_node(element) {\n if (element == null) {\n return false;\n }\n var tagName = element.tagName.toLowerCase();\n if (tagName == 'jmnode') {\n return true;\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\n return false;\n } else {\n return this.is_node(element.parentElement);\n }\n }\n /**\n * @param {HTMLElement} element\n * @returns {boolean}\n */\n is_expander(element) {\n return element.tagName.toLowerCase() == 'jmexpander';\n }\n reset() {\n logger.debug('view.reset');\n this.selected_node = null;\n this.clear_lines();\n this.clear_nodes();\n this.reset_theme();\n }\n reset_theme() {\n var theme_name = this.jm.options.theme;\n if (!!theme_name) {\n this.e_nodes.className = 'theme-' + theme_name;\n } else {\n this.e_nodes.className = '';\n }\n }\n /** Reset custom styles for all nodes. */\n reset_custom_style() {\n var nodes = this.jm.mind.nodes;\n for (var nodeid in nodes) {\n this.reset_node_custom_style(nodes[nodeid]);\n }\n }\n /** Load and initialize the view. */\n load() {\n logger.debug('view.load');\n this.setup_canvas_draggable(this.opts.draggable);\n this.init_nodes();\n this._initialized = true;\n }\n /** Calculate and set the expanded canvas size. */\n expand_size() {\n var min_size = this.layout.get_min_size();\n var min_width = min_size.w + this.opts.hmargin * 2;\n var min_height = min_size.h + this.opts.vmargin * 2;\n var client_w = this.e_panel.clientWidth;\n var client_h = this.e_panel.clientHeight;\n if (client_w < min_width) {\n client_w = min_width;\n }\n if (client_h < min_height) {\n client_h = min_height;\n }\n this.size.w = client_w;\n this.size.h = client_h;\n }\n /**\n * Initialize size data for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n init_nodes_size(node) {\n var view_data = node._data.view;\n view_data.width = view_data.element.clientWidth;\n view_data.height = view_data.element.clientHeight;\n }\n /** Initialize DOM elements for all nodes. */\n init_nodes() {\n var nodes = this.jm.mind.nodes;\n var doc_frag = $.d.createDocumentFragment();\n for (var nodeid in nodes) {\n this.create_node_element(nodes[nodeid], doc_frag);\n }\n this.e_nodes.appendChild(doc_frag);\n\n this.run_in_c11y_mode_if_needed(() => {\n for (var nodeid in nodes) {\n this.init_nodes_size(nodes[nodeid]);\n }\n });\n }\n /**\n * Add a new node to the view.\n * @param {import('./jsmind.node.js').Node} node - Node to add\n */\n add_node(node) {\n this.create_node_element(node, this.e_nodes);\n this.run_in_c11y_mode_if_needed(() => {\n this.init_nodes_size(node);\n });\n }\n /**\n * Run function in compatibility mode if container is not visible.\n * @param {Function} func - Function to execute\n */\n run_in_c11y_mode_if_needed(func) {\n if (!!this.container.offsetParent) {\n func();\n return;\n }\n logger.warn(\n 'init nodes in compatibility mode. because the container or its parent has style {display:none}. '\n );\n this.e_panel.style.position = 'absolute';\n this.e_panel.style.top = '-100000';\n $.d.body.appendChild(this.e_panel);\n func();\n this.container.appendChild(this.e_panel);\n this.e_panel.style.position = null;\n this.e_panel.style.top = null;\n }\n /**\n * Create a DOM element for a node and append to parent container.\n * @param {import('./jsmind.node.js').Node} node\n * @param {HTMLElement} parent_node\n */\n create_node_element(node, parent_node) {\n var view_data = null;\n if ('view' in node._data) {\n view_data = node._data.view;\n } else {\n view_data = {};\n node._data.view = view_data;\n }\n\n var d = $.c('jmnode');\n if (node.isroot) {\n d.className = 'root';\n } else {\n var d_e = $.c('jmexpander');\n $.t(d_e, '-');\n d_e.setAttribute('nodeid', node.id);\n d_e.style.visibility = 'hidden';\n parent_node.appendChild(d_e);\n view_data.expander = d_e;\n }\n if (!!node.topic) {\n this.render_node(d, node);\n }\n d.setAttribute('nodeid', node.id);\n d.style.visibility = 'hidden';\n this._reset_node_custom_style(d, node.data);\n\n parent_node.appendChild(d);\n view_data.element = d;\n }\n /**\n * Remove a node from the view.\n * @param {import('./jsmind.node.js').Node} node - Node to remove\n */\n remove_node(node) {\n if (this.selected_node != null && this.selected_node.id == node.id) {\n this.selected_node = null;\n }\n if (this.editing_node != null && this.editing_node.id == node.id) {\n node._data.view.element.removeChild(this.e_editor);\n this.editing_node = null;\n }\n var children = node.children;\n var i = children.length;\n while (i--) {\n this.remove_node(children[i]);\n }\n if (node._data.view) {\n var element = node._data.view.element;\n var expander = node._data.view.expander;\n this.e_nodes.removeChild(element);\n this.e_nodes.removeChild(expander);\n node._data.view.element = null;\n node._data.view.expander = null;\n }\n }\n /**\n * Update a node's display.\n * @param {import('./jsmind.node.js').Node} node - Node to update\n */\n update_node(node) {\n var view_data = node._data.view;\n var element = view_data.element;\n if (!!node.topic) {\n this.render_node(element, node);\n }\n if (this.layout.is_visible(node)) {\n view_data.width = element.clientWidth;\n view_data.height = element.clientHeight;\n } else {\n let origin_style = element.getAttribute('style');\n element.style = 'visibility: visible; left:0; top:0;';\n view_data.width = element.clientWidth;\n view_data.height = element.clientHeight;\n element.style = origin_style;\n }\n }\n /**\n * Select a node visually.\n * @param {import('./jsmind.node.js').Node|null} node - Node to select\n */\n select_node(node) {\n if (!!this.selected_node) {\n var element = this.selected_node._data.view.element;\n element.className = element.className.replace(/\\s*selected\\b/i, '');\n this.restore_selected_node_custom_style(this.selected_node);\n }\n if (!!node) {\n this.selected_node = node;\n node._data.view.element.className += ' selected';\n this.clear_selected_node_custom_style(node);\n }\n }\n /** Clear node selection. */\n select_clear() {\n this.select_node(null);\n }\n /**\n * Get currently editing node.\n * @returns {import('./jsmind.node.js').Node|null} Currently editing node\n */\n get_editing_node() {\n return this.editing_node;\n }\n /**\n * Check if any node is being edited.\n * @returns {boolean} True if editing\n */\n is_editing() {\n return !!this.editing_node;\n }\n /**\n * Begin editing a node.\n * @param {import('./jsmind.node.js').Node} node - Node to edit\n */\n edit_node_begin(node) {\n if (!node.topic) {\n logger.warn(\"don't edit image nodes\");\n return;\n }\n if (this.editing_node != null) {\n this.edit_node_end();\n }\n this.editing_node = node;\n var view_data = node._data.view;\n var element = view_data.element;\n var topic = node.topic;\n var ncs = getComputedStyle(element);\n this.e_editor.value = topic;\n this.e_editor.style.width =\n element.clientWidth -\n parseInt(ncs.getPropertyValue('padding-left')) -\n parseInt(ncs.getPropertyValue('padding-right')) +\n 'px';\n element.innerHTML = '';\n element.appendChild(this.e_editor);\n element.style.zIndex = 5;\n this.e_editor.focus();\n this.e_editor.select();\n }\n /** End editing current node. */\n edit_node_end() {\n if (this.editing_node != null) {\n var node = this.editing_node;\n this.editing_node = null;\n var view_data = node._data.view;\n var element = view_data.element;\n var topic = this.e_editor.value;\n element.style.zIndex = 'auto';\n element.removeChild(this.e_editor);\n if (util.text.is_empty(topic) || node.topic === topic) {\n this.render_node(element, node);\n } else {\n this.jm.update_node(node.id, topic);\n }\n }\n this.e_panel.focus();\n }\n /** @returns {{x:number,y:number}} */\n get_view_offset() {\n var bounds = this.layout.bounds;\n var _x = (this.size.w - bounds.e - bounds.w) / 2;\n var _y = this.size.h / 2;\n return { x: _x, y: _y };\n }\n /** Resize the view to fit container. */\n resize() {\n this.graph.set_size(1, 1);\n this.e_nodes.style.width = '1px';\n this.e_nodes.style.height = '1px';\n\n this.expand_size();\n this._show();\n }\n /**\n * Internal show implementation.\n * @private\n */\n _show() {\n this.graph.set_size(this.size.w, this.size.h);\n this.e_nodes.style.width = this.size.w + 'px';\n this.e_nodes.style.height = this.size.h + 'px';\n this.show_nodes();\n this.show_lines();\n //this.layout.cache_valid = true;\n this.jm.invoke_event_handle(EventType.resize, { data: [] });\n }\n /**\n * Zoom in the view.\n * @param {MouseEvent=} e - Mouse event for zoom center\n * @returns {boolean} True if zoom succeeded\n */\n zoom_in(e) {\n return this.set_zoom(this.zoom_current + this.opts.zoom.step, e);\n }\n /**\n * Zoom out the view.\n * @param {MouseEvent=} e - Mouse event for zoom center\n * @returns {boolean} True if zoom succeeded\n */\n zoom_out(e) {\n return this.set_zoom(this.zoom_current - this.opts.zoom.step, e);\n }\n /**\n * Set zoom level and keep scroll around zoom center.\n * @param {number} zoom\n * @param {MouseEvent=} e\n */\n set_zoom(zoom, e) {\n if (zoom < this.opts.zoom.min || zoom > this.opts.zoom.max) {\n return false;\n }\n let e_panel_rect = this.e_panel.getBoundingClientRect();\n if (\n zoom < 1 &&\n zoom < this.zoom_current &&\n this.size.w * zoom < e_panel_rect.width &&\n this.size.h * zoom < e_panel_rect.height\n ) {\n return false;\n }\n let zoom_center = !!e\n ? { x: e.x - e_panel_rect.x, y: e.y - e_panel_rect.y }\n : { x: e_panel_rect.width / 2, y: e_panel_rect.height / 2 };\n let panel_scroll_x =\n ((this.e_panel.scrollLeft + zoom_center.x) * zoom) / this.zoom_current - zoom_center.x;\n let panel_scroll_y =\n ((this.e_panel.scrollTop + zoom_center.y) * zoom) / this.zoom_current - zoom_center.y;\n\n this.zoom_current = zoom;\n for (var i = 0; i < this.e_panel.children.length; i++) {\n this.e_panel.children[i].style.zoom = zoom;\n }\n this._show();\n this.e_panel.scrollLeft = panel_scroll_x;\n this.e_panel.scrollTop = panel_scroll_y;\n return true;\n }\n /** @param {boolean=} keep_center */\n show(keep_center) {\n logger.debug(`view.show: {keep_center: ${keep_center}}`);\n this.expand_size();\n this._show();\n if (!!keep_center) {\n this.center_node(this.jm.mind.root);\n }\n }\n relayout() {\n this.expand_size();\n this._show();\n }\n /** @param {import('./jsmind.node.js').Node} node */\n save_location(node) {\n var vd = node._data.view;\n vd._saved_location = {\n x: parseInt(vd.element.style.left) - this.e_panel.scrollLeft,\n y: parseInt(vd.element.style.top) - this.e_panel.scrollTop,\n };\n }\n /** @param {import('./jsmind.node.js').Node} node */\n restore_location(node) {\n var vd = node._data.view;\n this.e_panel.scrollLeft = parseInt(vd.element.style.left) - vd._saved_location.x;\n this.e_panel.scrollTop = parseInt(vd.element.style.top) - vd._saved_location.y;\n }\n clear_nodes() {\n var mind = this.jm.mind;\n if (mind == null) {\n return;\n }\n var nodes = mind.nodes;\n var node = null;\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n node._data.view.element = null;\n node._data.view.expander = null;\n }\n this.e_nodes.innerHTML = '';\n }\n /** Render node elements and expanders to screen. */\n show_nodes() {\n var nodes = this.jm.mind.nodes;\n var node = null;\n var node_element = null;\n var p = null;\n var view_data = null;\n var view_offset = this.get_view_offset();\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n view_data = node._data.view;\n node_element = view_data.element;\n if (!this.layout.is_visible(node)) {\n node_element.style.display = 'none';\n view_data.expander.style.display = 'none';\n continue;\n }\n this.reset_node_custom_style(node);\n p = this.layout.get_node_point(node);\n view_data.abs_x = view_offset.x + p.x;\n view_data.abs_y = view_offset.y + p.y;\n node_element.style.left = view_offset.x + p.x + 'px';\n node_element.style.top = view_offset.y + p.y + 'px';\n node_element.style.display = '';\n node_element.style.visibility = 'visible';\n this._show_expander(node, view_offset);\n }\n }\n /** @param {import('./jsmind.node.js').Node} node @param {{x:number,y:number}} view_offset */\n _show_expander(node, view_offset) {\n if (node.isroot) {\n return;\n }\n\n var expander = node._data.view.expander;\n if (node.children.length == 0) {\n expander.style.display = 'none';\n expander.style.visibility = 'hidden';\n return;\n }\n\n let expander_text = this._get_expander_text(node);\n $.t(expander, expander_text);\n\n let p_expander = this.layout.get_expander_point(node);\n expander.style.left = view_offset.x + p_expander.x + 'px';\n expander.style.top = view_offset.y + p_expander.y + 'px';\n expander.style.display = '';\n expander.style.visibility = 'visible';\n }\n\n /** @param {import('./jsmind.node.js').Node} node */\n _get_expander_text(node) {\n let style = !!this.opts.expander_style ? this.opts.expander_style.toLowerCase() : 'char';\n if (style === 'number') {\n return node.children.length > 99 ? '...' : node.children.length;\n }\n if (style === 'char') {\n return node.expanded ? '-' : '+';\n }\n }\n\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\n _default_node_render(ele, node) {\n if (this.opts.support_html) {\n $.h(ele, node.topic);\n } else {\n $.t(ele, node.topic);\n }\n }\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\n _custom_node_render(ele, node) {\n let rendered = this.opts.custom_node_render(this.jm, ele, node);\n if (!rendered) {\n this._default_node_render(ele, node);\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n reset_node_custom_style(node) {\n this._reset_node_custom_style(node._data.view.element, node.data);\n }\n /** @param {HTMLElement} node_element @param {Record<string,string|number>} node_data */\n _reset_node_custom_style(node_element, node_data) {\n if ('background-color' in node_data) {\n node_element.style.backgroundColor = node_data['background-color'];\n }\n if ('foreground-color' in node_data) {\n node_element.style.color = node_data['foreground-color'];\n }\n if ('width' in node_data) {\n node_element.style.width = node_data['width'] + 'px';\n }\n if ('height' in node_data) {\n node_element.style.height = node_data['height'] + 'px';\n }\n if ('font-size' in node_data) {\n node_element.style.fontSize = node_data['font-size'] + 'px';\n }\n if ('font-weight' in node_data) {\n node_element.style.fontWeight = node_data['font-weight'];\n }\n if ('font-style' in node_data) {\n node_element.style.fontStyle = node_data['font-style'];\n }\n if ('background-image' in node_data) {\n var backgroundImage = node_data['background-image'];\n if (backgroundImage.startsWith('data') && node_data['width'] && node_data['height']) {\n var img = new Image();\n\n img.onload = function () {\n var c = $.c('canvas');\n c.width = node_element.clientWidth;\n c.height = node_element.clientHeight;\n var img = this;\n if (c.getContext) {\n var ctx = c.getContext('2d');\n ctx.drawImage(\n img,\n 2,\n 2,\n node_element.clientWidth,\n node_element.clientHeight\n );\n var scaledImageData = c.toDataURL();\n node_element.style.backgroundImage = 'url(' + scaledImageData + ')';\n }\n };\n img.src = backgroundImage;\n } else {\n node_element.style.backgroundImage = 'url(' + backgroundImage + ')';\n }\n node_element.style.backgroundSize = '99%';\n\n if ('background-rotation' in node_data) {\n node_element.style.transform =\n 'rotate(' + node_data['background-rotation'] + 'deg)';\n }\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n restore_selected_node_custom_style(node) {\n var node_element = node._data.view.element;\n var node_data = node.data;\n if ('background-color' in node_data) {\n node_element.style.backgroundColor = node_data['background-color'];\n }\n if ('foreground-color' in node_data) {\n node_element.style.color = node_data['foreground-color'];\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n clear_selected_node_custom_style(node) {\n var node_element = node._data.view.element;\n node_element.style.backgroundColor = '';\n node_element.style.color = '';\n }\n clear_lines() {\n this.graph.clear();\n }\n show_lines() {\n this.clear_lines();\n var nodes = this.jm.mind.nodes;\n var node = null;\n var pin = null;\n var pout = null;\n var color = null;\n var _offset = this.get_view_offset();\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n if (!!node.isroot) {\n continue;\n }\n if (!this.layout.is_visible(node)) {\n continue;\n }\n pin = this.layout.get_node_point_in(node);\n pout = this.layout.get_node_point_out(node.parent);\n color = node.data['leading-line-color'];\n this.graph.draw_line(pout, pin, _offset, color);\n }\n }\n // Drag the whole mind map with your mouse, when it's larger that the container\n /**\n * Enable/disable dragging the whole canvas with mouse.\n * @param {boolean} enabled\n */\n setup_canvas_draggable(enabled) {\n this.opts.draggable = enabled;\n if (!this._initialized) {\n let dragging = false;\n let x, y;\n if (this.opts.hide_scrollbars_when_draggable) {\n // Avoid scrollbars when mind map is larger than the container (e_panel = id jsmind-inner)\n this.e_panel.style = 'overflow: hidden';\n }\n // Move the whole mind map with mouse moves, while button is down.\n $.on(this.container, 'mousedown', eventDown => {\n if (this.opts.draggable) {\n dragging = true;\n // Record current mouse position.\n x = eventDown.clientX;\n y = eventDown.clientY;\n }\n });\n // Stop moving mind map once mouse button is released.\n $.on(this.container, 'mouseup', () => {\n dragging = false;\n });\n // Follow current mouse position and move mind map accordingly.\n $.on(this.container, 'mousemove', eventMove => {\n if (this.opts.draggable) {\n if (dragging) {\n this.e_panel.scrollBy(x - eventMove.clientX, y - eventMove.clientY);\n // Record new current position.\n x = eventMove.clientX;\n y = eventMove.clientY;\n }\n }\n });\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n center_node(node) {\n if (!this.layout.is_visible(node)) {\n logger.warn('can not scroll to the node, because it is invisible');\n return false;\n }\n let view_data = node._data.view;\n let e_panel_rect = this.e_panel.getBoundingClientRect();\n let node_center_point = {\n x: view_data.abs_x + view_data.width / 2,\n y: view_data.abs_y + view_data.height / 2,\n };\n this.e_panel.scrollTo(\n node_center_point.x * this.zoom_current - e_panel_rect.width / 2,\n node_center_point.y * this.zoom_current - e_panel_rect.height / 2\n );\n return true;\n }\n\n /** @param {MouseEvent=} e */\n zoomIn(e) {\n logger.warn('please use zoom_in instead');\n return this.zoom_in(e);\n }\n /** @param {MouseEvent=} e */\n zoomOut(e) {\n logger.warn('please use zoom_out instead');\n return this.zoom_out(e);\n }\n /** @param {number} zoom @param {MouseEvent=} e */\n setZoom(zoom, e) {\n logger.warn('please use set_zoom instead');\n return this.set_zoom(zoom, e);\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\nimport { util } from './jsmind.util.js';\nimport { Direction } from './jsmind.common.js';\n\nexport class ShortcutProvider {\n /**\n * @param {import('./jsmind.js').default} jm\n * @param {{ enable:boolean, handles: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping: Record<string, number|number[]>, id_generator?: ()=>string }} options\n */\n constructor(jm, options) {\n this.jm = jm;\n this.opts = options;\n /** @type {Record<string, number|number[]>} */\n this.mapping = options.mapping;\n /** @type {Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\n this.handles = options.handles;\n /** @type {()=>string|null} */\n this._newid = null;\n /** @type {Record<number,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\n this._mapping = {};\n }\n init() {\n $.on(this.jm.view.e_panel, 'keydown', this.handler.bind(this));\n\n this.handles['addchild'] = this.handle_addchild;\n this.handles['addbrother'] = this.handle_addbrother;\n this.handles['editnode'] = this.handle_editnode;\n this.handles['delnode'] = this.handle_delnode;\n this.handles['toggle'] = this.handle_toggle;\n this.handles['up'] = this.handle_up;\n this.handles['down'] = this.handle_down;\n this.handles['left'] = this.handle_left;\n this.handles['right'] = this.handle_right;\n\n for (var handle in this.mapping) {\n if (!!this.mapping[handle] && handle in this.handles) {\n let keys = this.mapping[handle];\n if (!Array.isArray(keys)) {\n keys = [keys];\n }\n for (let key of keys) {\n this._mapping[key] = this.handles[handle];\n }\n }\n }\n\n if (typeof this.opts.id_generator === 'function') {\n this._newid = this.opts.id_generator;\n } else {\n this._newid = util.uuid.newid;\n }\n }\n enable_shortcut() {\n this.opts.enable = true;\n }\n disable_shortcut() {\n this.opts.enable = false;\n }\n /** @param {KeyboardEvent} e */\n handler(e) {\n if (e.which == 9) {\n e.preventDefault();\n } //prevent tab to change focus in browser\n if (this.jm.view.is_editing()) {\n return;\n }\n var evt = e || event;\n if (!this.opts.enable) {\n return true;\n }\n var kc =\n evt.keyCode +\n (evt.metaKey << 13) +\n (evt.ctrlKey << 12) +\n (evt.altKey << 11) +\n (evt.shiftKey << 10);\n if (kc in this._mapping) {\n this._mapping[kc].call(this, this.jm, e);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_addchild(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var node_id = this._newid();\n var node = _jm.add_node(selected_node, node_id, 'New Node');\n if (!!node) {\n _jm.select_node(node_id);\n _jm.begin_edit(node_id);\n }\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_addbrother(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node && !selected_node.isroot) {\n var node_id = this._newid();\n var node = _jm.insert_node_after(selected_node, node_id, 'New Node');\n if (!!node) {\n _jm.select_node(node_id);\n _jm.begin_edit(node_id);\n }\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_editnode(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n _jm.begin_edit(selected_node);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_delnode(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node && !selected_node.isroot) {\n _jm.select_node(selected_node.parent);\n _jm.remove_node(selected_node);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_toggle(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n _jm.toggle_node(selected_node.id);\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_up(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var up_node = _jm.find_node_before(selected_node);\n if (!up_node) {\n var np = _jm.find_node_before(selected_node.parent);\n if (!!np && np.children.length > 0) {\n up_node = np.children[np.children.length - 1];\n }\n }\n if (!!up_node) {\n _jm.select_node(up_node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_down(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var down_node = _jm.find_node_after(selected_node);\n if (!down_node) {\n var np = _jm.find_node_after(selected_node.parent);\n if (!!np && np.children.length > 0) {\n down_node = np.children[0];\n }\n }\n if (!!down_node) {\n _jm.select_node(down_node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_left(_jm, e) {\n this._handle_direction(_jm, e, Direction.left);\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_right(_jm, e) {\n this._handle_direction(_jm, e, Direction.right);\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e @param {number} d */\n _handle_direction(_jm, e, d) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n var node = null;\n if (!!selected_node) {\n if (selected_node.isroot) {\n var c = selected_node.children;\n var children = [];\n for (var i = 0; i < c.length; i++) {\n if (c[i].direction === d) {\n children.push(i);\n }\n }\n node = c[children[Math.floor((children.length - 1) / 2)]];\n } else if (selected_node.direction === d) {\n var children = selected_node.children;\n var children_count = children.length;\n if (children_count > 0) {\n node = children[Math.floor((children_count - 1) / 2)];\n }\n } else {\n node = selected_node.parent;\n }\n if (!!node) {\n _jm.select_node(node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/** @type {{ plugins: Array<Plugin<object>> }} */\nconst plugin_data = {\n plugins: [],\n};\n\n/**\n * Register a plugin instance.\n * @param {Plugin<object>} plugin\n */\nexport function register(plugin) {\n if (!(plugin instanceof Plugin)) {\n throw new Error('can not register plugin, it is not an instance of Plugin');\n }\n if (plugin_data.plugins.map(p => p.name).includes(plugin.name)) {\n throw new Error('can not register plugin ' + plugin.name + ': plugin name already exist');\n }\n plugin_data.plugins.push(plugin);\n}\n\n/**\n * Apply registered plugins asynchronously.\n * @param {import('./jsmind.js').default} jm\n * @param {Record<string, object>} options\n */\nexport function apply(jm, options) {\n $.w.setTimeout(function () {\n _apply(jm, options);\n }, 0);\n}\n\n/**\n * @param {import('./jsmind.js').default} jm\n * @param {Record<string, object>} options */\nfunction _apply(jm, options) {\n plugin_data.plugins.forEach(p => p.fn_init(jm, options[p.name]));\n}\n\nexport class Plugin {\n /**\n * @template [TOptions=object]\n * @param {string} name\n * @param {(jm: import('./jsmind.js').default, options: TOptions)=>void} fn_init\n */\n constructor(name, fn_init) {\n if (!name) {\n throw new Error('plugin must has a name');\n }\n if (!fn_init || typeof fn_init !== 'function') {\n throw new Error('plugin must has an init function');\n }\n this.name = name;\n this.fn_init = fn_init;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\n\n/**\n * Enhanced Plugin Manager\n * Manages the lifecycle of enhanced plugins with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class EnhancedPluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, EnhancedPlugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.enhancedPluginList.filter(d => d.preload);\n logger.info('Initializing ' + preloadPlugins.length + ' preload plugins');\n preloadPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Initialize normal plugins (after core modules)\n */\n initNormalPlugins() {\n const normalPlugins = this.jm.constructor.enhancedPluginList.filter(d => !d.preload);\n logger.info('Initializing ' + normalPlugins.length + ' normal plugins');\n normalPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Internal method: Initialize a single plugin\n * @param {PluginDescriptor} descriptor\n * @private\n */\n _initPlugin(descriptor) {\n try {\n const { PluginClass, pluginOpt } = descriptor;\n\n // Check instanceName\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n\n // Check naming conflict\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n // Instantiate plugin\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n // Save instance\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('Enhanced plugin ' + PluginClass.instanceName + ' initialized');\n } catch (error) {\n logger.error('Failed to initialize plugin ' + descriptor.PluginClass.name + ':', error);\n }\n }\n\n /**\n * Remove a plugin\n * @param {typeof EnhancedPlugin} PluginClass\n */\n removePlugin(PluginClass) {\n const instanceName = PluginClass.instanceName;\n if (!instanceName) {\n return;\n }\n\n const instance = this.plugins.get(instanceName);\n if (!instance) {\n return;\n }\n\n try {\n // Call lifecycle hook\n if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n // Remove from Map\n this.plugins.delete(instanceName);\n\n // Remove from jsMind instance\n delete this.jm[instanceName];\n\n // Remove from plugin list\n const list = this.jm.constructor.enhancedPluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('Enhanced plugin ' + instanceName + ' removed');\n } catch (error) {\n logger.error('Failed to remove plugin ' + instanceName + ':', error);\n }\n }\n\n /**\n * Destroy all plugins\n */\n destroyAllPlugins() {\n this.plugins.forEach((instance, instanceName) => {\n try {\n // Call lifecycle hook\n if (typeof instance.beforePluginDestroy === 'function') {\n instance.beforePluginDestroy();\n }\n } catch (error) {\n logger.error('Failed to destroy plugin ' + instanceName + ':', error);\n }\n });\n\n this.plugins.clear();\n }\n\n /**\n * Get plugin instance by name\n * @param {string} instanceName\n * @returns {EnhancedPlugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Enhanced Plugin Base Class\n * Provides standard interface for enhanced plugins\n */\nexport class EnhancedPlugin {\n /**\n * Plugin instance name (must be defined by subclass)\n * @type {string}\n */\n static instanceName = '';\n\n /**\n * Whether to initialize before core modules\n * @type {boolean}\n */\n static preload = false;\n\n /**\n * @param {{ jm: import('./jsmind.js').default, pluginOpt: object }} params\n */\n constructor({ jm, pluginOpt }) {\n this.jm = jm;\n this.options = pluginOpt || {};\n }\n\n /**\n * Called before plugin is removed\n * Override this method to clean up resources\n */\n beforePluginRemove() {\n // Default implementation: do nothing\n }\n\n /**\n * Called before jsMind instance is destroyed\n * Override this method to clean up resources\n */\n beforePluginDestroy() {\n // Default implementation: call beforePluginRemove\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof EnhancedPlugin} PluginClass - Plugin class\n * @property {string} instanceName - Plugin instance name\n * @property {boolean} preload - Whether to preload\n * @property {object} pluginOpt - Plugin options\n * @property {EnhancedPlugin | null} instance - Plugin instance (after initialization)\n */\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { __version__, logger, EventType, Direction, LogLevel } from './jsmind.common.js';\nimport { merge_option } from './jsmind.option.js';\nimport { Mind } from './jsmind.mind.js';\nimport { Node } from './jsmind.node.js';\nimport { DataProvider } from './jsmind.data_provider.js';\nimport { LayoutProvider } from './jsmind.layout_provider.js';\nimport { ViewProvider } from './jsmind.view_provider.js';\nimport { ShortcutProvider } from './jsmind.shortcut_provider.js';\nimport { Plugin, register as _register_plugin, apply as apply_plugins } from './jsmind.plugin.js';\nimport { EnhancedPluginManager, EnhancedPlugin } from './jsmind.enhanced-plugin.js';\nimport { format } from './jsmind.format.js';\nimport { $ } from './jsmind.dom.js';\nimport { util as _util } from './jsmind.util.js';\n\n/**\n * Event callback payload\n * @typedef {{ evt?: string, data?: unknown[], node?: string }} EventData\n */\n\n/**\n * jsMind runtime: orchestrates data/layout/view/shortcut and exposes public API.\n */\nexport default class jsMind {\n static mind = Mind;\n static node = Node;\n static direction = Direction;\n static event_type = EventType;\n static $ = $;\n static plugin = Plugin;\n static register_plugin = _register_plugin;\n static util = _util;\n static enhanced_plugin = EnhancedPlugin;\n\n /** @type {Array<import('./jsmind.enhanced-plugin.js').PluginDescriptor>} */\n static enhancedPluginList = [];\n\n /**\n * Register an enhanced plugin\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n * @param {object} [options={}] - Plugin options\n * @returns {typeof jsMind}\n */\n static usePlugin(PluginClass, options = {}) {\n // Check if already registered\n const exists = jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\n if (exists) {\n logger.warn('Plugin ' + PluginClass.name + ' already registered');\n return jsMind;\n }\n\n // Check instanceName\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n\n // Add to plugin list\n jsMind.enhancedPluginList.push({\n PluginClass,\n instanceName: PluginClass.instanceName,\n preload: PluginClass.preload || false,\n pluginOpt: options,\n instance: null,\n });\n\n return jsMind;\n }\n\n /**\n * Check if an enhanced plugin is registered\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n * @returns {boolean}\n */\n static hasEnhancedPlugin(PluginClass) {\n return jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\n }\n\n /**\n * Create a jsMind instance.\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\n */\n constructor(options) {\n jsMind.current = this;\n this.options = merge_option(options);\n logger.level(LogLevel[this.options.log_level]);\n this.version = __version__;\n this.initialized = false;\n this.mind = null;\n /** @type {Array<(type: number, data: EventData) => void>} */\n this.event_handles = [];\n this.init();\n }\n\n /** Initialize sub-systems and plugins. */\n init() {\n if (!!this.initialized) {\n return;\n }\n this.initialized = true;\n\n // Initialize enhanced plugin manager\n this.enhancedPluginManager = new EnhancedPluginManager(this);\n\n // Initialize preload plugins (before core modules)\n this.enhancedPluginManager.initPreloadPlugins();\n\n var opts_layout = {\n mode: this.options.mode,\n hspace: this.options.layout.hspace,\n vspace: this.options.layout.vspace,\n pspace: this.options.layout.pspace,\n cousin_space: this.options.layout.cousin_space,\n };\n var opts_view = {\n container: this.options.container,\n support_html: this.options.support_html,\n engine: this.options.view.engine,\n enable_device_pixel_ratio: this.options.view.enable_device_pixel_ratio,\n hmargin: this.options.view.hmargin,\n vmargin: this.options.view.vmargin,\n line_width: this.options.view.line_width,\n line_color: this.options.view.line_color,\n line_style: this.options.view.line_style,\n custom_line_render: this.options.view.custom_line_render,\n draggable: this.options.view.draggable,\n hide_scrollbars_when_draggable: this.options.view.hide_scrollbars_when_draggable,\n node_overflow: this.options.view.node_overflow,\n zoom: this.options.view.zoom,\n custom_node_render: this.options.view.custom_node_render,\n expander_style: this.options.view.expander_style,\n };\n // create instance of function provider\n this.data = new DataProvider(this);\n this.layout = new LayoutProvider(this, opts_layout);\n this.view = new ViewProvider(this, opts_view);\n this.shortcut = new ShortcutProvider(this, this.options.shortcut);\n\n this.data.init();\n this.layout.init();\n this.view.init();\n this.shortcut.init();\n\n this._event_bind();\n\n // Initialize normal plugins (after core modules)\n this.enhancedPluginManager.initNormalPlugins();\n\n // Apply old plugins (asynchronously)\n apply_plugins(this, this.options.plugin);\n }\n /** @returns {boolean} whether current mind map is editable */\n get_editable() {\n return this.options.editable;\n }\n /** enable editing */\n enable_edit() {\n this.options.editable = true;\n }\n /** disable editing */\n disable_edit() {\n this.options.editable = false;\n }\n /** @returns {boolean} whether view is draggable */\n get_view_draggable() {\n return this.options.view.draggable;\n }\n /** enable view dragging */\n enable_view_draggable() {\n this.options.view.draggable = true;\n this.view.setup_canvas_draggable(true);\n }\n /** disable view dragging */\n disable_view_draggable() {\n this.options.view.draggable = false;\n this.view.setup_canvas_draggable(false);\n }\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\n /**\n * Enable default event handle.\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\n */\n enable_event_handle(event_handle) {\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = true;\n }\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\n /**\n * Disable default event handle.\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\n */\n disable_event_handle(event_handle) {\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = false;\n }\n /**\n * Set theme name.\n * @param {string|null=} theme\n */\n set_theme(theme) {\n var theme_old = this.options.theme;\n this.options.theme = !!theme ? theme : null;\n if (theme_old != this.options.theme) {\n this.view.reset_theme();\n this.view.reset_custom_style();\n }\n }\n /** bind internal DOM events */\n _event_bind() {\n this.view.add_event(this, 'mousedown', this.mousedown_handle);\n this.view.add_event(this, 'click', this.click_handle);\n this.view.add_event(this, 'dblclick', this.dblclick_handle);\n this.view.add_event(this, 'wheel', this.mousewheel_handle, true);\n }\n /** @param {MouseEvent} e */\n mousedown_handle(e) {\n if (!this.options.default_event_handle['enable_mousedown_handle']) {\n return;\n }\n var element = e.target || event.srcElement;\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n if (this.view.is_node(element)) {\n this.select_node(node_id);\n }\n } else {\n this.select_clear();\n }\n }\n /** @param {MouseEvent} e */\n click_handle(e) {\n if (!this.options.default_event_handle['enable_click_handle']) {\n return;\n }\n var element = e.target || event.srcElement;\n var is_expander = this.view.is_expander(element);\n if (is_expander) {\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n this.toggle_node(node_id);\n }\n }\n }\n /** @param {MouseEvent} e */\n dblclick_handle(e) {\n if (!this.options.default_event_handle['enable_dblclick_handle']) {\n return;\n }\n if (this.get_editable()) {\n var element = e.target || event.srcElement;\n var is_node = this.view.is_node(element);\n if (is_node) {\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n this.begin_edit(node_id);\n }\n }\n }\n }\n // Use [Ctrl] + Mousewheel, to zoom in/out.\n /** @param {WheelEvent} e */\n mousewheel_handle(e) {\n // Test if mousewheel option is enabled and Ctrl key is pressed.\n var kc = (e.metaKey << 13) + (e.ctrlKey << 12) + (e.altKey << 11) + (e.shiftKey << 10);\n if (\n !this.options.default_event_handle['enable_mousewheel_handle'] ||\n this.options.view.zoom.mask_key !== kc\n ) {\n return;\n }\n var evt = e || event;\n // Avoid default page scrolling behavior.\n evt.preventDefault();\n\n if (evt.deltaY < 0) {\n this.view.zoom_in(evt); // wheel down\n } else {\n this.view.zoom_out(evt);\n }\n }\n /**\n * Begin editing a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {boolean|void}\n */\n begin_edit(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return false;\n } else {\n return this.begin_edit(the_node);\n }\n }\n if (this.get_editable()) {\n this.view.edit_node_begin(node);\n } else {\n logger.error('fail, this mind map is not editable.');\n return;\n }\n }\n /** End editing */\n end_edit() {\n this.view.edit_node_end();\n }\n /**\n * Toggle a node's expanded state.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n toggle_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.toggle_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.toggle_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /**\n * Expand a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n expand_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.expand_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.expand_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /**\n * Collapse a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n collapse_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.collapse_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.collapse_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /** Expand all nodes */\n expand_all() {\n this.layout.expand_all();\n this.view.relayout();\n }\n /** Collapse all nodes */\n collapse_all() {\n this.layout.collapse_all();\n this.view.relayout();\n }\n /**\n * Expand nodes up to a specified depth level.\n * @param {number} depth\n */\n expand_to_depth(depth) {\n this.layout.expand_to_depth(depth);\n this.view.relayout();\n }\n /** reset view/layout/data */\n _reset() {\n this.invoke_event_handle(EventType.reset, { data: [] });\n this.view.reset();\n this.layout.reset();\n this.data.reset();\n }\n /**\n * Internal show flow.\n * @param {object | null} mind\n * @param {boolean=} skip_centering\n */\n _show(mind, skip_centering) {\n var m = mind || format.node_array.example;\n this.mind = this.data.load(m);\n if (!this.mind) {\n logger.error('data.load error');\n return;\n } else {\n logger.debug('data.load ok');\n }\n\n this.view.load();\n logger.debug('view.load ok');\n\n this.layout.layout();\n logger.debug('layout.layout ok');\n\n this.view.show(!skip_centering);\n logger.debug('view.show ok');\n\n this.invoke_event_handle(EventType.show, { data: [mind] });\n }\n /**\n * Show a mind (or example) on the canvas.\n * @param {object | null} mind\n * @param {boolean=} skip_centering\n */\n show(mind, skip_centering) {\n this._reset();\n this._show(mind, skip_centering);\n }\n /** @returns {{name:string,author:string,version:string}} */\n get_meta() {\n return {\n name: this.mind.name,\n author: this.mind.author,\n version: this.mind.version,\n };\n }\n /**\n * Serialize current mind to given format.\n * @param {'node_tree'|'node_array'|'freemind'|'text'} [data_format]\n * @returns {object}\n */\n get_data(data_format) {\n var df = data_format || 'node_tree';\n return this.data.get_data(df);\n }\n /** @returns {import('./jsmind.node.js').Node} */\n get_root() {\n return this.mind.root;\n }\n /**\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {import('./jsmind.node.js').Node}\n */\n get_node(node) {\n if (Node.is_node(node)) {\n return node;\n }\n return this.mind.get_node(node);\n }\n /**\n * Get the level/depth of a node in the mind map.\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\n * @returns {number} Node level (root node is 0, its children are 1, etc.)\n */\n get_node_level(node) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.warn('the node[id=' + node + '] can not be found.');\n return -1;\n }\n\n // Root node is at level 0\n if (the_node.isroot) {\n return 0;\n }\n\n var level = 0;\n var current = the_node;\n\n // Traverse up to root node, counting levels\n while (current.parent && !current.parent.isroot) {\n level++;\n current = current.parent;\n }\n\n // Add 1 for children of root node\n return level + 1;\n }\n /**\n * Add node data to the mind map without triggering UI refresh.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction\n * @returns {import('./jsmind.node.js').Node|null}\n */\n _add_node_data(parent_node, node_id, topic, data, direction) {\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(parent_node);\n }\n\n var node = this.mind.add_node(parent_node, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.view.reset_node_custom_style(node);\n }\n return node;\n }\n\n /**\n * Refresh UI after node changes.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n */\n _refresh_node_ui(parent_node) {\n this.layout.layout();\n this.view.show(false);\n this.expand_node(parent_node);\n }\n\n /**\n * Add a new node to the mind map.\n * @param {string | import('./jsmind.node.js').Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n add_node(parent_node, node_id, topic, data, direction) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n\n var the_parent_node = this.get_node(parent_node);\n if (!the_parent_node) {\n logger.error('parent node not found');\n return null;\n }\n\n var node = this._add_node_data(the_parent_node, node_id, topic, data, direction);\n if (!!node) {\n this._refresh_node_ui(the_parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'add_node',\n data: [the_parent_node.id, node_id, topic, data, Direction.of(direction)],\n node: node_id,\n });\n }\n return node;\n }\n\n /**\n * Add multiple nodes in batch.\n *\n * This method provides atomic batch node creation with automatic rollback on failure.\n * All nodes are created in a single operation, and if any node fails to create,\n * all previously created nodes in this batch will be automatically removed.\n *\n * **Note**: This is a batch operation API that uses standard field names only.\n * For data import with custom fieldNames, use `show()` instead.\n *\n * @example\n * // Using standard field names\n * jm.add_nodes('parent_id', [\n * { id: 'node1', topic: 'Node 1', data: { color: 'red' }, children: [\n * { id: 'node1-1', topic: 'Child 1' }\n * ]}\n * ]);\n *\n * @param {string | import('./jsmind.node.js').Node} parent_node - Parent node for all new nodes\n * @param {Array<{id: string, topic: string, data?: Record<string, any>, direction?: ('left'|'center'|'right'|'-1'|'0'|'1'|number), children?: Array}>} nodes_data - Array of node data objects with standard field names (id, topic, children, data, direction)\n * @returns {Array<import('./jsmind.node.js').Node|null>} Array of created nodes (flattened from all levels)\n */\n add_nodes(parent_node, nodes_data) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return [];\n }\n\n var the_parent_node = this.get_node(parent_node);\n if (!the_parent_node) {\n logger.error('parent node not found');\n return [];\n }\n\n if (!Array.isArray(nodes_data) || nodes_data.length === 0) {\n logger.warn('nodes_data should be a non-empty array');\n return [];\n }\n\n const expected_count = this._count_expected_nodes(nodes_data);\n let created_nodes = nodes_data\n .map(node_data => this._add_nodes_recursive(the_parent_node, node_data))\n .flat()\n .filter(n => n !== null);\n\n const actual_count = created_nodes.length;\n\n // Atomic operation: either all nodes succeed or cleanup all partial nodes\n if (actual_count === expected_count) {\n // All nodes created successfully, refresh UI\n this._refresh_node_ui(the_parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'add_nodes',\n data: [the_parent_node.id, nodes_data],\n nodes: created_nodes.map(node => node.id),\n });\n return created_nodes;\n } else {\n // Cleanup partially created nodes to ensure atomicity\n logger.warn(\n `Expected ${expected_count} nodes, but only created ${actual_count}. Cleaning up...`\n );\n this._cleanup_partial_nodes(created_nodes);\n return [];\n }\n }\n\n /**\n * Recursively add nodes using standard field names.\n * This is a batch operation API that uses standard field names only.\n * For data import with custom fieldNames, use `show()` instead.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n * @param {object} node_data - Node data object with standard field names (id, topic, children, data, direction)\n * @returns {Array<import('./jsmind.node.js').Node|null>}\n */\n _add_nodes_recursive(parent_node, node_data) {\n var created_nodes = [];\n\n // Validate required fields (using standard field names only)\n if (!node_data.id || !node_data.topic) {\n logger.warn('invalid node data:', node_data);\n return [];\n }\n\n // Create the node using standard field names\n var new_node = this._add_node_data(\n parent_node,\n node_data.id,\n node_data.topic,\n node_data.data || {},\n node_data.direction\n );\n\n if (new_node) {\n created_nodes.push(new_node);\n // Process children using standard field name\n if (Array.isArray(node_data.children)) {\n const sub_nodes = node_data.children\n .map(child => this._add_nodes_recursive(new_node, child))\n .flat();\n created_nodes = created_nodes.concat(sub_nodes);\n }\n }\n\n return created_nodes;\n }\n\n /**\n * Count expected nodes recursively.\n * Supports custom field names via options.fieldNames configuration.\n * @private\n * @param {Array} nodes_data\n * @returns {number}\n */\n _count_expected_nodes(nodes_data) {\n if (!Array.isArray(nodes_data)) {\n return 0;\n }\n\n // Get field names from options (support custom field names)\n var fn = this.options.fieldNames || {};\n var childrenKey = fn.children || 'children';\n\n return nodes_data.reduce((count, node_data) => {\n count++; // Count current node\n // Use custom children field name\n count += this._count_expected_nodes(node_data && node_data[childrenKey]);\n return count;\n }, 0);\n }\n\n /**\n * Clean up partially created nodes without triggering UI refresh for each node.\n * @private\n * @param {Array<import('./jsmind.node.js').Node>} created_nodes\n */\n _cleanup_partial_nodes(created_nodes) {\n if (created_nodes.length === 0) return;\n // Remove all created nodes in reverse order to avoid parent-child issues\n // Use direct view and mind operations without triggering layout/show\n [...created_nodes].reverse().forEach(node => {\n if (node && !node.isroot) {\n // Remove from view without triggering layout\n this.view.remove_node(node);\n // Remove from mind model without triggering layout\n this.mind.remove_node(node);\n }\n });\n }\n\n /**\n * Insert a node before target node.\n * @param {string | import('./jsmind.node.js').Node} node_before\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n insert_node_before(node_before, node_id, topic, data, direction) {\n if (this.get_editable()) {\n var the_node_before = this.get_node(node_before);\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(the_node_before.parent);\n }\n var node = this.mind.insert_node_before(the_node_before, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'insert_node_before',\n data: [the_node_before.id, node_id, topic, data, dir],\n node: node_id,\n });\n }\n return node;\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Insert a node after target node.\n * @param {string | import('./jsmind.node.js').Node} node_after\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n insert_node_after(node_after, node_id, topic, data, direction) {\n if (this.get_editable()) {\n var the_node_after = this.get_node(node_after);\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(the_node_after.parent);\n }\n var node = this.mind.insert_node_after(the_node_after, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'insert_node_after',\n data: [the_node_after.id, node_id, topic, data, dir],\n node: node_id,\n });\n }\n return node;\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Remove a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {boolean}\n */\n remove_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return false;\n } else {\n return this.remove_node(the_node);\n }\n }\n if (this.get_editable()) {\n if (node.isroot) {\n logger.error('fail, can not remove root node');\n return false;\n }\n var node_id = node.id;\n var parent_id = node.parent.id;\n var parent_node = this.get_node(parent_id);\n this.view.save_location(parent_node);\n this.view.remove_node(node);\n this.mind.remove_node(node);\n this.layout.layout();\n this.view.show(false);\n this.view.restore_location(parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'remove_node',\n data: [node_id],\n node: parent_id,\n });\n return true;\n } else {\n logger.error('fail, this mind map is not editable');\n return false;\n }\n }\n /**\n * Update node topic text or multiple node properties.\n * @param {string} node_id - The ID of the node to update\n * @param {string|Partial<Pick<import('./jsmind.node.js').Node, 'topic' | 'data' | 'id' | 'index' | 'expanded' | 'direction'>>} topic_or_updates - Topic string for backward compatibility, or partial Node object for comprehensive updates\n */\n update_node(node_id, topic_or_updates) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return;\n }\n\n var node = this.get_node(node_id);\n if (!!node) {\n // Handle backward compatibility: string parameter\n if (typeof topic_or_updates === 'string') {\n if (_util.text.is_empty(topic_or_updates)) {\n logger.warn('fail, topic can not be empty');\n return;\n }\n if (node.topic === topic_or_updates) {\n logger.info('nothing changed');\n this.view.update_node(node);\n return;\n }\n node.topic = topic_or_updates;\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'update_node',\n data: [node_id, topic_or_updates],\n node: node_id,\n });\n return;\n }\n\n // Handle advanced updates with object parameter\n if (typeof topic_or_updates === 'object' && topic_or_updates !== null) {\n var originalId = node.id;\n var hasChanges = false;\n\n // Validate and apply topic change\n if (topic_or_updates.topic !== undefined) {\n if (_util.text.is_empty(topic_or_updates.topic)) {\n logger.warn('fail, topic can not be empty');\n return;\n }\n if (node.topic !== topic_or_updates.topic) {\n node.topic = topic_or_updates.topic;\n hasChanges = true;\n }\n }\n\n // Validate and apply data changes\n if (topic_or_updates.data && typeof topic_or_updates.data === 'object') {\n for (var key in topic_or_updates.data) {\n if (topic_or_updates.data.hasOwnProperty(key)) {\n if (node.data[key] !== topic_or_updates.data[key]) {\n node.data[key] = topic_or_updates.data[key];\n hasChanges = true;\n }\n }\n }\n }\n\n // Validate and apply ID change\n if (topic_or_updates.id !== undefined) {\n if (\n typeof topic_or_updates.id !== 'string' ||\n topic_or_updates.id.trim() === ''\n ) {\n logger.error('fail, new node id must be a non-empty string');\n return;\n }\n\n // Only proceed if there's an actual ID change\n if (node.id !== topic_or_updates.id) {\n // Validation checks\n if (node.isroot) {\n logger.error('fail, cannot change root node id');\n return;\n }\n\n if (topic_or_updates.id in this.mind.nodes) {\n logger.error(\n 'fail, new id \"' + topic_or_updates.id + '\" already exists'\n );\n return;\n }\n\n // Direct ID change implementation\n var oldId = node.id;\n\n // Remove from old mapping\n delete this.mind.nodes[oldId];\n\n // Update node ID\n node.id = topic_or_updates.id;\n\n // Add to new mapping\n this.mind.nodes[topic_or_updates.id] = node;\n\n // Update selected state if needed\n if (this.mind.selected && this.mind.selected.id === oldId) {\n this.mind.selected = node;\n }\n\n hasChanges = true;\n }\n }\n\n // Apply other Node properties\n ['index', 'expanded', 'direction'].forEach(function (prop) {\n if (\n topic_or_updates[prop] !== undefined &&\n node[prop] !== topic_or_updates[prop]\n ) {\n node[prop] = topic_or_updates[prop];\n hasChanges = true;\n }\n });\n\n if (!hasChanges) {\n logger.info('nothing changed');\n this.view.update_node(node);\n return;\n }\n\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'update_node',\n data: [originalId, topic_or_updates],\n node: originalId,\n });\n }\n } else {\n logger.error('fail, node not found');\n return;\n }\n }\n /**\n * Move a node and optionally change direction.\n * @param {string} node_id\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\n * @param {string=} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1). Only effective for second-level nodes (children of root). If not provided, direction will be determined automatically.\n */\n move_node(node_id, before_id, parent_id, direction) {\n if (this.get_editable()) {\n var node = this.get_node(node_id);\n var updated_node = this.mind.move_node(node, before_id, parent_id, direction);\n if (!!updated_node) {\n this.view.update_node(updated_node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'move_node',\n data: [node_id, before_id, parent_id, direction],\n node: node_id,\n });\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return;\n }\n }\n /**\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n select_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.select_node(the_node);\n return;\n }\n }\n if (!this.layout.is_visible(node)) {\n return;\n }\n this.mind.selected = node;\n this.view.select_node(node);\n this.invoke_event_handle(EventType.select, { evt: 'select_node', data: [], node: node.id });\n }\n /**\n * Get the currently selected node.\n *\n * This is a query API that returns the internal Node instance.\n * For data export with custom fieldNames, use `get_data()` instead.\n *\n * @returns {import('./jsmind.node.js').Node|null} Node instance or null\n */\n get_selected_node() {\n if (!!this.mind) {\n return this.mind.selected;\n } else {\n return null;\n }\n }\n /** clear selection */\n select_clear() {\n if (!!this.mind) {\n this.mind.selected = null;\n this.view.select_clear();\n }\n }\n /** @param {string | import('./jsmind.node.js').Node} node */\n is_node_visible(node) {\n return this.layout.is_visible(node);\n }\n /**\n * Scroll the mind map to center the specified node.\n * @param {string | import('./jsmind.node.js').Node} node\n */\n scroll_node_to_center(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n } else {\n this.scroll_node_to_center(the_node);\n }\n return;\n }\n this.view.center_node(node);\n }\n /**\n * Find the previous sibling node of the given node.\n *\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\n * @returns {import('./jsmind.node.js').Node | null}\n */\n find_node_before(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n return this.find_node_before(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var n = null;\n if (node.parent.isroot) {\n var c = node.parent.children;\n var prev = null;\n var ni = null;\n for (var i = 0; i < c.length; i++) {\n ni = c[i];\n if (node.direction === ni.direction) {\n if (node.id === ni.id) {\n n = prev;\n }\n prev = ni;\n }\n }\n } else {\n n = this.mind.get_node_before(node);\n }\n return n;\n }\n /**\n * Find the next sibling node of the given node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {import('./jsmind.node.js').Node | null}\n */\n find_node_after(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n return this.find_node_after(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var n = null;\n if (node.parent.isroot) {\n var c = node.parent.children;\n var found = false;\n var ni = null;\n for (var i = 0; i < c.length; i++) {\n ni = c[i];\n if (node.direction === ni.direction) {\n if (found) {\n n = ni;\n break;\n }\n if (node.id === ni.id) {\n found = true;\n }\n }\n }\n } else {\n n = this.mind.get_node_after(node);\n }\n return n;\n }\n /**\n * Set background and foreground colors for a node.\n * @param {string} node_id\n * @param {string=} bg_color\n * @param {string=} fg_color\n * @returns {void}\n */\n set_node_color(node_id, bg_color, fg_color) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!bg_color) {\n node.data['background-color'] = bg_color;\n }\n if (!!fg_color) {\n node.data['foreground-color'] = fg_color;\n }\n this.view.reset_node_custom_style(node);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Set font style for a node.\n * @param {string} node_id\n * @param {number=} size\n * @param {string=} weight\n * @param {string=} style\n * @returns {void}\n */\n set_node_font_style(node_id, size, weight, style) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!size) {\n node.data['font-size'] = size;\n }\n if (!!weight) {\n node.data['font-weight'] = weight;\n }\n if (!!style) {\n node.data['font-style'] = style;\n }\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Set background image for a node.\n * @param {string} node_id\n * @param {string=} image\n * @param {number=} width\n * @param {number=} height\n * @param {number=} rotation\n * @returns {void}\n */\n set_node_background_image(node_id, image, width, height, rotation) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!image) {\n node.data['background-image'] = image;\n }\n if (!!width) {\n node.data['width'] = width;\n }\n if (!!height) {\n node.data['height'] = height;\n }\n if (!!rotation) {\n node.data['background-rotation'] = rotation;\n }\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * @param {string} node_id\n * @param {number} rotation\n * @returns {void}\n */\n set_node_background_rotation(node_id, rotation) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!node.data['background-image']) {\n logger.error(\n 'fail, only can change rotation angle of node with background image'\n );\n return null;\n }\n node.data['background-rotation'] = rotation;\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /** trigger view resize */\n resize() {\n this.view.resize();\n }\n // callback(type ,data)\n /** @param {(type:number, data: EventData)=>void} callback */\n add_event_listener(callback) {\n if (typeof callback === 'function') {\n this.event_handles.push(callback);\n }\n }\n /** clear event listeners */\n clear_event_listener() {\n this.event_handles = [];\n }\n /** @param {number} type @param {EventData} data */\n invoke_event_handle(type, data) {\n var j = this;\n $.w.setTimeout(function () {\n j._invoke_event_handle(type, data);\n }, 0);\n }\n /** @param {number} type @param {EventData} data */\n _invoke_event_handle(type, data) {\n var l = this.event_handles.length;\n for (var i = 0; i < l; i++) {\n this.event_handles[i](type, data);\n }\n }\n\n /**\n * Remove an enhanced plugin\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n */\n removePlugin(PluginClass) {\n if (this.enhancedPluginManager) {\n this.enhancedPluginManager.removePlugin(PluginClass);\n }\n }\n\n /**\n * Get an enhanced plugin instance\n * @param {string} instanceName - Plugin instance name\n * @returns {EnhancedPlugin | undefined}\n */\n getPlugin(instanceName) {\n if (this.enhancedPluginManager) {\n return this.enhancedPluginManager.getPlugin(instanceName);\n }\n return undefined;\n }\n\n /**\n * Destroy the jsMind instance and clean up resources\n */\n destroy() {\n // Destroy enhanced plugins\n if (this.enhancedPluginManager) {\n this.enhancedPluginManager.destroyAllPlugins();\n }\n\n // Clear event listeners\n this.clear_event_listener();\n\n // Clean up view\n if (this.view) {\n this.view.reset();\n }\n\n // Clear mind data\n this.mind = null;\n this.initialized = false;\n }\n\n /**\n * Deprecated: static show constructor helper.\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\n * @param {object | null} mind\n * @returns {jsMind}\n */\n static show(options, mind) {\n logger.warn(\n '`jsMind.show(options, mind)` is deprecated, please use `jm = new jsMind(options); jm.show(mind);` instead'\n );\n var _jm = new jsMind(options);\n _jm.show(mind);\n return _jm;\n }\n}\n"],"names":["__version__","String","prototype","startsWith","p","this","slice","length","Direction","left","center","right","of","dir","parseInt","toLowerCase","EventType","show","resize","edit","select","reset","history_change","LogLevel","debug","info","warn","error","disable","_noop","logger","console","level","log","log_level","$","constructor","w","d","document","g","id","getElementById","c","tag","createElement","t","n","hasChildNodes","firstChild","nodeValue","appendChild","createTextNode","h","HTMLElement","innerHTML","i","el","nodeType","style","ownerDocument","on","e","addEventListener","attachEvent","window","util","file","read","file_data","fn_callback","reader","FileReader","onload","result","name","readAsText","save","type","blob","Blob","bb","BlobBuilder","MozBlobBuilder","WebKitBlobBuilder","MSBlobBuilder","append","getBlob","navigator","msSaveBlob","blob_url","URL","webkitURL","createObjectURL","anchor","visibility","href","download","body","evt","createEvent","initEvent","dispatchEvent","removeChild","location","json","json2string","JSON","stringify","string2json","json_str","parse","merge","b","a","o","Object","toString","call","uuid","newid","Date","getTime","Math","random","substring","text","is_empty","s","replace","default_options","container","editable","theme","mode","support_html","view","engine","enable_device_pixel_ratio","hmargin","vmargin","line_width","line_color","line_style","draggable","hide_scrollbars_when_draggable","node_overflow","zoom","min","max","step","mask_key","custom_node_render","expander_style","layout","hspace","vspace","pspace","cousin_space","default_event_handle","enable_mousedown_handle","enable_click_handle","enable_dblclick_handle","enable_mousewheel_handle","shortcut","enable","handles","mapping","addchild","addbrother","editnode","delnode","toggle","up","down","fieldNames","topic","children","parentid","isroot","direction","expanded","plugin","Node","sId","iIndex","sTopic","oData","bIsRoot","oParent","eDirection","bExpanded","index","data","parent","_data","get_location","vd","x","abs_x","y","abs_y","get_size","width","height","compare","node1","node2","i1","i2","inherited","parent_node","node","pid","is_node","toObject","includeChildren","fn","idKey","topicKey","childrenKey","directionKey","expandedKey","obj","k","map","child","Mind","author","version","root","selected","nodes","get_node","node_id","set_root","_put_node","add_node","idx","push","_update_index","insert_node_before","node_before","node_index","get_node_before","the_node","insert_node_after","node_after","get_node_after","move_node","before_id","parent_id","_move_node","_flow_node_direction","len","_move_node_internal","sibling","si","splice","origin_parent","remove_node","ci","node_parent","sort","DEFAULT_META","format","node_tree","example","meta","get_mind","source","df","mind","_parse","get_data","_build_node","node_root","_extract_data","_extract_subnode","node_json","node_data","node_array","_array","reverse","root_node","_extract_root","isrootKey","root_json","parentidKey","extract_count","node_direction","sub_extract_count","_array_node","freemind","xml","xml_doc","_parse_xml","xml_root","_find_root","_load_node","xml_lines","_build_map","join","DOMParser","parseFromString","ActiveXObject","async","loadXML","childNodes","tagName","ns","xml_node","getAttribute","node_topic","node_folded","topic_children","topic_child","textContent","_load_attributes","node_expanded","node_foreground_color","node_background_color","node_position","attr","attr_data","pos","_escape","_line_regex","lines","split","_fill_nodes","node_path","line","match","substr","diff","pop","_build_lines","prefix","Array","DataProvider","jm","init","load","mind_data","options","data_format","LayoutProvider","opts","isside","bounds","cache_valid","calculate_next_child_direction","children_len","r","layout_direction","layout_offset","_layout_direction_root","layout_data","children_count","side_index","_layout_direction_side","subnode","offset_x","offset_y","outer_height","left_nodes","right_nodes","unshift","outer_height_left","_layout_offset_subnodes","outer_height_right","total_height","nodes_count","node_outer_height","base_y","pd","set_visible","_should_reserve_cousin_space","middle_height","_layout_offset_subnodes_height","get_node_offset","offset_cache","_offset_","offset_p","get_node_point","view_data","get_node_point_in","get_node_point_out","pout_cache","_pout_","get_expander_point","ex_p","ceil","get_min_size","pout","toggle_node","collapse_node","expand_node","part_layout","invoke_event_handle","expand_all","collapse_all","expand_to_depth","target_depth","curr_nodes","curr_depth","depth","root_layout_data","visible","is_expand","is_visible","SvgGraph","e_svg","setAttribute","size","line_drawing","straight","_line_to","curved","_bezier_to","init_line_render","createElementNS","custom_line_render","drawing","path","x1","y1","x2","y2","ctx","start_point","end_point","element","set_size","clear","draw_line","pin","offset","color","copy_to","dest_canvas_ctx","callback","img","Image","drawImage","src","btoa","XMLSerializer","serializeToString","CanvasGraph","e_canvas","className","canvas_ctx","getContext","dpr","device_pixel_ratio","scale","clearRect","strokeStyle","lineWidth","lineCap","beginPath","moveTo","bezierCurveTo","stroke","lineTo","ViewProvider","e_panel","e_nodes","selected_node","editing_node","graph","render_node","_custom_node_render","_default_node_render","zoom_current","devicePixelRatio","_initialized","e_editor","tabIndex","v","event","keyCode","edit_node_end","stopPropagation","offsetParent","IntersectionObserver","entities","observer","isIntersecting","unobserve","observe","add_event","event_name","event_handle","capture_by_panel","target","get_binded_nodeid","parentElement","is_expander","clear_lines","clear_nodes","reset_theme","theme_name","reset_custom_style","nodeid","reset_node_custom_style","setup_canvas_draggable","init_nodes","expand_size","min_size","min_width","min_height","client_w","clientWidth","client_h","clientHeight","init_nodes_size","doc_frag","createDocumentFragment","create_node_element","run_in_c11y_mode_if_needed","func","position","top","d_e","expander","_reset_node_custom_style","update_node","origin_style","select_node","restore_selected_node_custom_style","clear_selected_node_custom_style","select_clear","get_editing_node","is_editing","edit_node_begin","ncs","getComputedStyle","value","getPropertyValue","zIndex","focus","get_view_offset","_show","show_nodes","show_lines","zoom_in","set_zoom","zoom_out","e_panel_rect","getBoundingClientRect","zoom_center","panel_scroll_x","scrollLeft","panel_scroll_y","scrollTop","keep_center","center_node","relayout","save_location","_saved_location","restore_location","node_element","view_offset","display","_show_expander","expander_text","_get_expander_text","p_expander","ele","backgroundColor","fontSize","fontWeight","fontStyle","backgroundImage","scaledImageData","toDataURL","backgroundSize","transform","_offset","enabled","dragging","eventDown","clientX","clientY","eventMove","scrollBy","node_center_point","scrollTo","zoomIn","zoomOut","setZoom","ShortcutProvider","_newid","_mapping","handle","handler","bind","handle_addchild","handle_addbrother","handle_editnode","handle_delnode","handle_toggle","handle_up","handle_down","handle_left","handle_right","keys","isArray","key","id_generator","enable_shortcut","disable_shortcut","which","preventDefault","kc","metaKey","ctrlKey","altKey","shiftKey","_jm","get_selected_node","begin_edit","up_node","find_node_before","np","down_node","find_node_after","_handle_direction","floor","plugin_data","plugins","register","Plugin","Error","includes","apply","setTimeout","forEach","fn_init","_apply","EnhancedPluginManager","Map","initPreloadPlugins","preloadPlugins","enhancedPluginList","filter","preload","descriptor","_initPlugin","initNormalPlugins","normalPlugins","PluginClass","pluginOpt","instanceName","has","instance","set","removePlugin","get","beforePluginRemove","delete","list","findIndex","destroyAllPlugins","beforePluginDestroy","getPlugin","EnhancedPlugin","static","jsMind","_register_plugin","_util","usePlugin","some","hasEnhancedPlugin","current","merge_option","initialized","event_handles","enhancedPluginManager","opts_layout","opts_view","_event_bind","apply_plugins","get_editable","enable_edit","disable_edit","get_view_draggable","enable_view_draggable","disable_view_draggable","enable_event_handle","disable_event_handle","set_theme","theme_old","mousedown_handle","click_handle","dblclick_handle","mousewheel_handle","srcElement","deltaY","end_edit","_reset","skip_centering","m","get_meta","get_root","get_node_level","_add_node_data","undefined","_refresh_node_ui","the_parent_node","add_nodes","nodes_data","expected_count","_count_expected_nodes","created_nodes","_add_nodes_recursive","flat","actual_count","_cleanup_partial_nodes","new_node","sub_nodes","concat","reduce","count","the_node_before","the_node_after","topic_or_updates","originalId","hasChanges","hasOwnProperty","trim","oldId","prop","updated_node","is_node_visible","scroll_node_to_center","prev","ni","found","set_node_color","bg_color","fg_color","set_node_font_style","weight","set_node_background_image","image","rotation","set_node_background_rotation","add_event_listener","clear_event_listener","j","_invoke_event_handle","l","destroy"],"mappings":"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"}
|