You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

799 lines
22 KiB

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