PluginProbe
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP / 1.2.74
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP v1.2.74
1.2.74 1.2.73 1.2.72 1.2.71 1.2.70 1.2.69 1.2.68 1.2.67 1.2.66 1.2.65 1.2.64 1.2.63 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 All 174 releases
userswp / admin / assets / js / jquery.nestable.js

jquery.nestable.js in UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP 1.2.74, at admin/assets/js/jquery.nestable.js

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