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

Last change on this file since 9559 was 9559, checked in by patdenice, 14 years ago

Update jQuery UI to 1.8.10.
Improve jquery ui management in template class.

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