PageSourceSearch

https://www.libriincantina.it/wp-includes/js/jquery/ui/sortable.js?ver=1.14.2

js libriincantina.it collected 2026-10-02 07:12:57 UTC 47,368 bytes, 1,608 lines download raw bytes

vendor: 47,368 bytes, lines 1-1608
1/*!
2 * jQuery UI Sortable 1.14.2
3 * https://jqueryui.com
4 *
5 * Copyright OpenJS Foundation and other contributors
6 * Released under the MIT license.
7 * https://jquery.org/license
8 */
9
10//>>label: Sortable
11//>>group: Interactions
12//>>description: Enables items in a list to be sorted using the mouse.
13//>>docs: https://api.jqueryui.com/sortable/
14//>>demos: https://jqueryui.com/sortable/
15//>>css.structure: ../../themes/base/sortable.css
16
17( function( factory ) {
18	"use strict";
19
20	if ( typeof define === "function" && define.amd ) {
21
22		// AMD. Register as an anonymous module.
23		define( [
24			"jquery",
25			"./mouse",
26			"../data",
27			"../scroll-parent",
28			"../version",
29			"../widget"
30		], factory );
31	} else {
32
33		// Browser globals
34		factory( jQuery );
35	}
36} )( function( $ ) {
37"use strict";
38
39return $.widget( "ui.sortable", $.ui.mouse, {
40	version: "1.14.2",
41	widgetEventPrefix: "sort",
42	ready: false,
43	options: {
44		appendTo: "parent",
45		axis: false,
46		connectWith: false,
47		containment: false,
48		cursor: "auto",
49		cursorAt: false,
50		dropOnEmpty: true,
51		forcePlaceholderSize: false,
52		forceHelperSize: false,
53		grid: false,
54		handle: false,
55		helper: "original",
56		items: "> *",
57		opacity: false,
58		placeholder: false,
59		revert: false,
60		scroll: true,
61		scrollSensitivity: 20,
62		scrollSpeed: 20,
63		scope: "default",
64		tolerance: "intersect",
65		zIndex: 1000,
66
67		// Callbacks
68		activate: null,
69		beforeStop: null,
70		change: null,
71		deactivate: null,
72		out: null,
73		over: null,
74		receive: null,
75		remove: null,
76		sort: null,
77		start: null,
78		stop: null,
79		update: null
80	},
81
82	_isOverAxis: function( x, reference, size ) {
83		return ( x >= reference ) && ( x < ( reference + size ) );
84	},
85
86	_isFloating: function( item ) {
87		return ( /left|right/ ).test( item.css( "float" ) ) ||
88			( /inline|table-cell/ ).test( item.css( "display" ) );
89	},
90
91	_create: function() {
92		this.containerCache = {};
93		this._addClass( "ui-sortable" );
94
95		//Get the items
96		this.refresh();
97
98		//Let's determine the parent's offset
99		this.offset = this.element.offset();
100
101		//Initialize mouse events for interaction
102		this._mouseInit();
103
104		this._setHandleClassName();
105
106		//We're ready to go
107		this.ready = true;
108
109	},
110
111	_setOption: function( key, value ) {
112		this._super( key, value );
113
114		if ( key === "handle" ) {
115			this._setHandleClassName();
116		}
117	},
118
119	_setHandleClassName: function() {
120		var that = this;
121		this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
122		$.each( this.items, function() {
123			that._addClass(
124				this.instance.options.handle ?
125					this.item.find( this.instance.options.handle ) :
126					this.item,
127				"ui-sortable-handle"
128			);
129		} );
130	},
131
132	_destroy: function() {
133		this._mouseDestroy();
134
135		for ( var i = this.items.length - 1; i >= 0; i-- ) {
136			this.items[ i ].item.removeData( this.widgetName + "-item" );
137		}
138
139		return this;
140	},
141
142	_mouseCapture: function( event, overrideHandle ) {
143		var currentItem = null,
144			validHandle = false,
145			that = this;
146
147		if ( this.reverting ) {
148			return false;
149		}
150
151		if ( this.options.disabled || this.options.type === "static" ) {
152			return false;
153		}
154
155		//We have to refresh the items data once first
156		this._refreshItems( event );
157
158		//Find out if the clicked node (or one of its parents) is a actual item in this.items
159		$( event.target ).parents().each( function() {
160			if ( $.data( this, that.widgetName + "-item" ) === that ) {
161				currentItem = $( this );
162				return false;
163			}
164		} );
165		if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
166			currentItem = $( event.target );
167		}
168
169		if ( !currentItem ) {
170			return false;
171		}
172		if ( this.options.handle && !overrideHandle ) {
173			$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
174				if ( this === event.target ) {
175					validHandle = true;
176				}
177			} );
178			if ( !validHandle ) {
179				return false;
180			}
181		}
182
183		this.currentItem = currentItem;
184		this._removeCurrentsFromItems();
185		return true;
186
187	},
188
189	_mouseStart: function( event, overrideHandle, noActivation ) {
190
191		var i, body,
192			o = this.options;
193
194		this.currentContainer = this;
195
196		//We only need to call refreshPositions, because the refreshItems call has been moved to
197		// mouseCapture
198		this.refreshPositions();
199
200		//Prepare the dragged items parent
201		this.appendTo = $( o.appendTo !== "parent" ?
202				o.appendTo :
203				this.currentItem.parent() );
204
205		//Create and append the visible helper
206		this.helper = this._createHelper( event );
207
208		//Cache the helper size
209		this._cacheHelperProportions();
210
211		/*
212		 * - Position generation -
213		 * This block generates everything position related - it's the core of draggables.
214		 */
215
216		//Cache the margins of the original element
217		this._cacheMargins();
218
219		//The element's absolute position on the page minus margins
220		this.offset = this.currentItem.offset();
221		this.offset = {
222			top: this.offset.top - this.margins.top,
223			left: this.offset.left - this.margins.left
224		};
225
226		$.extend( this.offset, {
227			click: { //Where the click happened, relative to the element
228				left: event.pageX - this.offset.left,
229				top: event.pageY - this.offset.top
230			},
231
232			// This is a relative to absolute position minus the actual position calculation -
233			// only used for relative positioned helper
234			relative: this._getRelativeOffset()
235		} );
236
237		// After we get the helper offset, but before we get the parent offset we can
238		// change the helper's position to absolute
239		// TODO: Still need to figure out a way to make relative sorting possible
240		this.helper.css( "position", "absolute" );
241		this.cssPosition = this.helper.css( "position" );
242
243		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
244		if ( o.cursorAt ) {
245			this._adjustOffsetFromHelper( o.cursorAt );
246		}
247
248		//Cache the former DOM position
249		this.domPosition = {
250			prev: this.currentItem.prev()[ 0 ],
251			parent: this.currentItem.parent()[ 0 ]
252		};
253
254		// If the helper is not the original, hide the original so it's not playing any role during
255		// the drag, won't cause anything bad this way
256		if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
257			this.currentItem.hide();
258		}
259
260		//Create the placeholder
261		this._createPlaceholder();
262
263		//Get the next scrolling parent
264		this.scrollParent = this.placeholder.scrollParent();
265
266		$.extend( this.offset, {
267			parent: this._getParentOffset()
268		} );
269
270		//Set a containment if given in the options
271		if ( o.containment ) {
272			this._setContainment();
273		}
274
275		if ( o.cursor && o.cursor !== "auto" ) { // cursor option
276			body = this.document.find( "body" );
277
278			this._storedStylesheet =
279				$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
280		}
281
282		// We need to make sure to grab the zIndex before setting the
283		// opacity, because setting the opacity to anything lower than 1
284		// causes the zIndex to change from "auto" to 0.
285		if ( o.zIndex ) { // zIndex option
286			if ( this.helper.css( "zIndex" ) ) {
287				this._storedZIndex = this.helper.css( "zIndex" );
288			}
289			this.helper.css( "zIndex", o.zIndex );
290		}
291
292		if ( o.opacity ) { // opacity option
293			if ( this.helper.css( "opacity" ) ) {
294				this._storedOpacity = this.helper.css( "opacity" );
295			}
296			this.helper.css( "opacity", o.opacity );
297		}
298
299		//Prepare scrolling
300		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
301				this.scrollParent[ 0 ].tagName !== "HTML" ) {
302			this.overflowOffset = this.scrollParent.offset();
303		}
304
305		//Call callbacks
306		this._trigger( "start", event, this._uiHash() );
307
308		//Recache the helper size
309		if ( !this._preserveHelperProportions ) {
310			this._cacheHelperProportions();
311		}
312
313		//Post "activate" events to possible containers
314		if ( !noActivation ) {
315			for ( i = this.containers.length - 1; i >= 0; i-- ) {
316				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
317			}
318		}
319
320		//Prepare possible droppables
321		if ( $.ui.ddmanager ) {
322			$.ui.ddmanager.current = this;
323		}
324
325		if ( $.ui.ddmanager && !o.dropBehaviour ) {
326			$.ui.ddmanager.prepareOffsets( this, event );
327		}
328
329		this.dragging = true;
330
331		this._addClass( this.helper, "ui-sortable-helper" );
332
333		//Move the helper, if needed
334		if ( !this.helper.parent().is( this.appendTo ) ) {
335			this.helper.detach().appendTo( this.appendTo );
336
337			//Update position
338			this.offset.parent = this._getParentOffset();
339		}
340
341		//Generate the original position
342		this.position = this.originalPosition = this._generatePosition( event );
343		this.originalPageX = event.pageX;
344		this.originalPageY = event.pageY;
345		this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
346
347		this._mouseDrag( event );
348
349		return true;
350
351	},
352
353	_scroll: function( event ) {
354		var o = this.options,
355			scrolled = false;
356
357		if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
358				this.scrollParent[ 0 ].tagName !== "HTML" ) {
359
360			if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
361					event.pageY < o.scrollSensitivity ) {
362				this.scrollParent[ 0 ].scrollTop =
363					scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
364			} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
365				this.scrollParent[ 0 ].scrollTop =
366					scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
367			}
368
369			if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
370					event.pageX < o.scrollSensitivity ) {
371				this.scrollParent[ 0 ].scrollLeft = scrolled =
372					this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
373			} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
374				this.scrollParent[ 0 ].scrollLeft = scrolled =
375					this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
376			}
377
378		} else {
379
380			if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
381				scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
382			} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
383					o.scrollSensitivity ) {
384				scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
385			}
386
387			if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
388				scrolled = this.document.scrollLeft(
389					this.document.scrollLeft() - o.scrollSpeed
390				);
391			} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
392					o.scrollSensitivity ) {
393				scrolled = this.document.scrollLeft(
394					this.document.scrollLeft() + o.scrollSpeed
395				);
396			}
397
398		}
399
400		return scrolled;
401	},
402
403	_mouseDrag: function( event ) {
404		var i, item, itemElement, intersection,
405			o = this.options;
406
407		//Compute the helpers position
408		this.position = this._generatePosition( event );
409		this.positionAbs = this._convertPositionTo( "absolute" );
410
411		//Set the helper position
412		if ( !this.options.axis || this.options.axis !== "y" ) {
413			this.helper[ 0 ].style.left = this.position.left + "px";
414		}
415		if ( !this.options.axis || this.options.axis !== "x" ) {
416			this.helper[ 0 ].style.top = this.position.top + "px";
417		}
418
419		//Do scrolling
420		if ( o.scroll ) {
421			if ( this._scroll( event ) !== false ) {
422
423				//Update item positions used in position checks
424				this._refreshItemPositions( true );
425
426				if ( $.ui.ddmanager && !o.dropBehaviour ) {
427					$.ui.ddmanager.prepareOffsets( this, event );
428				}
429			}
430		}
431
432		this.dragDirection = {
433			vertical: this._getDragVerticalDirection(),
434			horizontal: this._getDragHorizontalDirection()
435		};
436
437		//Rearrange
438		for ( i = this.items.length - 1; i >= 0; i-- ) {
439
440			//Cache variables and intersection, continue if no intersection
441			item = this.items[ i ];
442			itemElement = item.item[ 0 ];
443			intersection = this._intersectsWithPointer( item );
444			if ( !intersection ) {
445				continue;
446			}
447
448			// Only put the placeholder inside the current Container, skip all
449			// items from other containers. This works because when moving
450			// an item from one container to another the
451			// currentContainer is switched before the placeholder is moved.
452			//
453			// Without this, moving items in "sub-sortables" can cause
454			// the placeholder to jitter between the outer and inner container.
455			if ( item.instance !== this.currentContainer ) {
456				continue;
457			}
458
459			// Cannot intersect with itself
460			// no useless actions that have been done before
461			// no action if the item moved is the parent of the item checked
462			if ( itemElement !== this.currentItem[ 0 ] &&
463				this.placeholder[ intersection === 1 ?
464				"next" : "prev" ]()[ 0 ] !== itemElement &&
465				!$.contains( this.placeholder[ 0 ], itemElement ) &&
466				( this.options.type === "semi-dynamic" ?
467					!$.contains( this.element[ 0 ], itemElement ) :
468					true
469				)
470			) {
471
472				this.direction = intersection === 1 ? "down" : "up";
473
474				if ( this.options.tolerance === "pointer" ||
475						this._intersectsWithSides( item ) ) {
476					this._rearrange( event, item );
477				} else {
478					break;
479				}
480
481				this._trigger( "change", event, this._uiHash() );
482				break;
483			}
484		}
485
486		//Post events to containers
487		this._contactContainers( event );
488
489		//Interconnect with droppables
490		if ( $.ui.ddmanager ) {
491			$.ui.ddmanager.drag( this, event );
492		}
493
494		//Call callbacks
495		this._trigger( "sort", event, this._uiHash() );
496
497		this.lastPositionAbs = this.positionAbs;
498		return false;
499
500	},
501
502	_mouseStop: function( event, noPropagation ) {
503
504		if ( !event ) {
505			return;
506		}
507
508		//If we are using droppables, inform the manager about the drop
509		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
510			$.ui.ddmanager.drop( this, event );
511		}
512
513		if ( this.options.revert ) {
514			var that = this,
515				cur = this.placeholder.offset(),
516				axis = this.options.axis,
517				animation = {};
518
519			if ( !axis || axis === "x" ) {
520				animation.left = cur.left - this.offset.parent.left - this.margins.left +
521					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
522						0 :
523						this.offsetParent[ 0 ].scrollLeft
524					);
525			}
526			if ( !axis || axis === "y" ) {
527				animation.top = cur.top - this.offset.parent.top - this.margins.top +
528					( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
529						0 :
530						this.offsetParent[ 0 ].scrollTop
531					);
532			}
533			this.reverting = true;
534			$( this.helper ).animate(
535				animation,
536				parseInt( this.options.revert, 10 ) || 500,
537				function() {
538					that._clear( event );
539				}
540			);
541		} else {
542			this._clear( event, noPropagation );
543		}
544
545		return false;
546
547	},
548
549	cancel: function() {
550
551		if ( this.dragging ) {
552
553			this._mouseUp( new $.Event( "mouseup", { target: null } ) );
554
555			if ( this.options.helper === "original" ) {
556				this.currentItem.css( this._storedCSS );
557				this._removeClass( this.currentItem, "ui-sortable-helper" );
558			} else {
559				this.currentItem.show();
560			}
561
562			//Post deactivating events to containers
563			for ( var i = this.containers.length - 1; i >= 0; i-- ) {
564				this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
565				if ( this.containers[ i ].containerCache.over ) {
566					this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
567					this.containers[ i ].containerCache.over = 0;
568				}
569			}
570
571		}
572
573		if ( this.placeholder ) {
574
575			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
576			// it unbinds ALL events from the original node!
577			if ( this.placeholder[ 0 ].parentNode ) {
578				this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
579			}
580			if ( this.options.helper !== "original" && this.helper &&
581					this.helper[ 0 ].parentNode ) {
582				this.helper.remove();
583			}
584
585			$.extend( this, {
586				helper: null,
587				dragging: false,
588				reverting: false,
589				_noFinalSort: null
590			} );
591
592			if ( this.domPosition.prev ) {
593				$( this.domPosition.prev ).after( this.currentItem );
594			} else {
595				$( this.domPosition.parent ).prepend( this.currentItem );
596			}
597		}
598
599		return this;
600
601	},
602
603	serialize: function( o ) {
604
605		var items = this._getItemsAsjQuery( o && o.connected ),
606			str = [];
607		o = o || {};
608
609		$( items ).each( function() {
610			var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
611				.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
612			if ( res ) {
613				str.push(
614					( o.key || res[ 1 ] + "[]" ) +
615					"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
616			}
617		} );
618
619		if ( !str.length && o.key ) {
620			str.push( o.key + "=" );
621		}
622
623		return str.join( "&" );
624
625	},
626
627	toArray: function( o ) {
628
629		var items = this._getItemsAsjQuery( o && o.connected ),
630			ret = [];
631
632		o = o || {};
633
634		items.each( function() {
635			ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
636		} );
637		return ret;
638
639	},
640
641	/* Be careful with the following core functions */
642	_intersectsWith: function( item ) {
643
644		var x1 = this.positionAbs.left,
645			x2 = x1 + this.helperProportions.width,
646			y1 = this.positionAbs.top,
647			y2 = y1 + this.helperProportions.height,
648			l = item.left,
649			r = l + item.width,
650			t = item.top,
651			b = t + item.height,
652			dyClick = this.offset.click.top,
653			dxClick = this.offset.click.left,
654			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
655				( y1 + dyClick ) < b ),
656			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
657				( x1 + dxClick ) < r ),
658			isOverElement = isOverElementHeight && isOverElementWidth;
659
660		if ( this.options.tolerance === "pointer" ||
661			this.options.forcePointerForContainers ||
662			( this.options.tolerance !== "pointer" &&
663				this.helperProportions[ this.floating ? "width" : "height" ] >
664				item[ this.floating ? "width" : "height" ] )
665		) {
666			return isOverElement;
667		} else {
668
669			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
670				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
671				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
672				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
673
674		}
675	},
676
677	_intersectsWithPointer: function( item ) {
678		var verticalDirection, horizontalDirection,
679			isOverElementHeight = ( this.options.axis === "x" ) ||
680				this._isOverAxis(
681					this.positionAbs.top + this.offset.click.top, item.top, item.height ),
682			isOverElementWidth = ( this.options.axis === "y" ) ||
683				this._isOverAxis(
684					this.positionAbs.left + this.offset.click.left, item.left, item.width ),
685			isOverElement = isOverElementHeight && isOverElementWidth;
686
687		if ( !isOverElement ) {
688			return false;
689		}
690
691		verticalDirection = this.dragDirection.vertical;
692		horizontalDirection = this.dragDirection.horizontal;
693
694		return this.floating ?
695			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
696			( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
697
698	},
699
700	_intersectsWithSides: function( item ) {
701
702		var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
703				this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
704			isOverRightHalf = this._isOverAxis( this.positionAbs.left +
705				this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
706			verticalDirection = this.dragDirection.vertical,
707			horizontalDirection = this.dragDirection.horizontal;
708
709		if ( this.floating && horizontalDirection ) {
710			return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
711				( horizontalDirection === "left" && !isOverRightHalf ) );
712		} else {
713			return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
714				( verticalDirection === "up" && !isOverBottomHalf ) );
715		}
716
717	},
718
719	_getDragVerticalDirection: function() {
720		var delta = this.positionAbs.top - this.lastPositionAbs.top;
721		return delta !== 0 && ( delta > 0 ? "down" : "up" );
722	},
723
724	_getDragHorizontalDirection: function() {
725		var delta = this.positionAbs.left - this.lastPositionAbs.left;
726		return delta !== 0 && ( delta > 0 ? "right" : "left" );
727	},
728
729	refresh: function( event ) {
730		this._refreshItems( event );
731		this._setHandleClassName();
732		this.refreshPositions();
733		return this;
734	},
735
736	_connectWith: function() {
737		var options = this.options;
738		return options.connectWith.constructor === String ?
739			[ options.connectWith ] :
740			options.connectWith;
741	},
742
743	_getItemsAsjQuery: function( connected ) {
744
745		var i, j, cur, inst,
746			items = [],
747			queries = [],
748			connectWith = this._connectWith();
749
750		if ( connectWith && connected ) {
751			for ( i = connectWith.length - 1; i >= 0; i-- ) {
752				cur = $( connectWith[ i ], this.document[ 0 ] );
753				for ( j = cur.length - 1; j >= 0; j-- ) {
754					inst = $.data( cur[ j ], this.widgetFullName );
755					if ( inst && inst !== this && !inst.options.disabled ) {
756						queries.push( [ typeof inst.options.items === "function" ?
757							inst.options.items.call( inst.element ) :
758							$( inst.options.items, inst.element )
759								.not( ".ui-sortable-helper" )
760								.not( ".ui-sortable-placeholder" ), inst ] );
761					}
762				}
763			}
764		}
765
766		queries.push( [ typeof this.options.items === "function" ?
767			this.options.items
768				.call( this.element, null, { options: this.options, item: this.currentItem } ) :
769			$( this.options.items, this.element )
770				.not( ".ui-sortable-helper" )
771				.not( ".ui-sortable-placeholder" ), this ] );
772
773		function addItems() {
774			items.push( this );
775		}
776		for ( i = queries.length - 1; i >= 0; i-- ) {
777			queries[ i ][ 0 ].each( addItems );
778		}
779
780		return $( items );
781
782	},
783
784	_removeCurrentsFromItems: function() {
785
786		var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
787
788		this.items = $.grep( this.items, function( item ) {
789			for ( var j = 0; j < list.length; j++ ) {
790				if ( list[ j ] === item.item[ 0 ] ) {
791					return false;
792				}
793			}
794			return true;
795		} );
796
797	},
798
799	_refreshItems: function( event ) {
800
801		this.items = [];
802		this.containers = [ this ];
803
804		var i, j, cur, inst, targetData, _queries, item, queriesLength,
805			items = this.items,
806			queries = [ [ typeof this.options.items === "function" ?
807				this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
808				$( this.options.items, this.element ), this ] ],
809			connectWith = this._connectWith();
810
811		//Shouldn't be run the first time through due to massive slow-down
812		if ( connectWith && this.ready ) {
813			for ( i = connectWith.length - 1; i >= 0; i-- ) {
814				cur = $( connectWith[ i ], this.document[ 0 ] );
815				for ( j = cur.length - 1; j >= 0; j-- ) {
816					inst = $.data( cur[ j ], this.widgetFullName );
817					if ( inst && inst !== this && !inst.options.disabled ) {
818						queries.push( [ typeof inst.options.items === "function" ?
819							inst.options.items
820								.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
821							$( inst.options.items, inst.element ), inst ] );
822						this.containers.push( inst );
823					}
824				}
825			}
826		}
827
828		for ( i = queries.length - 1; i >= 0; i-- ) {
829			targetData = queries[ i ][ 1 ];
830			_queries = queries[ i ][ 0 ];
831
832			for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
833				item = $( _queries[ j ] );
834
835				// Data for target checking (mouse manager)
836				item.data( this.widgetName + "-item", targetData );
837
838				items.push( {
839					item: item,
840					instance: targetData,
841					width: 0, height: 0,
842					left: 0, top: 0
843				} );
844			}
845		}
846
847	},
848
849	_refreshItemPositions: function( fast ) {
850		var i, item, t, p;
851
852		for ( i = this.items.length - 1; i >= 0; i-- ) {
853			item = this.items[ i ];
854
855			//We ignore calculating positions of all connected containers when we're not over them
856			if ( this.currentContainer && item.instance !== this.currentContainer &&
857					item.item[ 0 ] !== this.currentItem[ 0 ] ) {
858				continue;
859			}
860
861			t = this.options.toleranceElement ?
862				$( this.options.toleranceElement, item.item ) :
863				item.item;
864
865			if ( !fast ) {
866				item.width = t.outerWidth();
867				item.height = t.outerHeight();
868			}
869
870			p = t.offset();
871			item.left = p.left;
872			item.top = p.top;
873		}
874	},
875
876	refreshPositions: function( fast ) {
877
878		// Determine whether items are being displayed horizontally
879		this.floating = this.items.length ?
880			this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
881			false;
882
883		// This has to be redone because due to the item being moved out/into the offsetParent,
884		// the offsetParent's position will change
885		if ( this.offsetParent && this.helper ) {
886			this.offset.parent = this._getParentOffset();
887		}
888
889		this._refreshItemPositions( fast );
890
891		var i, p;
892
893		if ( this.options.custom && this.options.custom.refreshContainers ) {
894			this.options.custom.refreshContainers.call( this );
895		} else {
896			for ( i = this.containers.length - 1; i >= 0; i-- ) {
897				p = this.containers[ i ].element.offset();
898				this.containers[ i ].containerCache.left = p.left;
899				this.containers[ i ].containerCache.top = p.top;
900				this.containers[ i ].containerCache.width =
901					this.containers[ i ].element.outerWidth();
902				this.containers[ i ].containerCache.height =
903					this.containers[ i ].element.outerHeight();
904			}
905		}
906
907		return this;
908	},
909
910	_createPlaceholder: function( that ) {
911		that = that || this;
912		var className, nodeName,
913			o = that.options;
914
915		if ( !o.placeholder || o.placeholder.constructor === String ) {
916			className = o.placeholder;
917			nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
918			o.placeholder = {
919				element: function() {
920
921					var element = $( "<" + nodeName + ">", that.document[ 0 ] );
922
923					that._addClass( element, "ui-sortable-placeholder",
924							className || that.currentItem[ 0 ].className )
925						._removeClass( element, "ui-sortable-helper" );
926
927					if ( nodeName === "tbody" ) {
928						that._createTrPlaceholder(
929							that.currentItem.find( "tr" ).eq( 0 ),
930							$( "<tr>", that.document[ 0 ] ).appendTo( element )
931						);
932					} else if ( nodeName === "tr" ) {
933						that._createTrPlaceholder( that.currentItem, element );
934					} else if ( nodeName === "img" ) {
935						element.attr( "src", that.currentItem.attr( "src" ) );
936					}
937
938					if ( !className ) {
939						element.css( "visibility", "hidden" );
940					}
941
942					return element;
943				},
944				update: function( container, p ) {
945
946					// 1. If a className is set as 'placeholder option, we don't force sizes -
947					// the class is responsible for that
948					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
949					// class name is specified
950					if ( className && !o.forcePlaceholderSize ) {
951						return;
952					}
953
954					// If the element doesn't have a actual height or width by itself (without
955					// styles coming from a stylesheet), it receives the inline height and width
956					// from the dragged item. Or, if it's a tbody or tr, it's going to have a height
957					// anyway since we're populating them with <td>s above, but they're unlikely to
958					// be the correct height on their own if the row heights are dynamic, so we'll
959					// always assign the height of the dragged item given forcePlaceholderSize
960					// is true.
961					if ( !p.height() || ( o.forcePlaceholderSize &&
962							( nodeName === "tbody" || nodeName === "tr" ) ) ) {
963						p.height(
964							that.currentItem.innerHeight() -
965							parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
966							parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
967					}
968					if ( !p.width() ) {
969						p.width(
970							that.currentItem.innerWidth() -
971							parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
972							parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
973					}
974				}
975			};
976		}
977
978		//Create the placeholder
979		that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
980
981		//Append it after the actual current item
982		that.currentItem.after( that.placeholder );
983
984		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
985		o.placeholder.update( that, that.placeholder );
986
987	},
988
989	_createTrPlaceholder: function( sourceTr, targetTr ) {
990		var that = this;
991
992		sourceTr.children().each( function() {
993			$( "<td>&#160;</td>", that.document[ 0 ] )
994				.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
995				.appendTo( targetTr );
996		} );
997	},
998
999	_contactContainers: function( event ) {
1000		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
1001			floating, axis,
1002			innermostContainer = null,
1003			innermostIndex = null;
1004
1005		// Get innermost container that intersects with item
1006		for ( i = this.containers.length - 1; i >= 0; i-- ) {
1007
1008			// Never consider a container that's located within the item itself
1009			if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
1010				continue;
1011			}
1012
1013			if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
1014
1015				// If we've already found a container and it's more "inner" than this, then continue
1016				if ( innermostContainer &&
1017						$.contains(
1018							this.containers[ i ].element[ 0 ],
1019							innermostContainer.element[ 0 ] ) ) {
1020					continue;
1021				}
1022
1023				innermostContainer = this.containers[ i ];
1024				innermostIndex = i;
1025
1026			} else {
1027
1028				// container doesn't intersect. trigger "out" event if necessary
1029				if ( this.containers[ i ].containerCache.over ) {
1030					this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
1031					this.containers[ i ].containerCache.over = 0;
1032				}
1033			}
1034
1035		}
1036
1037		// If no intersecting containers found, return
1038		if ( !innermostContainer ) {
1039			return;
1040		}
1041
1042		// Move the item into the container if it's not there already
1043		if ( this.containers.length === 1 ) {
1044			if ( !this.containers[ innermostIndex ].containerCache.over ) {
1045				this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
1046				this.containers[ innermostIndex ].containerCache.over = 1;
1047			}
1048		} else {
1049
1050			// When entering a new container, we will find the item with the least distance and
1051			// append our item near it
1052			dist = 10000;
1053			itemWithLeastDistance = null;
1054			floating = innermostContainer.floating || this._isFloating( this.currentItem );
1055			posProperty = floating ? "left" : "top";
1056			sizeProperty = floating ? "width" : "height";
1057			axis = floating ? "pageX" : "pageY";
1058
1059			for ( j = this.items.length - 1; j >= 0; j-- ) {
1060				if ( !$.contains(
1061						this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
1062				) {
1063					continue;
1064				}
1065				if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
1066					continue;
1067				}
1068
1069				cur = this.items[ j ].item.offset()[ posProperty ];
1070				nearBottom = false;
1071				if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
1072					nearBottom = true;
1073				}
1074
1075				if ( Math.abs( event[ axis ] - cur ) < dist ) {
1076					dist = Math.abs( event[ axis ] - cur );
1077					itemWithLeastDistance = this.items[ j ];
1078					this.direction = nearBottom ? "up" : "down";
1079				}
1080			}
1081
1082			//Check if dropOnEmpty is enabled
1083			if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
1084				return;
1085			}
1086
1087			if ( this.currentContainer === this.containers[ innermostIndex ] ) {
1088				if ( !this.currentContainer.containerCache.over ) {
1089					this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
1090					this.currentContainer.containerCache.over = 1;
1091				}
1092				return;
1093			}
1094
1095			if ( itemWithLeastDistance ) {
1096				this._rearrange( event, itemWithLeastDistance, null, true );
1097			} else {
1098				this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
1099			}
1100			this._trigger( "change", event, this._uiHash() );
1101			this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
1102			this.currentContainer = this.containers[ innermostIndex ];
1103
1104			//Update the placeholder
1105			this.options.placeholder.update( this.currentContainer, this.placeholder );
1106
1107			//Update scrollParent
1108			this.scrollParent = this.placeholder.scrollParent();
1109
1110			//Update overflowOffset
1111			if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
1112					this.scrollParent[ 0 ].tagName !== "HTML" ) {
1113				this.overflowOffset = this.scrollParent.offset();
1114			}
1115
1116			this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
1117			this.containers[ innermostIndex ].containerCache.over = 1;
1118		}
1119
1120	},
1121
1122	_createHelper: function( event ) {
1123
1124		var o = this.options,
1125			helper = typeof o.helper === "function" ?
1126				$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
1127				( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
1128
1129		//Add the helper to the DOM if that didn't happen already
1130		if ( !helper.parents( "body" ).length ) {
1131			this.appendTo[ 0 ].appendChild( helper[ 0 ] );
1132		}
1133
1134		if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
1135			this._storedCSS = {
1136				width: this.currentItem[ 0 ].style.width,
1137				height: this.currentItem[ 0 ].style.height,
1138				position: this.currentItem.css( "position" ),
1139				top: this.currentItem.css( "top" ),
1140				left: this.currentItem.css( "left" )
1141			};
1142		}
1143
1144		if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
1145			helper.width( this.currentItem.width() );
1146		}
1147		if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
1148			helper.height( this.currentItem.height() );
1149		}
1150
1151		return helper;
1152
1153	},
1154
1155	_adjustOffsetFromHelper: function( obj ) {
1156		if ( typeof obj === "string" ) {
1157			obj = obj.split( " " );
1158		}
1159		if ( Array.isArray( obj ) ) {
1160			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
1161		}
1162		if ( "left" in obj ) {
1163			this.offset.click.left = obj.left + this.margins.left;
1164		}
1165		if ( "right" in obj ) {
1166			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1167		}
1168		if ( "top" in obj ) {
1169			this.offset.click.top = obj.top + this.margins.top;
1170		}
1171		if ( "bottom" in obj ) {
1172			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1173		}
1174	},
1175
1176	_getParentOffset: function() {
1177
1178		//Get the offsetParent and cache its position
1179		this.offsetParent = this.helper.offsetParent();
1180		var po = this.offsetParent.offset();
1181
1182		// This is a special case where we need to modify a offset calculated on start, since the
1183		// following happened:
1184		// 1. The position of the helper is absolute, so it's position is calculated based on the
1185		// next positioned parent
1186		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
1187		// the document, which means that the scroll is included in the initial calculation of the
1188		// offset of the parent, and never recalculated upon drag
1189		if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
1190				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
1191			po.left += this.scrollParent.scrollLeft();
1192			po.top += this.scrollParent.scrollTop();
1193		}
1194
1195		// This needs to be actually done for all browsers, since pageX/pageY includes
1196		// this information.
1197		if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
1198			po = { top: 0, left: 0 };
1199		}
1200
1201		return {
1202			top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
1203			left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
1204		};
1205
1206	},
1207
1208	_getRelativeOffset: function() {
1209
1210		if ( this.cssPosition === "relative" ) {
1211			var p = this.currentItem.position();
1212			return {
1213				top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
1214					this.scrollParent.scrollTop(),
1215				left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
1216					this.scrollParent.scrollLeft()
1217			};
1218		} else {
1219			return { top: 0, left: 0 };
1220		}
1221
1222	},
1223
1224	_cacheMargins: function() {
1225		this.margins = {
1226			left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
1227			top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
1228		};
1229	},
1230
1231	_cacheHelperProportions: function() {
1232		this.helperProportions = {
1233			width: this.helper.outerWidth(),
1234			height: this.helper.outerHeight()
1235		};
1236	},
1237
1238	_setContainment: function() {
1239
1240		var ce, co, over,
1241			o = this.options;
1242		if ( o.containment === "parent" ) {
1243			o.containment = this.helper[ 0 ].parentNode;
1244		}
1245		if ( o.containment === "document" || o.containment === "window" ) {
1246			this.containment = [
1247				0 - this.offset.relative.left - this.offset.parent.left,
1248				0 - this.offset.relative.top - this.offset.parent.top,
1249				o.containment === "document" ?
1250					this.document.width() :
1251					this.window.width() - this.helperProportions.width - this.margins.left,
1252				( o.containment === "document" ?
1253					( this.document.height() || document.body.parentNode.scrollHeight ) :
1254					this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
1255				) - this.helperProportions.height - this.margins.top
1256			];
1257		}
1258
1259		if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
1260			ce = $( o.containment )[ 0 ];
1261			co = $( o.containment ).offset();
1262			over = ( $( ce ).css( "overflow" ) !== "hidden" );
1263
1264			this.containment = [
1265				co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
1266					( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
1267				co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
1268					( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
1269				co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
1270					( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
1271					( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
1272					this.helperProportions.width - this.margins.left,
1273				co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
1274					( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
1275					( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
1276					this.helperProportions.height - this.margins.top
1277			];
1278		}
1279
1280	},
1281
1282	_convertPositionTo: function( d, pos ) {
1283
1284		if ( !pos ) {
1285			pos = this.position;
1286		}
1287		var mod = d === "absolute" ? 1 : -1,
1288			scroll = this.cssPosition === "absolute" &&
1289				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
1290				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
1291					this.offsetParent :
1292					this.scrollParent,
1293			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
1294
1295		return {
1296			top: (
1297
1298				// The absolute mouse position
1299				pos.top	+
1300
1301				// Only for relative positioned nodes: Relative offset from element to offset parent
1302				this.offset.relative.top * mod +
1303
1304				// The offsetParent's offset without borders (offset + border)
1305				this.offset.parent.top * mod -
1306				( ( this.cssPosition === "fixed" ?
1307					-this.scrollParent.scrollTop() :
1308					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
1309			),
1310			left: (
1311
1312				// The absolute mouse position
1313				pos.left +
1314
1315				// Only for relative positioned nodes: Relative offset from element to offset parent
1316				this.offset.relative.left * mod +
1317
1318				// The offsetParent's offset without borders (offset + border)
1319				this.offset.parent.left * mod	-
1320				( ( this.cssPosition === "fixed" ?
1321					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
1322					scroll.scrollLeft() ) * mod )
1323			)
1324		};
1325
1326	},
1327
1328	_generatePosition: function( event ) {
1329
1330		var top, left,
1331			o = this.options,
1332			pageX = event.pageX,
1333			pageY = event.pageY,
1334			scroll = this.cssPosition === "absolute" &&
1335				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
1336				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
1337					this.offsetParent :
1338					this.scrollParent,
1339				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
1340
1341		// This is another very weird special case that only happens for relative elements:
1342		// 1. If the css position is relative
1343		// 2. and the scroll parent is the document or similar to the offset parent
1344		// we have to refresh the relative offset during the scroll so there are no jumps
1345		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
1346				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
1347			this.offset.relative = this._getRelativeOffset();
1348		}
1349
1350		/*
1351		 * - Position constraining -
1352		 * Constrain the position to a mix of grid, containment.
1353		 */
1354
1355		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
1356
1357			if ( this.containment ) {
1358				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
1359					pageX = this.containment[ 0 ] + this.offset.click.left;
1360				}
1361				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
1362					pageY = this.containment[ 1 ] + this.offset.click.top;
1363				}
1364				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
1365					pageX = this.containment[ 2 ] + this.offset.click.left;
1366				}
1367				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
1368					pageY = this.containment[ 3 ] + this.offset.click.top;
1369				}
1370			}
1371
1372			if ( o.grid ) {
1373				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
1374					o.grid[ 1 ] ) * o.grid[ 1 ];
1375				pageY = this.containment ?
1376					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
1377						top - this.offset.click.top <= this.containment[ 3 ] ) ?
1378							top :
1379							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
1380								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
1381								top;
1382
1383				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
1384					o.grid[ 0 ] ) * o.grid[ 0 ];
1385				pageX = this.containment ?
1386					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
1387						left - this.offset.click.left <= this.containment[ 2 ] ) ?
1388							left :
1389							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
1390								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
1391								left;
1392			}
1393
1394		}
1395
1396		return {
1397			top: (
1398
1399				// The absolute mouse position
1400				pageY -
1401
1402				// Click offset (relative to the element)
1403				this.offset.click.top -
1404
1405				// Only for relative positioned nodes: Relative offset from element to offset parent
1406				this.offset.relative.top -
1407
1408				// The offsetParent's offset without borders (offset + border)
1409				this.offset.parent.top +
1410				( ( this.cssPosition === "fixed" ?
1411					-this.scrollParent.scrollTop() :
1412					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
1413			),
1414			left: (
1415
1416				// The absolute mouse position
1417				pageX -
1418
1419				// Click offset (relative to the element)
1420				this.offset.click.left -
1421
1422				// Only for relative positioned nodes: Relative offset from element to offset parent
1423				this.offset.relative.left -
1424
1425				// The offsetParent's offset without borders (offset + border)
1426				this.offset.parent.left +
1427				( ( this.cssPosition === "fixed" ?
1428					-this.scrollParent.scrollLeft() :
1429					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
1430			)
1431		};
1432
1433	},
1434
1435	_rearrange: function( event, i, a, hardRefresh ) {
1436
1437		if ( a ) {
1438			a[ 0 ].appendChild( this.placeholder[ 0 ] );
1439		} else {
1440			i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
1441				( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
1442		}
1443
1444		//Various things done here to improve the performance:
1445		// 1. we create a setTimeout, that calls refreshPositions
1446		// 2. on the instance, we have a counter variable, that get's higher after every append
1447		// 3. on the local scope, we copy the counter variable, and check in the timeout,
1448		// if it's still the same
1449		// 4. this lets only the last addition to the timeout stack through
1450		this.counter = this.counter ? ++this.counter : 1;
1451		var counter = this.counter;
1452
1453		this._delay( function() {
1454			if ( counter === this.counter ) {
1455
1456				//Precompute after each DOM insertion, NOT on mousemove
1457				this.refreshPositions( !hardRefresh );
1458			}
1459		} );
1460
1461	},
1462
1463	_clear: function( event, noPropagation ) {
1464
1465		this.reverting = false;
1466
1467		// We delay all events that have to be triggered to after the point where the placeholder
1468		// has been removed and everything else normalized again
1469		var i,
1470			delayedTriggers = [];
1471
1472		// We first have to update the dom position of the actual currentItem
1473		// Note: don't do it if the current item is already removed (by a user), or it gets
1474		// reappended (see #4088)
1475		if ( !this._noFinalSort && this.currentItem.parent().length ) {
1476			this.placeholder.before( this.currentItem );
1477		}
1478		this._noFinalSort = null;
1479
1480		if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
1481			for ( i in this._storedCSS ) {
1482				if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
1483					this._storedCSS[ i ] = "";
1484				}
1485			}
1486			this.currentItem.css( this._storedCSS );
1487			this._removeClass( this.currentItem, "ui-sortable-helper" );
1488		} else {
1489			this.currentItem.show();
1490		}
1491
1492		if ( this.fromOutside && !noPropagation ) {
1493			delayedTriggers.push( function( event ) {
1494				this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
1495			} );
1496		}
1497		if ( ( this.fromOutside ||
1498				this.domPosition.prev !==
1499				this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
1500				this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
1501
1502			// Trigger update callback if the DOM position has changed
1503			delayedTriggers.push( function( event ) {
1504				this._trigger( "update", event, this._uiHash() );
1505			} );
1506		}
1507
1508		// Check if the items Container has Changed and trigger appropriate
1509		// events.
1510		if ( this !== this.currentContainer ) {
1511			if ( !noPropagation ) {
1512				delayedTriggers.push( function( event ) {
1513					this._trigger( "remove", event, this._uiHash() );
1514				} );
1515				delayedTriggers.push( ( function( c ) {
1516					return function( event ) {
1517						c._trigger( "receive", event, this._uiHash( this ) );
1518					};
1519				} ).call( this, this.currentContainer ) );
1520				delayedTriggers.push( ( function( c ) {
1521					return function( event ) {
1522						c._trigger( "update", event, this._uiHash( this ) );
1523					};
1524				} ).call( this, this.currentContainer ) );
1525			}
1526		}
1527
1528		//Post events to containers
1529		function delayEvent( type, instance, container ) {
1530			return function( event ) {
1531				container._trigger( type, event, instance._uiHash( instance ) );
1532			};
1533		}
1534		for ( i = this.containers.length - 1; i >= 0; i-- ) {
1535			if ( !noPropagation ) {
1536				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
1537			}
1538			if ( this.containers[ i ].containerCache.over ) {
1539				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
1540				this.containers[ i ].containerCache.over = 0;
1541			}
1542		}
1543
1544		//Do what was originally in plugins
1545		if ( this._storedStylesheet ) {
1546			this._storedStylesheet.remove();
1547			this._storedStylesheet = null;
1548		}
1549		if ( this._storedOpacity ) {
1550			this.helper.css( "opacity", this._storedOpacity );
1551		}
1552		if ( this._storedZIndex ) {
1553			this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
1554		}
1555
1556		this.dragging = false;
1557
1558		if ( !noPropagation ) {
1559			this._trigger( "beforeStop", event, this._uiHash() );
1560		}
1561
1562		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
1563		// it unbinds ALL events from the original node!
1564		this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
1565
1566		if ( !this.cancelHelperRemoval ) {
1567			if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
1568				this.helper.remove();
1569			}
1570			this.helper = null;
1571		}
1572
1573		if ( !noPropagation ) {
1574			for ( i = 0; i < delayedTriggers.length; i++ ) {
1575
1576				// Trigger all delayed events
1577				delayedTriggers[ i ].call( this, event );
1578			}
1579			this._trigger( "stop", event, this._uiHash() );
1580		}
1581
1582		this.fromOutside = false;
1583		return !this.cancelHelperRemoval;
1584
1585	},
1586
1587	_trigger: function() {
1588		if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
1589			this.cancel();
1590		}
1591	},
1592
1593	_uiHash: function( _inst ) {
1594		var inst = _inst || this;
1595		return {
1596			helper: inst.helper,
1597			placeholder: inst.placeholder || $( [] ),
1598			position: inst.position,
1599			originalPosition: inst.originalPosition,
1600			offset: inst.positionAbs,
1601			item: inst.currentItem,
1602			sender: _inst ? _inst.element : null
1603		};
1604	}
1605
1606} );
1607
1608} );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.