@umbraci/jsmind 0.10.18 → 1.0.0-beta
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/README.md +7 -7
- package/dist/jsmind.draggable-node.js +7 -472
- package/dist/jsmind.draggable-node.js.map +1 -1
- package/dist/jsmind.history.js +7 -980
- package/dist/jsmind.history.js.map +1 -1
- package/dist/jsmind.js +7 -2624
- package/dist/jsmind.js.map +1 -1
- package/dist/jsmind.multi-select.js +7 -671
- package/dist/jsmind.multi-select.js.map +1 -1
- package/dist/jsmind.multiline-text.js +7 -156
- package/dist/jsmind.multiline-text.js.map +1 -1
- package/dist/jsmind.screenshot.js +7 -156
- package/dist/jsmind.screenshot.js.map +1 -1
- package/es/jsmind.draggable-node.js +7 -443
- package/es/jsmind.draggable-node.js.map +1 -1
- package/es/jsmind.history.js +7 -944
- package/es/jsmind.history.js.map +1 -1
- package/es/jsmind.js +7 -2570
- package/es/jsmind.js.map +1 -1
- package/es/jsmind.multi-select.js +7 -621
- package/es/jsmind.multi-select.js.map +1 -1
- package/es/jsmind.multiline-text.js +7 -136
- package/es/jsmind.multiline-text.js.map +1 -1
- package/es/jsmind.screenshot.js +7 -136
- package/es/jsmind.screenshot.js.map +1 -1
- package/lib/jsmind.draggable-node.js +7 -450
- package/lib/jsmind.draggable-node.js.map +1 -1
- package/lib/jsmind.history.js +7 -946
- package/lib/jsmind.history.js.map +1 -1
- package/lib/jsmind.js +7 -2571
- package/lib/jsmind.js.map +1 -1
- package/lib/jsmind.multi-select.js +7 -623
- package/lib/jsmind.multi-select.js.map +1 -1
- package/lib/jsmind.multiline-text.js +7 -141
- package/lib/jsmind.multiline-text.js.map +1 -1
- package/lib/jsmind.screenshot.js +7 -145
- package/lib/jsmind.screenshot.js.map +1 -1
- package/package.json +26 -25
- package/types/generated/jsmind.d.ts +21 -24
- package/types/generated/jsmind.mind.d.ts +7 -0
- package/types/generated/{jsmind.enhanced-plugin.d.ts → jsmind.plugin-system.d.ts} +10 -10
- package/types/generated/jsmind.plugin.d.ts +93 -13
- package/types/generated/jsmind.view_provider.d.ts +1 -1
- package/types/generated/plugins/history/history-diff.d.ts +10 -0
- package/types/generated/plugins/history/jsmind.history.d.ts +2 -2
- package/types/generated/plugins/jsmind.draggable-node.d.ts +13 -3
- package/types/generated/plugins/jsmind.multi-select.d.ts +3 -3
- package/types/generated/plugins/jsmind.multiline-text.d.ts +67 -21
- package/types/generated/plugins/jsmind.screenshot.d.ts +12 -3
- package/types/tsconfig.declaration.json +6 -1
- package/dist/jsmind.copy-paste.js +0 -283
- package/dist/jsmind.copy-paste.js.map +0 -1
- package/es/jsmind.copy-paste.js +0 -260
- package/es/jsmind.copy-paste.js.map +0 -1
- package/types/generated/plugins/jsmind.multiline-text-v2.d.ts +0 -58
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.draggable-node.js","sources":["../src/plugins/jsmind.draggable-node.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport jsMind from '@umbraci/jsmind';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nconst $ = jsMind.$;\n\nconst clear_selection =\n 'getSelection' in $.w\n ? function () {\n $.w.getSelection().removeAllRanges();\n }\n : function () {\n $.d.selection.empty();\n };\n\n/**\n * Default options for draggable node plugin.\n * @typedef {Object} DraggableNodeOptions\n * @property {number} [line_width]\n * @property {string} [line_color]\n * @property {string} [line_color_invalid]\n * @property {number} [lookup_delay]\n * @property {number} [lookup_interval]\n * @property {number} [scrolling_trigger_width]\n * @property {number} [scrolling_step_length]\n * @property {string} [shadow_node_class_name]\n * @property {(draggedNode:import('../jsmind.node.js').Node, targetNode:import('../jsmind.node.js').Node|null)=>boolean} [validate_drag]\n */\nconst DEFAULT_OPTIONS = {\n line_width: 5,\n line_color: 'rgba(0,0,0,0.3)',\n line_color_invalid: 'rgba(255,51,51,0.6)',\n lookup_delay: 200,\n lookup_interval: 100,\n scrolling_trigger_width: 20,\n scrolling_step_length: 10,\n shadow_node_class_name: 'jsmind-draggable-shadow-node',\n};\n\n/**\n * Draggable node plugin for jsMind.\n */\nexport class DraggableNode {\n /**\n * Create draggable node plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<DraggableNodeOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.4.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {DraggableNodeOptions} */\n this.options = opts;\n /** @type {boolean} */\n this.is_svg_engine = jm.view.opts.engine === 'svg';\n /** @type {HTMLCanvasElement|SVGSVGElement|null} */\n this.e_canvas = null;\n /** @type {CanvasRenderingContext2D|null} */\n this.canvas_ctx = null;\n /** @type {SVGPathElement|null} */\n this.helper_line = null;\n /** @type {HTMLElement|null} */\n this.shadow = null;\n /** @type {number} */\n this.shadow_p_x = 0;\n /** @type {number} */\n this.shadow_p_y = 0;\n /** @type {number} */\n this.shadow_w = 0;\n /** @type {number} */\n this.shadow_h = 0;\n /** @type {import('../jsmind.node.js').Node|null} */\n this.active_node = null;\n /** @type {import('../jsmind.node.js').Node|null} */\n this.target_node = null;\n /** @type {number|null} */\n this.target_direct = null;\n /** @type {number} */\n this.client_w = 0;\n /** @type {number} */\n this.client_h = 0;\n /** @type {number} */\n this.offset_x = 0;\n /** @type {number} */\n this.offset_y = 0;\n /** @type {number} */\n this.hlookup_delay = 0;\n /** @type {number} */\n this.hlookup_timer = 0;\n /** @type {boolean} */\n this.capture = false;\n /** @type {boolean} */\n this.moved = false;\n /** @type {boolean} */\n this.canvas_draggable = jm.get_view_draggable();\n /** @type {HTMLElement} */\n this.view_panel = jm.view.e_panel;\n /** @type {DOMRect|null} */\n this.view_panel_rect = null;\n }\n /** Initialize the draggable node plugin. */\n init() {\n this.create_canvas();\n this.create_shadow();\n this.event_bind();\n }\n /** Resize canvas/SVG and shadow elements. */\n resize() {\n this.jm.view.e_nodes.appendChild(this.shadow);\n if (this.is_svg_engine) {\n this.e_canvas.setAttribute('width', this.jm.view.size.w);\n this.e_canvas.setAttribute('height', this.jm.view.size.h);\n } else {\n this.e_canvas.width = this.jm.view.size.w;\n this.e_canvas.height = this.jm.view.size.h;\n }\n }\n /** Create canvas or SVG for drawing drag lines. */\n create_canvas() {\n if (this.is_svg_engine) {\n // Create SVG element for helper lines\n var svg = this._create_svg_element('svg');\n svg.setAttribute('class', 'jsmind-draggable-helper');\n svg.setAttribute('style', 'position: absolute; top: 0; left: 0; pointer-events: none;');\n this.jm.view.e_panel.appendChild(svg);\n this.e_canvas = svg;\n } else {\n // Create Canvas element for helper lines\n var c = $.c('canvas');\n this.jm.view.e_panel.appendChild(c);\n var ctx = c.getContext('2d');\n this.e_canvas = c;\n this.canvas_ctx = ctx;\n }\n }\n /**\n * Create SVG element with proper namespace.\n * @param {string} tag - SVG tag name\n * @returns {SVGElement}\n * @private\n */\n _create_svg_element(tag) {\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\n }\n create_shadow() {\n var s = $.c('jmnode');\n s.style.visibility = 'hidden';\n s.style.zIndex = '3';\n s.style.cursor = 'move';\n s.style.opacity = '0.7';\n s.className = this.options.shadow_node_class_name;\n this.shadow = s;\n }\n /**\n * Reset shadow element style and cache its size.\n * @param {HTMLElement} el - The node element to mirror as shadow\n */\n reset_shadow(el) {\n var s = this.shadow.style;\n this.shadow.innerHTML = el.innerHTML;\n s.left = el.style.left;\n s.top = el.style.top;\n s.width = el.style.width;\n s.height = el.style.height;\n s.backgroundImage = el.style.backgroundImage;\n s.backgroundSize = el.style.backgroundSize;\n s.transform = el.style.transform;\n this.shadow_w = this.shadow.clientWidth;\n this.shadow_h = this.shadow.clientHeight;\n }\n /** Show the shadow element. */\n show_shadow() {\n if (!this.moved) {\n this.shadow.style.visibility = 'visible';\n }\n }\n /** Hide the shadow element. */\n hide_shadow() {\n this.shadow.style.visibility = 'hidden';\n }\n /**\n * Draw a helper line between the shadow and target node.\n * @param {{x:number,y:number}} shadow_p - Shadow anchor point\n * @param {{x:number,y:number}} node_p - Target node anchor point\n * @param {boolean} invalid - Whether current target is invalid\n */\n magnet_shadow(shadow_p, node_p, invalid) {\n this.clear_lines();\n var color = invalid ? this.options.line_color_invalid : this.options.line_color;\n\n if (this.is_svg_engine) {\n this.svg_draw_line(shadow_p.x, shadow_p.y, node_p.x, node_p.y, color);\n } else {\n this.canvas_ctx.lineWidth = this.options.line_width;\n this.canvas_ctx.strokeStyle = color;\n this.canvas_ctx.lineCap = 'round';\n this.canvas_lineto(shadow_p.x, shadow_p.y, node_p.x, node_p.y);\n }\n }\n /** Clear helper lines from canvas or SVG. */\n clear_lines() {\n if (this.is_svg_engine) {\n if (this.helper_line && this.helper_line.parentNode) {\n this.e_canvas.removeChild(this.helper_line);\n this.helper_line = null;\n }\n } else {\n this.canvas_ctx.clearRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n }\n /**\n * Draw a straight helper line on canvas.\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n */\n canvas_lineto(x1, y1, x2, y2) {\n this.canvas_ctx.beginPath();\n this.canvas_ctx.moveTo(x1, y1);\n this.canvas_ctx.lineTo(x2, y2);\n this.canvas_ctx.stroke();\n }\n /**\n * Draw a helper line on SVG using bezier curve.\n * Reuses the line drawing logic from SvgGraph.\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 * @param {string} color - Line color\n */\n svg_draw_line(x1, y1, x2, y2, color) {\n // Create SVG path element for helper line\n this.helper_line = this._create_svg_element('path');\n this.helper_line.setAttribute('stroke', color);\n this.helper_line.setAttribute('stroke-width', this.options.line_width);\n this.helper_line.setAttribute('fill', 'transparent');\n this.helper_line.setAttribute('stroke-linecap', 'round');\n\n // Draw bezier curve (same as SvgGraph._bezier_to)\n this._svg_bezier_to(this.helper_line, x1, y1, x2, y2);\n\n // Add to SVG container\n this.e_canvas.appendChild(this.helper_line);\n }\n /**\n * Draw bezier curve to SVG path element.\n * Reuses logic from SvgGraph._bezier_to.\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 * @private\n */\n _svg_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 /** Bind mouse/touch events for dragging. */\n event_bind() {\n var jd = this;\n var container = this.jm.view.container;\n $.on(container, 'mousedown', function (e) {\n if (e.button === 0) {\n jd.dragstart.call(jd, e);\n }\n });\n $.on(container, 'mousemove', function (e) {\n if (e.movementX !== 0 || e.movementY !== 0) {\n jd.drag.call(jd, e);\n }\n });\n $.on(container, 'mouseup', function (e) {\n jd.dragend.call(jd, e);\n });\n $.on(container, 'touchstart', function (e) {\n jd.dragstart.call(jd, e);\n });\n $.on(container, 'touchmove', function (e) {\n jd.drag.call(jd, e);\n });\n $.on(container, 'touchend', function (e) {\n jd.dragend.call(jd, e);\n });\n }\n /**\n * Begin dragging interaction.\n * @param {MouseEvent|TouchEvent} e - Pointer down event\n */\n dragstart(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.capture) {\n return;\n }\n var jview = this.jm.view;\n if (jview.is_editing()) {\n return;\n }\n this.active_node = null;\n this.view_draggable = this.jm.get_view_draggable();\n\n var el = this.find_node_element(e.target);\n if (!el) {\n return;\n }\n if (this.view_draggable) {\n this.jm.disable_view_draggable();\n }\n var nodeid = jview.get_binded_nodeid(el);\n if (!!nodeid) {\n var node = this.jm.get_node(nodeid);\n if (!node.isroot) {\n // 检查节点是否允许拖拽\n if (node.data && node.data.draggable === false) {\n return;\n }\n this.reset_shadow(el);\n this.view_panel_rect = this.view_panel.getBoundingClientRect();\n this.active_node = node;\n this.offset_x =\n (e.clientX || e.touches[0].clientX) / jview.zoom_current - el.offsetLeft;\n this.offset_y =\n (e.clientY || e.touches[0].clientY) / jview.zoom_current - el.offsetTop;\n this.client_hw = Math.floor(el.clientWidth / 2);\n this.client_hh = Math.floor(el.clientHeight / 2);\n if (this.hlookup_delay != 0) {\n $.w.clearTimeout(this.hlookup_delay);\n }\n if (this.hlookup_timer != 0) {\n $.w.clearInterval(this.hlookup_timer);\n }\n var jd = this;\n this.hlookup_delay = $.w.setTimeout(function () {\n jd.hlookup_delay = 0;\n jd.hlookup_timer = $.w.setInterval(function () {\n jd.lookup_target_node.call(jd);\n }, jd.options.lookup_interval);\n }, this.options.lookup_delay);\n jd.capture = true;\n }\n }\n }\n /**\n * Drag handler to move shadow and auto-scroll container.\n * @param {MouseEvent|TouchEvent} e - Pointer move event\n */\n drag(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.capture) {\n e.preventDefault();\n this.show_shadow();\n this.moved = true;\n clear_selection();\n var jview = this.jm.view;\n var px = (e.clientX || e.touches[0].clientX) / jview.zoom_current - this.offset_x;\n var py = (e.clientY || e.touches[0].clientY) / jview.zoom_current - this.offset_y;\n // scrolling container axisY if drag nodes exceeding container\n if (\n e.clientY - this.view_panel_rect.top < this.options.scrolling_trigger_width &&\n this.view_panel.scrollTop > this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(0, -this.options.scrolling_step_length);\n this.offset_y += this.options.scrolling_step_length / jview.zoom_current;\n } else if (\n this.view_panel_rect.bottom - e.clientY < this.options.scrolling_trigger_width &&\n this.view_panel.scrollTop <\n this.view_panel.scrollHeight -\n this.view_panel_rect.height -\n this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(0, this.options.scrolling_step_length);\n this.offset_y -= this.options.scrolling_step_length / jview.zoom_current;\n }\n // scrolling container axisX if drag nodes exceeding container\n if (\n e.clientX - this.view_panel_rect.left < this.options.scrolling_trigger_width &&\n this.view_panel.scrollLeft > this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(-this.options.scrolling_step_length, 0);\n this.offset_x += this.options.scrolling_step_length / jview.zoom_current;\n } else if (\n this.view_panel_rect.right - e.clientX < this.options.scrolling_trigger_width &&\n this.view_panel.scrollLeft <\n this.view_panel.scrollWidth -\n this.view_panel_rect.width -\n this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(this.options.scrolling_step_length, 0);\n this.offset_x -= this.options.scrolling_step_length / jview.zoom_current;\n }\n this.shadow.style.left = px + 'px';\n this.shadow.style.top = py + 'px';\n clear_selection();\n }\n }\n /**\n * Finish dragging, move the node if applicable.\n * @param {MouseEvent|TouchEvent} e - Pointer up event\n */\n dragend(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.view_draggable) {\n this.jm.enable_view_draggable();\n }\n if (this.capture) {\n if (this.hlookup_delay != 0) {\n $.w.clearTimeout(this.hlookup_delay);\n this.hlookup_delay = 0;\n this.clear_lines();\n }\n if (this.hlookup_timer != 0) {\n $.w.clearInterval(this.hlookup_timer);\n this.hlookup_timer = 0;\n this.clear_lines();\n }\n if (this.moved) {\n var src_node = this.active_node;\n var target_node = this.target_node;\n var target_direct = this.target_direct;\n this.move_node(src_node, target_node, target_direct);\n }\n this.hide_shadow();\n }\n this.view_panel_rect = null;\n this.moved = false;\n this.capture = false;\n }\n /**\n * Find the closest node element from an event target.\n * @param {HTMLElement} el - Current DOM element\n * @returns {HTMLElement|null} Matched node element or null\n */\n find_node_element(el) {\n if (\n el === this.jm.view.e_nodes ||\n el === this.jm.view.e_panel ||\n el === this.jm.view.container\n ) {\n return null;\n }\n if (el.tagName.toLowerCase() === 'jmnode') {\n return el;\n }\n return this.find_node_element(el.parentNode);\n }\n /** Recompute target node under the shadow and draw helper. */\n lookup_target_node() {\n let sx = this.shadow.offsetLeft;\n let sy = this.shadow.offsetTop;\n if (sx === this.shadow_p_x && sy === this.shadow_p_y) {\n return;\n }\n this.shadow_p_x = sx;\n this.shadow_p_y = sy;\n\n let target_direction =\n this.shadow_p_x + this.shadow_w / 2 >= this.get_root_x()\n ? jsMind.direction.right\n : jsMind.direction.left;\n let overlapping_node = this.lookup_overlapping_node_parent(target_direction);\n let target_node = overlapping_node || this.lookup_close_node(target_direction);\n if (!!target_node) {\n let points = this.calc_point_of_node(target_node, target_direction);\n let invalid = jsMind.node.inherited(this.active_node, target_node);\n this.magnet_shadow(points.sp, points.np, invalid);\n this.target_node = target_node;\n this.target_direct = target_direction;\n }\n }\n /**\n * Get X coordinate of root node center.\n * @returns {number}\n */\n get_root_x() {\n let root = this.jm.get_root();\n let root_location = root.get_location();\n let root_size = root.get_size();\n return root_location.x + root_size.w / 2;\n }\n\n /**\n * Lookup overlapping node's parent near the shadow position.\n * @param {number} direction - Direction constant\n * @returns {import('../jsmind.node.js').Node|null}\n */\n lookup_overlapping_node_parent(direction) {\n let shadowRect = this.shadow.getBoundingClientRect();\n let x = shadowRect.x + (shadowRect.width * (1 - direction)) / 2;\n let deltaX = (this.jm.options.layout.hspace + this.jm.options.layout.pspace) * direction;\n let deltaY = shadowRect.height;\n let points = [\n [x, shadowRect.y],\n [x, shadowRect.y + deltaY / 2],\n [x, shadowRect.y + deltaY],\n [x + deltaX / 2, shadowRect.y],\n [x + deltaX / 2, shadowRect.y + deltaY / 2],\n [x + deltaX / 2, shadowRect.y + deltaY],\n [x + deltaX, shadowRect.y],\n [x + deltaX, shadowRect.y + deltaY / 2],\n [x + deltaX, shadowRect.y + deltaY],\n ];\n for (const p of points) {\n let n = this.lookup_node_parent_by_location(p[0], p[1]);\n if (!!n) {\n return n;\n }\n }\n }\n\n /**\n * Find node's parent by a screen location.\n * @param {number} x - Client X\n * @param {number} y - Client Y\n * @returns {import('../jsmind.node.js').Node|null}\n */\n lookup_node_parent_by_location(x, y) {\n return $.d\n .elementsFromPoint(x, y)\n .filter(\n x => x.tagName === 'JMNODE' && x.className !== this.options.shadow_node_class_name\n )\n .map(el => this.jm.view.get_binded_nodeid(el))\n .map(id => id && this.jm.mind.nodes[id])\n .map(n => n && n.parent)\n .find(n => n);\n }\n\n /**\n * Lookup the closest node along a direction.\n * @param {number} direction\n * @returns {import('../jsmind.node.js').Node}\n */\n lookup_close_node(direction) {\n return Object.values(this.jm.mind.nodes)\n .filter(n => n.direction == direction || n.isroot)\n .filter(n => this.jm.layout.is_visible(n))\n .filter(n => this.shadow_on_target_side(n, direction))\n .map(n => ({ node: n, distance: this.shadow_to_node(n, direction) }))\n .reduce(\n (prev, curr) => {\n return prev.distance < curr.distance ? prev : curr;\n },\n { node: this.jm.get_root(), distance: Number.MAX_VALUE }\n ).node;\n }\n\n /**\n * Check if shadow is on the target side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {boolean}\n */\n shadow_on_target_side(node, dir) {\n return (\n (dir == jsMind.direction.right && this.shadow_to_right_of_node(node) > 0) ||\n (dir == jsMind.direction.left && this.shadow_to_left_of_node(node) > 0)\n );\n }\n\n /**\n * Distance from shadow to the right side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_right_of_node(node) {\n return this.shadow_p_x - node.get_location().x - node.get_size().w;\n }\n\n /**\n * Distance from shadow to the left side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_left_of_node(node) {\n return node.get_location().x - this.shadow_p_x - this.shadow_w;\n }\n\n /**\n * Vertical distance between shadow centerline and node centerline.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_base_line_of_node(node) {\n return this.shadow_p_y + this.shadow_h / 2 - node.get_location().y - node.get_size().h / 2;\n }\n\n /**\n * Manhattan distance to a node along a direction.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {number}\n */\n shadow_to_node(node, dir) {\n let distance_x =\n dir === jsMind.direction.right\n ? Math.abs(this.shadow_to_right_of_node(node))\n : Math.abs(this.shadow_to_left_of_node(node));\n let distance_y = Math.abs(this.shadow_to_base_line_of_node(node));\n return distance_x + distance_y;\n }\n\n /**\n * Calculate connection points of a node and the shadow.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {{sp:{x:number,y:number}, np:{x:number,y:number}}}\n */\n calc_point_of_node(node, dir) {\n let ns = node.get_size();\n let nl = node.get_location();\n let node_x = node.isroot\n ? nl.x + ns.w / 2\n : nl.x + (ns.w * (1 + dir)) / 2 + this.options.line_width * dir;\n let node_y = nl.y + ns.h / 2;\n let shadow_x =\n this.shadow_p_x + (this.shadow_w * (1 - dir)) / 2 - this.options.line_width * dir;\n let shadow_y = this.shadow_p_y + this.shadow_h / 2;\n return {\n sp: { x: shadow_x, y: shadow_y },\n np: { x: node_x, y: node_y },\n };\n }\n\n /**\n * Move a node to a new parent/position.\n * @param {import('../jsmind.node.js').Node} src_node\n * @param {import('../jsmind.node.js').Node|null} target_node\n * @param {number|null} target_direct\n */\n move_node(src_node, target_node, target_direct) {\n var shadow_h = this.shadow.offsetTop;\n if (!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)) {\n // Call validate_drag function if provided, to validate the drag operation\n if (this.options.validate_drag && typeof this.options.validate_drag === 'function') {\n const isValid = this.options.validate_drag(src_node, target_node);\n if (!isValid) {\n // Drag operation is not allowed, cleanup and return\n this.active_node = null;\n this.target_node = null;\n this.target_direct = null;\n return;\n }\n }\n\n // lookup before_node\n var sibling_nodes = target_node.children;\n var sc = sibling_nodes.length;\n var node = null;\n var delta_y = Number.MAX_VALUE;\n var node_before = null;\n var beforeid = '_last_';\n while (sc--) {\n node = sibling_nodes[sc];\n if (node.direction == target_direct && node.id != src_node.id) {\n var dy = node.get_location().y - shadow_h;\n if (dy > 0 && dy < delta_y) {\n delta_y = dy;\n node_before = node;\n beforeid = '_first_';\n }\n }\n }\n if (!!node_before) {\n beforeid = node_before.id;\n }\n this.jm.move_node(src_node.id, beforeid, target_node.id, target_direct);\n }\n this.active_node = null;\n this.target_node = null;\n this.target_direct = null;\n }\n /**\n * Handle jsMind events.\n * @param {number|string} type - Event type\n * @param {object} [data] - Event data\n */\n jm_event_handle(type, data) {\n if (type === jsMind.event_type.resize) {\n this.resize();\n }\n }\n}\n\n/**\n * Draggable node plugin registration.\n * @type {import('../jsmind.plugin.js').Plugin<Partial<DraggableNodeOptions>>}\n */\nexport const draggable_plugin = new jsMind.plugin('draggable_node', function (jm, options) {\n var jd = new DraggableNode(jm, options);\n jd.init();\n jm.add_event_listener(function (type, data) {\n jd.jm_event_handle.call(jd, type, data);\n });\n});\n\njsMind.register_plugin(draggable_plugin);\n\nexport default DraggableNode;\n"],"names":["jsMind","Error","$","clear_selection","w","getSelection","removeAllRanges","d","selection","empty","DEFAULT_OPTIONS","line_width","line_color","line_color_invalid","lookup_delay","lookup_interval","scrolling_trigger_width","scrolling_step_length","shadow_node_class_name","DraggableNode","constructor","jm","options","opts","util","json","merge","this","version","is_svg_engine","view","engine","e_canvas","canvas_ctx","helper_line","shadow","shadow_p_x","shadow_p_y","shadow_w","shadow_h","active_node","target_node","target_direct","client_w","client_h","offset_x","offset_y","hlookup_delay","hlookup_timer","capture","moved","canvas_draggable","get_view_draggable","view_panel","e_panel","view_panel_rect","init","create_canvas","create_shadow","event_bind","resize","e_nodes","appendChild","setAttribute","size","h","width","height","svg","_create_svg_element","c","ctx","getContext","tag","createElementNS","s","style","visibility","zIndex","cursor","opacity","className","reset_shadow","el","innerHTML","left","top","backgroundImage","backgroundSize","transform","clientWidth","clientHeight","show_shadow","hide_shadow","magnet_shadow","shadow_p","node_p","invalid","clear_lines","color","svg_draw_line","x","y","lineWidth","strokeStyle","lineCap","canvas_lineto","parentNode","removeChild","clearRect","x1","y1","x2","y2","beginPath","moveTo","lineTo","stroke","_svg_bezier_to","path","jd","container","on","e","button","dragstart","call","movementX","movementY","drag","dragend","get_editable","jview","is_editing","view_draggable","find_node_element","target","disable_view_draggable","nodeid","get_binded_nodeid","node","get_node","isroot","data","draggable","getBoundingClientRect","clientX","touches","zoom_current","offsetLeft","clientY","offsetTop","client_hw","Math","floor","client_hh","clearTimeout","clearInterval","setTimeout","setInterval","lookup_target_node","preventDefault","px","py","scrollTop","scrollBy","bottom","scrollHeight","scrollLeft","right","scrollWidth","enable_view_draggable","src_node","move_node","tagName","toLowerCase","sx","sy","target_direction","get_root_x","direction","lookup_overlapping_node_parent","lookup_close_node","points","calc_point_of_node","inherited","sp","np","root","get_root","root_location","get_location","root_size","get_size","shadowRect","deltaX","layout","hspace","pspace","deltaY","p","n","lookup_node_parent_by_location","elementsFromPoint","filter","map","id","mind","nodes","parent","find","Object","values","is_visible","shadow_on_target_side","distance","shadow_to_node","reduce","prev","curr","Number","MAX_VALUE","dir","shadow_to_right_of_node","shadow_to_left_of_node","shadow_to_base_line_of_node","abs","ns","nl","node_x","node_y","validate_drag","sibling_nodes","children","sc","length","delta_y","node_before","beforeid","dy","jm_event_handle","type","event_type","draggable_plugin","plugin","add_event_listener","register_plugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"jsmind.draggable-node.js","sources":["../src/jsmind.common.js","../src/jsmind.plugin.js","../src/plugins/jsmind.draggable-node.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.1';\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\nimport { logger } from './jsmind.common.js';\n\n/**\n * Plugin Manager\n * Manages plugin lifecycle with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class PluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, Plugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.pluginList.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.pluginList.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 if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('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 Plugin} 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 if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n this.plugins.delete(instanceName);\n delete this.jm[instanceName];\n\n const list = this.jm.constructor.pluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('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 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 {Plugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Plugin Base Class\n * Provides standard plugin interface.\n */\nexport class Plugin {\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 */\n beforePluginRemove() {}\n\n /**\n * Called before jsMind instance is destroyed\n */\n beforePluginDestroy() {\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof Plugin} 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 {Plugin | 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 jsMind from '@umbraci/jsmind';\nimport { Plugin } from '../jsmind.plugin.js';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nconst $ = jsMind.$;\n\nconst clear_selection =\n 'getSelection' in $.w\n ? function () {\n $.w.getSelection().removeAllRanges();\n }\n : function () {\n $.d.selection.empty();\n };\n\n/**\n * Default options for draggable node plugin.\n * @typedef {Object} DraggableNodeOptions\n * @property {number} [line_width]\n * @property {string} [line_color]\n * @property {string} [line_color_invalid]\n * @property {number} [lookup_delay]\n * @property {number} [lookup_interval]\n * @property {number} [scrolling_trigger_width]\n * @property {number} [scrolling_step_length]\n * @property {string} [shadow_node_class_name]\n * @property {(draggedNode:import('../jsmind.node.js').Node, targetNode:import('../jsmind.node.js').Node|null)=>boolean} [validate_drag]\n */\nconst DEFAULT_OPTIONS = {\n line_width: 5,\n line_color: 'rgba(0,0,0,0.3)',\n line_color_invalid: 'rgba(255,51,51,0.6)',\n lookup_delay: 200,\n lookup_interval: 100,\n scrolling_trigger_width: 20,\n scrolling_step_length: 10,\n shadow_node_class_name: 'jsmind-draggable-shadow-node',\n};\n\n/**\n * Draggable node plugin for jsMind.\n */\nexport class DraggableNode {\n /**\n * Create draggable node plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<DraggableNodeOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.4.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {DraggableNodeOptions} */\n this.options = opts;\n /** @type {boolean} */\n this.is_svg_engine = jm.view.opts.engine === 'svg';\n /** @type {HTMLCanvasElement|SVGSVGElement|null} */\n this.e_canvas = null;\n /** @type {CanvasRenderingContext2D|null} */\n this.canvas_ctx = null;\n /** @type {SVGPathElement|null} */\n this.helper_line = null;\n /** @type {HTMLElement|null} */\n this.shadow = null;\n /** @type {number} */\n this.shadow_p_x = 0;\n /** @type {number} */\n this.shadow_p_y = 0;\n /** @type {number} */\n this.shadow_w = 0;\n /** @type {number} */\n this.shadow_h = 0;\n /** @type {import('../jsmind.node.js').Node|null} */\n this.active_node = null;\n /** @type {import('../jsmind.node.js').Node|null} */\n this.target_node = null;\n /** @type {number|null} */\n this.target_direct = null;\n /** @type {number} */\n this.client_w = 0;\n /** @type {number} */\n this.client_h = 0;\n /** @type {number} */\n this.offset_x = 0;\n /** @type {number} */\n this.offset_y = 0;\n /** @type {number} */\n this.hlookup_delay = 0;\n /** @type {number} */\n this.hlookup_timer = 0;\n /** @type {boolean} */\n this.capture = false;\n /** @type {boolean} */\n this.moved = false;\n /** @type {boolean} */\n this.canvas_draggable = jm.get_view_draggable();\n /** @type {HTMLElement} */\n this.view_panel = jm.view.e_panel;\n /** @type {DOMRect|null} */\n this.view_panel_rect = null;\n }\n /** Initialize the draggable node plugin. */\n init() {\n this.create_canvas();\n this.create_shadow();\n this.event_bind();\n }\n /** Resize canvas/SVG and shadow elements. */\n resize() {\n this.jm.view.e_nodes.appendChild(this.shadow);\n if (this.is_svg_engine) {\n this.e_canvas.setAttribute('width', this.jm.view.size.w);\n this.e_canvas.setAttribute('height', this.jm.view.size.h);\n } else {\n this.e_canvas.width = this.jm.view.size.w;\n this.e_canvas.height = this.jm.view.size.h;\n }\n }\n /** Create canvas or SVG for drawing drag lines. */\n create_canvas() {\n if (this.is_svg_engine) {\n // Create SVG element for helper lines\n var svg = this._create_svg_element('svg');\n svg.setAttribute('class', 'jsmind-draggable-helper');\n svg.setAttribute('style', 'position: absolute; top: 0; left: 0; pointer-events: none;');\n this.jm.view.e_panel.appendChild(svg);\n this.e_canvas = svg;\n } else {\n // Create Canvas element for helper lines\n var c = $.c('canvas');\n this.jm.view.e_panel.appendChild(c);\n var ctx = c.getContext('2d');\n this.e_canvas = c;\n this.canvas_ctx = ctx;\n }\n }\n /**\n * Create SVG element with proper namespace.\n * @param {string} tag - SVG tag name\n * @returns {SVGElement}\n * @private\n */\n _create_svg_element(tag) {\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\n }\n create_shadow() {\n var s = $.c('jmnode');\n s.style.visibility = 'hidden';\n s.style.zIndex = '3';\n s.style.cursor = 'move';\n s.style.opacity = '0.7';\n s.className = this.options.shadow_node_class_name;\n this.shadow = s;\n }\n /**\n * Reset shadow element style and cache its size.\n * @param {HTMLElement} el - The node element to mirror as shadow\n */\n reset_shadow(el) {\n var shadowStyle = this.shadow.style;\n var inlineStyle = el.style;\n var computedStyle = $.w.getComputedStyle(el);\n\n this.shadow.innerHTML = el.innerHTML;\n\n var copiedInlineProps = [\n 'left',\n 'top',\n 'width',\n 'height',\n 'backgroundImage',\n 'backgroundSize',\n 'transform',\n ];\n copiedInlineProps.forEach(prop => {\n shadowStyle[prop] = inlineStyle[prop];\n });\n\n var textLayoutProps = ['whiteSpace', 'wordBreak', 'overflowWrap', 'maxWidth'];\n textLayoutProps.forEach(prop => {\n shadowStyle[prop] = inlineStyle[prop] || computedStyle[prop];\n });\n\n this.shadow_w = this.shadow.clientWidth;\n this.shadow_h = this.shadow.clientHeight;\n }\n /** Show the shadow element. */\n show_shadow() {\n if (!this.moved) {\n this.shadow.style.visibility = 'visible';\n }\n }\n /** Hide the shadow element. */\n hide_shadow() {\n this.shadow.style.visibility = 'hidden';\n }\n /**\n * Draw a helper line between the shadow and target node.\n * @param {{x:number,y:number}} shadow_p - Shadow anchor point\n * @param {{x:number,y:number}} node_p - Target node anchor point\n * @param {boolean} invalid - Whether current target is invalid\n */\n magnet_shadow(shadow_p, node_p, invalid) {\n this.clear_lines();\n var color = invalid ? this.options.line_color_invalid : this.options.line_color;\n\n if (this.is_svg_engine) {\n this.svg_draw_line(shadow_p.x, shadow_p.y, node_p.x, node_p.y, color);\n } else {\n this.canvas_ctx.lineWidth = this.options.line_width;\n this.canvas_ctx.strokeStyle = color;\n this.canvas_ctx.lineCap = 'round';\n this.canvas_lineto(shadow_p.x, shadow_p.y, node_p.x, node_p.y);\n }\n }\n /** Clear helper lines from canvas or SVG. */\n clear_lines() {\n if (this.is_svg_engine) {\n if (this.helper_line && this.helper_line.parentNode) {\n this.e_canvas.removeChild(this.helper_line);\n this.helper_line = null;\n }\n } else {\n this.canvas_ctx.clearRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n }\n /**\n * Draw a straight helper line on canvas.\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n */\n canvas_lineto(x1, y1, x2, y2) {\n this.canvas_ctx.beginPath();\n this.canvas_ctx.moveTo(x1, y1);\n this.canvas_ctx.lineTo(x2, y2);\n this.canvas_ctx.stroke();\n }\n /**\n * Draw a helper line on SVG using bezier curve.\n * Reuses the line drawing logic from SvgGraph.\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 * @param {string} color - Line color\n */\n svg_draw_line(x1, y1, x2, y2, color) {\n // Create SVG path element for helper line\n this.helper_line = this._create_svg_element('path');\n this.helper_line.setAttribute('stroke', color);\n this.helper_line.setAttribute('stroke-width', this.options.line_width);\n this.helper_line.setAttribute('fill', 'transparent');\n this.helper_line.setAttribute('stroke-linecap', 'round');\n\n // Draw bezier curve (same as SvgGraph._bezier_to)\n this._svg_bezier_to(this.helper_line, x1, y1, x2, y2);\n\n // Add to SVG container\n this.e_canvas.appendChild(this.helper_line);\n }\n /**\n * Draw bezier curve to SVG path element.\n * Reuses logic from SvgGraph._bezier_to.\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 * @private\n */\n _svg_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 /** Bind mouse/touch events for dragging. */\n event_bind() {\n var jd = this;\n var container = this.jm.view.container;\n $.on(container, 'mousedown', function (e) {\n if (e.button === 0) {\n jd.dragstart.call(jd, e);\n }\n });\n $.on(container, 'mousemove', function (e) {\n if (e.movementX !== 0 || e.movementY !== 0) {\n jd.drag.call(jd, e);\n }\n });\n $.on(container, 'mouseup', function (e) {\n jd.dragend.call(jd, e);\n });\n $.on(container, 'touchstart', function (e) {\n jd.dragstart.call(jd, e);\n });\n $.on(container, 'touchmove', function (e) {\n jd.drag.call(jd, e);\n });\n $.on(container, 'touchend', function (e) {\n jd.dragend.call(jd, e);\n });\n }\n /**\n * Begin dragging interaction.\n * @param {MouseEvent|TouchEvent} e - Pointer down event\n */\n dragstart(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.capture) {\n return;\n }\n var jview = this.jm.view;\n if (jview.is_editing()) {\n return;\n }\n this.active_node = null;\n this.view_draggable = this.jm.get_view_draggable();\n\n var el = this.find_node_element(e.target);\n if (!el) {\n return;\n }\n if (this.view_draggable) {\n this.jm.disable_view_draggable();\n }\n var nodeid = jview.get_binded_nodeid(el);\n if (!!nodeid) {\n var node = this.jm.get_node(nodeid);\n if (!node.isroot) {\n // 检查节点是否允许拖拽\n if (node.data && node.data.draggable === false) {\n return;\n }\n this.reset_shadow(el);\n this.view_panel_rect = this.view_panel.getBoundingClientRect();\n this.active_node = node;\n this.offset_x =\n (e.clientX || e.touches[0].clientX) / jview.zoom_current - el.offsetLeft;\n this.offset_y =\n (e.clientY || e.touches[0].clientY) / jview.zoom_current - el.offsetTop;\n this.client_hw = Math.floor(el.clientWidth / 2);\n this.client_hh = Math.floor(el.clientHeight / 2);\n if (this.hlookup_delay != 0) {\n $.w.clearTimeout(this.hlookup_delay);\n }\n if (this.hlookup_timer != 0) {\n $.w.clearInterval(this.hlookup_timer);\n }\n var jd = this;\n this.hlookup_delay = $.w.setTimeout(function () {\n jd.hlookup_delay = 0;\n jd.hlookup_timer = $.w.setInterval(function () {\n jd.lookup_target_node.call(jd);\n }, jd.options.lookup_interval);\n }, this.options.lookup_delay);\n jd.capture = true;\n }\n }\n }\n /**\n * Drag handler to move shadow and auto-scroll container.\n * @param {MouseEvent|TouchEvent} e - Pointer move event\n */\n drag(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.capture) {\n e.preventDefault();\n this.show_shadow();\n this.moved = true;\n clear_selection();\n var jview = this.jm.view;\n var px = (e.clientX || e.touches[0].clientX) / jview.zoom_current - this.offset_x;\n var py = (e.clientY || e.touches[0].clientY) / jview.zoom_current - this.offset_y;\n // scrolling container axisY if drag nodes exceeding container\n if (\n e.clientY - this.view_panel_rect.top < this.options.scrolling_trigger_width &&\n this.view_panel.scrollTop > this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(0, -this.options.scrolling_step_length);\n this.offset_y += this.options.scrolling_step_length / jview.zoom_current;\n } else if (\n this.view_panel_rect.bottom - e.clientY < this.options.scrolling_trigger_width &&\n this.view_panel.scrollTop <\n this.view_panel.scrollHeight -\n this.view_panel_rect.height -\n this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(0, this.options.scrolling_step_length);\n this.offset_y -= this.options.scrolling_step_length / jview.zoom_current;\n }\n // scrolling container axisX if drag nodes exceeding container\n if (\n e.clientX - this.view_panel_rect.left < this.options.scrolling_trigger_width &&\n this.view_panel.scrollLeft > this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(-this.options.scrolling_step_length, 0);\n this.offset_x += this.options.scrolling_step_length / jview.zoom_current;\n } else if (\n this.view_panel_rect.right - e.clientX < this.options.scrolling_trigger_width &&\n this.view_panel.scrollLeft <\n this.view_panel.scrollWidth -\n this.view_panel_rect.width -\n this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(this.options.scrolling_step_length, 0);\n this.offset_x -= this.options.scrolling_step_length / jview.zoom_current;\n }\n this.shadow.style.left = px + 'px';\n this.shadow.style.top = py + 'px';\n clear_selection();\n }\n }\n /**\n * Finish dragging, move the node if applicable.\n * @param {MouseEvent|TouchEvent} e - Pointer up event\n */\n dragend(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.view_draggable) {\n this.jm.enable_view_draggable();\n }\n if (this.capture) {\n if (this.hlookup_delay != 0) {\n $.w.clearTimeout(this.hlookup_delay);\n this.hlookup_delay = 0;\n this.clear_lines();\n }\n if (this.hlookup_timer != 0) {\n $.w.clearInterval(this.hlookup_timer);\n this.hlookup_timer = 0;\n this.clear_lines();\n }\n if (this.moved) {\n var src_node = this.active_node;\n var target_node = this.target_node;\n var target_direct = this.target_direct;\n this.move_node(src_node, target_node, target_direct);\n }\n this.hide_shadow();\n }\n this.view_panel_rect = null;\n this.moved = false;\n this.capture = false;\n }\n /**\n * Find the closest node element from an event target.\n * @param {HTMLElement} el - Current DOM element\n * @returns {HTMLElement|null} Matched node element or null\n */\n find_node_element(el) {\n if (\n el === this.jm.view.e_nodes ||\n el === this.jm.view.e_panel ||\n el === this.jm.view.container\n ) {\n return null;\n }\n if (el.tagName.toLowerCase() === 'jmnode') {\n return el;\n }\n return this.find_node_element(el.parentNode);\n }\n /** Recompute target node under the shadow and draw helper. */\n lookup_target_node() {\n let sx = this.shadow.offsetLeft;\n let sy = this.shadow.offsetTop;\n if (sx === this.shadow_p_x && sy === this.shadow_p_y) {\n return;\n }\n this.shadow_p_x = sx;\n this.shadow_p_y = sy;\n\n let target_direction =\n this.shadow_p_x + this.shadow_w / 2 >= this.get_root_x()\n ? jsMind.direction.right\n : jsMind.direction.left;\n let overlapping_node = this.lookup_overlapping_node_parent(target_direction);\n let target_node = overlapping_node || this.lookup_close_node(target_direction);\n if (!!target_node) {\n let points = this.calc_point_of_node(target_node, target_direction);\n let invalid = jsMind.node.inherited(this.active_node, target_node);\n this.magnet_shadow(points.sp, points.np, invalid);\n this.target_node = target_node;\n this.target_direct = target_direction;\n }\n }\n /**\n * Get X coordinate of root node center.\n * @returns {number}\n */\n get_root_x() {\n let root = this.jm.get_root();\n let root_location = root.get_location();\n let root_size = root.get_size();\n return root_location.x + root_size.w / 2;\n }\n\n /**\n * Lookup overlapping node's parent near the shadow position.\n * @param {number} direction - Direction constant\n * @returns {import('../jsmind.node.js').Node|null}\n */\n lookup_overlapping_node_parent(direction) {\n let shadowRect = this.shadow.getBoundingClientRect();\n let x = shadowRect.x + (shadowRect.width * (1 - direction)) / 2;\n let deltaX = (this.jm.options.layout.hspace + this.jm.options.layout.pspace) * direction;\n let deltaY = shadowRect.height;\n let points = [\n [x, shadowRect.y],\n [x, shadowRect.y + deltaY / 2],\n [x, shadowRect.y + deltaY],\n [x + deltaX / 2, shadowRect.y],\n [x + deltaX / 2, shadowRect.y + deltaY / 2],\n [x + deltaX / 2, shadowRect.y + deltaY],\n [x + deltaX, shadowRect.y],\n [x + deltaX, shadowRect.y + deltaY / 2],\n [x + deltaX, shadowRect.y + deltaY],\n ];\n for (const p of points) {\n let n = this.lookup_node_parent_by_location(p[0], p[1]);\n if (!!n) {\n return n;\n }\n }\n }\n\n /**\n * Find node's parent by a screen location.\n * @param {number} x - Client X\n * @param {number} y - Client Y\n * @returns {import('../jsmind.node.js').Node|null}\n */\n lookup_node_parent_by_location(x, y) {\n return $.d\n .elementsFromPoint(x, y)\n .filter(\n x => x.tagName === 'JMNODE' && x.className !== this.options.shadow_node_class_name\n )\n .map(el => this.jm.view.get_binded_nodeid(el))\n .map(id => id && this.jm.mind.nodes[id])\n .map(n => n && n.parent)\n .find(n => n);\n }\n\n /**\n * Lookup the closest node along a direction.\n * @param {number} direction\n * @returns {import('../jsmind.node.js').Node}\n */\n lookup_close_node(direction) {\n return Object.values(this.jm.mind.nodes)\n .filter(n => n.direction == direction || n.isroot)\n .filter(n => this.jm.layout.is_visible(n))\n .filter(n => this.shadow_on_target_side(n, direction))\n .map(n => ({ node: n, distance: this.shadow_to_node(n, direction) }))\n .reduce(\n (prev, curr) => {\n return prev.distance < curr.distance ? prev : curr;\n },\n { node: this.jm.get_root(), distance: Number.MAX_VALUE }\n ).node;\n }\n\n /**\n * Check if shadow is on the target side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {boolean}\n */\n shadow_on_target_side(node, dir) {\n return (\n (dir == jsMind.direction.right && this.shadow_to_right_of_node(node) > 0) ||\n (dir == jsMind.direction.left && this.shadow_to_left_of_node(node) > 0)\n );\n }\n\n /**\n * Distance from shadow to the right side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_right_of_node(node) {\n return this.shadow_p_x - node.get_location().x - node.get_size().w;\n }\n\n /**\n * Distance from shadow to the left side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_left_of_node(node) {\n return node.get_location().x - this.shadow_p_x - this.shadow_w;\n }\n\n /**\n * Vertical distance between shadow centerline and node centerline.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_base_line_of_node(node) {\n return this.shadow_p_y + this.shadow_h / 2 - node.get_location().y - node.get_size().h / 2;\n }\n\n /**\n * Manhattan distance to a node along a direction.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {number}\n */\n shadow_to_node(node, dir) {\n let distance_x =\n dir === jsMind.direction.right\n ? Math.abs(this.shadow_to_right_of_node(node))\n : Math.abs(this.shadow_to_left_of_node(node));\n let distance_y = Math.abs(this.shadow_to_base_line_of_node(node));\n return distance_x + distance_y;\n }\n\n /**\n * Calculate connection points of a node and the shadow.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {{sp:{x:number,y:number}, np:{x:number,y:number}}}\n */\n calc_point_of_node(node, dir) {\n let ns = node.get_size();\n let nl = node.get_location();\n let node_x = node.isroot\n ? nl.x + ns.w / 2\n : nl.x + (ns.w * (1 + dir)) / 2 + this.options.line_width * dir;\n let node_y = nl.y + ns.h / 2;\n let shadow_x =\n this.shadow_p_x + (this.shadow_w * (1 - dir)) / 2 - this.options.line_width * dir;\n let shadow_y = this.shadow_p_y + this.shadow_h / 2;\n return {\n sp: { x: shadow_x, y: shadow_y },\n np: { x: node_x, y: node_y },\n };\n }\n\n /**\n * Move a node to a new parent/position.\n * @param {import('../jsmind.node.js').Node} src_node\n * @param {import('../jsmind.node.js').Node|null} target_node\n * @param {number|null} target_direct\n */\n move_node(src_node, target_node, target_direct) {\n var shadow_h = this.shadow.offsetTop;\n if (!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)) {\n // Call validate_drag function if provided, to validate the drag operation\n if (this.options.validate_drag && typeof this.options.validate_drag === 'function') {\n const isValid = this.options.validate_drag(src_node, target_node);\n if (!isValid) {\n // Drag operation is not allowed, cleanup and return\n this.active_node = null;\n this.target_node = null;\n this.target_direct = null;\n return;\n }\n }\n\n // lookup before_node\n var sibling_nodes = target_node.children;\n var sc = sibling_nodes.length;\n var node = null;\n var delta_y = Number.MAX_VALUE;\n var node_before = null;\n var beforeid = '_last_';\n while (sc--) {\n node = sibling_nodes[sc];\n if (node.direction == target_direct && node.id != src_node.id) {\n var dy = node.get_location().y - shadow_h;\n if (dy > 0 && dy < delta_y) {\n delta_y = dy;\n node_before = node;\n beforeid = '_first_';\n }\n }\n }\n if (!!node_before) {\n beforeid = node_before.id;\n }\n this.jm.move_node(src_node.id, beforeid, target_node.id, target_direct);\n }\n this.active_node = null;\n this.target_node = null;\n this.target_direct = null;\n }\n /**\n * Handle jsMind events.\n * @param {number|string} type - Event type\n * @param {object} [data] - Event data\n */\n jm_event_handle(type, data) {\n if (type === jsMind.event_type.resize) {\n this.resize();\n }\n }\n}\n\n/**\n * Draggable node plugin for unified plugin system.\n */\nexport class DraggableNodePlugin extends Plugin {\n static instanceName = 'draggable';\n static preload = false;\n\n /**\n * @param {{ jm: import('../jsmind.js').default, pluginOpt: Partial<DraggableNodeOptions> }} params\n */\n constructor({ jm, pluginOpt }) {\n super({ jm, pluginOpt });\n this.draggable = new DraggableNode(jm, pluginOpt);\n this.draggable.init();\n this._eventHandle = (type, data) => {\n this.draggable.jm_event_handle(type, data);\n };\n jm.add_event_listener(this._eventHandle);\n jm.draggable = this.draggable;\n }\n\n beforePluginRemove() {\n delete this.jm.draggable;\n }\n}\n\njsMind.usePlugin(DraggableNodePlugin);\n\nexport default DraggableNode;\n"],"names":["String","prototype","startsWith","p","this","slice","length","Plugin","static","constructor","jm","pluginOpt","options","beforePluginRemove","beforePluginDestroy","jsMind","Error","$","clear_selection","w","getSelection","removeAllRanges","d","selection","empty","DEFAULT_OPTIONS","line_width","line_color","line_color_invalid","lookup_delay","lookup_interval","scrolling_trigger_width","scrolling_step_length","shadow_node_class_name","DraggableNode","opts","util","json","merge","version","is_svg_engine","view","engine","e_canvas","canvas_ctx","helper_line","shadow","shadow_p_x","shadow_p_y","shadow_w","shadow_h","active_node","target_node","target_direct","client_w","client_h","offset_x","offset_y","hlookup_delay","hlookup_timer","capture","moved","canvas_draggable","get_view_draggable","view_panel","e_panel","view_panel_rect","init","create_canvas","create_shadow","event_bind","resize","e_nodes","appendChild","setAttribute","size","h","width","height","svg","_create_svg_element","c","ctx","getContext","tag","createElementNS","s","style","visibility","zIndex","cursor","opacity","className","reset_shadow","el","shadowStyle","inlineStyle","computedStyle","getComputedStyle","innerHTML","forEach","prop","clientWidth","clientHeight","show_shadow","hide_shadow","magnet_shadow","shadow_p","node_p","invalid","clear_lines","color","svg_draw_line","x","y","lineWidth","strokeStyle","lineCap","canvas_lineto","parentNode","removeChild","clearRect","x1","y1","x2","y2","beginPath","moveTo","lineTo","stroke","_svg_bezier_to","path","jd","container","on","e","button","dragstart","call","movementX","movementY","drag","dragend","get_editable","jview","is_editing","view_draggable","find_node_element","target","disable_view_draggable","nodeid","get_binded_nodeid","node","get_node","isroot","data","draggable","getBoundingClientRect","clientX","touches","zoom_current","offsetLeft","clientY","offsetTop","client_hw","Math","floor","client_hh","clearTimeout","clearInterval","setTimeout","setInterval","lookup_target_node","preventDefault","px","py","top","scrollTop","scrollBy","bottom","scrollHeight","left","scrollLeft","right","scrollWidth","enable_view_draggable","src_node","move_node","tagName","toLowerCase","sx","sy","target_direction","get_root_x","direction","lookup_overlapping_node_parent","lookup_close_node","points","calc_point_of_node","inherited","sp","np","root","get_root","root_location","get_location","root_size","get_size","shadowRect","deltaX","layout","hspace","pspace","deltaY","n","lookup_node_parent_by_location","elementsFromPoint","filter","map","id","mind","nodes","parent","find","Object","values","is_visible","shadow_on_target_side","distance","shadow_to_node","reduce","prev","curr","Number","MAX_VALUE","dir","shadow_to_right_of_node","shadow_to_left_of_node","shadow_to_base_line_of_node","abs","ns","nl","node_x","node_y","validate_drag","sibling_nodes","children","sc","delta_y","node_before","beforeid","dy","jm_event_handle","type","event_type","DraggableNodePlugin","super","_eventHandle","add_event_listener","usePlugin"],"mappings":"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"}
|