PageRenderTime 146ms CodeModel.GetById 16ms app.highlight 115ms RepoModel.GetById 1ms app.codeStats 0ms

/static/scripts/jquery.ui.sortable.slider.js

https://bitbucket.org/cistrome/cistrome-harvard/
JavaScript | 2086 lines | 1490 code | 389 blank | 207 comment | 485 complexity | 0fb94f061421dfd49684bdf234862a1d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file