Project

General

Profile

1
/*!
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);
(22-22/32)