Projet

Général

Profil

Paste
Télécharger (30,4 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / jquery_update / replace / ui / ui / jquery.ui.draggable.js @ 503b3f7b

1
/*!
2
 * jQuery UI Draggable 1.10.2
3
 * http://jqueryui.com
4
 *
5
 * Copyright 2013 jQuery Foundation and other contributors
6
 * Released under the MIT license.
7
 * http://jquery.org/license
8
 *
9
 * http://api.jqueryui.com/draggable/
10
 *
11
 * Depends:
12
 *        jquery.ui.core.js
13
 *        jquery.ui.mouse.js
14
 *        jquery.ui.widget.js
15
 */
16
(function( $, undefined ) {
17

    
18
$.widget("ui.draggable", $.ui.mouse, {
19
        version: "1.10.2",
20
        widgetEventPrefix: "drag",
21
        options: {
22
                addClasses: true,
23
                appendTo: "parent",
24
                axis: false,
25
                connectToSortable: false,
26
                containment: false,
27
                cursor: "auto",
28
                cursorAt: false,
29
                grid: false,
30
                handle: false,
31
                helper: "original",
32
                iframeFix: false,
33
                opacity: false,
34
                refreshPositions: false,
35
                revert: false,
36
                revertDuration: 500,
37
                scope: "default",
38
                scroll: true,
39
                scrollSensitivity: 20,
40
                scrollSpeed: 20,
41
                snap: false,
42
                snapMode: "both",
43
                snapTolerance: 20,
44
                stack: false,
45
                zIndex: false,
46

    
47
                // callbacks
48
                drag: null,
49
                start: null,
50
                stop: null
51
        },
52
        _create: function() {
53

    
54
                if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
55
                        this.element[0].style.position = "relative";
56
                }
57
                if (this.options.addClasses){
58
                        this.element.addClass("ui-draggable");
59
                }
60
                if (this.options.disabled){
61
                        this.element.addClass("ui-draggable-disabled");
62
                }
63

    
64
                this._mouseInit();
65

    
66
        },
67

    
68
        _destroy: function() {
69
                this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
70
                this._mouseDestroy();
71
        },
72

    
73
        _mouseCapture: function(event) {
74

    
75
                var o = this.options;
76

    
77
                // among others, prevent a drag on a resizable-handle
78
                if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
79
                        return false;
80
                }
81

    
82
                //Quit if we're not on a valid handle
83
                this.handle = this._getHandle(event);
84
                if (!this.handle) {
85
                        return false;
86
                }
87

    
88
                $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
89
                        $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
90
                        .css({
91
                                width: this.offsetWidth+"px", height: this.offsetHeight+"px",
92
                                position: "absolute", opacity: "0.001", zIndex: 1000
93
                        })
94
                        .css($(this).offset())
95
                        .appendTo("body");
96
                });
97

    
98
                return true;
99

    
100
        },
101

    
102
        _mouseStart: function(event) {
103

    
104
                var o = this.options;
105

    
106
                //Create and append the visible helper
107
                this.helper = this._createHelper(event);
108

    
109
                this.helper.addClass("ui-draggable-dragging");
110

    
111
                //Cache the helper size
112
                this._cacheHelperProportions();
113

    
114
                //If ddmanager is used for droppables, set the global draggable
115
                if($.ui.ddmanager) {
116
                        $.ui.ddmanager.current = this;
117
                }
118

    
119
                /*
120
                 * - Position generation -
121
                 * This block generates everything position related - it's the core of draggables.
122
                 */
123

    
124
                //Cache the margins of the original element
125
                this._cacheMargins();
126

    
127
                //Store the helper's css position
128
                this.cssPosition = this.helper.css("position");
129
                this.scrollParent = this.helper.scrollParent();
130

    
131
                //The element's absolute position on the page minus margins
132
                this.offset = this.positionAbs = this.element.offset();
133
                this.offset = {
134
                        top: this.offset.top - this.margins.top,
135
                        left: this.offset.left - this.margins.left
136
                };
137

    
138
                $.extend(this.offset, {
139
                        click: { //Where the click happened, relative to the element
140
                                left: event.pageX - this.offset.left,
141
                                top: event.pageY - this.offset.top
142
                        },
143
                        parent: this._getParentOffset(),
144
                        relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
145
                });
146

    
147
                //Generate the original position
148
                this.originalPosition = this.position = this._generatePosition(event);
149
                this.originalPageX = event.pageX;
150
                this.originalPageY = event.pageY;
151

    
152
                //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
153
                (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
154

    
155
                //Set a containment if given in the options
156
                if(o.containment) {
157
                        this._setContainment();
158
                }
159

    
160
                //Trigger event + callbacks
161
                if(this._trigger("start", event) === false) {
162
                        this._clear();
163
                        return false;
164
                }
165

    
166
                //Recache the helper size
167
                this._cacheHelperProportions();
168

    
169
                //Prepare the droppable offsets
170
                if ($.ui.ddmanager && !o.dropBehaviour) {
171
                        $.ui.ddmanager.prepareOffsets(this, event);
172
                }
173

    
174

    
175
                this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
176

    
177
                //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
178
                if ( $.ui.ddmanager ) {
179
                        $.ui.ddmanager.dragStart(this, event);
180
                }
181

    
182
                return true;
183
        },
184

    
185
        _mouseDrag: function(event, noPropagation) {
186

    
187
                //Compute the helpers position
188
                this.position = this._generatePosition(event);
189
                this.positionAbs = this._convertPositionTo("absolute");
190

    
191
                //Call plugins and callbacks and use the resulting position if something is returned
192
                if (!noPropagation) {
193
                        var ui = this._uiHash();
194
                        if(this._trigger("drag", event, ui) === false) {
195
                                this._mouseUp({});
196
                                return false;
197
                        }
198
                        this.position = ui.position;
199
                }
200

    
201
                if(!this.options.axis || this.options.axis !== "y") {
202
                        this.helper[0].style.left = this.position.left+"px";
203
                }
204
                if(!this.options.axis || this.options.axis !== "x") {
205
                        this.helper[0].style.top = this.position.top+"px";
206
                }
207
                if($.ui.ddmanager) {
208
                        $.ui.ddmanager.drag(this, event);
209
                }
210

    
211
                return false;
212
        },
213

    
214
        _mouseStop: function(event) {
215

    
216
                //If we are using droppables, inform the manager about the drop
217
                var element,
218
                        that = this,
219
                        elementInDom = false,
220
                        dropped = false;
221
                if ($.ui.ddmanager && !this.options.dropBehaviour) {
222
                        dropped = $.ui.ddmanager.drop(this, event);
223
                }
224

    
225
                //if a drop comes from outside (a sortable)
226
                if(this.dropped) {
227
                        dropped = this.dropped;
228
                        this.dropped = false;
229
                }
230

    
231
                //if the original element is no longer in the DOM don't bother to continue (see #8269)
232
                element = this.element[0];
233
                while ( element && (element = element.parentNode) ) {
234
                        if (element === document ) {
235
                                elementInDom = true;
236
                        }
237
                }
238
                if ( !elementInDom && this.options.helper === "original" ) {
239
                        return false;
240
                }
241

    
242
                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))) {
243
                        $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
244
                                if(that._trigger("stop", event) !== false) {
245
                                        that._clear();
246
                                }
247
                        });
248
                } else {
249
                        if(this._trigger("stop", event) !== false) {
250
                                this._clear();
251
                        }
252
                }
253

    
254
                return false;
255
        },
256

    
257
        _mouseUp: function(event) {
258
                //Remove frame helpers
259
                $("div.ui-draggable-iframeFix").each(function() {
260
                        this.parentNode.removeChild(this);
261
                });
262

    
263
                //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
264
                if( $.ui.ddmanager ) {
265
                        $.ui.ddmanager.dragStop(this, event);
266
                }
267

    
268
                return $.ui.mouse.prototype._mouseUp.call(this, event);
269
        },
270

    
271
        cancel: function() {
272

    
273
                if(this.helper.is(".ui-draggable-dragging")) {
274
                        this._mouseUp({});
275
                } else {
276
                        this._clear();
277
                }
278

    
279
                return this;
280

    
281
        },
282

    
283
        _getHandle: function(event) {
284
                return this.options.handle ?
285
                        !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
286
                        true;
287
        },
288

    
289
        _createHelper: function(event) {
290

    
291
                var o = this.options,
292
                        helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
293

    
294
                if(!helper.parents("body").length) {
295
                        helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
296
                }
297

    
298
                if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
299
                        helper.css("position", "absolute");
300
                }
301

    
302
                return helper;
303

    
304
        },
305

    
306
        _adjustOffsetFromHelper: function(obj) {
307
                if (typeof obj === "string") {
308
                        obj = obj.split(" ");
309
                }
310
                if ($.isArray(obj)) {
311
                        obj = {left: +obj[0], top: +obj[1] || 0};
312
                }
313
                if ("left" in obj) {
314
                        this.offset.click.left = obj.left + this.margins.left;
315
                }
316
                if ("right" in obj) {
317
                        this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
318
                }
319
                if ("top" in obj) {
320
                        this.offset.click.top = obj.top + this.margins.top;
321
                }
322
                if ("bottom" in obj) {
323
                        this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
324
                }
325
        },
326

    
327
        _getParentOffset: function() {
328

    
329
                //Get the offsetParent and cache its position
330
                this.offsetParent = this.helper.offsetParent();
331
                var po = this.offsetParent.offset();
332

    
333
                // This is a special case where we need to modify a offset calculated on start, since the following happened:
334
                // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
335
                // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
336
                //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
337
                if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
338
                        po.left += this.scrollParent.scrollLeft();
339
                        po.top += this.scrollParent.scrollTop();
340
                }
341

    
342
                //This needs to be actually done for all browsers, since pageX/pageY includes this information
343
                //Ugly IE fix
344
                if((this.offsetParent[0] === document.body) ||
345
                        (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
346
                        po = { top: 0, left: 0 };
347
                }
348

    
349
                return {
350
                        top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
351
                        left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
352
                };
353

    
354
        },
355

    
356
        _getRelativeOffset: function() {
357

    
358
                if(this.cssPosition === "relative") {
359
                        var p = this.element.position();
360
                        return {
361
                                top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
362
                                left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
363
                        };
364
                } else {
365
                        return { top: 0, left: 0 };
366
                }
367

    
368
        },
369

    
370
        _cacheMargins: function() {
371
                this.margins = {
372
                        left: (parseInt(this.element.css("marginLeft"),10) || 0),
373
                        top: (parseInt(this.element.css("marginTop"),10) || 0),
374
                        right: (parseInt(this.element.css("marginRight"),10) || 0),
375
                        bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
376
                };
377
        },
378

    
379
        _cacheHelperProportions: function() {
380
                this.helperProportions = {
381
                        width: this.helper.outerWidth(),
382
                        height: this.helper.outerHeight()
383
                };
384
        },
385

    
386
        _setContainment: function() {
387

    
388
                var over, c, ce,
389
                        o = this.options;
390

    
391
                if(o.containment === "parent") {
392
                        o.containment = this.helper[0].parentNode;
393
                }
394
                if(o.containment === "document" || o.containment === "window") {
395
                        this.containment = [
396
                                o.containment === "document" ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
397
                                o.containment === "document" ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
398
                                (o.containment === "document" ? 0 : $(window).scrollLeft()) + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
399
                                (o.containment === "document" ? 0 : $(window).scrollTop()) + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
400
                        ];
401
                }
402

    
403
                if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor !== Array) {
404
                        c = $(o.containment);
405
                        ce = c[0];
406

    
407
                        if(!ce) {
408
                                return;
409
                        }
410

    
411
                        over = ($(ce).css("overflow") !== "hidden");
412

    
413
                        this.containment = [
414
                                (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
415
                                (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
416
                                (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderRightWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
417
                                (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderBottomWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
418
                        ];
419
                        this.relative_container = c;
420

    
421
                } else if(o.containment.constructor === Array) {
422
                        this.containment = o.containment;
423
                }
424

    
425
        },
426

    
427
        _convertPositionTo: function(d, pos) {
428

    
429
                if(!pos) {
430
                        pos = this.position;
431
                }
432

    
433
                var mod = d === "absolute" ? 1 : -1,
434
                        scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
435

    
436
                return {
437
                        top: (
438
                                pos.top        +                                                                                                                                // The absolute mouse position
439
                                this.offset.relative.top * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
440
                                this.offset.parent.top * mod -                                                                                // The offsetParent's offset without borders (offset + border)
441
                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
442
                        ),
443
                        left: (
444
                                pos.left +                                                                                                                                // The absolute mouse position
445
                                this.offset.relative.left * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
446
                                this.offset.parent.left * mod        -                                                                                // The offsetParent's offset without borders (offset + border)
447
                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
448
                        )
449
                };
450

    
451
        },
452

    
453
        _generatePosition: function(event) {
454

    
455
                var containment, co, top, left,
456
                        o = this.options,
457
                        scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
458
                        scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName),
459
                        pageX = event.pageX,
460
                        pageY = event.pageY;
461

    
462
                /*
463
                 * - Position constraining -
464
                 * Constrain the position to a mix of grid, containment.
465
                 */
466

    
467
                if(this.originalPosition) { //If we are not dragging yet, we won't check for options
468
                        if(this.containment) {
469
                        if (this.relative_container){
470
                                co = this.relative_container.offset();
471
                                containment = [ this.containment[0] + co.left,
472
                                        this.containment[1] + co.top,
473
                                        this.containment[2] + co.left,
474
                                        this.containment[3] + co.top ];
475
                        }
476
                        else {
477
                                containment = this.containment;
478
                        }
479

    
480
                                if(event.pageX - this.offset.click.left < containment[0]) {
481
                                        pageX = containment[0] + this.offset.click.left;
482
                                }
483
                                if(event.pageY - this.offset.click.top < containment[1]) {
484
                                        pageY = containment[1] + this.offset.click.top;
485
                                }
486
                                if(event.pageX - this.offset.click.left > containment[2]) {
487
                                        pageX = containment[2] + this.offset.click.left;
488
                                }
489
                                if(event.pageY - this.offset.click.top > containment[3]) {
490
                                        pageY = containment[3] + this.offset.click.top;
491
                                }
492
                        }
493

    
494
                        if(o.grid) {
495
                                //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
496
                                top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
497
                                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;
498

    
499
                                left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
500
                                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;
501
                        }
502

    
503
                }
504

    
505
                return {
506
                        top: (
507
                                pageY -                                                                                                                                        // The absolute mouse position
508
                                this.offset.click.top        -                                                                                                // Click offset (relative to the element)
509
                                this.offset.relative.top -                                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
510
                                this.offset.parent.top +                                                                                                // The offsetParent's offset without borders (offset + border)
511
                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
512
                        ),
513
                        left: (
514
                                pageX -                                                                                                                                        // The absolute mouse position
515
                                this.offset.click.left -                                                                                                // Click offset (relative to the element)
516
                                this.offset.relative.left -                                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
517
                                this.offset.parent.left +                                                                                                // The offsetParent's offset without borders (offset + border)
518
                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
519
                        )
520
                };
521

    
522
        },
523

    
524
        _clear: function() {
525
                this.helper.removeClass("ui-draggable-dragging");
526
                if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
527
                        this.helper.remove();
528
                }
529
                this.helper = null;
530
                this.cancelHelperRemoval = false;
531
        },
532

    
533
        // From now on bulk stuff - mainly helpers
534

    
535
        _trigger: function(type, event, ui) {
536
                ui = ui || this._uiHash();
537
                $.ui.plugin.call(this, type, [event, ui]);
538
                //The absolute position has to be recalculated after plugins
539
                if(type === "drag") {
540
                        this.positionAbs = this._convertPositionTo("absolute");
541
                }
542
                return $.Widget.prototype._trigger.call(this, type, event, ui);
543
        },
544

    
545
        plugins: {},
546

    
547
        _uiHash: function() {
548
                return {
549
                        helper: this.helper,
550
                        position: this.position,
551
                        originalPosition: this.originalPosition,
552
                        offset: this.positionAbs
553
                };
554
        }
555

    
556
});
557

    
558
$.ui.plugin.add("draggable", "connectToSortable", {
559
        start: function(event, ui) {
560

    
561
                var inst = $(this).data("ui-draggable"), o = inst.options,
562
                        uiSortable = $.extend({}, ui, { item: inst.element });
563
                inst.sortables = [];
564
                $(o.connectToSortable).each(function() {
565
                        var sortable = $.data(this, "ui-sortable");
566
                        if (sortable && !sortable.options.disabled) {
567
                                inst.sortables.push({
568
                                        instance: sortable,
569
                                        shouldRevert: sortable.options.revert
570
                                });
571
                                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).
572
                                sortable._trigger("activate", event, uiSortable);
573
                        }
574
                });
575

    
576
        },
577
        stop: function(event, ui) {
578

    
579
                //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
580
                var inst = $(this).data("ui-draggable"),
581
                        uiSortable = $.extend({}, ui, { item: inst.element });
582

    
583
                $.each(inst.sortables, function() {
584
                        if(this.instance.isOver) {
585

    
586
                                this.instance.isOver = 0;
587

    
588
                                inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
589
                                this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
590

    
591
                                //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
592
                                if(this.shouldRevert) {
593
                                        this.instance.options.revert = this.shouldRevert;
594
                                }
595

    
596
                                //Trigger the stop of the sortable
597
                                this.instance._mouseStop(event);
598

    
599
                                this.instance.options.helper = this.instance.options._helper;
600

    
601
                                //If the helper has been the original item, restore properties in the sortable
602
                                if(inst.options.helper === "original") {
603
                                        this.instance.currentItem.css({ top: "auto", left: "auto" });
604
                                }
605

    
606
                        } else {
607
                                this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
608
                                this.instance._trigger("deactivate", event, uiSortable);
609
                        }
610

    
611
                });
612

    
613
        },
614
        drag: function(event, ui) {
615

    
616
                var inst = $(this).data("ui-draggable"), that = this;
617

    
618
                $.each(inst.sortables, function() {
619

    
620
                        var innermostIntersecting = false,
621
                                thisSortable = this;
622

    
623
                        //Copy over some variables to allow calling the sortable's native _intersectsWith
624
                        this.instance.positionAbs = inst.positionAbs;
625
                        this.instance.helperProportions = inst.helperProportions;
626
                        this.instance.offset.click = inst.offset.click;
627

    
628
                        if(this.instance._intersectsWith(this.instance.containerCache)) {
629
                                innermostIntersecting = true;
630
                                $.each(inst.sortables, function () {
631
                                        this.instance.positionAbs = inst.positionAbs;
632
                                        this.instance.helperProportions = inst.helperProportions;
633
                                        this.instance.offset.click = inst.offset.click;
634
                                        if (this !== thisSortable &&
635
                                                this.instance._intersectsWith(this.instance.containerCache) &&
636
                                                $.contains(thisSortable.instance.element[0], this.instance.element[0])
637
                                        ) {
638
                                                innermostIntersecting = false;
639
                                        }
640
                                        return innermostIntersecting;
641
                                });
642
                        }
643

    
644

    
645
                        if(innermostIntersecting) {
646
                                //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
647
                                if(!this.instance.isOver) {
648

    
649
                                        this.instance.isOver = 1;
650
                                        //Now we fake the start of dragging for the sortable instance,
651
                                        //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
652
                                        //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)
653
                                        this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
654
                                        this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
655
                                        this.instance.options.helper = function() { return ui.helper[0]; };
656

    
657
                                        event.target = this.instance.currentItem[0];
658
                                        this.instance._mouseCapture(event, true);
659
                                        this.instance._mouseStart(event, true, true);
660

    
661
                                        //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
662
                                        this.instance.offset.click.top = inst.offset.click.top;
663
                                        this.instance.offset.click.left = inst.offset.click.left;
664
                                        this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
665
                                        this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
666

    
667
                                        inst._trigger("toSortable", event);
668
                                        inst.dropped = this.instance.element; //draggable revert needs that
669
                                        //hack so receive/update callbacks work (mostly)
670
                                        inst.currentItem = inst.element;
671
                                        this.instance.fromOutside = inst;
672

    
673
                                }
674

    
675
                                //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
676
                                if(this.instance.currentItem) {
677
                                        this.instance._mouseDrag(event);
678
                                }
679

    
680
                        } else {
681

    
682
                                //If it doesn't intersect with the sortable, and it intersected before,
683
                                //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
684
                                if(this.instance.isOver) {
685

    
686
                                        this.instance.isOver = 0;
687
                                        this.instance.cancelHelperRemoval = true;
688

    
689
                                        //Prevent reverting on this forced stop
690
                                        this.instance.options.revert = false;
691

    
692
                                        // The out event needs to be triggered independently
693
                                        this.instance._trigger("out", event, this.instance._uiHash(this.instance));
694

    
695
                                        this.instance._mouseStop(event, true);
696
                                        this.instance.options.helper = this.instance.options._helper;
697

    
698
                                        //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
699
                                        this.instance.currentItem.remove();
700
                                        if(this.instance.placeholder) {
701
                                                this.instance.placeholder.remove();
702
                                        }
703

    
704
                                        inst._trigger("fromSortable", event);
705
                                        inst.dropped = false; //draggable revert needs that
706
                                }
707

    
708
                        }
709

    
710
                });
711

    
712
        }
713
});
714

    
715
$.ui.plugin.add("draggable", "cursor", {
716
        start: function() {
717
                var t = $("body"), o = $(this).data("ui-draggable").options;
718
                if (t.css("cursor")) {
719
                        o._cursor = t.css("cursor");
720
                }
721
                t.css("cursor", o.cursor);
722
        },
723
        stop: function() {
724
                var o = $(this).data("ui-draggable").options;
725
                if (o._cursor) {
726
                        $("body").css("cursor", o._cursor);
727
                }
728
        }
729
});
730

    
731
$.ui.plugin.add("draggable", "opacity", {
732
        start: function(event, ui) {
733
                var t = $(ui.helper), o = $(this).data("ui-draggable").options;
734
                if(t.css("opacity")) {
735
                        o._opacity = t.css("opacity");
736
                }
737
                t.css("opacity", o.opacity);
738
        },
739
        stop: function(event, ui) {
740
                var o = $(this).data("ui-draggable").options;
741
                if(o._opacity) {
742
                        $(ui.helper).css("opacity", o._opacity);
743
                }
744
        }
745
});
746

    
747
$.ui.plugin.add("draggable", "scroll", {
748
        start: function() {
749
                var i = $(this).data("ui-draggable");
750
                if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
751
                        i.overflowOffset = i.scrollParent.offset();
752
                }
753
        },
754
        drag: function( event ) {
755

    
756
                var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
757

    
758
                if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
759

    
760
                        if(!o.axis || o.axis !== "x") {
761
                                if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
762
                                        i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
763
                                } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
764
                                        i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
765
                                }
766
                        }
767

    
768
                        if(!o.axis || o.axis !== "y") {
769
                                if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
770
                                        i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
771
                                } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
772
                                        i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
773
                                }
774
                        }
775

    
776
                } else {
777

    
778
                        if(!o.axis || o.axis !== "x") {
779
                                if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
780
                                        scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
781
                                } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
782
                                        scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
783
                                }
784
                        }
785

    
786
                        if(!o.axis || o.axis !== "y") {
787
                                if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
788
                                        scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
789
                                } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
790
                                        scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
791
                                }
792
                        }
793

    
794
                }
795

    
796
                if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
797
                        $.ui.ddmanager.prepareOffsets(i, event);
798
                }
799

    
800
        }
801
});
802

    
803
$.ui.plugin.add("draggable", "snap", {
804
        start: function() {
805

    
806
                var i = $(this).data("ui-draggable"),
807
                        o = i.options;
808

    
809
                i.snapElements = [];
810

    
811
                $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
812
                        var $t = $(this),
813
                                $o = $t.offset();
814
                        if(this !== i.element[0]) {
815
                                i.snapElements.push({
816
                                        item: this,
817
                                        width: $t.outerWidth(), height: $t.outerHeight(),
818
                                        top: $o.top, left: $o.left
819
                                });
820
                        }
821
                });
822

    
823
        },
824
        drag: function(event, ui) {
825

    
826
                var ts, bs, ls, rs, l, r, t, b, i, first,
827
                        inst = $(this).data("ui-draggable"),
828
                        o = inst.options,
829
                        d = o.snapTolerance,
830
                        x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
831
                        y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
832

    
833
                for (i = inst.snapElements.length - 1; i >= 0; i--){
834

    
835
                        l = inst.snapElements[i].left;
836
                        r = l + inst.snapElements[i].width;
837
                        t = inst.snapElements[i].top;
838
                        b = t + inst.snapElements[i].height;
839

    
840
                        //Yes, I know, this is insane ;)
841
                        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))) {
842
                                if(inst.snapElements[i].snapping) {
843
                                        (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
844
                                }
845
                                inst.snapElements[i].snapping = false;
846
                                continue;
847
                        }
848

    
849
                        if(o.snapMode !== "inner") {
850
                                ts = Math.abs(t - y2) <= d;
851
                                bs = Math.abs(b - y1) <= d;
852
                                ls = Math.abs(l - x2) <= d;
853
                                rs = Math.abs(r - x1) <= d;
854
                                if(ts) {
855
                                        ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
856
                                }
857
                                if(bs) {
858
                                        ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
859
                                }
860
                                if(ls) {
861
                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
862
                                }
863
                                if(rs) {
864
                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
865
                                }
866
                        }
867

    
868
                        first = (ts || bs || ls || rs);
869

    
870
                        if(o.snapMode !== "outer") {
871
                                ts = Math.abs(t - y1) <= d;
872
                                bs = Math.abs(b - y2) <= d;
873
                                ls = Math.abs(l - x1) <= d;
874
                                rs = Math.abs(r - x2) <= d;
875
                                if(ts) {
876
                                        ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
877
                                }
878
                                if(bs) {
879
                                        ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
880
                                }
881
                                if(ls) {
882
                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
883
                                }
884
                                if(rs) {
885
                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
886
                                }
887
                        }
888

    
889
                        if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
890
                                (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
891
                        }
892
                        inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
893

    
894
                }
895

    
896
        }
897
});
898

    
899
$.ui.plugin.add("draggable", "stack", {
900
        start: function() {
901
                var min,
902
                        o = this.data("ui-draggable").options,
903
                        group = $.makeArray($(o.stack)).sort(function(a,b) {
904
                                return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
905
                        });
906

    
907
                if (!group.length) { return; }
908

    
909
                min = parseInt($(group[0]).css("zIndex"), 10) || 0;
910
                $(group).each(function(i) {
911
                        $(this).css("zIndex", min + i);
912
                });
913
                this.css("zIndex", (min + group.length));
914
        }
915
});
916

    
917
$.ui.plugin.add("draggable", "zIndex", {
918
        start: function(event, ui) {
919
                var t = $(ui.helper), o = $(this).data("ui-draggable").options;
920
                if(t.css("zIndex")) {
921
                        o._zIndex = t.css("zIndex");
922
                }
923
                t.css("zIndex", o.zIndex);
924
        },
925
        stop: function(event, ui) {
926
                var o = $(this).data("ui-draggable").options;
927
                if(o._zIndex) {
928
                        $(ui.helper).css("zIndex", o._zIndex);
929
                }
930
        }
931
});
932

    
933
})(jQuery);