AutorÃa | Ultima modificación | Ver Log |
{"version":3,"file":"sortable_list.min.js","sources":["../src/sortable_list.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to handle list items drag and drop\n *\n * Example of usage:\n *\n * Create a list (for example `<ul>` or `<tbody>`) where each draggable element has a drag handle.\n * The best practice is to use
the template core/drag_handle:\n * $OUTPUT->render_from_template('core/drag_handle', ['movetitle' => get_string('movecontent', 'moodle', ELEMENTNAME)]);\n *\n * Attach this JS module to this list:\n *\n * Space between define and ( critical in comment but not allowed in code in order to function\n * correctly with Moodle's requirejs.php\n *\n * For the full list of possible parameters see var defaultParameters below.\n *\n * The following jQuery events are fired:\n * - SortableList.EVENTS.DRAGSTART : when user started dragging a list element\n * - SortableList.EVENTS.DRAG : when user dragged a list element to a new position\n * - SortableList.EVENTS.DROP : when user dropped a list element\n * - SortableList.EVENTS.DROPEND : when user finished dragging - either fired right after dropping or\n * if \"Esc\" was pressed during dragging\n *\n * @example\n * define (['jquery', 'core/sortable_list'], function($, SortableList) {\n * var list = new SortableList('ul.my-awesome-list'); //
source list (usually <ul> or <tbody>) - selector or element\n *\n * // Listen to the events when element is dragged.\n * $('ul.my-awesome-list > *').on(SortableList.EVENTS.DROP, function(evt, info) {\n * console.log(info);\n * });\n *\n * // Advanced usage. Overwrite methods getElementName, getDestinationName, moveDialogueTitle, for example:\n * list.getElementName = function(element) {\n * return $.Deferred().resolve(element.attr('data-name'));\n * }\n * });\n *\n * @module core/sortable_list\n * @class core/sortable_list\n * @copyright 2018 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/log', 'core/autoscroll', 'core/str', 'core/modal_cancel', 'core/modal_events', 'core/notification'],\nfunction($, log, autoScroll, str, ModalCancel, ModalEvents, Notification) {\n\n /**\n * Default parameters\n *\n * @private\n * @type {Object}\n */\n var defaultParameters = {\n
targetListSelector: null,\n moveHandlerSelector: '[data-drag-type=move]',\n isHorizontal: false,\n autoScroll: true\n };\n\n /**\n * Class names for different elements that may be changed during sorting\n *\n * @private\n * @type {Object}\n */\n var CSS = {\n keyboardDragClass: 'dragdrop-keyboard-drag',\n isDraggedClass: 'sortable-list-is-dragged',\n isDroppedClass: 'sortable-list-is-dropped',\n currentPositionClass: 'sortable-list-current-position',\n sourceListClass: 'sortable-list-source',\n targetListClass: 'sortable-list-target',\n overElementClass: 'sortable-list-over-element'\n };\n\n /**\n * Test the browser support for options objects on event listeners.\n * @return {Boolean}\n */\n var eventListenerOptionsSupported = function() {\n var passivesupported = false,\n options,\n testeventname = \"testpassiveeventoptions\";\n\n // Options suppor
t testing example from:\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener\n\n try {\n options = Object.defineProperty({}, \"passive\", {\n // eslint-disable-next-line getter-return\n get: function() {\n passivesupported = true;\n }\n });\n\n // We use an event name that is not likely to conflict with any real event.\n document.addEventListener(testeventname, options, options);\n // We remove the event listener as we have tested the options already.\n document.removeEventListener(testeventname, options, options);\n } catch (err) {\n // It's already false.\n passivesupported = false;\n }\n return passivesupported;\n };\n\n /**\n * Allow to create non-passive touchstart listeners and prevent page scrolling when dragging\n * From: https://stackoverflow.com/a/48098097\n *\n *
@param {string} eventname\n * @returns {object}\n */\n var registerNotPassiveListeners = function(eventname) {\n return {\n setup: function(x, ns, handle) {\n if (ns.includes('notPassive')) {\n this.addEventListener(eventname, handle, {passive: false});\n return true;\n } else {\n return false;\n }\n }\n };\n };\n\n if (eventListenerOptionsSupported) {\n $.event.special.touchstart = registerNotPassiveListeners('touchstart');\n $.event.special.touchmove = registerNotPassiveListeners('touchmove');\n $.event.special.touchend = registerNotPassiveListeners('touchend');\n }\n\n /**\n * Initialise sortable list.\n *\n * @param {(String|jQuery|Element)} root JQuery/DOM element representing sortable list (i.e. <ul>, <tbody>) or CSS selector\n * @param {Object} config Parameters for the list. See defaultParameters above fo
r examples.\n * @param {(String|jQuery|Element)} config.targetListSelector target lists, by default same as root\n * @param {String} config.moveHandlerSelector CSS selector for a drag handle. By default '[data-drag-type=move]'\n * @param {String} config.listSelector CSS selector for target lists. By default the same as root\n * @param {(Boolean|Function)} config.isHorizontal Set to true if the list is horizontal (can also be a callback\n * with list as an argument)\n * @param {Boolean} config.autoScroll Engages autoscroll module for automatic vertical scrolling of the whole page,\n * by default true\n */\n var SortableList = function(root, config) {\n\n this.info = null;\n this.proxy = null;\n this.proxyDelta = null;\n this.dragCounter = 0;\n this.lastEvent = null;\n\n this.config = $.extend({}, defaultParameters, config || {});\n this.confi
g.listSelector = root;\n if (!this.config.targetListSelector) {\n this.config.targetListSelector = root;\n }\n if (typeof this.config.listSelector === 'object') {\n // The root is an element on the page. Register a listener for this element.\n $(this.config.listSelector).on('mousedown touchstart.notPassive', $.proxy(this.dragStartHandler, this));\n } else {\n // The root is a CSS selector. Register a listener that picks up the element dynamically.\n $('body').on('mousedown touchstart.notPassive', this.config.listSelector, $.proxy(this.dragStartHandler, this));\n }\n if (this.config.moveHandlerSelector !== null) {\n $('body').on('click keypress', this.config.moveHandlerSelector, $.proxy(this.clickHandler, this));\n }\n\n };\n\n /**\n * Events fired by this entity\n *\n * @public\n * @type {Object}\n */\n SortableList.EVENTS = {\n DRAGSTART: 'sortablelist-dragst
art',\n DRAG: 'sortablelist-drag',\n DROP: 'sortablelist-drop',\n DRAGEND: 'sortablelist-dragend'\n };\n\n /**\n * Resets the temporary classes assigned during dragging\n * @private\n */\n SortableList.prototype.resetDraggedClasses = function() {\n var classes = [\n CSS.isDraggedClass,\n CSS.currentPositionClass,\n CSS.overElementClass,\n CSS.targetListClass,\n ];\n for (var i in classes) {\n $('.' + classes[i]).removeClass(classes[i]);\n }\n if (this.proxy) {\n this.proxy.remove();\n this.proxy = $();\n }\n };\n\n /**\n * Calculates evt.pageX, evt.pageY, evt.clientX and evt.clientY\n *\n * For touch events pageX and pageY are taken from the first touch;\n * For the emulated mousemove event they are taken from the last real event.\n *\n * @private\n * @param {Event} evt\n */\n SortableList.prototype.calculate
PositionOnPage = function(evt) {\n\n if (evt.originalEvent && evt.originalEvent.touches && evt.originalEvent.touches[0] !== undefined) {\n // This is a touchmove or touchstart event, get position from the first touch position.\n var touch = evt.originalEvent.touches[0];\n evt.pageX = touch.pageX;\n evt.pageY = touch.pageY;\n }\n\n if (evt.pageX === undefined) {\n // Information is not present in case of touchend or when event was emulated by autoScroll.\n // Take the absolute mouse position from the last event.\n evt.pageX = this.lastEvent.pageX;\n evt.pageY = this.lastEvent.pageY;\n } else {\n this.lastEvent = evt;\n }\n\n if (evt.clientX === undefined) {\n // If not provided in event calculate relative mouse position.\n evt.clientX = Math.round(evt.pageX - $(window).scrollLeft());\n evt.clientY = Math.round(evt.pageY - $(window).scroll
Top());\n }\n };\n\n /**\n * Handler from dragstart event\n *\n * @private\n * @param {Event} evt\n */\n SortableList.prototype.dragStartHandler = function(evt) {\n if (this.info !== null) {\n if (this.info.type === 'click' || this.info.type === 'touchend') {\n // Ignore double click.\n return;\n }\n // Mouse down or touch while already dragging, cancel previous dragging.\n this.moveElement(this.info.sourceList, this.info.sourceNextElement);\n this.finishDragging();\n }\n\n if (evt.type === 'mousedown' && evt.which !== 1) {\n // We only need left mouse click. If this is a mousedown event with right/middle click ignore it.\n return;\n }\n\n this.calculatePositionOnPage(evt);\n var movedElement = $(evt.target).closest($(evt.currentTarget).children());\n if (!movedElement.length) {\n // Can't find the element us
er wants to drag. They clicked on the list but outside of any element of the list.\n return;\n }\n\n // Check that we grabbed the element by the handle.\n if (this.config.moveHandlerSelector !== null) {\n if (!$(evt.target).closest(this.config.moveHandlerSelector, movedElement).length) {\n return;\n }\n }\n\n evt.stopPropagation();\n evt.preventDefault();\n\n // Information about moved element with original location.\n // This object is passed to event observers.\n this.dragCounter++;\n this.info = {\n element: movedElement,\n sourceNextElement: movedElement.next(),\n sourceList: movedElement.parent(),\n targetNextElement: movedElement.next(),\n targetList: movedElement.parent(),\n type: evt.type,\n dropped: false,\n startX: evt.pageX,\n startY: evt.pageY,\n startTime: new Date().getT
ime()\n };\n\n $(this.config.targetListSelector).addClass(CSS.targetListClass);\n\n var offset = movedElement.offset();\n movedElement.addClass(CSS.currentPositionClass);\n this.proxyDelta = {x: offset.left - evt.pageX, y: offset.top - evt.pageY};\n this.proxy = $();\n var thisDragCounter = this.dragCounter;\n setTimeout($.proxy(function() {\n // This mousedown event may in fact be a beginning of a 'click' event. Use timeout before showing the\n // dragged object so we can catch click event. When timeout finishes make sure that click event\n // has not happened during this half a second.\n // Verify dragcounter to make sure the user did not manage to do two very fast drag actions one after another.\n if (this.info === null || this.info.type === 'click' || this.info.type === 'keypress'\n || this.dragCounter !== thisDragCounter) {\n return;\n }\n\n
// Create a proxy - the copy of the dragged element that moves together with a mouse.\n this.createProxy();\n }, this), 500);\n\n // Start drag.\n $(window).on('mousemove touchmove.notPassive mouseup touchend.notPassive', $.proxy(this.dragHandler, this));\n $(window).on('keypress', $.proxy(this.dragcancelHandler, this));\n\n // Start autoscrolling. Every time the page is scrolled emulate the mousemove event.\n if (this.config.autoScroll) {\n autoScroll.start(function() {\n $(window).trigger('mousemove');\n });\n }\n\n this.executeCallback(SortableList.EVENTS.DRAGSTART);\n };\n\n /**\n * Creates a \"proxy\" object - a copy of the element that is being moved that always follows the mouse\n * @private\n */\n SortableList.prototype.createProxy = function() {\n this.proxy = this.info.element.clone();\n this.info.sourceList.append(this.proxy);\n this.proxy.removeAttr('
id').removeClass(CSS.currentPositionClass)\n .addClass(CSS.isDraggedClass).css({position: 'fixed'});\n this.proxy.offset({top: this.proxyDelta.y + this.lastEvent.pageY, left: this.proxyDelta.x + this.lastEvent.pageX});\n };\n\n /**\n * Handler for click event - when user clicks on the drag handler or presses Enter on keyboard\n *\n * @private\n * @param {Event} evt\n */\n SortableList.prototype.clickHandler = function(evt) {\n if (evt.type === 'keypress' && evt.originalEvent.keyCode !== 13 && evt.originalEvent.keyCode !== 32) {\n return;\n }\n if (this.info !== null) {\n // Ignore double click.\n return;\n }\n\n // Find the element that this draghandle belongs to.\n var clickedElement = $(evt.target).closest(this.config.moveHandlerSelector),\n sourceList = clickedElement.closest(this.config.listSelector),\n movedElement = clickedElement.closest(sourceList.children())
;\n if (!movedElement.length) {\n return;\n }\n\n evt.preventDefault();\n evt.stopPropagation();\n\n // Store information about moved element with original location.\n this.dragCounter++;\n this.info = {\n element: movedElement,\n sourceNextElement: movedElement.next(),\n sourceList: sourceList,\n targetNextElement: movedElement.next(),\n targetList: sourceList,\n dropped: false,\n type: evt.type,\n startTime: new Date().getTime()\n };\n\n this.executeCallback(SortableList.EVENTS.DRAGSTART);\n this.displayMoveDialogue(clickedElement);\n };\n\n /**\n * Finds the position of the mouse inside the element - on the top, on the bottom, on the right or on the left\\\n *\n * Used to determine if the moved element should be moved after or before the current element\n *\n * @private\n * @param {Number} pageX\n * @param
{Number} pageY\n * @param {jQuery} element\n * @returns {(Object|null)}\n */\n SortableList.prototype.getPositionInNode = function(pageX, pageY, element) {\n if (!element.length) {\n return null;\n }\n var node = element[0],\n offset = 0,\n rect = node.getBoundingClientRect(),\n y = pageY - (rect.top + window.scrollY),\n x = pageX - (rect.left + window.scrollX);\n if (x >= -offset && x <= rect.width + offset && y >= -offset && y <= rect.height + offset) {\n return {\n x: x,\n y: y,\n xRatio: rect.width ? (x / rect.width) : 0,\n yRatio: rect.height ? (y / rect.height) : 0\n };\n }\n return null;\n };\n\n /**\n * Check if list is horizontal\n *\n * @param {jQuery} element\n * @return {Boolean}\n */\n SortableList.prototype.isListHorizontal = function(element) {\n var isHorizontal = t
his.config.isHorizontal;\n if (isHorizontal === true || isHorizontal === false) {\n return isHorizontal;\n }\n return isHorizontal(element);\n };\n\n /**\n * Handler for events mousemove touchmove mouseup touchend\n *\n * @private\n * @param {Event} evt\n */\n SortableList.prototype.dragHandler = function(evt) {\n\n evt.preventDefault();\n evt.stopPropagation();\n\n this.calculatePositionOnPage(evt);\n\n // We can not use evt.target here because it will most likely be our proxy.\n // Move the proxy out of the way so we can find the element at the current mouse position.\n this.proxy.offset({top: -1000, left: -1000});\n // Find the element at the current mouse position.\n var element = $(document.elementFromPoint(evt.clientX, evt.clientY));\n\n // Find the list element and the list over the mouse position.\n var mainElement = this.info.element[0],\n isNotSelf = function
() {\n return this !== mainElement;\n },\n current = element.closest('.' + CSS.targetListClass + ' > :not(.' + CSS.isDraggedClass + ')').filter(isNotSelf),\n currentList = element.closest('.' + CSS.targetListClass),\n proxy = this.proxy,\n isNotProxy = function() {\n return !proxy || !proxy.length || this !== proxy[0];\n };\n\n // Add the specified class to the list element we are hovering.\n $('.' + CSS.overElementClass).removeClass(CSS.overElementClass);\n current.addClass(CSS.overElementClass);\n\n // Move proxy to the current position.\n this.proxy.offset({top: this.proxyDelta.y + evt.pageY, left: this.proxyDelta.x + evt.pageX});\n\n if (currentList.length && !currentList.children().filter(isNotProxy).length) {\n // Mouse is over an empty list.\n this.moveElement(currentList, $());\n } else if (current.length === 1 && !this.info.element.fin
d(current[0]).length) {\n // Mouse is over an element in a list - find whether we should move the current position\n // above or below this element.\n var coordinates = this.getPositionInNode(evt.pageX, evt.pageY, current);\n if (coordinates) {\n var parent = current.parent(),\n ratio = this.isListHorizontal(parent) ? coordinates.xRatio : coordinates.yRatio,\n subList = current.find('.' + CSS.targetListClass),\n subListEmpty = !subList.children().filter(isNotProxy).filter(isNotSelf).length;\n if (subList.length && subListEmpty && ratio > 0.2 && ratio < 0.8) {\n // This is an element that is a parent of an empty list and we are around the middle of this element.\n // Treat it as if we are over this empty list.\n this.moveElement(subList, $());\n } else if (ratio > 0.5) {\n // Insert after thi
s element.\n this.moveElement(parent, current.next().filter(isNotProxy));\n } else {\n // Insert before this element.\n this.moveElement(parent, current);\n }\n }\n }\n\n if (evt.type === 'mouseup' || evt.type === 'touchend') {\n // Drop the moved element.\n this.info.endX = evt.pageX;\n this.info.endY = evt.pageY;\n this.info.endTime = new Date().getTime();\n this.info.dropped = true;\n this.info.positionChanged = this.hasPositionChanged(this.info);\n var oldinfo = this.info;\n this.executeCallback(SortableList.EVENTS.DROP);\n this.finishDragging();\n\n if (evt.type === 'touchend'\n && this.config.moveHandlerSelector !== null\n && (oldinfo.endTime - oldinfo.startTime < 500)\n && !oldinfo.positionChanged) {\n // The click
event is not triggered on touch screens because we call preventDefault in touchstart handler.\n // If the touchend quickly followed touchstart without moving, consider it a \"click\".\n this.clickHandler(evt);\n } else if (oldinfo.positionChanged) {\n mainElement.classList.add(CSS.isDroppedClass);\n }\n }\n };\n\n /**\n * Checks if the position of the dragged element in the list has changed\n *\n * @private\n * @param {Object} info\n * @return {Boolean}\n */\n SortableList.prototype.hasPositionChanged = function(info) {\n return info.sourceList[0] !== info.targetList[0] ||\n info.sourceNextElement.length !== info.targetNextElement.length ||\n (info.sourceNextElement.length && info.sourceNextElement[0] !== info.targetNextElement[0]);\n };\n\n /**\n * Moves the current position of the dragged element\n *\n * @private\n * @param {jQuery} parentElement\n
* @param {jQuery} beforeElement\n */\n SortableList.prototype.moveElement = function(parentElement, beforeElement) {\n var dragEl = this.info.element;\n if (beforeElement.length && beforeElement[0] === dragEl[0]) {\n // Insert before the current position of the dragged element - nothing to do.\n return;\n }\n if (parentElement[0] === this.info.targetList[0] &&\n beforeElement.length === this.info.targetNextElement.length &&\n beforeElement[0] === this.info.targetNextElement[0]) {\n // Insert in the same location as the current position - nothing to do.\n return;\n }\n\n if (beforeElement.length) {\n // Move the dragged element before the specified element.\n parentElement[0].insertBefore(dragEl[0], beforeElement[0]);\n } else if (this.proxy && this.proxy.parent().length && this.proxy.parent()[0] === parentElement[0]) {\n // We need to move to th
e end of the list but the last element in this list is a proxy.\n // Always leave the proxy in the end of the list.\n parentElement[0].insertBefore(dragEl[0], this.proxy[0]);\n } else {\n // Insert in the end of a list (when proxy is in another list).\n parentElement[0].appendChild(dragEl[0]);\n }\n\n // Save the current position of the dragged element in the list.\n this.info.targetList = parentElement;\n this.info.targetNextElement = beforeElement;\n this.executeCallback(SortableList.EVENTS.DRAG);\n };\n\n /**\n * Finish dragging (when dropped or cancelled).\n * @private\n */\n SortableList.prototype.finishDragging = function() {\n this.resetDraggedClasses();\n if (this.config.autoScroll) {\n autoScroll.stop();\n }\n $(window).off('mousemove touchmove.notPassive mouseup touchend.notPassive', $.proxy(this.dragHandler, this));\n $(window).off('keypress', $.p
roxy(this.dragcancelHandler, this));\n this.executeCallback(SortableList.EVENTS.DRAGEND);\n this.info = null;\n };\n\n /**\n * Executes callback specified in sortable list parameters\n *\n * @private\n * @param {String} eventName\n */\n SortableList.prototype.executeCallback = function(eventName) {\n this.info.element.trigger(eventName, this.info);\n };\n\n /**\n * Handler from keypress event (cancel dragging when Esc is pressed)\n *\n * @private\n * @param {Event} evt\n */\n SortableList.prototype.dragcancelHandler = function(evt) {\n if (evt.type !== 'keypress' || evt.originalEvent.keyCode !== 27) {\n // Only cancel dragging when Esc was pressed.\n return;\n }\n // Dragging was cancelled. Return item to the original position.\n this.moveElement(this.info.sourceList, this.info.sourceNextElement);\n this.finishDragging();\n };\n\n /**\n * Returns the name of the cu
rrent element to be used in the move dialogue\n *\n * @public\n * @param {jQuery} element\n * @return {Promise}\n */\n SortableList.prototype.getElementName = function(element) {\n return $.Deferred().resolve(element.text());\n };\n\n /**\n * Returns the label for the potential move destination, i.e. \"After ElementX\" or \"To the top of the list\"\n *\n * Note that we use \"after\" in the label for better UX\n *\n * @public\n * @param {jQuery} parentElement\n * @param {jQuery} afterElement\n * @return {Promise}\n */\n SortableList.prototype.getDestinationName = function(parentElement, afterElement) {\n if (!afterElement.length) {\n return str.get_string('movecontenttothetop', 'moodle');\n } else {\n return this.getElementName(afterElement)\n .then(function(name) {\n return str.get_string('movecontentafter', 'moodle', name);\n });\n }\n };\n
\n /**\n * Returns the title for the move dialogue (\"Move elementY\")\n *\n * @public\n * @param {jQuery} element\n * @param {jQuery} handler\n * @return {Promise}\n */\n SortableList.prototype.getMoveDialogueTitle = function(element, handler) {\n if (handler.attr('title')) {\n return $.Deferred().resolve(handler.attr('title'));\n }\n return this.getElementName(element).then(function(name) {\n return str.get_string('movecontent', 'moodle', name);\n });\n };\n\n /**\n * Returns the list of possible move destinations\n *\n * @private\n * @return {Promise}\n */\n SortableList.prototype.getDestinationsList = function() {\n var addedLists = [],\n targets = $(this.config.targetListSelector),\n destinations = $('<ul/>').addClass(CSS.keyboardDragClass),\n result = $.when().then(function() {\n return destinations;\n }),\n createL
ink = $.proxy(function(parentElement, beforeElement, afterElement) {\n if (beforeElement.is(this.info.element) || afterElement.is(this.info.element)) {\n // Can not move before or after itself.\n return;\n }\n if ($.contains(this.info.element[0], parentElement[0])) {\n // Can not move to its own child.\n return;\n }\n result = result\n .then($.proxy(function() {\n return this.getDestinationName(parentElement, afterElement);\n }, this))\n .then(function(txt) {\n var li = $('<li/>').appendTo(destinations);\n var a = $('<a href=\"#\"/>').attr('data-core_sortable_list-quickmove', 1).appendTo(li);\n a.data('parent-element', parentElement).data('before-element', beforeElement).text(txt);\n return destinations;\n }
);\n }, this),\n addList = function() {\n // Destination lists may be nested. We want to add all move destinations in the same\n // order they appear on the screen for the user.\n if ($.inArray(this, addedLists) !== -1) {\n return;\n }\n addedLists.push(this);\n var list = $(this),\n children = list.children();\n children.each(function() {\n var element = $(this);\n createLink(list, element, element.prev());\n // Add all nested lists.\n element.find(targets).each(addList);\n });\n createLink(list, $(), children.last());\n };\n targets.each(addList);\n return result;\n };\n\n /**\n * Displays the dialogue to move element.\n * @param {jQuery} clickedElement element to return focus to after the modal is clo
sed\n * @private\n */\n SortableList.prototype.displayMoveDialogue = function(clickedElement) {\n ModalCancel.create({\n title: this.getMoveDialogueTitle(this.info.element, clickedElement),\n body: this.getDestinationsList()\n }).then($.proxy(function(modal) {\n var quickMoveHandler = $.proxy(function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.moveElement($(e.currentTarget).data('parent-element'), $(e.currentTarget).data('before-element'));\n this.info.endTime = new Date().getTime();\n this.info.positionChanged = this.hasPositionChanged(this.info);\n this.info.dropped = true;\n clickedElement.focus();\n this.executeCallback(SortableList.EVENTS.DROP);\n modal.hide();\n }, this);\n modal.getRoot().on('click', '[data-core_sortable_list-quickmove]', quickMoveHandler);\n modal.
getRoot().on(ModalEvents.hidden, $.proxy(function() {\n // Always destroy when hidden, it is generated dynamically each time.\n modal.getRoot().off('click', '[data-core_sortable_list-quickmove]', quickMoveHandler);\n modal.destroy();\n this.finishDragging();\n }, this));\n modal.setLarge();\n modal.show();\n return modal;\n }, this)).catch(Notification.exception);\n };\n\n return SortableList;\n\n});\n"],"names":["define","$","log","autoScroll","str","ModalCancel","ModalEvents","Notification","defaultParameters","targetListSelector","moveHandlerSelector","isHorizontal","CSS","registerNotPassiveListeners","eventname","setup","x","ns","handle","includes","addEventListener","passive","options","passivesupported","Object","defineProperty","get","document","removeEventListener","err","event","special","touchstart","touchmove","touchend","SortableList","root","config","info","proxy","proxyDelta","dr
agCounter","lastEvent","extend","listSelector","this","on","dragStartHandler","clickHandler","EVENTS","DRAGSTART","DRAG","DROP","DRAGEND","prototype","resetDraggedClasses","classes","i","removeClass","remove","calculatePositionOnPage","evt","originalEvent","touches","undefined","touch","pageX","pageY","clientX","Math","round","window","scrollLeft","clientY","scrollTop","type","moveElement","sourceList","sourceNextElement","finishDragging","which","movedElement","target","closest","currentTarget","children","length","stopPropagation","preventDefault","element","next","parent","targetNextElement","targetList","dropped","startX","startY","startTime","Date","getTime","addClass","offset","left","y","top","thisDragCounter","setTimeout","createProxy","dragHandler","dragcancelHandler","start","trigger","executeCallback","clone","append","removeAttr","css","position","keyCode","clickedElement","displayMoveDialogue","getPositionInNode","rect","getBoundingClientRect","scrollY","scrollX","width","height","xRatio","yRati
o","isListHorizontal","elementFromPoint","mainElement","isNotSelf","current","filter","currentList","isNotProxy","find","coordinates","ratio","subList","subListEmpty","endX","endY","endTime","positionChanged","hasPositionChanged","oldinfo","classList","add","parentElement","beforeElement","dragEl","insertBefore","appendChild","stop","off","eventName","getElementName","Deferred","resolve","text","getDestinationName","afterElement","then","name","get_string","getMoveDialogueTitle","handler","attr","getDestinationsList","addedLists","targets","destinations","result","when","createLink","is","contains","txt","li","appendTo","data","addList","inArray","push","list","each","prev","last","create","title","body","modal","quickMoveHandler","e","focus","hide","getRoot","hidden","destroy","setLarge","show","catch","exception"],"mappings":"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"}