12 //>>description: Enables drop targets for draggable elements. |
12 //>>description: Enables drop targets for draggable elements. |
13 //>>docs: http://api.jqueryui.com/droppable/ |
13 //>>docs: http://api.jqueryui.com/droppable/ |
14 //>>demos: http://jqueryui.com/droppable/ |
14 //>>demos: http://jqueryui.com/droppable/ |
15 |
15 |
16 ( function( factory ) { |
16 ( function( factory ) { |
|
17 "use strict"; |
|
18 |
17 if ( typeof define === "function" && define.amd ) { |
19 if ( typeof define === "function" && define.amd ) { |
18 |
20 |
19 // AMD. Register as an anonymous module. |
21 // AMD. Register as an anonymous module. |
20 define( [ |
22 define( [ |
21 "jquery", |
23 "jquery", |
106 }, |
111 }, |
107 |
112 |
108 _setOption: function( key, value ) { |
113 _setOption: function( key, value ) { |
109 |
114 |
110 if ( key === "accept" ) { |
115 if ( key === "accept" ) { |
111 this.accept = $.isFunction( value ) ? value : function( d ) { |
116 this.accept = typeof value === "function" ? value : function( d ) { |
112 return d.is( value ); |
117 return d.is( value ); |
113 }; |
118 }; |
114 } else if ( key === "scope" ) { |
119 } else if ( key === "scope" ) { |
115 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; |
120 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; |
116 |
121 |
143 |
148 |
144 var draggable = $.ui.ddmanager.current; |
149 var draggable = $.ui.ddmanager.current; |
145 |
150 |
146 // Bail if draggable and droppable are same element |
151 // Bail if draggable and droppable are same element |
147 if ( !draggable || ( draggable.currentItem || |
152 if ( !draggable || ( draggable.currentItem || |
148 draggable.element )[ 0 ] === this.element[ 0 ] ) { |
153 draggable.element )[ 0 ] === this.element[ 0 ] ) { |
149 return; |
154 return; |
150 } |
155 } |
151 |
156 |
152 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || |
157 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || |
153 draggable.element ) ) ) { |
158 draggable.element ) ) ) { |
154 this._addHoverClass(); |
159 this._addHoverClass(); |
155 this._trigger( "over", event, this.ui( draggable ) ); |
160 this._trigger( "over", event, this.ui( draggable ) ); |
156 } |
161 } |
157 |
162 |
158 }, |
163 }, |
161 |
166 |
162 var draggable = $.ui.ddmanager.current; |
167 var draggable = $.ui.ddmanager.current; |
163 |
168 |
164 // Bail if draggable and droppable are same element |
169 // Bail if draggable and droppable are same element |
165 if ( !draggable || ( draggable.currentItem || |
170 if ( !draggable || ( draggable.currentItem || |
166 draggable.element )[ 0 ] === this.element[ 0 ] ) { |
171 draggable.element )[ 0 ] === this.element[ 0 ] ) { |
167 return; |
172 return; |
168 } |
173 } |
169 |
174 |
170 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || |
175 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || |
171 draggable.element ) ) ) { |
176 draggable.element ) ) ) { |
172 this._removeHoverClass(); |
177 this._removeHoverClass(); |
173 this._trigger( "out", event, this.ui( draggable ) ); |
178 this._trigger( "out", event, this.ui( draggable ) ); |
174 } |
179 } |
175 |
180 |
176 }, |
181 }, |
180 var draggable = custom || $.ui.ddmanager.current, |
185 var draggable = custom || $.ui.ddmanager.current, |
181 childrenIntersection = false; |
186 childrenIntersection = false; |
182 |
187 |
183 // Bail if draggable and droppable are same element |
188 // Bail if draggable and droppable are same element |
184 if ( !draggable || ( draggable.currentItem || |
189 if ( !draggable || ( draggable.currentItem || |
185 draggable.element )[ 0 ] === this.element[ 0 ] ) { |
190 draggable.element )[ 0 ] === this.element[ 0 ] ) { |
186 return false; |
191 return false; |
187 } |
192 } |
188 |
193 |
189 this.element |
194 this.element |
190 .find( ":data(ui-droppable)" ) |
195 .find( ":data(ui-droppable)" ) |
196 !inst.options.disabled && |
201 !inst.options.disabled && |
197 inst.options.scope === draggable.options.scope && |
202 inst.options.scope === draggable.options.scope && |
198 inst.accept.call( |
203 inst.accept.call( |
199 inst.element[ 0 ], ( draggable.currentItem || draggable.element ) |
204 inst.element[ 0 ], ( draggable.currentItem || draggable.element ) |
200 ) && |
205 ) && |
201 intersect( |
206 $.ui.intersect( |
202 draggable, |
207 draggable, |
203 $.extend( inst, { offset: inst.element.offset() } ), |
208 $.extend( inst, { offset: inst.element.offset() } ), |
204 inst.options.tolerance, event |
209 inst.options.tolerance, event |
205 ) |
210 ) |
206 ) { |
211 ) { |
207 childrenIntersection = true; |
212 childrenIntersection = true; |
208 return false; } |
213 return false; |
|
214 } |
209 } ); |
215 } ); |
210 if ( childrenIntersection ) { |
216 if ( childrenIntersection ) { |
211 return false; |
217 return false; |
212 } |
218 } |
213 |
219 |
214 if ( this.accept.call( this.element[ 0 ], |
220 if ( this.accept.call( this.element[ 0 ], |
215 ( draggable.currentItem || draggable.element ) ) ) { |
221 ( draggable.currentItem || draggable.element ) ) ) { |
216 this._removeActiveClass(); |
222 this._removeActiveClass(); |
217 this._removeHoverClass(); |
223 this._removeHoverClass(); |
218 |
224 |
219 this._trigger( "drop", event, this.ui( draggable ) ); |
225 this._trigger( "drop", event, this.ui( draggable ) ); |
220 return this.element; |
226 return this.element; |
232 offset: c.positionAbs |
238 offset: c.positionAbs |
233 }; |
239 }; |
234 }, |
240 }, |
235 |
241 |
236 // Extension points just to make backcompat sane and avoid duplicating logic |
242 // Extension points just to make backcompat sane and avoid duplicating logic |
237 // TODO: Remove in 1.13 along with call to it below |
243 // TODO: Remove in 1.14 along with call to it below |
238 _addHoverClass: function() { |
244 _addHoverClass: function() { |
239 this._addClass( "ui-droppable-hover" ); |
245 this._addClass( "ui-droppable-hover" ); |
240 }, |
246 }, |
241 |
247 |
242 _removeHoverClass: function() { |
248 _removeHoverClass: function() { |
250 _removeActiveClass: function() { |
256 _removeActiveClass: function() { |
251 this._removeClass( "ui-droppable-active" ); |
257 this._removeClass( "ui-droppable-active" ); |
252 } |
258 } |
253 } ); |
259 } ); |
254 |
260 |
255 var intersect = $.ui.intersect = ( function() { |
261 $.ui.intersect = ( function() { |
256 function isOverAxis( x, reference, size ) { |
262 function isOverAxis( x, reference, size ) { |
257 return ( x >= reference ) && ( x < ( reference + size ) ); |
263 return ( x >= reference ) && ( x < ( reference + size ) ); |
258 } |
264 } |
259 |
265 |
260 return function( draggable, droppable, toleranceMode, event ) { |
266 return function( draggable, droppable, toleranceMode, event ) { |
273 t = droppable.offset.top, |
279 t = droppable.offset.top, |
274 r = l + droppable.proportions().width, |
280 r = l + droppable.proportions().width, |
275 b = t + droppable.proportions().height; |
281 b = t + droppable.proportions().height; |
276 |
282 |
277 switch ( toleranceMode ) { |
283 switch ( toleranceMode ) { |
278 case "fit": |
284 case "fit": |
279 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); |
285 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); |
280 case "intersect": |
286 case "intersect": |
281 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half |
287 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half |
282 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half |
288 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half |
283 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half |
289 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half |
284 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half |
290 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half |
285 case "pointer": |
291 case "pointer": |
286 return isOverAxis( event.pageY, t, droppable.proportions().height ) && |
292 return isOverAxis( event.pageY, t, droppable.proportions().height ) && |
287 isOverAxis( event.pageX, l, droppable.proportions().width ); |
293 isOverAxis( event.pageX, l, droppable.proportions().width ); |
288 case "touch": |
294 case "touch": |
289 return ( |
295 return ( |
290 ( y1 >= t && y1 <= b ) || // Top edge touching |
296 ( y1 >= t && y1 <= b ) || // Top edge touching |
291 ( y2 >= t && y2 <= b ) || // Bottom edge touching |
297 ( y2 >= t && y2 <= b ) || // Bottom edge touching |
292 ( y1 < t && y2 > b ) // Surrounded vertically |
298 ( y1 < t && y2 > b ) // Surrounded vertically |
293 ) && ( |
299 ) && ( |
294 ( x1 >= l && x1 <= r ) || // Left edge touching |
300 ( x1 >= l && x1 <= r ) || // Left edge touching |
295 ( x2 >= l && x2 <= r ) || // Right edge touching |
301 ( x2 >= l && x2 <= r ) || // Right edge touching |
296 ( x1 < l && x2 > r ) // Surrounded horizontally |
302 ( x1 < l && x2 > r ) // Surrounded horizontally |
297 ); |
303 ); |
298 default: |
304 default: |
299 return false; |
305 return false; |
300 } |
306 } |
301 }; |
307 }; |
302 } )(); |
308 } )(); |
303 |
309 |
304 /* |
310 /* |
316 |
322 |
317 droppablesLoop: for ( i = 0; i < m.length; i++ ) { |
323 droppablesLoop: for ( i = 0; i < m.length; i++ ) { |
318 |
324 |
319 // No disabled and non-accepted |
325 // No disabled and non-accepted |
320 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], |
326 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], |
321 ( t.currentItem || t.element ) ) ) ) { |
327 ( t.currentItem || t.element ) ) ) ) { |
322 continue; |
328 continue; |
323 } |
329 } |
324 |
330 |
325 // Filter out elements in the current dragged item |
331 // Filter out elements in the current dragged item |
326 for ( j = 0; j < list.length; j++ ) { |
332 for ( j = 0; j < list.length; j++ ) { |
358 |
364 |
359 if ( !this.options ) { |
365 if ( !this.options ) { |
360 return; |
366 return; |
361 } |
367 } |
362 if ( !this.options.disabled && this.visible && |
368 if ( !this.options.disabled && this.visible && |
363 intersect( draggable, this, this.options.tolerance, event ) ) { |
369 $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { |
364 dropped = this._drop.call( this, event ) || dropped; |
370 dropped = this._drop.call( this, event ) || dropped; |
365 } |
371 } |
366 |
372 |
367 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], |
373 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], |
368 ( draggable.currentItem || draggable.element ) ) ) { |
374 ( draggable.currentItem || draggable.element ) ) ) { |
369 this.isout = true; |
375 this.isout = true; |
370 this.isover = false; |
376 this.isover = false; |
371 this._deactivate.call( this, event ); |
377 this._deactivate.call( this, event ); |
372 } |
378 } |
373 |
379 |
399 if ( this.options.disabled || this.greedyChild || !this.visible ) { |
405 if ( this.options.disabled || this.greedyChild || !this.visible ) { |
400 return; |
406 return; |
401 } |
407 } |
402 |
408 |
403 var parentInstance, scope, parent, |
409 var parentInstance, scope, parent, |
404 intersects = intersect( draggable, this, this.options.tolerance, event ), |
410 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), |
405 c = !intersects && this.isover ? |
411 c = !intersects && this.isover ? |
406 "isout" : |
412 "isout" : |
407 ( intersects && !this.isover ? "isover" : null ); |
413 ( intersects && !this.isover ? "isover" : null ); |
408 if ( !c ) { |
414 if ( !c ) { |
409 return; |
415 return; |