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