integration/back-office/lib/jquery-ui/ui/jquery.ui.draggable.js
changeset 2 78f71aa0a477
parent 1 b95aebb070b5
child 3 54f80d24f469
child 6 547b3ddedf7f
equal deleted inserted replaced
1:b95aebb070b5 2:78f71aa0a477
     1 /*!
       
     2  * jQuery UI Draggable 1.10.3
       
     3  * http://jqueryui.com
       
     4  *
       
     5  * Copyright 2013 jQuery Foundation and other contributors
       
     6  * Released under the MIT license.
       
     7  * http://jquery.org/license
       
     8  *
       
     9  * http://api.jqueryui.com/draggable/
       
    10  *
       
    11  * Depends:
       
    12  *	jquery.ui.core.js
       
    13  *	jquery.ui.mouse.js
       
    14  *	jquery.ui.widget.js
       
    15  */
       
    16 (function( $, undefined ) {
       
    17 
       
    18 $.widget("ui.draggable", $.ui.mouse, {
       
    19 	version: "1.10.3",
       
    20 	widgetEventPrefix: "drag",
       
    21 	options: {
       
    22 		addClasses: true,
       
    23 		appendTo: "parent",
       
    24 		axis: false,
       
    25 		connectToSortable: false,
       
    26 		containment: false,
       
    27 		cursor: "auto",
       
    28 		cursorAt: false,
       
    29 		grid: false,
       
    30 		handle: false,
       
    31 		helper: "original",
       
    32 		iframeFix: false,
       
    33 		opacity: false,
       
    34 		refreshPositions: false,
       
    35 		revert: false,
       
    36 		revertDuration: 500,
       
    37 		scope: "default",
       
    38 		scroll: true,
       
    39 		scrollSensitivity: 20,
       
    40 		scrollSpeed: 20,
       
    41 		snap: false,
       
    42 		snapMode: "both",
       
    43 		snapTolerance: 20,
       
    44 		stack: false,
       
    45 		zIndex: false,
       
    46 
       
    47 		// callbacks
       
    48 		drag: null,
       
    49 		start: null,
       
    50 		stop: null
       
    51 	},
       
    52 	_create: function() {
       
    53 
       
    54 		if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
       
    55 			this.element[0].style.position = "relative";
       
    56 		}
       
    57 		if (this.options.addClasses){
       
    58 			this.element.addClass("ui-draggable");
       
    59 		}
       
    60 		if (this.options.disabled){
       
    61 			this.element.addClass("ui-draggable-disabled");
       
    62 		}
       
    63 
       
    64 		this._mouseInit();
       
    65 
       
    66 	},
       
    67 
       
    68 	_destroy: function() {
       
    69 		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
       
    70 		this._mouseDestroy();
       
    71 	},
       
    72 
       
    73 	_mouseCapture: function(event) {
       
    74 
       
    75 		var o = this.options;
       
    76 
       
    77 		// among others, prevent a drag on a resizable-handle
       
    78 		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
       
    79 			return false;
       
    80 		}
       
    81 
       
    82 		//Quit if we're not on a valid handle
       
    83 		this.handle = this._getHandle(event);
       
    84 		if (!this.handle) {
       
    85 			return false;
       
    86 		}
       
    87 
       
    88 		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
       
    89 			$("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
       
    90 			.css({
       
    91 				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
       
    92 				position: "absolute", opacity: "0.001", zIndex: 1000
       
    93 			})
       
    94 			.css($(this).offset())
       
    95 			.appendTo("body");
       
    96 		});
       
    97 
       
    98 		return true;
       
    99 
       
   100 	},
       
   101 
       
   102 	_mouseStart: function(event) {
       
   103 
       
   104 		var o = this.options;
       
   105 
       
   106 		//Create and append the visible helper
       
   107 		this.helper = this._createHelper(event);
       
   108 
       
   109 		this.helper.addClass("ui-draggable-dragging");
       
   110 
       
   111 		//Cache the helper size
       
   112 		this._cacheHelperProportions();
       
   113 
       
   114 		//If ddmanager is used for droppables, set the global draggable
       
   115 		if($.ui.ddmanager) {
       
   116 			$.ui.ddmanager.current = this;
       
   117 		}
       
   118 
       
   119 		/*
       
   120 		 * - Position generation -
       
   121 		 * This block generates everything position related - it's the core of draggables.
       
   122 		 */
       
   123 
       
   124 		//Cache the margins of the original element
       
   125 		this._cacheMargins();
       
   126 
       
   127 		//Store the helper's css position
       
   128 		this.cssPosition = this.helper.css( "position" );
       
   129 		this.scrollParent = this.helper.scrollParent();
       
   130 		this.offsetParent = this.helper.offsetParent();
       
   131 		this.offsetParentCssPosition = this.offsetParent.css( "position" );
       
   132 
       
   133 		//The element's absolute position on the page minus margins
       
   134 		this.offset = this.positionAbs = this.element.offset();
       
   135 		this.offset = {
       
   136 			top: this.offset.top - this.margins.top,
       
   137 			left: this.offset.left - this.margins.left
       
   138 		};
       
   139 
       
   140 		//Reset scroll cache
       
   141 		this.offset.scroll = false;
       
   142 
       
   143 		$.extend(this.offset, {
       
   144 			click: { //Where the click happened, relative to the element
       
   145 				left: event.pageX - this.offset.left,
       
   146 				top: event.pageY - this.offset.top
       
   147 			},
       
   148 			parent: this._getParentOffset(),
       
   149 			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
       
   150 		});
       
   151 
       
   152 		//Generate the original position
       
   153 		this.originalPosition = this.position = this._generatePosition(event);
       
   154 		this.originalPageX = event.pageX;
       
   155 		this.originalPageY = event.pageY;
       
   156 
       
   157 		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
       
   158 		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
       
   159 
       
   160 		//Set a containment if given in the options
       
   161 		this._setContainment();
       
   162 
       
   163 		//Trigger event + callbacks
       
   164 		if(this._trigger("start", event) === false) {
       
   165 			this._clear();
       
   166 			return false;
       
   167 		}
       
   168 
       
   169 		//Recache the helper size
       
   170 		this._cacheHelperProportions();
       
   171 
       
   172 		//Prepare the droppable offsets
       
   173 		if ($.ui.ddmanager && !o.dropBehaviour) {
       
   174 			$.ui.ddmanager.prepareOffsets(this, event);
       
   175 		}
       
   176 
       
   177 
       
   178 		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
       
   179 
       
   180 		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
       
   181 		if ( $.ui.ddmanager ) {
       
   182 			$.ui.ddmanager.dragStart(this, event);
       
   183 		}
       
   184 
       
   185 		return true;
       
   186 	},
       
   187 
       
   188 	_mouseDrag: function(event, noPropagation) {
       
   189 		// reset any necessary cached properties (see #5009)
       
   190 		if ( this.offsetParentCssPosition === "fixed" ) {
       
   191 			this.offset.parent = this._getParentOffset();
       
   192 		}
       
   193 
       
   194 		//Compute the helpers position
       
   195 		this.position = this._generatePosition(event);
       
   196 		this.positionAbs = this._convertPositionTo("absolute");
       
   197 
       
   198 		//Call plugins and callbacks and use the resulting position if something is returned
       
   199 		if (!noPropagation) {
       
   200 			var ui = this._uiHash();
       
   201 			if(this._trigger("drag", event, ui) === false) {
       
   202 				this._mouseUp({});
       
   203 				return false;
       
   204 			}
       
   205 			this.position = ui.position;
       
   206 		}
       
   207 
       
   208 		if(!this.options.axis || this.options.axis !== "y") {
       
   209 			this.helper[0].style.left = this.position.left+"px";
       
   210 		}
       
   211 		if(!this.options.axis || this.options.axis !== "x") {
       
   212 			this.helper[0].style.top = this.position.top+"px";
       
   213 		}
       
   214 		if($.ui.ddmanager) {
       
   215 			$.ui.ddmanager.drag(this, event);
       
   216 		}
       
   217 
       
   218 		return false;
       
   219 	},
       
   220 
       
   221 	_mouseStop: function(event) {
       
   222 
       
   223 		//If we are using droppables, inform the manager about the drop
       
   224 		var that = this,
       
   225 			dropped = false;
       
   226 		if ($.ui.ddmanager && !this.options.dropBehaviour) {
       
   227 			dropped = $.ui.ddmanager.drop(this, event);
       
   228 		}
       
   229 
       
   230 		//if a drop comes from outside (a sortable)
       
   231 		if(this.dropped) {
       
   232 			dropped = this.dropped;
       
   233 			this.dropped = false;
       
   234 		}
       
   235 
       
   236 		//if the original element is no longer in the DOM don't bother to continue (see #8269)
       
   237 		if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
       
   238 			return false;
       
   239 		}
       
   240 
       
   241 		if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
       
   242 			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
       
   243 				if(that._trigger("stop", event) !== false) {
       
   244 					that._clear();
       
   245 				}
       
   246 			});
       
   247 		} else {
       
   248 			if(this._trigger("stop", event) !== false) {
       
   249 				this._clear();
       
   250 			}
       
   251 		}
       
   252 
       
   253 		return false;
       
   254 	},
       
   255 
       
   256 	_mouseUp: function(event) {
       
   257 		//Remove frame helpers
       
   258 		$("div.ui-draggable-iframeFix").each(function() {
       
   259 			this.parentNode.removeChild(this);
       
   260 		});
       
   261 
       
   262 		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
       
   263 		if( $.ui.ddmanager ) {
       
   264 			$.ui.ddmanager.dragStop(this, event);
       
   265 		}
       
   266 
       
   267 		return $.ui.mouse.prototype._mouseUp.call(this, event);
       
   268 	},
       
   269 
       
   270 	cancel: function() {
       
   271 
       
   272 		if(this.helper.is(".ui-draggable-dragging")) {
       
   273 			this._mouseUp({});
       
   274 		} else {
       
   275 			this._clear();
       
   276 		}
       
   277 
       
   278 		return this;
       
   279 
       
   280 	},
       
   281 
       
   282 	_getHandle: function(event) {
       
   283 		return this.options.handle ?
       
   284 			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
       
   285 			true;
       
   286 	},
       
   287 
       
   288 	_createHelper: function(event) {
       
   289 
       
   290 		var o = this.options,
       
   291 			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
       
   292 
       
   293 		if(!helper.parents("body").length) {
       
   294 			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
       
   295 		}
       
   296 
       
   297 		if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
       
   298 			helper.css("position", "absolute");
       
   299 		}
       
   300 
       
   301 		return helper;
       
   302 
       
   303 	},
       
   304 
       
   305 	_adjustOffsetFromHelper: function(obj) {
       
   306 		if (typeof obj === "string") {
       
   307 			obj = obj.split(" ");
       
   308 		}
       
   309 		if ($.isArray(obj)) {
       
   310 			obj = {left: +obj[0], top: +obj[1] || 0};
       
   311 		}
       
   312 		if ("left" in obj) {
       
   313 			this.offset.click.left = obj.left + this.margins.left;
       
   314 		}
       
   315 		if ("right" in obj) {
       
   316 			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
       
   317 		}
       
   318 		if ("top" in obj) {
       
   319 			this.offset.click.top = obj.top + this.margins.top;
       
   320 		}
       
   321 		if ("bottom" in obj) {
       
   322 			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
       
   323 		}
       
   324 	},
       
   325 
       
   326 	_getParentOffset: function() {
       
   327 
       
   328 		//Get the offsetParent and cache its position
       
   329 		var po = this.offsetParent.offset();
       
   330 
       
   331 		// This is a special case where we need to modify a offset calculated on start, since the following happened:
       
   332 		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
       
   333 		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
       
   334 		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
       
   335 		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
       
   336 			po.left += this.scrollParent.scrollLeft();
       
   337 			po.top += this.scrollParent.scrollTop();
       
   338 		}
       
   339 
       
   340 		//This needs to be actually done for all browsers, since pageX/pageY includes this information
       
   341 		//Ugly IE fix
       
   342 		if((this.offsetParent[0] === document.body) ||
       
   343 			(this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
       
   344 			po = { top: 0, left: 0 };
       
   345 		}
       
   346 
       
   347 		return {
       
   348 			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
       
   349 			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
       
   350 		};
       
   351 
       
   352 	},
       
   353 
       
   354 	_getRelativeOffset: function() {
       
   355 
       
   356 		if(this.cssPosition === "relative") {
       
   357 			var p = this.element.position();
       
   358 			return {
       
   359 				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
       
   360 				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
       
   361 			};
       
   362 		} else {
       
   363 			return { top: 0, left: 0 };
       
   364 		}
       
   365 
       
   366 	},
       
   367 
       
   368 	_cacheMargins: function() {
       
   369 		this.margins = {
       
   370 			left: (parseInt(this.element.css("marginLeft"),10) || 0),
       
   371 			top: (parseInt(this.element.css("marginTop"),10) || 0),
       
   372 			right: (parseInt(this.element.css("marginRight"),10) || 0),
       
   373 			bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
       
   374 		};
       
   375 	},
       
   376 
       
   377 	_cacheHelperProportions: function() {
       
   378 		this.helperProportions = {
       
   379 			width: this.helper.outerWidth(),
       
   380 			height: this.helper.outerHeight()
       
   381 		};
       
   382 	},
       
   383 
       
   384 	_setContainment: function() {
       
   385 
       
   386 		var over, c, ce,
       
   387 			o = this.options;
       
   388 
       
   389 		if ( !o.containment ) {
       
   390 			this.containment = null;
       
   391 			return;
       
   392 		}
       
   393 
       
   394 		if ( o.containment === "window" ) {
       
   395 			this.containment = [
       
   396 				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
       
   397 				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
       
   398 				$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
       
   399 				$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
       
   400 			];
       
   401 			return;
       
   402 		}
       
   403 
       
   404 		if ( o.containment === "document") {
       
   405 			this.containment = [
       
   406 				0,
       
   407 				0,
       
   408 				$( document ).width() - this.helperProportions.width - this.margins.left,
       
   409 				( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
       
   410 			];
       
   411 			return;
       
   412 		}
       
   413 
       
   414 		if ( o.containment.constructor === Array ) {
       
   415 			this.containment = o.containment;
       
   416 			return;
       
   417 		}
       
   418 
       
   419 		if ( o.containment === "parent" ) {
       
   420 			o.containment = this.helper[ 0 ].parentNode;
       
   421 		}
       
   422 
       
   423 		c = $( o.containment );
       
   424 		ce = c[ 0 ];
       
   425 
       
   426 		if( !ce ) {
       
   427 			return;
       
   428 		}
       
   429 
       
   430 		over = c.css( "overflow" ) !== "hidden";
       
   431 
       
   432 		this.containment = [
       
   433 			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
       
   434 			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
       
   435 			( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
       
   436 			( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top  - this.margins.bottom
       
   437 		];
       
   438 		this.relative_container = c;
       
   439 	},
       
   440 
       
   441 	_convertPositionTo: function(d, pos) {
       
   442 
       
   443 		if(!pos) {
       
   444 			pos = this.position;
       
   445 		}
       
   446 
       
   447 		var mod = d === "absolute" ? 1 : -1,
       
   448 			scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
       
   449 
       
   450 		//Cache the scroll
       
   451 		if (!this.offset.scroll) {
       
   452 			this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
       
   453 		}
       
   454 
       
   455 		return {
       
   456 			top: (
       
   457 				pos.top	+																// The absolute mouse position
       
   458 				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
       
   459 				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
       
   460 				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
       
   461 			),
       
   462 			left: (
       
   463 				pos.left +																// The absolute mouse position
       
   464 				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
       
   465 				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
       
   466 				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
       
   467 			)
       
   468 		};
       
   469 
       
   470 	},
       
   471 
       
   472 	_generatePosition: function(event) {
       
   473 
       
   474 		var containment, co, top, left,
       
   475 			o = this.options,
       
   476 			scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
       
   477 			pageX = event.pageX,
       
   478 			pageY = event.pageY;
       
   479 
       
   480 		//Cache the scroll
       
   481 		if (!this.offset.scroll) {
       
   482 			this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
       
   483 		}
       
   484 
       
   485 		/*
       
   486 		 * - Position constraining -
       
   487 		 * Constrain the position to a mix of grid, containment.
       
   488 		 */
       
   489 
       
   490 		// If we are not dragging yet, we won't check for options
       
   491 		if ( this.originalPosition ) {
       
   492 			if ( this.containment ) {
       
   493 				if ( this.relative_container ){
       
   494 					co = this.relative_container.offset();
       
   495 					containment = [
       
   496 						this.containment[ 0 ] + co.left,
       
   497 						this.containment[ 1 ] + co.top,
       
   498 						this.containment[ 2 ] + co.left,
       
   499 						this.containment[ 3 ] + co.top
       
   500 					];
       
   501 				}
       
   502 				else {
       
   503 					containment = this.containment;
       
   504 				}
       
   505 
       
   506 				if(event.pageX - this.offset.click.left < containment[0]) {
       
   507 					pageX = containment[0] + this.offset.click.left;
       
   508 				}
       
   509 				if(event.pageY - this.offset.click.top < containment[1]) {
       
   510 					pageY = containment[1] + this.offset.click.top;
       
   511 				}
       
   512 				if(event.pageX - this.offset.click.left > containment[2]) {
       
   513 					pageX = containment[2] + this.offset.click.left;
       
   514 				}
       
   515 				if(event.pageY - this.offset.click.top > containment[3]) {
       
   516 					pageY = containment[3] + this.offset.click.top;
       
   517 				}
       
   518 			}
       
   519 
       
   520 			if(o.grid) {
       
   521 				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
       
   522 				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
       
   523 				pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
       
   524 
       
   525 				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
       
   526 				pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
       
   527 			}
       
   528 
       
   529 		}
       
   530 
       
   531 		return {
       
   532 			top: (
       
   533 				pageY -																	// The absolute mouse position
       
   534 				this.offset.click.top	-												// Click offset (relative to the element)
       
   535 				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
       
   536 				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
       
   537 				( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
       
   538 			),
       
   539 			left: (
       
   540 				pageX -																	// The absolute mouse position
       
   541 				this.offset.click.left -												// Click offset (relative to the element)
       
   542 				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
       
   543 				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
       
   544 				( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
       
   545 			)
       
   546 		};
       
   547 
       
   548 	},
       
   549 
       
   550 	_clear: function() {
       
   551 		this.helper.removeClass("ui-draggable-dragging");
       
   552 		if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
       
   553 			this.helper.remove();
       
   554 		}
       
   555 		this.helper = null;
       
   556 		this.cancelHelperRemoval = false;
       
   557 	},
       
   558 
       
   559 	// From now on bulk stuff - mainly helpers
       
   560 
       
   561 	_trigger: function(type, event, ui) {
       
   562 		ui = ui || this._uiHash();
       
   563 		$.ui.plugin.call(this, type, [event, ui]);
       
   564 		//The absolute position has to be recalculated after plugins
       
   565 		if(type === "drag") {
       
   566 			this.positionAbs = this._convertPositionTo("absolute");
       
   567 		}
       
   568 		return $.Widget.prototype._trigger.call(this, type, event, ui);
       
   569 	},
       
   570 
       
   571 	plugins: {},
       
   572 
       
   573 	_uiHash: function() {
       
   574 		return {
       
   575 			helper: this.helper,
       
   576 			position: this.position,
       
   577 			originalPosition: this.originalPosition,
       
   578 			offset: this.positionAbs
       
   579 		};
       
   580 	}
       
   581 
       
   582 });
       
   583 
       
   584 $.ui.plugin.add("draggable", "connectToSortable", {
       
   585 	start: function(event, ui) {
       
   586 
       
   587 		var inst = $(this).data("ui-draggable"), o = inst.options,
       
   588 			uiSortable = $.extend({}, ui, { item: inst.element });
       
   589 		inst.sortables = [];
       
   590 		$(o.connectToSortable).each(function() {
       
   591 			var sortable = $.data(this, "ui-sortable");
       
   592 			if (sortable && !sortable.options.disabled) {
       
   593 				inst.sortables.push({
       
   594 					instance: sortable,
       
   595 					shouldRevert: sortable.options.revert
       
   596 				});
       
   597 				sortable.refreshPositions();	// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
       
   598 				sortable._trigger("activate", event, uiSortable);
       
   599 			}
       
   600 		});
       
   601 
       
   602 	},
       
   603 	stop: function(event, ui) {
       
   604 
       
   605 		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
       
   606 		var inst = $(this).data("ui-draggable"),
       
   607 			uiSortable = $.extend({}, ui, { item: inst.element });
       
   608 
       
   609 		$.each(inst.sortables, function() {
       
   610 			if(this.instance.isOver) {
       
   611 
       
   612 				this.instance.isOver = 0;
       
   613 
       
   614 				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
       
   615 				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
       
   616 
       
   617 				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
       
   618 				if(this.shouldRevert) {
       
   619 					this.instance.options.revert = this.shouldRevert;
       
   620 				}
       
   621 
       
   622 				//Trigger the stop of the sortable
       
   623 				this.instance._mouseStop(event);
       
   624 
       
   625 				this.instance.options.helper = this.instance.options._helper;
       
   626 
       
   627 				//If the helper has been the original item, restore properties in the sortable
       
   628 				if(inst.options.helper === "original") {
       
   629 					this.instance.currentItem.css({ top: "auto", left: "auto" });
       
   630 				}
       
   631 
       
   632 			} else {
       
   633 				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
       
   634 				this.instance._trigger("deactivate", event, uiSortable);
       
   635 			}
       
   636 
       
   637 		});
       
   638 
       
   639 	},
       
   640 	drag: function(event, ui) {
       
   641 
       
   642 		var inst = $(this).data("ui-draggable"), that = this;
       
   643 
       
   644 		$.each(inst.sortables, function() {
       
   645 
       
   646 			var innermostIntersecting = false,
       
   647 				thisSortable = this;
       
   648 
       
   649 			//Copy over some variables to allow calling the sortable's native _intersectsWith
       
   650 			this.instance.positionAbs = inst.positionAbs;
       
   651 			this.instance.helperProportions = inst.helperProportions;
       
   652 			this.instance.offset.click = inst.offset.click;
       
   653 
       
   654 			if(this.instance._intersectsWith(this.instance.containerCache)) {
       
   655 				innermostIntersecting = true;
       
   656 				$.each(inst.sortables, function () {
       
   657 					this.instance.positionAbs = inst.positionAbs;
       
   658 					this.instance.helperProportions = inst.helperProportions;
       
   659 					this.instance.offset.click = inst.offset.click;
       
   660 					if (this !== thisSortable &&
       
   661 						this.instance._intersectsWith(this.instance.containerCache) &&
       
   662 						$.contains(thisSortable.instance.element[0], this.instance.element[0])
       
   663 					) {
       
   664 						innermostIntersecting = false;
       
   665 					}
       
   666 					return innermostIntersecting;
       
   667 				});
       
   668 			}
       
   669 
       
   670 
       
   671 			if(innermostIntersecting) {
       
   672 				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
       
   673 				if(!this.instance.isOver) {
       
   674 
       
   675 					this.instance.isOver = 1;
       
   676 					//Now we fake the start of dragging for the sortable instance,
       
   677 					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
       
   678 					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
       
   679 					this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
       
   680 					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
       
   681 					this.instance.options.helper = function() { return ui.helper[0]; };
       
   682 
       
   683 					event.target = this.instance.currentItem[0];
       
   684 					this.instance._mouseCapture(event, true);
       
   685 					this.instance._mouseStart(event, true, true);
       
   686 
       
   687 					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
       
   688 					this.instance.offset.click.top = inst.offset.click.top;
       
   689 					this.instance.offset.click.left = inst.offset.click.left;
       
   690 					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
       
   691 					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
       
   692 
       
   693 					inst._trigger("toSortable", event);
       
   694 					inst.dropped = this.instance.element; //draggable revert needs that
       
   695 					//hack so receive/update callbacks work (mostly)
       
   696 					inst.currentItem = inst.element;
       
   697 					this.instance.fromOutside = inst;
       
   698 
       
   699 				}
       
   700 
       
   701 				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
       
   702 				if(this.instance.currentItem) {
       
   703 					this.instance._mouseDrag(event);
       
   704 				}
       
   705 
       
   706 			} else {
       
   707 
       
   708 				//If it doesn't intersect with the sortable, and it intersected before,
       
   709 				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
       
   710 				if(this.instance.isOver) {
       
   711 
       
   712 					this.instance.isOver = 0;
       
   713 					this.instance.cancelHelperRemoval = true;
       
   714 
       
   715 					//Prevent reverting on this forced stop
       
   716 					this.instance.options.revert = false;
       
   717 
       
   718 					// The out event needs to be triggered independently
       
   719 					this.instance._trigger("out", event, this.instance._uiHash(this.instance));
       
   720 
       
   721 					this.instance._mouseStop(event, true);
       
   722 					this.instance.options.helper = this.instance.options._helper;
       
   723 
       
   724 					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
       
   725 					this.instance.currentItem.remove();
       
   726 					if(this.instance.placeholder) {
       
   727 						this.instance.placeholder.remove();
       
   728 					}
       
   729 
       
   730 					inst._trigger("fromSortable", event);
       
   731 					inst.dropped = false; //draggable revert needs that
       
   732 				}
       
   733 
       
   734 			}
       
   735 
       
   736 		});
       
   737 
       
   738 	}
       
   739 });
       
   740 
       
   741 $.ui.plugin.add("draggable", "cursor", {
       
   742 	start: function() {
       
   743 		var t = $("body"), o = $(this).data("ui-draggable").options;
       
   744 		if (t.css("cursor")) {
       
   745 			o._cursor = t.css("cursor");
       
   746 		}
       
   747 		t.css("cursor", o.cursor);
       
   748 	},
       
   749 	stop: function() {
       
   750 		var o = $(this).data("ui-draggable").options;
       
   751 		if (o._cursor) {
       
   752 			$("body").css("cursor", o._cursor);
       
   753 		}
       
   754 	}
       
   755 });
       
   756 
       
   757 $.ui.plugin.add("draggable", "opacity", {
       
   758 	start: function(event, ui) {
       
   759 		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
       
   760 		if(t.css("opacity")) {
       
   761 			o._opacity = t.css("opacity");
       
   762 		}
       
   763 		t.css("opacity", o.opacity);
       
   764 	},
       
   765 	stop: function(event, ui) {
       
   766 		var o = $(this).data("ui-draggable").options;
       
   767 		if(o._opacity) {
       
   768 			$(ui.helper).css("opacity", o._opacity);
       
   769 		}
       
   770 	}
       
   771 });
       
   772 
       
   773 $.ui.plugin.add("draggable", "scroll", {
       
   774 	start: function() {
       
   775 		var i = $(this).data("ui-draggable");
       
   776 		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
       
   777 			i.overflowOffset = i.scrollParent.offset();
       
   778 		}
       
   779 	},
       
   780 	drag: function( event ) {
       
   781 
       
   782 		var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
       
   783 
       
   784 		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
       
   785 
       
   786 			if(!o.axis || o.axis !== "x") {
       
   787 				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
       
   788 					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
       
   789 				} else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
       
   790 					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
       
   791 				}
       
   792 			}
       
   793 
       
   794 			if(!o.axis || o.axis !== "y") {
       
   795 				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
       
   796 					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
       
   797 				} else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
       
   798 					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
       
   799 				}
       
   800 			}
       
   801 
       
   802 		} else {
       
   803 
       
   804 			if(!o.axis || o.axis !== "x") {
       
   805 				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
       
   806 					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
       
   807 				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
       
   808 					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
       
   809 				}
       
   810 			}
       
   811 
       
   812 			if(!o.axis || o.axis !== "y") {
       
   813 				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
       
   814 					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
       
   815 				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
       
   816 					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
       
   817 				}
       
   818 			}
       
   819 
       
   820 		}
       
   821 
       
   822 		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
       
   823 			$.ui.ddmanager.prepareOffsets(i, event);
       
   824 		}
       
   825 
       
   826 	}
       
   827 });
       
   828 
       
   829 $.ui.plugin.add("draggable", "snap", {
       
   830 	start: function() {
       
   831 
       
   832 		var i = $(this).data("ui-draggable"),
       
   833 			o = i.options;
       
   834 
       
   835 		i.snapElements = [];
       
   836 
       
   837 		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
       
   838 			var $t = $(this),
       
   839 				$o = $t.offset();
       
   840 			if(this !== i.element[0]) {
       
   841 				i.snapElements.push({
       
   842 					item: this,
       
   843 					width: $t.outerWidth(), height: $t.outerHeight(),
       
   844 					top: $o.top, left: $o.left
       
   845 				});
       
   846 			}
       
   847 		});
       
   848 
       
   849 	},
       
   850 	drag: function(event, ui) {
       
   851 
       
   852 		var ts, bs, ls, rs, l, r, t, b, i, first,
       
   853 			inst = $(this).data("ui-draggable"),
       
   854 			o = inst.options,
       
   855 			d = o.snapTolerance,
       
   856 			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
       
   857 			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
       
   858 
       
   859 		for (i = inst.snapElements.length - 1; i >= 0; i--){
       
   860 
       
   861 			l = inst.snapElements[i].left;
       
   862 			r = l + inst.snapElements[i].width;
       
   863 			t = inst.snapElements[i].top;
       
   864 			b = t + inst.snapElements[i].height;
       
   865 
       
   866 			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
       
   867 				if(inst.snapElements[i].snapping) {
       
   868 					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
       
   869 				}
       
   870 				inst.snapElements[i].snapping = false;
       
   871 				continue;
       
   872 			}
       
   873 
       
   874 			if(o.snapMode !== "inner") {
       
   875 				ts = Math.abs(t - y2) <= d;
       
   876 				bs = Math.abs(b - y1) <= d;
       
   877 				ls = Math.abs(l - x2) <= d;
       
   878 				rs = Math.abs(r - x1) <= d;
       
   879 				if(ts) {
       
   880 					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
       
   881 				}
       
   882 				if(bs) {
       
   883 					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
       
   884 				}
       
   885 				if(ls) {
       
   886 					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
       
   887 				}
       
   888 				if(rs) {
       
   889 					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
       
   890 				}
       
   891 			}
       
   892 
       
   893 			first = (ts || bs || ls || rs);
       
   894 
       
   895 			if(o.snapMode !== "outer") {
       
   896 				ts = Math.abs(t - y1) <= d;
       
   897 				bs = Math.abs(b - y2) <= d;
       
   898 				ls = Math.abs(l - x1) <= d;
       
   899 				rs = Math.abs(r - x2) <= d;
       
   900 				if(ts) {
       
   901 					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
       
   902 				}
       
   903 				if(bs) {
       
   904 					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
       
   905 				}
       
   906 				if(ls) {
       
   907 					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
       
   908 				}
       
   909 				if(rs) {
       
   910 					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
       
   911 				}
       
   912 			}
       
   913 
       
   914 			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
       
   915 				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
       
   916 			}
       
   917 			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
       
   918 
       
   919 		}
       
   920 
       
   921 	}
       
   922 });
       
   923 
       
   924 $.ui.plugin.add("draggable", "stack", {
       
   925 	start: function() {
       
   926 		var min,
       
   927 			o = this.data("ui-draggable").options,
       
   928 			group = $.makeArray($(o.stack)).sort(function(a,b) {
       
   929 				return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
       
   930 			});
       
   931 
       
   932 		if (!group.length) { return; }
       
   933 
       
   934 		min = parseInt($(group[0]).css("zIndex"), 10) || 0;
       
   935 		$(group).each(function(i) {
       
   936 			$(this).css("zIndex", min + i);
       
   937 		});
       
   938 		this.css("zIndex", (min + group.length));
       
   939 	}
       
   940 });
       
   941 
       
   942 $.ui.plugin.add("draggable", "zIndex", {
       
   943 	start: function(event, ui) {
       
   944 		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
       
   945 		if(t.css("zIndex")) {
       
   946 			o._zIndex = t.css("zIndex");
       
   947 		}
       
   948 		t.css("zIndex", o.zIndex);
       
   949 	},
       
   950 	stop: function(event, ui) {
       
   951 		var o = $(this).data("ui-draggable").options;
       
   952 		if(o._zIndex) {
       
   953 			$(ui.helper).css("zIndex", o._zIndex);
       
   954 		}
       
   955 	}
       
   956 });
       
   957 
       
   958 })(jQuery);