jquery.mjs.nestedSortable.js
4 years ago
jquery.ui.touch-punch.min.js
11 years ago
nestedpages-factory.js
3 years ago
nestedpages.bulk-actions.js
4 years ago
nestedpages.check-all.js
9 years ago
nestedpages.clone.js
3 years ago
nestedpages.confirm-delete.js
8 years ago
nestedpages.dropdowns.js
8 years ago
nestedpages.formatter.js
3 years ago
nestedpages.hidden-item-count.js
9 years ago
nestedpages.manual-sync.js
9 years ago
nestedpages.menu-links.js
3 years ago
nestedpages.menu-search.js
1 year ago
nestedpages.menu-toggle.js
8 years ago
nestedpages.modals.js
8 years ago
nestedpages.move-post.js
8 years ago
nestedpages.nesting.js
3 years ago
nestedpages.new-post.js
6 years ago
nestedpages.page-toggle.js
4 years ago
nestedpages.post-search.js
9 years ago
nestedpages.quickedit-link.js
8 years ago
nestedpages.quickedit-post.js
3 years ago
nestedpages.settings-admin-customization.js
6 years ago
nestedpages.settings-reset.js
6 years ago
nestedpages.settings.js
3 years ago
nestedpages.sync-menu-setting.js
8 years ago
nestedpages.tabs.js
6 years ago
nestedpages.trash-with-children.js
6 years ago
nestedpages.trash.js
8 years ago
nestedpages.userprefs-reset.js
7 years ago
nestedpages.wpml.js
8 years ago
jquery.mjs.nestedSortable.js
913 lines
| 1 | /* |
| 2 | * jQuery UI Nested Sortable |
| 3 | * v 2.1a / 2016-02-04 |
| 4 | * https://github.com/ilikenwf/nestedSortable |
| 5 | * |
| 6 | * Depends on: |
| 7 | * jquery.ui.sortable.js 1.10+ |
| 8 | * |
| 9 | * Copyright (c) 2010-2016 Manuele J Sarfatti and contributors |
| 10 | * Licensed under the MIT License |
| 11 | * http://www.opensource.org/licenses/mit-license.php |
| 12 | */ |
| 13 | (function( factory ) { |
| 14 | "use strict"; |
| 15 | |
| 16 | if ( typeof define === "function" && define.amd ) { |
| 17 | |
| 18 | // AMD. Register as an anonymous module. |
| 19 | define([ |
| 20 | "jquery", |
| 21 | "jquery-ui/ui/sortable" |
| 22 | ], factory ); |
| 23 | } else { |
| 24 | |
| 25 | // Browser globals |
| 26 | factory( window.jQuery ); |
| 27 | } |
| 28 | }(function($) { |
| 29 | "use strict"; |
| 30 | |
| 31 | function isOverAxis( x, reference, size ) { |
| 32 | return ( x > reference ) && ( x < ( reference + size ) ); |
| 33 | } |
| 34 | |
| 35 | $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, { |
| 36 | |
| 37 | options: { |
| 38 | disableParentChange: false, |
| 39 | doNotClear: false, |
| 40 | expandOnHover: 700, |
| 41 | isAllowed: function() { return true; }, |
| 42 | isTree: false, |
| 43 | listType: "ol", |
| 44 | maxLevels: 0, |
| 45 | protectRoot: false, |
| 46 | rootID: null, |
| 47 | rtl: false, |
| 48 | startCollapsed: false, |
| 49 | tabSize: 20, |
| 50 | |
| 51 | branchClass: "mjs-nestedSortable-branch", |
| 52 | collapsedClass: "mjs-nestedSortable-collapsed", |
| 53 | disableNestingClass: "mjs-nestedSortable-no-nesting", |
| 54 | errorClass: "mjs-nestedSortable-error", |
| 55 | expandedClass: "mjs-nestedSortable-expanded", |
| 56 | hoveringClass: "mjs-nestedSortable-hovering", |
| 57 | leafClass: "mjs-nestedSortable-leaf", |
| 58 | disabledClass: "mjs-nestedSortable-disabled" |
| 59 | }, |
| 60 | |
| 61 | _create: function() { |
| 62 | var self = this, |
| 63 | err; |
| 64 | |
| 65 | this.element.data("ui-sortable", this.element.data("mjs-nestedSortable")); |
| 66 | |
| 67 | // mjs - prevent browser from freezing if the HTML is not correct |
| 68 | if (!this.element.is(this.options.listType)) { |
| 69 | err = "nestedSortable: " + |
| 70 | "Please check that the listType option is set to your actual list type"; |
| 71 | |
| 72 | throw new Error(err); |
| 73 | } |
| 74 | |
| 75 | // if we have a tree with expanding/collapsing functionality, |
| 76 | // force 'intersect' tolerance method |
| 77 | if (this.options.isTree && this.options.expandOnHover) { |
| 78 | this.options.tolerance = "intersect"; |
| 79 | } |
| 80 | |
| 81 | $.ui.sortable.prototype._create.apply(this, arguments); |
| 82 | |
| 83 | // prepare the tree by applying the right classes |
| 84 | // (the CSS is responsible for actual hide/show functionality) |
| 85 | if (this.options.isTree) { |
| 86 | $(this.items).each(function() { |
| 87 | var $li = this.item, |
| 88 | hasCollapsedClass = $li.hasClass(self.options.collapsedClass), |
| 89 | hasExpandedClass = $li.hasClass(self.options.expandedClass); |
| 90 | |
| 91 | if ($li.children(self.options.listType).length) { |
| 92 | $li.addClass(self.options.branchClass); |
| 93 | // expand/collapse class only if they have children |
| 94 | |
| 95 | if ( !hasCollapsedClass && !hasExpandedClass ) { |
| 96 | if (self.options.startCollapsed) { |
| 97 | $li.addClass(self.options.collapsedClass); |
| 98 | } else { |
| 99 | $li.addClass(self.options.expandedClass); |
| 100 | } |
| 101 | } |
| 102 | } else { |
| 103 | $li.addClass(self.options.leafClass); |
| 104 | } |
| 105 | }); |
| 106 | } |
| 107 | }, |
| 108 | |
| 109 | _destroy: function() { |
| 110 | this.element |
| 111 | .removeData("mjs-nestedSortable") |
| 112 | .removeData("ui-sortable"); |
| 113 | return $.ui.sortable.prototype._destroy.apply(this, arguments); |
| 114 | }, |
| 115 | |
| 116 | _mouseDrag: function(event) { |
| 117 | var i, |
| 118 | item, |
| 119 | itemElement, |
| 120 | intersection, |
| 121 | self = this, |
| 122 | o = this.options, |
| 123 | scrolled = false, |
| 124 | $document = $(document), |
| 125 | previousTopOffset, |
| 126 | parentItem, |
| 127 | level, |
| 128 | childLevels, |
| 129 | itemAfter, |
| 130 | itemBefore, |
| 131 | newList, |
| 132 | method, |
| 133 | a, |
| 134 | previousItem, |
| 135 | nextItem, |
| 136 | helperIsNotSibling; |
| 137 | |
| 138 | //Compute the helpers position |
| 139 | this.position = this._generatePosition(event); |
| 140 | this.positionAbs = this._convertPositionTo("absolute"); |
| 141 | |
| 142 | if (!this.lastPositionAbs) { |
| 143 | this.lastPositionAbs = this.positionAbs; |
| 144 | } |
| 145 | |
| 146 | //Do scrolling |
| 147 | if (this.options.scroll) { |
| 148 | if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { |
| 149 | |
| 150 | if ( |
| 151 | ( |
| 152 | this.overflowOffset.top + |
| 153 | this.scrollParent[0].offsetHeight |
| 154 | ) - |
| 155 | event.pageY < |
| 156 | o.scrollSensitivity |
| 157 | ) { |
| 158 | scrolled = this.scrollParent.scrollTop() + o.scrollSpeed; |
| 159 | this.scrollParent.scrollTop(scrolled); |
| 160 | } else if ( |
| 161 | event.pageY - |
| 162 | this.overflowOffset.top < |
| 163 | o.scrollSensitivity |
| 164 | ) { |
| 165 | scrolled = this.scrollParent.scrollTop() - o.scrollSpeed; |
| 166 | this.scrollParent.scrollTop(scrolled); |
| 167 | } |
| 168 | |
| 169 | if ( |
| 170 | ( |
| 171 | this.overflowOffset.left + |
| 172 | this.scrollParent[0].offsetWidth |
| 173 | ) - |
| 174 | event.pageX < |
| 175 | o.scrollSensitivity |
| 176 | ) { |
| 177 | scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed; |
| 178 | this.scrollParent.scrollLeft(scrolled); |
| 179 | } else if ( |
| 180 | event.pageX - |
| 181 | this.overflowOffset.left < |
| 182 | o.scrollSensitivity |
| 183 | ) { |
| 184 | scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed; |
| 185 | this.scrollParent.scrollLeft(scrolled); |
| 186 | } |
| 187 | |
| 188 | } else { |
| 189 | |
| 190 | if ( |
| 191 | event.pageY - |
| 192 | $document.scrollTop() < |
| 193 | o.scrollSensitivity |
| 194 | ) { |
| 195 | scrolled = $document.scrollTop() - o.scrollSpeed; |
| 196 | $document.scrollTop(scrolled); |
| 197 | } else if ( |
| 198 | $(window).height() - |
| 199 | ( |
| 200 | event.pageY - |
| 201 | $document.scrollTop() |
| 202 | ) < |
| 203 | o.scrollSensitivity |
| 204 | ) { |
| 205 | scrolled = $document.scrollTop() + o.scrollSpeed; |
| 206 | $document.scrollTop(scrolled); |
| 207 | } |
| 208 | |
| 209 | if ( |
| 210 | event.pageX - |
| 211 | $document.scrollLeft() < |
| 212 | o.scrollSensitivity |
| 213 | ) { |
| 214 | scrolled = $document.scrollLeft() - o.scrollSpeed; |
| 215 | $document.scrollLeft(scrolled); |
| 216 | } else if ( |
| 217 | $(window).width() - |
| 218 | ( |
| 219 | event.pageX - |
| 220 | $document.scrollLeft() |
| 221 | ) < |
| 222 | o.scrollSensitivity |
| 223 | ) { |
| 224 | scrolled = $document.scrollLeft() + o.scrollSpeed; |
| 225 | $document.scrollLeft(scrolled); |
| 226 | } |
| 227 | |
| 228 | } |
| 229 | |
| 230 | if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { |
| 231 | $.ui.ddmanager.prepareOffsets(this, event); |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | //Regenerate the absolute position used for position checks |
| 236 | this.positionAbs = this._convertPositionTo("absolute"); |
| 237 | |
| 238 | // mjs - find the top offset before rearrangement, |
| 239 | previousTopOffset = this.placeholder.offset().top; |
| 240 | |
| 241 | //Set the helper position |
| 242 | if (!this.options.axis || this.options.axis !== "y") { |
| 243 | this.helper[0].style.left = this.position.left + "px"; |
| 244 | } |
| 245 | if (!this.options.axis || this.options.axis !== "x") { |
| 246 | this.helper[0].style.top = (this.position.top) + "px"; |
| 247 | } |
| 248 | |
| 249 | // mjs - check and reset hovering state at each cycle |
| 250 | this.hovering = this.hovering ? this.hovering : null; |
| 251 | this.mouseentered = this.mouseentered ? this.mouseentered : false; |
| 252 | |
| 253 | // mjs - let's start caching some variables |
| 254 | (function() { |
| 255 | var _parentItem = this.placeholder.parent().parent(); |
| 256 | if (_parentItem && _parentItem.closest(".ui-sortable").length) { |
| 257 | parentItem = _parentItem; |
| 258 | } |
| 259 | }.call(this)); |
| 260 | |
| 261 | level = this._getLevel(this.placeholder); |
| 262 | childLevels = this._getChildLevels(this.helper); |
| 263 | newList = document.createElement(o.listType); |
| 264 | |
| 265 | // dragDirection object is required by jquery.ui.sortable.js 1.13+ |
| 266 | this.dragDirection = { |
| 267 | vertical: this._getDragVerticalDirection(), |
| 268 | horizontal: this._getDragHorizontalDirection() |
| 269 | }; |
| 270 | |
| 271 | //Rearrange |
| 272 | for (i = this.items.length - 1; i >= 0; i--) { |
| 273 | |
| 274 | //Cache variables and intersection, continue if no intersection |
| 275 | item = this.items[i]; |
| 276 | itemElement = item.item[0]; |
| 277 | intersection = this._intersectsWithPointer(item); |
| 278 | if (!intersection) { |
| 279 | continue; |
| 280 | } |
| 281 | |
| 282 | // Only put the placeholder inside the current Container, skip all |
| 283 | // items form other containers. This works because when moving |
| 284 | // an item from one container to another the |
| 285 | // currentContainer is switched before the placeholder is moved. |
| 286 | // |
| 287 | // Without this moving items in "sub-sortables" can cause the placeholder to jitter |
| 288 | // beetween the outer and inner container. |
| 289 | if (item.instance !== this.currentContainer) { |
| 290 | continue; |
| 291 | } |
| 292 | |
| 293 | // No action if intersected item is disabled |
| 294 | // and the element above or below in the direction we're going is also disabled |
| 295 | if (itemElement.className.indexOf(o.disabledClass) !== -1) { |
| 296 | // Note: intersection hardcoded direction values from |
| 297 | // jquery.ui.sortable.js:_intersectsWithPointer |
| 298 | if (intersection === 2) { |
| 299 | // Going down |
| 300 | itemAfter = this.items[i + 1]; |
| 301 | if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) { |
| 302 | continue; |
| 303 | } |
| 304 | |
| 305 | } else if (intersection === 1) { |
| 306 | // Going up |
| 307 | itemBefore = this.items[i - 1]; |
| 308 | if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) { |
| 309 | continue; |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | method = intersection === 1 ? "next" : "prev"; |
| 315 | |
| 316 | // cannot intersect with itself |
| 317 | // no useless actions that have been done before |
| 318 | // no action if the item moved is the parent of the item checked |
| 319 | if (itemElement !== this.currentItem[0] && |
| 320 | this.placeholder[method]()[0] !== itemElement && |
| 321 | !$.contains(this.placeholder[0], itemElement) && |
| 322 | ( |
| 323 | this.options.type === "semi-dynamic" ? |
| 324 | !$.contains(this.element[0], itemElement) : |
| 325 | true |
| 326 | ) |
| 327 | ) { |
| 328 | |
| 329 | // mjs - we are intersecting an element: |
| 330 | // trigger the mouseenter event and store this state |
| 331 | if (!this.mouseentered) { |
| 332 | $(itemElement).mouseenter(); |
| 333 | this.mouseentered = true; |
| 334 | } |
| 335 | |
| 336 | // mjs - if the element has children and they are hidden, |
| 337 | // show them after a delay (CSS responsible) |
| 338 | if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) { |
| 339 | if (!this.hovering) { |
| 340 | $(itemElement).addClass(o.hoveringClass); |
| 341 | this.hovering = window.setTimeout(function() { |
| 342 | $(itemElement) |
| 343 | .removeClass(o.collapsedClass) |
| 344 | .addClass(o.expandedClass); |
| 345 | |
| 346 | self.refreshPositions(); |
| 347 | self._trigger("expand", event, [self._uiHash(), itemElement]); |
| 348 | }, o.expandOnHover); |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | this.direction = intersection === 1 ? "down" : "up"; |
| 353 | |
| 354 | // mjs - rearrange the elements and reset timeouts and hovering state |
| 355 | if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { |
| 356 | $(itemElement).mouseleave(); |
| 357 | this.mouseentered = false; |
| 358 | $(itemElement).removeClass(o.hoveringClass); |
| 359 | if (this.hovering) { |
| 360 | window.clearTimeout(this.hovering); |
| 361 | } |
| 362 | this.hovering = null; |
| 363 | |
| 364 | // mjs - do not switch container if |
| 365 | // it's a root item and 'protectRoot' is true |
| 366 | // or if it's not a root item but we are trying to make it root |
| 367 | if (o.protectRoot && |
| 368 | !( |
| 369 | this.currentItem[0].parentNode === this.element[0] && |
| 370 | // it's a root item |
| 371 | itemElement.parentNode !== this.element[0] |
| 372 | // it's intersecting a non-root item |
| 373 | ) |
| 374 | ) { |
| 375 | if (this.currentItem[0].parentNode !== this.element[0] && |
| 376 | itemElement.parentNode === this.element[0] |
| 377 | ) { |
| 378 | |
| 379 | if ( !$(itemElement).children(o.listType).length) { |
| 380 | itemElement.appendChild(newList); |
| 381 | if (o.isTree) { |
| 382 | $(itemElement) |
| 383 | .removeClass(o.leafClass) |
| 384 | .addClass(o.branchClass + " " + o.expandedClass); |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | if (this.direction === "down") { |
| 389 | a = $(itemElement).prev().children(o.listType); |
| 390 | } else { |
| 391 | a = $(itemElement).children(o.listType); |
| 392 | } |
| 393 | |
| 394 | if (a[0] !== undefined) { |
| 395 | this._rearrange(event, null, a); |
| 396 | } |
| 397 | |
| 398 | } else { |
| 399 | this._rearrange(event, item); |
| 400 | } |
| 401 | } else if (!o.protectRoot) { |
| 402 | this._rearrange(event, item); |
| 403 | } |
| 404 | } else { |
| 405 | break; |
| 406 | } |
| 407 | |
| 408 | // Clear emtpy ul's/ol's |
| 409 | this._clearEmpty(itemElement); |
| 410 | |
| 411 | this._trigger("change", event, this._uiHash()); |
| 412 | break; |
| 413 | } |
| 414 | } |
| 415 | |
| 416 | // mjs - to find the previous sibling in the list, |
| 417 | // keep backtracking until we hit a valid list item. |
| 418 | (function() { |
| 419 | var _previousItem = this.placeholder.prev(); |
| 420 | if (_previousItem.length) { |
| 421 | previousItem = _previousItem; |
| 422 | } else { |
| 423 | previousItem = null; |
| 424 | } |
| 425 | }.call(this)); |
| 426 | |
| 427 | if (previousItem != null) { |
| 428 | while ( |
| 429 | previousItem[0].nodeName.toLowerCase() !== "li" || |
| 430 | previousItem[0].className.indexOf(o.disabledClass) !== -1 || |
| 431 | previousItem[0] === this.currentItem[0] || |
| 432 | previousItem[0] === this.helper[0] |
| 433 | ) { |
| 434 | if (previousItem[0].previousSibling) { |
| 435 | previousItem = $(previousItem[0].previousSibling); |
| 436 | } else { |
| 437 | previousItem = null; |
| 438 | break; |
| 439 | } |
| 440 | } |
| 441 | } |
| 442 | |
| 443 | // mjs - to find the next sibling in the list, |
| 444 | // keep stepping forward until we hit a valid list item. |
| 445 | (function() { |
| 446 | var _nextItem = this.placeholder.next(); |
| 447 | if (_nextItem.length) { |
| 448 | nextItem = _nextItem; |
| 449 | } else { |
| 450 | nextItem = null; |
| 451 | } |
| 452 | }.call(this)); |
| 453 | |
| 454 | if (nextItem != null) { |
| 455 | while ( |
| 456 | nextItem[0].nodeName.toLowerCase() !== "li" || |
| 457 | nextItem[0].className.indexOf(o.disabledClass) !== -1 || |
| 458 | nextItem[0] === this.currentItem[0] || |
| 459 | nextItem[0] === this.helper[0] |
| 460 | ) { |
| 461 | if (nextItem[0].nextSibling) { |
| 462 | nextItem = $(nextItem[0].nextSibling); |
| 463 | } else { |
| 464 | nextItem = null; |
| 465 | break; |
| 466 | } |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | this.beyondMaxLevels = 0; |
| 471 | |
| 472 | // mjs - if the item is moved to the left, send it one level up |
| 473 | // but only if it's at the bottom of the list |
| 474 | if (parentItem != null && |
| 475 | nextItem == null && |
| 476 | !(o.protectRoot && parentItem[0].parentNode == this.element[0]) && |
| 477 | ( |
| 478 | o.rtl && |
| 479 | ( |
| 480 | this.positionAbs.left + |
| 481 | this.helper.outerWidth() > parentItem.offset().left + |
| 482 | parentItem.outerWidth() |
| 483 | ) || |
| 484 | !o.rtl && (this.positionAbs.left < parentItem.offset().left) |
| 485 | ) |
| 486 | ) { |
| 487 | |
| 488 | parentItem.after(this.placeholder[0]); |
| 489 | helperIsNotSibling = !parentItem |
| 490 | .children(o.listItem) |
| 491 | .children("li:visible:not(.ui-sortable-helper)") |
| 492 | .length; |
| 493 | if (o.isTree && helperIsNotSibling) { |
| 494 | parentItem |
| 495 | .removeClass(this.options.branchClass + " " + this.options.expandedClass) |
| 496 | .addClass(this.options.leafClass); |
| 497 | } |
| 498 | if(typeof parentItem !== 'undefined') |
| 499 | this._clearEmpty(parentItem[0]); |
| 500 | this._trigger("change", event, this._uiHash()); |
| 501 | // mjs - if the item is below a sibling and is moved to the right, |
| 502 | // make it a child of that sibling |
| 503 | } else if (previousItem != null && |
| 504 | !previousItem.hasClass(o.disableNestingClass) && |
| 505 | ( |
| 506 | previousItem.children(o.listType).length && |
| 507 | previousItem.children(o.listType).is(":visible") || |
| 508 | !previousItem.children(o.listType).length |
| 509 | ) && |
| 510 | !(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) && |
| 511 | ( |
| 512 | o.rtl && |
| 513 | ( |
| 514 | this.positionAbs.left + |
| 515 | this.helper.outerWidth() < |
| 516 | previousItem.offset().left + |
| 517 | previousItem.outerWidth() - |
| 518 | o.tabSize |
| 519 | ) || |
| 520 | !o.rtl && |
| 521 | (this.positionAbs.left > previousItem.offset().left + o.tabSize) |
| 522 | ) |
| 523 | ) { |
| 524 | |
| 525 | this._isAllowed(previousItem, level, level + childLevels + 1); |
| 526 | |
| 527 | if (!previousItem.children(o.listType).length) { |
| 528 | previousItem[0].appendChild(newList); |
| 529 | if (o.isTree) { |
| 530 | previousItem |
| 531 | .removeClass(o.leafClass) |
| 532 | .addClass(o.branchClass + " " + o.expandedClass); |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | // mjs - if this item is being moved from the top, add it to the top of the list. |
| 537 | if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) { |
| 538 | previousItem.children(o.listType).prepend(this.placeholder); |
| 539 | } else { |
| 540 | // mjs - otherwise, add it to the bottom of the list. |
| 541 | previousItem.children(o.listType)[0].appendChild(this.placeholder[0]); |
| 542 | } |
| 543 | if(typeof parentItem !== 'undefined') |
| 544 | this._clearEmpty(parentItem[0]); |
| 545 | this._trigger("change", event, this._uiHash()); |
| 546 | } else { |
| 547 | this._isAllowed(parentItem, level, level + childLevels); |
| 548 | } |
| 549 | |
| 550 | //Post events to containers |
| 551 | this._contactContainers(event); |
| 552 | |
| 553 | //Interconnect with droppables |
| 554 | if ($.ui.ddmanager) { |
| 555 | $.ui.ddmanager.drag(this, event); |
| 556 | } |
| 557 | |
| 558 | //Call callbacks |
| 559 | this._trigger("sort", event, this._uiHash()); |
| 560 | |
| 561 | this.lastPositionAbs = this.positionAbs; |
| 562 | return false; |
| 563 | |
| 564 | }, |
| 565 | |
| 566 | _mouseStop: function(event) { |
| 567 | // mjs - if the item is in a position not allowed, send it back |
| 568 | if (this.beyondMaxLevels) { |
| 569 | |
| 570 | this.placeholder.removeClass(this.options.errorClass); |
| 571 | |
| 572 | if (this.domPosition.prev) { |
| 573 | $(this.domPosition.prev).after(this.placeholder); |
| 574 | } else { |
| 575 | $(this.domPosition.parent).prepend(this.placeholder); |
| 576 | } |
| 577 | |
| 578 | this._trigger("revert", event, this._uiHash()); |
| 579 | |
| 580 | } |
| 581 | |
| 582 | // mjs - clear the hovering timeout, just to be sure |
| 583 | $("." + this.options.hoveringClass) |
| 584 | .mouseleave() |
| 585 | .removeClass(this.options.hoveringClass); |
| 586 | |
| 587 | this.mouseentered = false; |
| 588 | if (this.hovering) { |
| 589 | window.clearTimeout(this.hovering); |
| 590 | } |
| 591 | this.hovering = null; |
| 592 | |
| 593 | this._relocate_event = event; |
| 594 | this._pid_current = $(this.domPosition.parent).parent().attr("id"); |
| 595 | this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0; |
| 596 | $.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event. |
| 597 | }, |
| 598 | |
| 599 | // mjs - this function is slightly modified |
| 600 | // to make it easier to hover over a collapsed element and have it expand |
| 601 | _intersectsWithSides: function(item) { |
| 602 | |
| 603 | var half = this.options.isTree ? .8 : .5, |
| 604 | isOverBottomHalf = isOverAxis( |
| 605 | this.positionAbs.top + this.offset.click.top, |
| 606 | item.top + (item.height * half), |
| 607 | item.height |
| 608 | ), |
| 609 | isOverTopHalf = isOverAxis( |
| 610 | this.positionAbs.top + this.offset.click.top, |
| 611 | item.top - (item.height * half), |
| 612 | item.height |
| 613 | ), |
| 614 | isOverRightHalf = isOverAxis( |
| 615 | this.positionAbs.left + this.offset.click.left, |
| 616 | item.left + (item.width / 2), |
| 617 | item.width |
| 618 | ), |
| 619 | verticalDirection = this._getDragVerticalDirection(), |
| 620 | horizontalDirection = this._getDragHorizontalDirection(); |
| 621 | |
| 622 | if (this.floating && horizontalDirection) { |
| 623 | return ( |
| 624 | (horizontalDirection === "right" && isOverRightHalf) || |
| 625 | (horizontalDirection === "left" && !isOverRightHalf) |
| 626 | ); |
| 627 | } else { |
| 628 | return verticalDirection && ( |
| 629 | (verticalDirection === "down" && isOverBottomHalf) || |
| 630 | (verticalDirection === "up" && isOverTopHalf) |
| 631 | ); |
| 632 | } |
| 633 | |
| 634 | }, |
| 635 | |
| 636 | _contactContainers: function() { |
| 637 | |
| 638 | if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0] ) { |
| 639 | return; |
| 640 | } |
| 641 | |
| 642 | $.ui.sortable.prototype._contactContainers.apply(this, arguments); |
| 643 | |
| 644 | }, |
| 645 | |
| 646 | _clear: function() { |
| 647 | var i, |
| 648 | item; |
| 649 | |
| 650 | $.ui.sortable.prototype._clear.apply(this, arguments); |
| 651 | |
| 652 | //relocate event |
| 653 | if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") && |
| 654 | this._sort_current === this._uiHash().item.index())) { |
| 655 | this._trigger("relocate", this._relocate_event, this._uiHash()); |
| 656 | } |
| 657 | |
| 658 | // mjs - clean last empty ul/ol |
| 659 | for (i = this.items.length - 1; i >= 0; i--) { |
| 660 | item = this.items[i].item[0]; |
| 661 | this._clearEmpty(item); |
| 662 | } |
| 663 | |
| 664 | }, |
| 665 | |
| 666 | serialize: function(options) { |
| 667 | |
| 668 | var o = $.extend({}, this.options, options), |
| 669 | items = this._getItemsAsjQuery(o && o.connected), |
| 670 | str = []; |
| 671 | |
| 672 | $(items).each(function() { |
| 673 | var res = ($(o.item || this).attr(o.attribute || "id") || "") |
| 674 | .match(o.expression || (/(.+)[-=_](.+)/)), |
| 675 | pid = ($(o.item || this).parent(o.listType) |
| 676 | .parent(o.items) |
| 677 | .attr(o.attribute || "id") || "") |
| 678 | .match(o.expression || (/(.+)[-=_](.+)/)); |
| 679 | |
| 680 | if (res) { |
| 681 | str.push( |
| 682 | ( |
| 683 | (o.key || res[1]) + |
| 684 | "[" + |
| 685 | (o.key && o.expression ? res[1] : res[2]) + "]" |
| 686 | ) + |
| 687 | "=" + |
| 688 | (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID)); |
| 689 | } |
| 690 | }); |
| 691 | |
| 692 | if (!str.length && o.key) { |
| 693 | str.push(o.key + "="); |
| 694 | } |
| 695 | |
| 696 | return str.join("&"); |
| 697 | |
| 698 | }, |
| 699 | |
| 700 | toHierarchy: function(options) { |
| 701 | |
| 702 | var o = $.extend({}, this.options, options), |
| 703 | ret = []; |
| 704 | |
| 705 | $(this.element).children(o.items).each(function() { |
| 706 | var level = _recursiveItems(this); |
| 707 | ret.push(level); |
| 708 | }); |
| 709 | |
| 710 | return ret; |
| 711 | |
| 712 | function _recursiveItems(item) { |
| 713 | var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)), |
| 714 | currentItem; |
| 715 | |
| 716 | var data = $(item).data(); |
| 717 | if (data.nestedSortableItem) { |
| 718 | delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data |
| 719 | } |
| 720 | |
| 721 | if (id) { |
| 722 | currentItem = { |
| 723 | "id": id[2] |
| 724 | }; |
| 725 | |
| 726 | currentItem = $.extend({}, currentItem, data); // Combine the two objects |
| 727 | |
| 728 | if ($(item).children(o.listType).children(o.items).length > 0) { |
| 729 | currentItem.children = []; |
| 730 | $(item).children(o.listType).children(o.items).each(function() { |
| 731 | var level = _recursiveItems(this); |
| 732 | currentItem.children.push(level); |
| 733 | }); |
| 734 | } |
| 735 | return currentItem; |
| 736 | } |
| 737 | } |
| 738 | }, |
| 739 | |
| 740 | toArray: function(options) { |
| 741 | |
| 742 | var o = $.extend({}, this.options, options), |
| 743 | sDepth = o.startDepthCount || 0, |
| 744 | ret = [], |
| 745 | left = 1; |
| 746 | |
| 747 | if (!o.excludeRoot) { |
| 748 | ret.push({ |
| 749 | "item_id": o.rootID, |
| 750 | "parent_id": null, |
| 751 | "depth": sDepth, |
| 752 | "left": left, |
| 753 | "right": ($(o.items, this.element).length + 1) * 2 |
| 754 | }); |
| 755 | left++; |
| 756 | } |
| 757 | |
| 758 | $(this.element).children(o.items).each(function() { |
| 759 | left = _recursiveArray(this, sDepth, left); |
| 760 | }); |
| 761 | |
| 762 | ret = ret.sort(function(a, b) { return (a.left - b.left); }); |
| 763 | |
| 764 | return ret; |
| 765 | |
| 766 | function _recursiveArray(item, depth, _left) { |
| 767 | |
| 768 | var right = _left + 1, |
| 769 | id, |
| 770 | pid, |
| 771 | parentItem; |
| 772 | |
| 773 | if ($(item).children(o.listType).children(o.items).length > 0) { |
| 774 | depth++; |
| 775 | $(item).children(o.listType).children(o.items).each(function() { |
| 776 | right = _recursiveArray($(this), depth, right); |
| 777 | }); |
| 778 | depth--; |
| 779 | } |
| 780 | |
| 781 | id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)); |
| 782 | |
| 783 | if (depth === sDepth) { |
| 784 | pid = o.rootID; |
| 785 | } else { |
| 786 | parentItem = ($(item).parent(o.listType) |
| 787 | .parent(o.items) |
| 788 | .attr(o.attribute || "id")) |
| 789 | .match(o.expression || (/(.+)[-=_](.+)/)); |
| 790 | pid = parentItem[2]; |
| 791 | } |
| 792 | |
| 793 | if (id) { |
| 794 | var data = $(item).children('div').data(); |
| 795 | var itemObj = $.extend( data, { |
| 796 | "id":id[2], |
| 797 | "parent_id":pid, |
| 798 | "depth":depth, |
| 799 | "left":_left, |
| 800 | "right":right |
| 801 | } ); |
| 802 | ret.push( itemObj ); |
| 803 | } |
| 804 | |
| 805 | _left = right + 1; |
| 806 | return _left; |
| 807 | } |
| 808 | |
| 809 | }, |
| 810 | |
| 811 | _clearEmpty: function (item) { |
| 812 | function replaceClass(elem, search, replace, swap) { |
| 813 | if (swap) { |
| 814 | search = [replace, replace = search][0]; |
| 815 | } |
| 816 | |
| 817 | $(elem).removeClass(search).addClass(replace); |
| 818 | } |
| 819 | |
| 820 | var o = this.options, |
| 821 | childrenList = $(item).children(o.listType), |
| 822 | hasChildren = childrenList.has('li').length; |
| 823 | |
| 824 | var doNotClear = |
| 825 | o.doNotClear || |
| 826 | hasChildren || |
| 827 | o.protectRoot && $(item)[0] === this.element[0]; |
| 828 | |
| 829 | if (o.isTree) { |
| 830 | replaceClass(item, o.branchClass, o.leafClass, doNotClear); |
| 831 | } |
| 832 | |
| 833 | if (!doNotClear) { |
| 834 | childrenList.parent().removeClass(o.expandedClass); |
| 835 | childrenList.remove(); |
| 836 | } |
| 837 | }, |
| 838 | |
| 839 | _getLevel: function(item) { |
| 840 | |
| 841 | var level = 1, |
| 842 | list; |
| 843 | |
| 844 | if (this.options.listType) { |
| 845 | list = item.closest(this.options.listType); |
| 846 | while (list && list.length > 0 && !list.is(".ui-sortable")) { |
| 847 | level++; |
| 848 | list = list.parent().closest(this.options.listType); |
| 849 | } |
| 850 | } |
| 851 | |
| 852 | return level; |
| 853 | }, |
| 854 | |
| 855 | _getChildLevels: function(parent, depth) { |
| 856 | var self = this, |
| 857 | o = this.options, |
| 858 | result = 0; |
| 859 | depth = depth || 0; |
| 860 | |
| 861 | $(parent).children(o.listType).children(o.items).each(function(index, child) { |
| 862 | result = Math.max(self._getChildLevels(child, depth + 1), result); |
| 863 | }); |
| 864 | |
| 865 | return depth ? result + 1 : result; |
| 866 | }, |
| 867 | |
| 868 | _isAllowed: function(parentItem, level, levels) { |
| 869 | var o = this.options, |
| 870 | // this takes into account the maxLevels set to the recipient list |
| 871 | maxLevels = this |
| 872 | .placeholder |
| 873 | .closest(".ui-sortable") |
| 874 | .nestedSortable("option", "maxLevels"), |
| 875 | |
| 876 | // Check if the parent has changed to prevent it, when o.disableParentChange is true |
| 877 | oldParent = this.currentItem.parent().parent(), |
| 878 | disabledByParentchange = o.disableParentChange && ( |
| 879 | //From somewhere to somewhere else, except the root |
| 880 | typeof parentItem !== 'undefined' && !oldParent.is(parentItem) || |
| 881 | typeof parentItem === 'undefined' && oldParent.is("li") //From somewhere to the root |
| 882 | ); |
| 883 | // mjs - is the root protected? |
| 884 | // mjs - are we nesting too deep? |
| 885 | if ( |
| 886 | disabledByParentchange || |
| 887 | !o.isAllowed(this.placeholder, parentItem, this.currentItem) |
| 888 | ) { |
| 889 | this.placeholder.addClass(o.errorClass); |
| 890 | if (maxLevels < levels && maxLevels !== 0) { |
| 891 | this.beyondMaxLevels = levels - maxLevels; |
| 892 | } else { |
| 893 | this.beyondMaxLevels = 1; |
| 894 | } |
| 895 | } else { |
| 896 | if (maxLevels < levels && maxLevels !== 0) { |
| 897 | this.placeholder.addClass(o.errorClass); |
| 898 | this.beyondMaxLevels = levels - maxLevels; |
| 899 | } else { |
| 900 | this.placeholder.removeClass(o.errorClass); |
| 901 | this.beyondMaxLevels = 0; |
| 902 | } |
| 903 | } |
| 904 | } |
| 905 | |
| 906 | })); |
| 907 | |
| 908 | $.mjs.nestedSortable.prototype.options = $.extend( |
| 909 | {}, |
| 910 | $.ui.sortable.prototype.options, |
| 911 | $.mjs.nestedSortable.prototype.options |
| 912 | ); |
| 913 | })); |