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