source: trunk/themes/default/js/ui/jquery.ui.draggable.js @ 20824

Last change on this file since 20824 was 20824, checked in by rvelices, 11 years ago

upgraded jquery ui from 1.9.0 to 1.10.1

File size: 30.5 KB
Line 
1/*!
2 * jQuery UI Draggable 1.10.1
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.1",
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
285                var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
286                $(this.options.handle, this.element)
287                        .find("*")
288                        .addBack()
289                        .each(function() {
290                                if(this === event.target) {
291                                        handle = true;
292                                }
293                        });
294
295                return handle;
296
297        },
298
299        _createHelper: function(event) {
300
301                var o = this.options,
302                        helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
303
304                if(!helper.parents("body").length) {
305                        helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
306                }
307
308                if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
309                        helper.css("position", "absolute");
310                }
311
312                return helper;
313
314        },
315
316        _adjustOffsetFromHelper: function(obj) {
317                if (typeof obj === "string") {
318                        obj = obj.split(" ");
319                }
320                if ($.isArray(obj)) {
321                        obj = {left: +obj[0], top: +obj[1] || 0};
322                }
323                if ("left" in obj) {
324                        this.offset.click.left = obj.left + this.margins.left;
325                }
326                if ("right" in obj) {
327                        this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
328                }
329                if ("top" in obj) {
330                        this.offset.click.top = obj.top + this.margins.top;
331                }
332                if ("bottom" in obj) {
333                        this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
334                }
335        },
336
337        _getParentOffset: function() {
338
339                //Get the offsetParent and cache its position
340                this.offsetParent = this.helper.offsetParent();
341                var po = this.offsetParent.offset();
342
343                // This is a special case where we need to modify a offset calculated on start, since the following happened:
344                // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
345                // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
346                //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
347                if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
348                        po.left += this.scrollParent.scrollLeft();
349                        po.top += this.scrollParent.scrollTop();
350                }
351
352                //This needs to be actually done for all browsers, since pageX/pageY includes this information
353                //Ugly IE fix
354                if((this.offsetParent[0] === document.body) ||
355                        (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
356                        po = { top: 0, left: 0 };
357                }
358
359                return {
360                        top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
361                        left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
362                };
363
364        },
365
366        _getRelativeOffset: function() {
367
368                if(this.cssPosition === "relative") {
369                        var p = this.element.position();
370                        return {
371                                top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
372                                left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
373                        };
374                } else {
375                        return { top: 0, left: 0 };
376                }
377
378        },
379
380        _cacheMargins: function() {
381                this.margins = {
382                        left: (parseInt(this.element.css("marginLeft"),10) || 0),
383                        top: (parseInt(this.element.css("marginTop"),10) || 0),
384                        right: (parseInt(this.element.css("marginRight"),10) || 0),
385                        bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
386                };
387        },
388
389        _cacheHelperProportions: function() {
390                this.helperProportions = {
391                        width: this.helper.outerWidth(),
392                        height: this.helper.outerHeight()
393                };
394        },
395
396        _setContainment: function() {
397
398                var over, c, ce,
399                        o = this.options;
400
401                if(o.containment === "parent") {
402                        o.containment = this.helper[0].parentNode;
403                }
404                if(o.containment === "document" || o.containment === "window") {
405                        this.containment = [
406                                o.containment === "document" ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
407                                o.containment === "document" ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
408                                (o.containment === "document" ? 0 : $(window).scrollLeft()) + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
409                                (o.containment === "document" ? 0 : $(window).scrollTop()) + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
410                        ];
411                }
412
413                if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor !== Array) {
414                        c = $(o.containment);
415                        ce = c[0];
416
417                        if(!ce) {
418                                return;
419                        }
420
421                        over = ($(ce).css("overflow") !== "hidden");
422
423                        this.containment = [
424                                (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
425                                (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
426                                (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,
427                                (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
428                        ];
429                        this.relative_container = c;
430
431                } else if(o.containment.constructor === Array) {
432                        this.containment = o.containment;
433                }
434
435        },
436
437        _convertPositionTo: function(d, pos) {
438
439                if(!pos) {
440                        pos = this.position;
441                }
442
443                var mod = d === "absolute" ? 1 : -1,
444                        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);
445
446                return {
447                        top: (
448                                pos.top +                                                                                                                               // The absolute mouse position
449                                this.offset.relative.top * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
450                                this.offset.parent.top * mod -                                                                          // The offsetParent's offset without borders (offset + border)
451                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
452                        ),
453                        left: (
454                                pos.left +                                                                                                                              // The absolute mouse position
455                                this.offset.relative.left * mod +                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
456                                this.offset.parent.left * mod   -                                                                               // The offsetParent's offset without borders (offset + border)
457                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
458                        )
459                };
460
461        },
462
463        _generatePosition: function(event) {
464
465                var containment, co, top, left,
466                        o = this.options,
467                        scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
468                        scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName),
469                        pageX = event.pageX,
470                        pageY = event.pageY;
471
472                /*
473                 * - Position constraining -
474                 * Constrain the position to a mix of grid, containment.
475                 */
476
477                if(this.originalPosition) { //If we are not dragging yet, we won't check for options
478                        if(this.containment) {
479                        if (this.relative_container){
480                                co = this.relative_container.offset();
481                                containment = [ this.containment[0] + co.left,
482                                        this.containment[1] + co.top,
483                                        this.containment[2] + co.left,
484                                        this.containment[3] + co.top ];
485                        }
486                        else {
487                                containment = this.containment;
488                        }
489
490                                if(event.pageX - this.offset.click.left < containment[0]) {
491                                        pageX = containment[0] + this.offset.click.left;
492                                }
493                                if(event.pageY - this.offset.click.top < containment[1]) {
494                                        pageY = containment[1] + this.offset.click.top;
495                                }
496                                if(event.pageX - this.offset.click.left > containment[2]) {
497                                        pageX = containment[2] + this.offset.click.left;
498                                }
499                                if(event.pageY - this.offset.click.top > containment[3]) {
500                                        pageY = containment[3] + this.offset.click.top;
501                                }
502                        }
503
504                        if(o.grid) {
505                                //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
506                                top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
507                                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;
508
509                                left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
510                                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;
511                        }
512
513                }
514
515                return {
516                        top: (
517                                pageY -                                                                                                                                 // The absolute mouse position
518                                this.offset.click.top   -                                                                                               // Click offset (relative to the element)
519                                this.offset.relative.top -                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
520                                this.offset.parent.top +                                                                                                // The offsetParent's offset without borders (offset + border)
521                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
522                        ),
523                        left: (
524                                pageX -                                                                                                                                 // The absolute mouse position
525                                this.offset.click.left -                                                                                                // Click offset (relative to the element)
526                                this.offset.relative.left -                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
527                                this.offset.parent.left +                                                                                               // The offsetParent's offset without borders (offset + border)
528                                ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
529                        )
530                };
531
532        },
533
534        _clear: function() {
535                this.helper.removeClass("ui-draggable-dragging");
536                if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
537                        this.helper.remove();
538                }
539                this.helper = null;
540                this.cancelHelperRemoval = false;
541        },
542
543        // From now on bulk stuff - mainly helpers
544
545        _trigger: function(type, event, ui) {
546                ui = ui || this._uiHash();
547                $.ui.plugin.call(this, type, [event, ui]);
548                //The absolute position has to be recalculated after plugins
549                if(type === "drag") {
550                        this.positionAbs = this._convertPositionTo("absolute");
551                }
552                return $.Widget.prototype._trigger.call(this, type, event, ui);
553        },
554
555        plugins: {},
556
557        _uiHash: function() {
558                return {
559                        helper: this.helper,
560                        position: this.position,
561                        originalPosition: this.originalPosition,
562                        offset: this.positionAbs
563                };
564        }
565
566});
567
568$.ui.plugin.add("draggable", "connectToSortable", {
569        start: function(event, ui) {
570
571                var inst = $(this).data("ui-draggable"), o = inst.options,
572                        uiSortable = $.extend({}, ui, { item: inst.element });
573                inst.sortables = [];
574                $(o.connectToSortable).each(function() {
575                        var sortable = $.data(this, "ui-sortable");
576                        if (sortable && !sortable.options.disabled) {
577                                inst.sortables.push({
578                                        instance: sortable,
579                                        shouldRevert: sortable.options.revert
580                                });
581                                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).
582                                sortable._trigger("activate", event, uiSortable);
583                        }
584                });
585
586        },
587        stop: function(event, ui) {
588
589                //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
590                var inst = $(this).data("ui-draggable"),
591                        uiSortable = $.extend({}, ui, { item: inst.element });
592
593                $.each(inst.sortables, function() {
594                        if(this.instance.isOver) {
595
596                                this.instance.isOver = 0;
597
598                                inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
599                                this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
600
601                                //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
602                                if(this.shouldRevert) {
603                                        this.instance.options.revert = true;
604                                }
605
606                                //Trigger the stop of the sortable
607                                this.instance._mouseStop(event);
608
609                                this.instance.options.helper = this.instance.options._helper;
610
611                                //If the helper has been the original item, restore properties in the sortable
612                                if(inst.options.helper === "original") {
613                                        this.instance.currentItem.css({ top: "auto", left: "auto" });
614                                }
615
616                        } else {
617                                this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
618                                this.instance._trigger("deactivate", event, uiSortable);
619                        }
620
621                });
622
623        },
624        drag: function(event, ui) {
625
626                var inst = $(this).data("ui-draggable"), that = this;
627
628                $.each(inst.sortables, function() {
629
630                        var innermostIntersecting = false,
631                                thisSortable = this;
632
633                        //Copy over some variables to allow calling the sortable's native _intersectsWith
634                        this.instance.positionAbs = inst.positionAbs;
635                        this.instance.helperProportions = inst.helperProportions;
636                        this.instance.offset.click = inst.offset.click;
637
638                        if(this.instance._intersectsWith(this.instance.containerCache)) {
639                                innermostIntersecting = true;
640                                $.each(inst.sortables, function () {
641                                        this.instance.positionAbs = inst.positionAbs;
642                                        this.instance.helperProportions = inst.helperProportions;
643                                        this.instance.offset.click = inst.offset.click;
644                                        if (this !== thisSortable &&
645                                                this.instance._intersectsWith(this.instance.containerCache) &&
646                                                $.contains(thisSortable.instance.element[0], this.instance.element[0])
647                                        ) {
648                                                innermostIntersecting = false;
649                                        }
650                                        return innermostIntersecting;
651                                });
652                        }
653
654
655                        if(innermostIntersecting) {
656                                //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
657                                if(!this.instance.isOver) {
658
659                                        this.instance.isOver = 1;
660                                        //Now we fake the start of dragging for the sortable instance,
661                                        //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
662                                        //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)
663                                        this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
664                                        this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
665                                        this.instance.options.helper = function() { return ui.helper[0]; };
666
667                                        event.target = this.instance.currentItem[0];
668                                        this.instance._mouseCapture(event, true);
669                                        this.instance._mouseStart(event, true, true);
670
671                                        //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
672                                        this.instance.offset.click.top = inst.offset.click.top;
673                                        this.instance.offset.click.left = inst.offset.click.left;
674                                        this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
675                                        this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
676
677                                        inst._trigger("toSortable", event);
678                                        inst.dropped = this.instance.element; //draggable revert needs that
679                                        //hack so receive/update callbacks work (mostly)
680                                        inst.currentItem = inst.element;
681                                        this.instance.fromOutside = inst;
682
683                                }
684
685                                //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
686                                if(this.instance.currentItem) {
687                                        this.instance._mouseDrag(event);
688                                }
689
690                        } else {
691
692                                //If it doesn't intersect with the sortable, and it intersected before,
693                                //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
694                                if(this.instance.isOver) {
695
696                                        this.instance.isOver = 0;
697                                        this.instance.cancelHelperRemoval = true;
698
699                                        //Prevent reverting on this forced stop
700                                        this.instance.options.revert = false;
701
702                                        // The out event needs to be triggered independently
703                                        this.instance._trigger("out", event, this.instance._uiHash(this.instance));
704
705                                        this.instance._mouseStop(event, true);
706                                        this.instance.options.helper = this.instance.options._helper;
707
708                                        //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
709                                        this.instance.currentItem.remove();
710                                        if(this.instance.placeholder) {
711                                                this.instance.placeholder.remove();
712                                        }
713
714                                        inst._trigger("fromSortable", event);
715                                        inst.dropped = false; //draggable revert needs that
716                                }
717
718                        }
719
720                });
721
722        }
723});
724
725$.ui.plugin.add("draggable", "cursor", {
726        start: function() {
727                var t = $("body"), o = $(this).data("ui-draggable").options;
728                if (t.css("cursor")) {
729                        o._cursor = t.css("cursor");
730                }
731                t.css("cursor", o.cursor);
732        },
733        stop: function() {
734                var o = $(this).data("ui-draggable").options;
735                if (o._cursor) {
736                        $("body").css("cursor", o._cursor);
737                }
738        }
739});
740
741$.ui.plugin.add("draggable", "opacity", {
742        start: function(event, ui) {
743                var t = $(ui.helper), o = $(this).data("ui-draggable").options;
744                if(t.css("opacity")) {
745                        o._opacity = t.css("opacity");
746                }
747                t.css("opacity", o.opacity);
748        },
749        stop: function(event, ui) {
750                var o = $(this).data("ui-draggable").options;
751                if(o._opacity) {
752                        $(ui.helper).css("opacity", o._opacity);
753                }
754        }
755});
756
757$.ui.plugin.add("draggable", "scroll", {
758        start: function() {
759                var i = $(this).data("ui-draggable");
760                if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
761                        i.overflowOffset = i.scrollParent.offset();
762                }
763        },
764        drag: function( event ) {
765
766                var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
767
768                if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
769
770                        if(!o.axis || o.axis !== "x") {
771                                if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
772                                        i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
773                                } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
774                                        i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
775                                }
776                        }
777
778                        if(!o.axis || o.axis !== "y") {
779                                if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
780                                        i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
781                                } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
782                                        i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
783                                }
784                        }
785
786                } else {
787
788                        if(!o.axis || o.axis !== "x") {
789                                if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
790                                        scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
791                                } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
792                                        scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
793                                }
794                        }
795
796                        if(!o.axis || o.axis !== "y") {
797                                if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
798                                        scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
799                                } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
800                                        scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
801                                }
802                        }
803
804                }
805
806                if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
807                        $.ui.ddmanager.prepareOffsets(i, event);
808                }
809
810        }
811});
812
813$.ui.plugin.add("draggable", "snap", {
814        start: function() {
815
816                var i = $(this).data("ui-draggable"),
817                        o = i.options;
818
819                i.snapElements = [];
820
821                $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
822                        var $t = $(this),
823                                $o = $t.offset();
824                        if(this !== i.element[0]) {
825                                i.snapElements.push({
826                                        item: this,
827                                        width: $t.outerWidth(), height: $t.outerHeight(),
828                                        top: $o.top, left: $o.left
829                                });
830                        }
831                });
832
833        },
834        drag: function(event, ui) {
835
836                var ts, bs, ls, rs, l, r, t, b, i, first,
837                        inst = $(this).data("ui-draggable"),
838                        o = inst.options,
839                        d = o.snapTolerance,
840                        x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
841                        y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
842
843                for (i = inst.snapElements.length - 1; i >= 0; i--){
844
845                        l = inst.snapElements[i].left;
846                        r = l + inst.snapElements[i].width;
847                        t = inst.snapElements[i].top;
848                        b = t + inst.snapElements[i].height;
849
850                        //Yes, I know, this is insane ;)
851                        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))) {
852                                if(inst.snapElements[i].snapping) {
853                                        (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
854                                }
855                                inst.snapElements[i].snapping = false;
856                                continue;
857                        }
858
859                        if(o.snapMode !== "inner") {
860                                ts = Math.abs(t - y2) <= d;
861                                bs = Math.abs(b - y1) <= d;
862                                ls = Math.abs(l - x2) <= d;
863                                rs = Math.abs(r - x1) <= d;
864                                if(ts) {
865                                        ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
866                                }
867                                if(bs) {
868                                        ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
869                                }
870                                if(ls) {
871                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
872                                }
873                                if(rs) {
874                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
875                                }
876                        }
877
878                        first = (ts || bs || ls || rs);
879
880                        if(o.snapMode !== "outer") {
881                                ts = Math.abs(t - y1) <= d;
882                                bs = Math.abs(b - y2) <= d;
883                                ls = Math.abs(l - x1) <= d;
884                                rs = Math.abs(r - x2) <= d;
885                                if(ts) {
886                                        ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
887                                }
888                                if(bs) {
889                                        ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
890                                }
891                                if(ls) {
892                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
893                                }
894                                if(rs) {
895                                        ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
896                                }
897                        }
898
899                        if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
900                                (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
901                        }
902                        inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
903
904                }
905
906        }
907});
908
909$.ui.plugin.add("draggable", "stack", {
910        start: function() {
911                var min,
912                        o = this.data("ui-draggable").options,
913                        group = $.makeArray($(o.stack)).sort(function(a,b) {
914                                return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
915                        });
916
917                if (!group.length) { return; }
918
919                min = parseInt($(group[0]).css("zIndex"), 10) || 0;
920                $(group).each(function(i) {
921                        $(this).css("zIndex", min + i);
922                });
923                this.css("zIndex", (min + group.length));
924        }
925});
926
927$.ui.plugin.add("draggable", "zIndex", {
928        start: function(event, ui) {
929                var t = $(ui.helper), o = $(this).data("ui-draggable").options;
930                if(t.css("zIndex")) {
931                        o._zIndex = t.css("zIndex");
932                }
933                t.css("zIndex", o.zIndex);
934        },
935        stop: function(event, ui) {
936                var o = $(this).data("ui-draggable").options;
937                if(o._zIndex) {
938                        $(ui.helper).css("zIndex", o._zIndex);
939                }
940        }
941});
942
943})(jQuery);
Note: See TracBrowser for help on using the repository browser.