PluginProbe ʕ •ᴥ•ʔ
Nested Pages / 1.3.4
Nested Pages v1.3.4
3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 trunk 1.0 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.3.0 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.2 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.3.1 1.6.3.2 1.6.4 1.6.5 1.6.5.1 1.6.5.2 1.6.6 1.6.7 1.6.8 1.7.0 1.7.1 2.0.1 2.0.2 2.0.3 2.0.4 3.0.1 3.0.10 3.0.11 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.21 3.1.22 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7
wp-nested-pages / assets / js / lib / jquery.mjs.nestedSortable.js
wp-nested-pages / assets / js / lib Last commit date
bs-modal.js 11 years ago jquery.mjs.nestedSortable.js 11 years ago jquery.ui.touch-punch.min.js 11 years ago nestedpages.js 11 years ago
jquery.mjs.nestedSortable.js
665 lines
1 /*
2 * jQuery UI Nested Sortable
3 * v 2.0 / 29 oct 2012
4 * http://mjsarfatti.com/sandbox/nestedSortable
5 *
6 * Depends on:
7 * jquery.ui.sortable.js 1.10+
8 *
9 * Copyright (c) 2010-2013 Manuele J Sarfatti
10 * Licensed under the MIT License
11 * http://www.opensource.org/licenses/mit-license.php
12 */
13 (function( factory ) {
14 if ( typeof define === "function" && define.amd ) {
15
16 // AMD. Register as an anonymous module.
17 define([
18 "jquery",
19 "jquery-ui/sortable"
20 ], factory );
21 } else {
22
23 // Browser globals
24 factory( jQuery );
25 }
26 }(function($) {
27
28 function isOverAxis( x, reference, size ) {
29 return ( x > reference ) && ( x < ( reference + size ) );
30 }
31
32 $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
33
34 options: {
35 disableParentChange: false,
36 doNotClear: false,
37 expandOnHover: 700,
38 isAllowed: function(placeholder, placeholderParent, originalItem) { return true; },
39 isTree: false,
40 listType: 'ol',
41 maxLevels: 0,
42 protectRoot: false,
43 rootID: null,
44 rtl: false,
45 startCollapsed: false,
46 tabSize: 20,
47
48 branchClass: 'mjs-nestedSortable-branch',
49 collapsedClass: 'mjs-nestedSortable-collapsed',
50 disableNestingClass: 'mjs-nestedSortable-no-nesting',
51 errorClass: 'mjs-nestedSortable-error',
52 expandedClass: 'mjs-nestedSortable-expanded',
53 hoveringClass: 'mjs-nestedSortable-hovering',
54 leafClass: 'mjs-nestedSortable-leaf',
55 disabledClass: 'mjs-nestedSortable-disabled'
56 },
57
58 _create: function() {
59 this.element.data('ui-sortable', this.element.data('mjs-nestedSortable'));
60
61 // mjs - prevent browser from freezing if the HTML is not correct
62 if (!this.element.is(this.options.listType))
63 throw new Error('nestedSortable: Please check that the listType option is set to your actual list type');
64
65 // mjs - force 'intersect' tolerance method if we have a tree with expanding/collapsing functionality
66 if (this.options.isTree && this.options.expandOnHover) {
67 this.options.tolerance = 'intersect';
68 }
69
70 $.ui.sortable.prototype._create.apply(this, arguments);
71
72 // mjs - prepare the tree by applying the right classes (the CSS is responsible for actual hide/show functionality)
73 if (this.options.isTree) {
74 var self = this;
75 $(this.items).each(function() {
76 var $li = this.item;
77 if ($li.children(self.options.listType).length) {
78 $li.addClass(self.options.branchClass);
79 // expand/collapse class only if they have children
80 if ( ! $li.hasClass( self.options.collapsedClass ) && ( ! $li.hasClass( self.options.expandedClass ) ) ) {
81 if (self.options.startCollapsed) $li.addClass(self.options.collapsedClass);
82 else $li.addClass(self.options.expandedClass);
83 }
84 } else {
85 $li.addClass(self.options.leafClass);
86 }
87 });
88 }
89 },
90
91 _destroy: function() {
92 this.element
93 .removeData("mjs-nestedSortable")
94 .removeData("ui-sortable");
95 return $.ui.sortable.prototype._destroy.apply(this, arguments);
96 },
97
98 _mouseDrag: function(event) {
99 var i, item, itemElement, intersection,
100 o = this.options,
101 scrolled = false;
102
103 //Compute the helpers position
104 this.position = this._generatePosition(event);
105 this.positionAbs = this._convertPositionTo("absolute");
106
107 if (!this.lastPositionAbs) {
108 this.lastPositionAbs = this.positionAbs;
109 }
110
111 //Do scrolling
112 if(this.options.scroll) {
113 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
114
115 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
116 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
117 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
118 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
119 }
120
121 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
122 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
123 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
124 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
125 }
126
127 } else {
128
129 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
130 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
131 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
132 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
133 }
134
135 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
136 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
137 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
138 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
139 }
140
141 }
142
143 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
144 $.ui.ddmanager.prepareOffsets(this, event);
145 }
146
147 //Regenerate the absolute position used for position checks
148 this.positionAbs = this._convertPositionTo("absolute");
149
150 // mjs - find the top offset before rearrangement,
151 var previousTopOffset = this.placeholder.offset().top;
152
153 //Set the helper position
154 if(!this.options.axis || this.options.axis !== "y") {
155 this.helper[0].style.left = this.position.left+"px";
156 }
157 if(!this.options.axis || this.options.axis !== "x") {
158 this.helper[0].style.top = this.position.top+"px";
159 }
160
161 // mjs - check and reset hovering state at each cycle
162 this.hovering = this.hovering ? this.hovering : null;
163 this.mouseentered = this.mouseentered ? this.mouseentered : false;
164
165 // mjs - let's start caching some variables
166 var parentItem = (this.placeholder[0].parentNode.parentNode &&
167 $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
168 ? $(this.placeholder[0].parentNode.parentNode)
169 : null,
170 level = this._getLevel(this.placeholder),
171 childLevels = this._getChildLevels(this.helper);
172
173 var newList = document.createElement(o.listType);
174
175 //Rearrange
176 for (i = this.items.length - 1; i >= 0; i--) {
177
178 //Cache variables and intersection, continue if no intersection
179 item = this.items[i];
180 itemElement = item.item[0];
181 intersection = this._intersectsWithPointer(item);
182 if (!intersection) {
183 continue;
184 }
185
186 // Only put the placeholder inside the current Container, skip all
187 // items form other containers. This works because when moving
188 // an item from one container to another the
189 // currentContainer is switched before the placeholder is moved.
190 //
191 // Without this moving items in "sub-sortables" can cause the placeholder to jitter
192 // beetween the outer and inner container.
193 if (item.instance !== this.currentContainer) {
194 continue;
195 }
196
197 // No action if intersected item is disabled
198 // and the element above or below in the direction we're going is also disabled
199 if (itemElement.className.indexOf(o.disabledClass) !== -1) {
200 // Note: intersection hardcoded direction values from jquery.ui.sortable.js:_intersectsWithPointer
201 if (intersection === 2) {
202 // Going down
203 var itemAfter = this.items[i + 1];
204 if (itemAfter && itemAfter.item[0].className.indexOf(o.disabledClass) !== -1){
205 continue;
206 }
207
208 }
209 else if (intersection === 1) {
210 // Going up
211 var itemBefore = this.items[i - 1];
212 if (itemBefore && itemBefore.item[0].className.indexOf(o.disabledClass) !== -1){
213 continue;
214 }
215 }
216 }
217
218 // cannot intersect with itself
219 // no useless actions that have been done before
220 // no action if the item moved is the parent of the item checked
221 if (itemElement !== this.currentItem[0] &&
222 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
223 !$.contains(this.placeholder[0], itemElement) &&
224 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
225 ) {
226
227 // mjs - we are intersecting an element: trigger the mouseenter event and store this state
228 if (!this.mouseentered) {
229 $(itemElement).mouseenter();
230 this.mouseentered = true;
231 }
232
233 // mjs - if the element has children and they are hidden, show them after a delay (CSS responsible)
234 if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {
235 if (!this.hovering) {
236 $(itemElement).addClass(o.hoveringClass);
237 var self = this;
238 this.hovering = window.setTimeout(function() {
239 $(itemElement).removeClass(o.collapsedClass).addClass(o.expandedClass);
240 self.refreshPositions();
241 self._trigger("expand", event, self._uiHash());
242 }, o.expandOnHover);
243 }
244 }
245
246 this.direction = intersection == 1 ? "down" : "up";
247
248 // mjs - rearrange the elements and reset timeouts and hovering state
249 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
250 $(itemElement).mouseleave();
251 this.mouseentered = false;
252 $(itemElement).removeClass(o.hoveringClass);
253 this.hovering && window.clearTimeout(this.hovering);
254 this.hovering = null;
255
256 // mjs - do not switch container if it's a root item and 'protectRoot' is true
257 // or if it's not a root item but we are trying to make it root
258 if (o.protectRoot
259 && ! (this.currentItem[0].parentNode == this.element[0] // it's a root item
260 && itemElement.parentNode != this.element[0]) // it's intersecting a non-root item
261 ) {
262 if (this.currentItem[0].parentNode != this.element[0]
263 && itemElement.parentNode == this.element[0]
264 ) {
265
266 if ( ! $(itemElement).children(o.listType).length) {
267 itemElement.appendChild(newList);
268 o.isTree && $(itemElement).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
269 }
270
271 var a = this.direction === "down" ? $(itemElement).prev().children(o.listType) : $(itemElement).children(o.listType);
272 if (a[0] !== undefined) {
273 this._rearrange(event, null, a);
274 }
275
276 } else {
277 this._rearrange(event, item);
278 }
279 } else if ( ! o.protectRoot) {
280 this._rearrange(event, item);
281 }
282 } else {
283 break;
284 }
285
286 // Clear emtpy ul's/ol's
287 this._clearEmpty(itemElement);
288
289 this._trigger("change", event, this._uiHash());
290 break;
291 }
292 }
293
294 // mjs - to find the previous sibling in the list, keep backtracking until we hit a valid list item.
295 var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
296 if (previousItem != null) {
297 while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0].className.indexOf(o.disabledClass) !== -1 || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
298 if (previousItem[0].previousSibling) {
299 previousItem = $(previousItem[0].previousSibling);
300 } else {
301 previousItem = null;
302 break;
303 }
304 }
305 }
306
307 // mjs - to find the next sibling in the list, keep stepping forward until we hit a valid list item.
308 var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
309 if (nextItem != null) {
310 while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0].className.indexOf(o.disabledClass) !== -1 || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
311 if (nextItem[0].nextSibling) {
312 nextItem = $(nextItem[0].nextSibling);
313 } else {
314 nextItem = null;
315 break;
316 }
317 }
318 }
319
320 this.beyondMaxLevels = 0;
321
322 // mjs - if the item is moved to the left, send it one level up but only if it's at the bottom of the list
323 if (parentItem != null
324 && nextItem == null
325 && ! (o.protectRoot && parentItem[0].parentNode == this.element[0])
326 &&
327 (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth())
328 || ! o.rtl && (this.positionAbs.left < parentItem.offset().left))
329 ) {
330
331 parentItem.after(this.placeholder[0]);
332 if (o.isTree && parentItem.children(o.listItem).children('li:visible:not(.ui-sortable-helper)').length < 1) {
333 parentItem.removeClass(this.options.branchClass + ' ' + this.options.expandedClass)
334 .addClass(this.options.leafClass);
335 }
336 this._clearEmpty(parentItem[0]);
337 this._trigger("change", event, this._uiHash());
338 }
339 // mjs - if the item is below a sibling and is moved to the right, make it a child of that sibling
340 else if (previousItem != null
341 && ! previousItem.hasClass(o.disableNestingClass)
342 &&
343 (previousItem.children(o.listType).length && previousItem.children(o.listType).is(':visible')
344 || ! previousItem.children(o.listType).length)
345 && ! (o.protectRoot && this.currentItem[0].parentNode == this.element[0])
346 &&
347 (o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize)
348 || ! o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))
349 ) {
350
351 this._isAllowed(previousItem, level, level+childLevels+1);
352
353 if (!previousItem.children(o.listType).length) {
354 previousItem[0].appendChild(newList);
355 o.isTree && previousItem.removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
356 }
357
358 // mjs - if this item is being moved from the top, add it to the top of the list.
359 if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
360 previousItem.children(o.listType).prepend(this.placeholder);
361 }
362 // mjs - otherwise, add it to the bottom of the list.
363 else {
364 previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
365 }
366
367 this._trigger("change", event, this._uiHash());
368 }
369 else {
370 this._isAllowed(parentItem, level, level+childLevels);
371 }
372
373 //Post events to containers
374 this._contactContainers(event);
375
376 //Interconnect with droppables
377 if($.ui.ddmanager) {
378 $.ui.ddmanager.drag(this, event);
379 }
380
381 //Call callbacks
382 this._trigger('sort', event, this._uiHash());
383
384 this.lastPositionAbs = this.positionAbs;
385 return false;
386
387 },
388
389 _mouseStop: function(event, noPropagation) {
390
391 // mjs - if the item is in a position not allowed, send it back
392 if (this.beyondMaxLevels) {
393
394 this.placeholder.removeClass(this.options.errorClass);
395
396 if (this.domPosition.prev) {
397 $(this.domPosition.prev).after(this.placeholder);
398 } else {
399 $(this.domPosition.parent).prepend(this.placeholder);
400 }
401
402 this._trigger("revert", event, this._uiHash());
403
404 }
405
406
407 // mjs - clear the hovering timeout, just to be sure
408 $('.'+this.options.hoveringClass).mouseleave().removeClass(this.options.hoveringClass);
409 this.mouseentered = false;
410 this.hovering && window.clearTimeout(this.hovering);
411 this.hovering = null;
412
413 $.ui.sortable.prototype._mouseStop.apply(this, arguments);
414
415 var pid = $(this.domPosition.parent).parent().attr("id");
416 var sort = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0;
417
418 if(!(pid == this._uiHash().item.parent().parent().attr("id") &&
419 sort == this._uiHash().item.index())) {
420 this._trigger("relocate", event, this._uiHash());
421 }
422
423 },
424
425 // mjs - this function is slightly modified to make it easier to hover over a collapsed element and have it expand
426 _intersectsWithSides: function(item) {
427
428 var half = this.options.isTree ? .8 : .5;
429
430 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height*half), item.height),
431 isOverTopHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top - (item.height*half), item.height),
432 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
433 verticalDirection = this._getDragVerticalDirection(),
434 horizontalDirection = this._getDragHorizontalDirection();
435
436 if (this.floating && horizontalDirection) {
437 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
438 } else {
439 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && isOverTopHalf));
440 }
441
442 },
443
444 _contactContainers: function(event) {
445
446 if (this.options.protectRoot && this.currentItem[0].parentNode == this.element[0] ) {
447 return;
448 }
449
450 $.ui.sortable.prototype._contactContainers.apply(this, arguments);
451
452 },
453
454 _clear: function(event, noPropagation) {
455
456 $.ui.sortable.prototype._clear.apply(this, arguments);
457
458 // mjs - clean last empty ul/ol
459 for (var i = this.items.length - 1; i >= 0; i--) {
460 var item = this.items[i].item[0];
461 this._clearEmpty(item);
462 }
463
464 },
465
466 serialize: function(options) {
467
468 var o = $.extend({}, this.options, options),
469 items = this._getItemsAsjQuery(o && o.connected),
470 str = [];
471
472 $(items).each(function() {
473 var res = ($(o.item || this).attr(o.attribute || 'id') || '')
474 .match(o.expression || (/(.+)[-=_](.+)/)),
475 pid = ($(o.item || this).parent(o.listType)
476 .parent(o.items)
477 .attr(o.attribute || 'id') || '')
478 .match(o.expression || (/(.+)[-=_](.+)/));
479
480 if (res) {
481 str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
482 + '='
483 + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
484 }
485 });
486
487 if(!str.length && o.key) {
488 str.push(o.key + '=');
489 }
490
491 return str.join('&');
492
493 },
494
495 toHierarchy: function(options) {
496
497 var o = $.extend({}, this.options, options),
498 sDepth = o.startDepthCount || 0,
499 ret = [];
500
501 $(this.element).children(o.items).each(function () {
502 var level = _recursiveItems(this);
503 ret.push(level);
504 });
505
506 return ret;
507
508 function _recursiveItems(item) {
509 var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
510 if (id) {
511 var currentItem = {"id" : id[2]};
512 if ($(item).children(o.listType).children(o.items).length > 0) {
513 currentItem.children = [];
514 $(item).children(o.listType).children(o.items).each(function() {
515 var level = _recursiveItems(this);
516 currentItem.children.push(level);
517 });
518 }
519 return currentItem;
520 }
521 }
522 },
523
524 toArray: function(options) {
525
526 var o = $.extend({}, this.options, options),
527 sDepth = o.startDepthCount || 0,
528 ret = [],
529 left = 1;
530
531 if (!o.excludeRoot) {
532 ret.push({
533 "item_id": o.rootID,
534 "parent_id": null,
535 "depth": sDepth,
536 "left": left,
537 "right": ($(o.items, this.element).length + 1) * 2
538 });
539 left++
540 }
541
542 $(this.element).children(o.items).each(function () {
543 left = _recursiveArray(this, sDepth + 1, left);
544 });
545
546 ret = ret.sort(function(a,b){ return (a.left - b.left); });
547
548 return ret;
549
550 function _recursiveArray(item, depth, left) {
551
552 var right = left + 1,
553 id,
554 pid;
555
556 if ($(item).children(o.listType).children(o.items).length > 0) {
557 depth ++;
558 $(item).children(o.listType).children(o.items).each(function () {
559 right = _recursiveArray($(this), depth, right);
560 });
561 depth --;
562 }
563
564 id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
565
566 if (depth === sDepth + 1) {
567 pid = o.rootID;
568 } else {
569 var parentItem = ($(item).parent(o.listType)
570 .parent(o.items)
571 .attr(o.attribute || 'id'))
572 .match(o.expression || (/(.+)[-=_](.+)/));
573 pid = parentItem[2];
574 }
575
576 if (id) {
577 ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
578 }
579
580 left = right + 1;
581 return left;
582 }
583
584 },
585
586 _clearEmpty: function(item) {
587 var o = this.options;
588
589 var emptyList = $(item).children(o.listType);
590
591 if (emptyList.length && !emptyList.children().length && !o.doNotClear) {
592 o.isTree && $(item).removeClass(o.branchClass + ' ' + o.expandedClass).addClass(o.leafClass);
593 emptyList.remove();
594 } else if (o.isTree && emptyList.length && emptyList.children().length && emptyList.is(':visible')) {
595 $(item).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
596 } else if (o.isTree && emptyList.length && emptyList.children().length && !emptyList.is(':visible')) {
597 $(item).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.collapsedClass);
598 }
599
600 },
601
602 _getLevel: function(item) {
603
604 var level = 1;
605
606 if (this.options.listType) {
607 var list = item.closest(this.options.listType);
608 while (list && list.length > 0 &&
609 !list.is('.ui-sortable')) {
610 level++;
611 list = list.parent().closest(this.options.listType);
612 }
613 }
614
615 return level;
616 },
617
618 _getChildLevels: function(parent, depth) {
619 var self = this,
620 o = this.options,
621 result = 0;
622 depth = depth || 0;
623
624 $(parent).children(o.listType).children(o.items).each(function (index, child) {
625 result = Math.max(self._getChildLevels(child, depth + 1), result);
626 });
627
628 return depth ? result + 1 : result;
629 },
630
631 _isAllowed: function(parentItem, level, levels) {
632 var o = this.options,
633 maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
634
635 // Check if the parent has changed to prevent it, when o.disableParentChange is true
636 var oldParent = this.currentItem.parent().parent();
637 var disabledByParentchange = o.disableParentChange && (
638 parentItem !== null && !oldParent.is(parentItem)//From somewhere to somewhere else, except the root
639 || parentItem === null && oldParent.is('li') //From somewhere to the root
640 );
641 // mjs - is the root protected?
642 // mjs - are we nesting too deep?
643 if (disabledByParentchange || ! o.isAllowed(this.placeholder, parentItem, this.currentItem)) {
644 this.placeholder.addClass(o.errorClass);
645 if (maxLevels < levels && maxLevels != 0) {
646 this.beyondMaxLevels = levels - maxLevels;
647 } else {
648 this.beyondMaxLevels = 1;
649 }
650 } else {
651 if (maxLevels < levels && maxLevels != 0) {
652 this.placeholder.addClass(o.errorClass);
653 this.beyondMaxLevels = levels - maxLevels;
654 } else {
655 this.placeholder.removeClass(o.errorClass);
656 this.beyondMaxLevels = 0;
657 }
658 }
659 }
660
661 }));
662
663 $.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
664 }));
665