Project

General

Profile

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