source: Dev/branches/jQueryUI/client/js/jquery/ui/jquery.ui.droppable.js @ 249

Last change on this file since 249 was 249, checked in by hendrikvanantwerpen, 13 years ago

This one's for Subversion, because it's so close...

First widget (stripped down sequencer).
Seperated client and server code in two direcotry trees.

File size: 9.9 KB
Line 
1/*
2 * jQuery UI Droppable 1.8.17
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/Droppables
9 *
10 * Depends:
11 *      jquery.ui.core.js
12 *      jquery.ui.widget.js
13 *      jquery.ui.mouse.js
14 *      jquery.ui.draggable.js
15 */
16(function( $, undefined ) {
17
18$.widget("ui.droppable", {
19        widgetEventPrefix: "drop",
20        options: {
21                accept: '*',
22                activeClass: false,
23                addClasses: true,
24                greedy: false,
25                hoverClass: false,
26                scope: 'default',
27                tolerance: 'intersect'
28        },
29        _create: function() {
30
31                var o = this.options, accept = o.accept;
32                this.isover = 0; this.isout = 1;
33
34                this.accept = $.isFunction(accept) ? accept : function(d) {
35                        return d.is(accept);
36                };
37
38                //Store the droppable's proportions
39                this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
40
41                // Add the reference and positions to the manager
42                $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
43                $.ui.ddmanager.droppables[o.scope].push(this);
44
45                (o.addClasses && this.element.addClass("ui-droppable"));
46
47        },
48
49        destroy: function() {
50                var drop = $.ui.ddmanager.droppables[this.options.scope];
51                for ( var i = 0; i < drop.length; i++ )
52                        if ( drop[i] == this )
53                                drop.splice(i, 1);
54
55                this.element
56                        .removeClass("ui-droppable ui-droppable-disabled")
57                        .removeData("droppable")
58                        .unbind(".droppable");
59
60                return this;
61        },
62
63        _setOption: function(key, value) {
64
65                if(key == 'accept') {
66                        this.accept = $.isFunction(value) ? value : function(d) {
67                                return d.is(value);
68                        };
69                }
70                $.Widget.prototype._setOption.apply(this, arguments);
71        },
72
73        _activate: function(event) {
74                var draggable = $.ui.ddmanager.current;
75                if(this.options.activeClass) this.element.addClass(this.options.activeClass);
76                (draggable && this._trigger('activate', event, this.ui(draggable)));
77        },
78
79        _deactivate: function(event) {
80                var draggable = $.ui.ddmanager.current;
81                if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
82                (draggable && this._trigger('deactivate', event, this.ui(draggable)));
83        },
84
85        _over: function(event) {
86
87                var draggable = $.ui.ddmanager.current;
88                if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
89
90                if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
91                        if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
92                        this._trigger('over', event, this.ui(draggable));
93                }
94
95        },
96
97        _out: function(event) {
98
99                var draggable = $.ui.ddmanager.current;
100                if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
101
102                if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
103                        if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
104                        this._trigger('out', event, this.ui(draggable));
105                }
106
107        },
108
109        _drop: function(event,custom) {
110
111                var draggable = custom || $.ui.ddmanager.current;
112                if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
113
114                var childrenIntersection = false;
115                this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
116                        var inst = $.data(this, 'droppable');
117                        if(
118                                inst.options.greedy
119                                && !inst.options.disabled
120                                && inst.options.scope == draggable.options.scope
121                                && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
122                                && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
123                        ) { childrenIntersection = true; return false; }
124                });
125                if(childrenIntersection) return false;
126
127                if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
128                        if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
129                        if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
130                        this._trigger('drop', event, this.ui(draggable));
131                        return this.element;
132                }
133
134                return false;
135
136        },
137
138        ui: function(c) {
139                return {
140                        draggable: (c.currentItem || c.element),
141                        helper: c.helper,
142                        position: c.position,
143                        offset: c.positionAbs
144                };
145        }
146
147});
148
149$.extend($.ui.droppable, {
150        version: "1.8.17"
151});
152
153$.ui.intersect = function(draggable, droppable, toleranceMode) {
154
155        if (!droppable.offset) return false;
156
157        var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
158                y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
159        var l = droppable.offset.left, r = l + droppable.proportions.width,
160                t = droppable.offset.top, b = t + droppable.proportions.height;
161
162        switch (toleranceMode) {
163                case 'fit':
164                        return (l <= x1 && x2 <= r
165                                && t <= y1 && y2 <= b);
166                        break;
167                case 'intersect':
168                        return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
169                                && x2 - (draggable.helperProportions.width / 2) < r // Left Half
170                                && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
171                                && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
172                        break;
173                case 'pointer':
174                        var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
175                                draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
176                                isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
177                        return isOver;
178                        break;
179                case 'touch':
180                        return (
181                                        (y1 >= t && y1 <= b) || // Top edge touching
182                                        (y2 >= t && y2 <= b) || // Bottom edge touching
183                                        (y1 < t && y2 > b)              // Surrounded vertically
184                                ) && (
185                                        (x1 >= l && x1 <= r) || // Left edge touching
186                                        (x2 >= l && x2 <= r) || // Right edge touching
187                                        (x1 < l && x2 > r)              // Surrounded horizontally
188                                );
189                        break;
190                default:
191                        return false;
192                        break;
193                }
194
195};
196
197/*
198        This manager tracks offsets of draggables and droppables
199*/
200$.ui.ddmanager = {
201        current: null,
202        droppables: { 'default': [] },
203        prepareOffsets: function(t, event) {
204
205                var m = $.ui.ddmanager.droppables[t.options.scope] || [];
206                var type = event ? event.type : null; // workaround for #2317
207                var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
208
209                droppablesLoop: for (var i = 0; i < m.length; i++) {
210
211                        if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
212                        for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
213                        m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
214
215                        if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
216
217                        m[i].offset = m[i].element.offset();
218                        m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
219
220                }
221
222        },
223        drop: function(draggable, event) {
224
225                var dropped = false;
226                $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
227
228                        if(!this.options) return;
229                        if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
230                                dropped = this._drop.call(this, event) || dropped;
231
232                        if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
233                                this.isout = 1; this.isover = 0;
234                                this._deactivate.call(this, event);
235                        }
236
237                });
238                return dropped;
239
240        },
241        dragStart: function( draggable, event ) {
242                //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
243                draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
244                        if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
245                });
246        },
247        drag: function(draggable, event) {
248
249                //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
250                if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
251
252                //Run through all droppables and check their positions based on specific tolerance options
253                $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
254
255                        if(this.options.disabled || this.greedyChild || !this.visible) return;
256                        var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
257
258                        var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
259                        if(!c) return;
260
261                        var parentInstance;
262                        if (this.options.greedy) {
263                                var parent = this.element.parents(':data(droppable):eq(0)');
264                                if (parent.length) {
265                                        parentInstance = $.data(parent[0], 'droppable');
266                                        parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
267                                }
268                        }
269
270                        // we just moved into a greedy child
271                        if (parentInstance && c == 'isover') {
272                                parentInstance['isover'] = 0;
273                                parentInstance['isout'] = 1;
274                                parentInstance._out.call(parentInstance, event);
275                        }
276
277                        this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
278                        this[c == "isover" ? "_over" : "_out"].call(this, event);
279
280                        // we just moved out of a greedy child
281                        if (parentInstance && c == 'isout') {
282                                parentInstance['isout'] = 0;
283                                parentInstance['isover'] = 1;
284                                parentInstance._over.call(parentInstance, event);
285                        }
286                });
287
288        },
289        dragStop: function( draggable, event ) {
290                draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
291                //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
292                if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
293        }
294};
295
296})(jQuery);
Note: See TracBrowser for help on using the repository browser.