1/*!
2 * jquery.fancytree.dnd.js
3 *
4 * Drag-and-drop support (jQuery UI draggable/droppable).
5 * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
6 *
7 * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
8 *
9 * Released under the MIT license
10 * https://github.com/mar10/fancytree/wiki/LicenseInfo
11 *
12 * @version 2.38.3
13 * @date 2023-02-01T20:52:50Z
14 */
15
16(function (factory) {
17	if (typeof define === "function" && define.amd) {
18		// AMD. Register as an anonymous module.
19		define([
20			"jquery",
21			"jquery-ui/ui/widgets/draggable",
22			"jquery-ui/ui/widgets/droppable",
23			"./jquery.fancytree",
24		], factory);
25	} else if (typeof module === "object" && module.exports) {
26		// Node/CommonJS
27		require("./jquery.fancytree");
28		module.exports = factory(require("jquery"));
29	} else {
30		// Browser globals
31		factory(jQuery);
32	}
33})(function ($) {
34	"use strict";
35
36	/******************************************************************************
37	 * Private functions and variables
38	 */
39	var didRegisterDnd = false,
40		classDropAccept = "fancytree-drop-accept",
41		classDropAfter = "fancytree-drop-after",
42		classDropBefore = "fancytree-drop-before",
43		classDropOver = "fancytree-drop-over",
44		classDropReject = "fancytree-drop-reject",
45		classDropTarget = "fancytree-drop-target";
46
47	/* Convert number to string and prepend +/-; return empty string for 0.*/
48	function offsetString(n) {
49		// eslint-disable-next-line no-nested-ternary
50		return n === 0 ? "" : n > 0 ? "+" + n : "" + n;
51	}
52
53	//--- Extend ui.draggable event handling --------------------------------------
54
55	function _registerDnd() {
56		if (didRegisterDnd) {
57			return;
58		}
59
60		// Register proxy-functions for draggable.start/drag/stop
61
62		$.ui.plugin.add("draggable", "connectToFancytree", {
63			start: function (event, ui) {
64				// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
65				var draggable =
66						$(this).data("ui-draggable") ||
67						$(this).data("draggable"),
68					sourceNode = ui.helper.data("ftSourceNode") || null;
69
70				if (sourceNode) {
71					// Adjust helper offset, so cursor is slightly outside top/left corner
72					draggable.offset.click.top = -2;
73					draggable.offset.click.left = +16;
74					// Trigger dragStart event
75					// TODO: when called as connectTo..., the return value is ignored(?)
76					return sourceNode.tree.ext.dnd._onDragEvent(
77						"start",
78						sourceNode,
79						null,
80						event,
81						ui,
82						draggable
83					);
84				}
85			},
86			drag: function (event, ui) {
87				var ctx,
88					isHelper,
89					logObject,
90					// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
91					draggable =
92						$(this).data("ui-draggable") ||
93						$(this).data("draggable"),
94					sourceNode = ui.helper.data("ftSourceNode") || null,
95					prevTargetNode = ui.helper.data("ftTargetNode") || null,
96					targetNode = $.ui.fancytree.getNode(event.target),
97					dndOpts = sourceNode && sourceNode.tree.options.dnd;
98
99				// logObject = sourceNode || prevTargetNode || $.ui.fancytree;
100				// logObject.debug("Drag event:", event, event.shiftKey);
101				if (event.target && !targetNode) {
102					// We got a drag event, but the targetNode could not be found
103					// at the event location. This may happen,
104					// 1. if the mouse jumped over the drag helper,
105					// 2. or if a non-fancytree element is dragged
106					// We ignore it:
107					isHelper =
108						$(event.target).closest(
109							"div.fancytree-drag-helper,#fancytree-drop-marker"
110						).length > 0;
111					if (isHelper) {
112						logObject =
113							sourceNode || prevTargetNode || $.ui.fancytree;
114						logObject.debug("Drag event over helper: ignored.");
115						return;
116					}
117				}
118				ui.helper.data("ftTargetNode", targetNode);
119
120				if (dndOpts && dndOpts.updateHelper) {
121					ctx = sourceNode.tree._makeHookContext(sourceNode, event, {
122						otherNode: targetNode,
123						ui: ui,
124						draggable: draggable,
125						dropMarker: $("#fancytree-drop-marker"),
126					});
127					dndOpts.updateHelper.call(sourceNode.tree, sourceNode, ctx);
128				}
129
130				// Leaving a tree node
131				if (prevTargetNode && prevTargetNode !== targetNode) {
132					prevTargetNode.tree.ext.dnd._onDragEvent(
133						"leave",
134						prevTargetNode,
135						sourceNode,
136						event,
137						ui,
138						draggable
139					);
140				}
141				if (targetNode) {
142					if (!targetNode.tree.options.dnd.dragDrop) {
143						// not enabled as drop target
144					} else if (targetNode === prevTargetNode) {
145						// Moving over same node
146						targetNode.tree.ext.dnd._onDragEvent(
147							"over",
148							targetNode,
149							sourceNode,
150							event,
151							ui,
152							draggable
153						);
154					} else {
155						// Entering this node first time
156						targetNode.tree.ext.dnd._onDragEvent(
157							"enter",
158							targetNode,
159							sourceNode,
160							event,
161							ui,
162							draggable
163						);
164						targetNode.tree.ext.dnd._onDragEvent(
165							"over",
166							targetNode,
167							sourceNode,
168							event,
169							ui,
170							draggable
171						);
172					}
173				}
174				// else go ahead with standard event handling
175			},
176			stop: function (event, ui) {
177				var logObject,
178					// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10:
179					draggable =
180						$(this).data("ui-draggable") ||
181						$(this).data("draggable"),
182					sourceNode = ui.helper.data("ftSourceNode") || null,
183					targetNode = ui.helper.data("ftTargetNode") || null,
184					dropped = event.type === "mouseup" && event.which === 1;
185
186				if (!dropped) {
187					logObject = sourceNode || targetNode || $.ui.fancytree;
188					logObject.debug("Drag was cancelled");
189				}
190				if (targetNode) {
191					if (dropped) {
192						targetNode.tree.ext.dnd._onDragEvent(
193							"drop",
194							targetNode,
195							sourceNode,
196							event,
197							ui,
198							draggable
199						);
200					}
201					targetNode.tree.ext.dnd._onDragEvent(
202						"leave",
203						targetNode,
204						sourceNode,
205						event,
206						ui,
207						draggable
208					);
209				}
210				if (sourceNode) {
211					sourceNode.tree.ext.dnd._onDragEvent(
212						"stop",
213						sourceNode,
214						null,
215						event,
216						ui,
217						draggable
218					);
219				}
220			},
221		});
222
223		didRegisterDnd = true;
224	}
225
226	/******************************************************************************
227	 * Drag and drop support
228	 */
229	function _initDragAndDrop(tree) {
230		var dnd = tree.options.dnd || null,
231			glyph = tree.options.glyph || null;
232
233		// Register 'connectToFancytree' option with ui.draggable
234		if (dnd) {
235			_registerDnd();
236		}
237		// Attach ui.draggable to this Fancytree instance
238		if (dnd && dnd.dragStart) {
239			tree.widget.element.draggable(
240				$.extend(
241					{
242						addClasses: false,
243						// DT issue 244: helper should be child of scrollParent:
244						appendTo: tree.$container,
245						//			appendTo: "body",
246						containment: false,
247						//			containment: "parent",
248						delay: 0,
249						distance: 4,
250						revert: false,
251						scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
252						scrollSpeed: 7,
253						scrollSensitivity: 10,
254						// Delegate draggable.start, drag, and stop events to our handler
255						connectToFancytree: true,
256						// Let source tree create the helper element
257						helper: function (event) {
258							var $helper,
259								$nodeTag,
260								opts,
261								sourceNode = $.ui.fancytree.getNode(
262									event.target
263								);
264
265							if (!sourceNode) {
266								// #405, DT issue 211: might happen, if dragging a table *header*
267								return "<div>ERROR?: helper requested but sourceNode not found</div>";
268							}
269							opts = sourceNode.tree.options.dnd;
270							$nodeTag = $(sourceNode.span);
271							// Only event and node argument is available
272							$helper = $(
273								"<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>"
274							)
275								.css({ zIndex: 3, position: "relative" }) // so it appears above ext-wide selection bar
276								.append(
277									$nodeTag
278										.find("span.fancytree-title")
279										.clone()
280								);
281
282							// Attach node reference to helper object
283							$helper.data("ftSourceNode", sourceNode);
284
285							// Support glyph symbols instead of icons
286							if (glyph) {
287								$helper
288									.find(".fancytree-drag-helper-img")
289									.addClass(
290										glyph.map._addClass +
291											" " +
292											glyph.map.dragHelper
293									);
294							}
295							// Allow to modify the helper, e.g. to add multi-node-drag feedback
296							if (opts.initHelper) {
297								opts.initHelper.call(
298									sourceNode.tree,
299									sourceNode,
300									{
301										node: sourceNode,
302										tree: sourceNode.tree,
303										originalEvent: event,
304										ui: { helper: $helper },
305									}
306								);
307							}
308							// We return an unconnected element, so `draggable` will add this
309							// to the parent specified as `appendTo` option
310							return $helper;
311						},
312						start: function (event, ui) {
313							var sourceNode = ui.helper.data("ftSourceNode");
314							return !!sourceNode; // Abort dragging if no node could be found
315						},
316					},
317					tree.options.dnd.draggable
318				)
319			);
320		}
321		// Attach ui.droppable to this Fancytree instance
322		if (dnd && dnd.dragDrop) {
323			tree.widget.element.droppable(
324				$.extend(
325					{
326						addClasses: false,
327						tolerance: "intersect",
328						greedy: false,
329						/*
330			activate: function(event, ui) {
331				tree.debug("droppable - activate", event, ui, this);
332			},
333			create: function(event, ui) {
334				tree.debug("droppable - create", event, ui);
335			},
336			deactivate: function(event, ui) {
337				tree.debug("droppable - deactivate", event, ui);
338			},
339			drop: function(event, ui) {
340				tree.debug("droppable - drop", event, ui);
341			},
342			out: function(event, ui) {
343				tree.debug("droppable - out", event, ui);
344			},
345			over: function(event, ui) {
346				tree.debug("droppable - over", event, ui);
347			}
348*/
349					},
350					tree.options.dnd.droppable
351				)
352			);
353		}
354	}
355
356	/******************************************************************************
357	 *
358	 */
359
360	$.ui.fancytree.registerExtension({
361		name: "dnd",
362		version: "2.38.3",
363		// Default options for this extension.
364		options: {
365			// Make tree nodes accept draggables
366			autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
367			draggable: null, // Additional options passed to jQuery draggable
368			droppable: null, // Additional options passed to jQuery droppable
369			focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
370			preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
371			preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
372			smartRevert: true, // set draggable.revert = true if drop was rejected
373			dropMarkerOffsetX: -24, // absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
374			dropMarkerInsertOffsetX: -16, // additional offset for drop-marker with hitMode = "before"/"after"
375			// Events (drag support)
376			dragStart: null, // Callback(sourceNode, data), return true, to enable dnd
377			dragStop: null, // Callback(sourceNode, data)
378			initHelper: null, // Callback(sourceNode, data)
379			updateHelper: null, // Callback(sourceNode, data)
380			// Events (drop support)
381			dragEnter: null, // Callback(targetNode, data)
382			dragOver: null, // Callback(targetNode, data)
383			dragExpand: null, // Callback(targetNode, data), return false to prevent autoExpand
384			dragDrop: null, // Callback(targetNode, data)
385			dragLeave: null, // Callback(targetNode, data)
386		},
387
388		treeInit: function (ctx) {
389			var tree = ctx.tree;
390			this._superApply(arguments);
391			// issue #270: draggable eats mousedown events
392			if (tree.options.dnd.dragStart) {
393				tree.$container.on("mousedown", function (event) {
394					//				if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
395					if (ctx.options.dnd.focusOnClick) {
396						// #270
397						var node = $.ui.fancytree.getNode(event);
398						if (node) {
399							node.debug(
400								"Re-enable focus that was prevented by jQuery UI draggable."
401							);
402							// node.setFocus();
403							// $(node.span).closest(":tabbable").focus();
404							// $(event.target).trigger("focus");
405							// $(event.target).closest(":tabbable").trigger("focus");
406						}
407						setTimeout(function () {
408							// #300
409							$(event.target).closest(":tabbable").focus();
410						}, 10);
411					}
412				});
413			}
414			_initDragAndDrop(tree);
415		},
416		/* Display drop marker according to hitMode ('after', 'before', 'over'). */
417		_setDndStatus: function (
418			sourceNode,
419			targetNode,
420			helper,
421			hitMode,
422			accept
423		) {
424			var markerOffsetX,
425				pos,
426				markerAt = "center",
427				instData = this._local,
428				dndOpt = this.options.dnd,
429				glyphOpt = this.options.glyph,
430				$source = sourceNode ? $(sourceNode.span) : null,
431				$target = $(targetNode.span),
432				$targetTitle = $target.find("span.fancytree-title");
433
434			if (!instData.$dropMarker) {
435				instData.$dropMarker = $(
436					"<div id='fancytree-drop-marker'></div>"
437				)
438					.hide()
439					.css({ "z-index": 1000 })
440					.prependTo($(this.$div).parent());
441				//                .prependTo("body");
442
443				if (glyphOpt) {
444					instData.$dropMarker.addClass(
445						glyphOpt.map._addClass + " " + glyphOpt.map.dropMarker
446					);
447				}
448			}
449			if (
450				hitMode === "after" ||
451				hitMode === "before" ||
452				hitMode === "over"
453			) {
454				markerOffsetX = dndOpt.dropMarkerOffsetX || 0;
455				switch (hitMode) {
456					case "before":
457						markerAt = "top";
458						markerOffsetX += dndOpt.dropMarkerInsertOffsetX || 0;
459						break;
460					case "after":
461						markerAt = "bottom";
462						markerOffsetX += dndOpt.dropMarkerInsertOffsetX || 0;
463						break;
464				}
465
466				pos = {
467					my: "left" + offsetString(markerOffsetX) + " center",
468					at: "left " + markerAt,
469					of: $targetTitle,
470				};
471				if (this.options.rtl) {
472					pos.my = "right" + offsetString(-markerOffsetX) + " center";
473					pos.at = "right " + markerAt;
474				}
475				instData.$dropMarker
476					.toggleClass(classDropAfter, hitMode === "after")
477					.toggleClass(classDropOver, hitMode === "over")
478					.toggleClass(classDropBefore, hitMode === "before")
479					.toggleClass("fancytree-rtl", !!this.options.rtl)
480					.show()
481					.position($.ui.fancytree.fixPositionOptions(pos));
482			} else {
483				instData.$dropMarker.hide();
484			}
485			if ($source) {
486				$source
487					.toggleClass(classDropAccept, accept === true)
488					.toggleClass(classDropReject, accept === false);
489			}
490			$target
491				.toggleClass(
492					classDropTarget,
493					hitMode === "after" ||
494						hitMode === "before" ||
495						hitMode === "over"
496				)
497				.toggleClass(classDropAfter, hitMode === "after")
498				.toggleClass(classDropBefore, hitMode === "before")
499				.toggleClass(classDropAccept, accept === true)
500				.toggleClass(classDropReject, accept === false);
501
502			helper
503				.toggleClass(classDropAccept, accept === true)
504				.toggleClass(classDropReject, accept === false);
505		},
506
507		/*
508		 * Handles drag'n'drop functionality.
509		 *
510		 * A standard jQuery drag-and-drop process may generate these calls:
511		 *
512		 * start:
513		 *     _onDragEvent("start", sourceNode, null, event, ui, draggable);
514		 * drag:
515		 *     _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
516		 *     _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
517		 *     _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
518		 * stop:
519		 *     _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
520		 *     _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
521		 *     _onDragEvent("stop", sourceNode, null, event, ui, draggable);
522		 */
523		_onDragEvent: function (
524			eventName,
525			node,
526			otherNode,
527			event,
528			ui,
529			draggable
530		) {
531			// if(eventName !== "over"){
532			// 	this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
533			// }
534			var accept,
535				nodeOfs,
536				parentRect,
537				rect,
538				relPos,
539				relPos2,
540				enterResponse,
541				hitMode,
542				r,
543				opts = this.options,
544				dnd = opts.dnd,
545				ctx = this._makeHookContext(node, event, {
546					otherNode: otherNode,
547					ui: ui,
548					draggable: draggable,
549				}),
550				res = null,
551				self = this,
552				$nodeTag = $(node.span);
553
554			if (dnd.smartRevert) {
555				draggable.options.revert = "invalid";
556			}
557
558			switch (eventName) {
559				case "start":
560					if (node.isStatusNode()) {
561						res = false;
562					} else if (dnd.dragStart) {
563						res = dnd.dragStart(node, ctx);
564					}
565					if (res === false) {
566						this.debug("tree.dragStart() cancelled");
567						//draggable._clear();
568						// NOTE: the return value seems to be ignored (drag is not cancelled, when false is returned)
569						// TODO: call this._cancelDrag()?
570						ui.helper.trigger("mouseup").hide();
571					} else {
572						if (dnd.smartRevert) {
573							// #567, #593: fix revert position
574							// rect = node.li.getBoundingClientRect();
575							rect =
576								node[
577									ctx.tree.nodeContainerAttrName
578								].getBoundingClientRect();
579							parentRect = $(
580								draggable.options.appendTo
581							)[0].getBoundingClientRect();
582							draggable.originalPosition.left = Math.max(
583								0,
584								rect.left - parentRect.left
585							);
586							draggable.originalPosition.top = Math.max(
587								0,
588								rect.top - parentRect.top
589							);
590						}
591						$nodeTag.addClass("fancytree-drag-source");
592						// Register global handlers to allow cancel
593						$(document).on(
594							"keydown.fancytree-dnd,mousedown.fancytree-dnd",
595							function (event) {
596								// node.tree.debug("dnd global event", event.type, event.which);
597								if (
598									event.type === "keydown" &&
599									event.which === $.ui.keyCode.ESCAPE
600								) {
601									self.ext.dnd._cancelDrag();
602								} else if (event.type === "mousedown") {
603									self.ext.dnd._cancelDrag();
604								}
605							}
606						);
607					}
608					break;
609
610				case "enter":
611					if (
612						dnd.preventRecursiveMoves &&
613						node.isDescendantOf(otherNode)
614					) {
615						r = false;
616					} else {
617						r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null;
618					}
619					if (!r) {
620						// convert null, undefined, false to false
621						res = false;
622					} else if (Array.isArray(r)) {
623						// TODO: also accept passing an object of this format directly
624						res = {
625							over: $.inArray("over", r) >= 0,
626							before: $.inArray("before", r) >= 0,
627							after: $.inArray("after", r) >= 0,
628						};
629					} else {
630						res = {
631							over: r === true || r === "over",
632							before: r === true || r === "before",
633							after: r === true || r === "after",
634						};
635					}
636					ui.helper.data("enterResponse", res);
637					// this.debug("helper.enterResponse: %o", res);
638					break;
639
640				case "over":
641					enterResponse = ui.helper.data("enterResponse");
642					hitMode = null;
643					if (enterResponse === false) {
644						// Don't call dragOver if onEnter returned false.
645						//                break;
646					} else if (typeof enterResponse === "string") {
647						// Use hitMode from onEnter if provided.
648						hitMode = enterResponse;
649					} else {
650						// Calculate hitMode from relative cursor position.
651						nodeOfs = $nodeTag.offset();
652						relPos = {
653							x: event.pageX - nodeOfs.left,
654							y: event.pageY - nodeOfs.top,
655						};
656						relPos2 = {
657							x: relPos.x / $nodeTag.width(),
658							y: relPos.y / $nodeTag.height(),
659						};
660
661						if (enterResponse.after && relPos2.y > 0.75) {
662							hitMode = "after";
663						} else if (
664							!enterResponse.over &&
665							enterResponse.after &&
666							relPos2.y > 0.5
667						) {
668							hitMode = "after";
669						} else if (enterResponse.before && relPos2.y <= 0.25) {
670							hitMode = "before";
671						} else if (
672							!enterResponse.over &&
673							enterResponse.before &&
674							relPos2.y <= 0.5
675						) {
676							hitMode = "before";
677						} else if (enterResponse.over) {
678							hitMode = "over";
679						}
680						// Prevent no-ops like 'before source node'
681						// TODO: these are no-ops when moving nodes, but not in copy mode
682						if (dnd.preventVoidMoves) {
683							if (node === otherNode) {
684								this.debug(
685									"    drop over source node prevented"
686								);
687								hitMode = null;
688							} else if (
689								hitMode === "before" &&
690								otherNode &&
691								node === otherNode.getNextSibling()
692							) {
693								this.debug(
694									"    drop after source node prevented"
695								);
696								hitMode = null;
697							} else if (
698								hitMode === "after" &&
699								otherNode &&
700								node === otherNode.getPrevSibling()
701							) {
702								this.debug(
703									"    drop before source node prevented"
704								);
705								hitMode = null;
706							} else if (
707								hitMode === "over" &&
708								otherNode &&
709								otherNode.parent === node &&
710								otherNode.isLastSibling()
711							) {
712								this.debug(
713									"    drop last child over own parent prevented"
714								);
715								hitMode = null;
716							}
717						}
718						//                this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
719						ui.helper.data("hitMode", hitMode);
720					}
721					// Auto-expand node (only when 'over' the node, not 'before', or 'after')
722					if (
723						hitMode !== "before" &&
724						hitMode !== "after" &&
725						dnd.autoExpandMS &&
726						node.hasChildren() !== false &&
727						!node.expanded &&
728						(!dnd.dragExpand || dnd.dragExpand(node, ctx) !== false)
729					) {
730						node.scheduleAction("expand", dnd.autoExpandMS);
731					}
732					if (hitMode && dnd.dragOver) {
733						// TODO: http://code.google.com/p/dynatree/source/detail?r=625
734						ctx.hitMode = hitMode;
735						res = dnd.dragOver(node, ctx);
736					}
737					accept = res !== false && hitMode !== null;
738					if (dnd.smartRevert) {
739						draggable.options.revert = !accept;
740					}
741					this._local._setDndStatus(
742						otherNode,
743						node,
744						ui.helper,
745						hitMode,
746						accept
747					);
748					break;
749
750				case "drop":
751					hitMode = ui.helper.data("hitMode");
752					if (hitMode && dnd.dragDrop) {
753						ctx.hitMode = hitMode;
754						dnd.dragDrop(node, ctx);
755					}
756					break;
757
758				case "leave":
759					// Cancel pending expand request
760					node.scheduleAction("cancel");
761					ui.helper.data("enterResponse", null);
762					ui.helper.data("hitMode", null);
763					this._local._setDndStatus(
764						otherNode,
765						node,
766						ui.helper,
767						"out",
768						undefined
769					);
770					if (dnd.dragLeave) {
771						dnd.dragLeave(node, ctx);
772					}
773					break;
774
775				case "stop":
776					$nodeTag.removeClass("fancytree-drag-source");
777					$(document).off(".fancytree-dnd");
778					if (dnd.dragStop) {
779						dnd.dragStop(node, ctx);
780					}
781					break;
782
783				default:
784					$.error("Unsupported drag event: " + eventName);
785			}
786			return res;
787		},
788
789		_cancelDrag: function () {
790			var dd = $.ui.ddmanager.current;
791			if (dd) {
792				dd.cancel();
793			}
794		},
795	});
796	// Value returned by `require('jquery.fancytree..')`
797	return $.ui.fancytree;
798}); // End of closure
799