PageSourceSearch

https://www.alfredstreet.org/wp-includes/js/jquery/ui/sortable.js?ver=1.13.3

js alfredstreet.org collected 2026-09-24 09:56:56 UTC 47,641 bytes, 1,615 lines download raw bytes

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

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.