2008-06-04 02:34:33 +00:00
/ *
2008-09-04 22:03:30 +00:00
* jQuery UI Droppable @ VERSION
2008-06-04 02:34:33 +00:00
*
2012-03-08 15:53:08 +00:00
* Copyright 2012 , AUTHORS . txt ( http : //jqueryui.com/about)
2010-07-09 13:01:04 +00:00
* Dual licensed under the MIT or GPL Version 2 licenses .
* http : //jquery.org/license
2008-11-20 04:10:34 +00:00
*
2008-06-04 02:34:33 +00:00
* http : //docs.jquery.com/UI/Droppables
*
* Depends :
2009-09-17 10:39:12 +00:00
* jquery . ui . core . js
2010-01-07 03:19:50 +00:00
* jquery . ui . widget . js
2009-12-22 19:51:24 +00:00
* jquery . ui . mouse . js
2010-02-03 23:19:48 +00:00
* jquery . ui . draggable . js
2008-06-04 02:34:33 +00:00
* /
2010-07-13 13:57:58 +00:00
( function ( $ , undefined ) {
2008-06-04 02:34:33 +00:00
$ . widget ( "ui.droppable" , {
2011-05-28 19:39:55 +00:00
version : "@VERSION" ,
2010-02-05 03:03:50 +00:00
widgetEventPrefix : "drop" ,
2010-01-07 03:19:50 +00:00
options : {
accept : '*' ,
activeClass : false ,
addClasses : true ,
greedy : false ,
hoverClass : false ,
scope : 'default' ,
tolerance : 'intersect'
} ,
2010-01-15 18:58:20 +00:00
_create : function ( ) {
2008-11-18 02:55:25 +00:00
2008-07-14 15:55:33 +00:00
var o = this . options , accept = o . accept ;
2008-06-04 02:34:33 +00:00
this . isover = 0 ; this . isout = 1 ;
2008-11-18 02:55:25 +00:00
2009-05-11 12:32:43 +00:00
this . accept = $ . isFunction ( accept ) ? accept : function ( d ) {
2008-07-14 14:21:07 +00:00
return d . is ( accept ) ;
} ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
//Store the droppable's proportions
2008-07-02 17:38:34 +00:00
this . proportions = { width : this . element [ 0 ] . offsetWidth , height : this . element [ 0 ] . offsetHeight } ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
// Add the reference and positions to the manager
2009-03-05 18:18:49 +00:00
$ . ui . ddmanager . droppables [ o . scope ] = $ . ui . ddmanager . droppables [ o . scope ] || [ ] ;
$ . ui . ddmanager . droppables [ o . scope ] . push ( this ) ;
2008-11-18 02:55:25 +00:00
2009-03-05 18:18:49 +00:00
( o . addClasses && this . element . addClass ( "ui-droppable" ) ) ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ,
2008-11-21 04:01:33 +00:00
2008-06-04 02:34:33 +00:00
destroy : function ( ) {
2008-07-28 18:34:01 +00:00
var drop = $ . ui . ddmanager . droppables [ this . options . scope ] ;
2008-06-04 02:34:33 +00:00
for ( var i = 0 ; i < drop . length ; i ++ )
if ( drop [ i ] == this )
drop . splice ( i , 1 ) ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
this . element
2009-02-02 07:18:27 +00:00
. removeClass ( "ui-droppable ui-droppable-disabled" )
2009-01-16 02:09:45 +00:00
. removeData ( "droppable" )
. unbind ( ".droppable" ) ;
2009-04-15 02:33:28 +00:00
return this ;
2008-06-04 02:34:33 +00:00
} ,
2008-11-21 04:01:33 +00:00
2010-01-07 03:19:50 +00:00
_setOption : function ( key , value ) {
2008-11-21 04:01:33 +00:00
if ( key == 'accept' ) {
2009-05-11 12:32:43 +00:00
this . accept = $ . isFunction ( value ) ? value : function ( d ) {
2009-03-05 15:18:07 +00:00
return d . is ( value ) ;
2008-11-21 04:01:33 +00:00
} ;
}
2010-01-07 03:19:50 +00:00
$ . Widget . prototype . _setOption . apply ( this , arguments ) ;
2008-11-21 04:01:33 +00:00
} ,
_activate : function ( event ) {
var draggable = $ . ui . ddmanager . current ;
2009-01-16 18:35:04 +00:00
if ( this . options . activeClass ) this . element . addClass ( this . options . activeClass ) ;
2009-01-03 15:30:23 +00:00
( draggable && this . _trigger ( 'activate' , event , this . ui ( draggable ) ) ) ;
2008-11-21 04:01:33 +00:00
} ,
_deactivate : function ( event ) {
var draggable = $ . ui . ddmanager . current ;
2009-01-16 18:35:04 +00:00
if ( this . options . activeClass ) this . element . removeClass ( this . options . activeClass ) ;
2009-01-03 15:30:23 +00:00
( draggable && this . _trigger ( 'deactivate' , event , this . ui ( draggable ) ) ) ;
2008-11-21 04:01:33 +00:00
} ,
2008-11-14 03:00:16 +00:00
_over : function ( event ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var draggable = $ . ui . ddmanager . current ;
if ( ! draggable || ( draggable . currentItem || draggable . element ) [ 0 ] == this . element [ 0 ] ) return ; // Bail if draggable and droppable are same element
2008-11-18 02:55:25 +00:00
2009-05-11 12:32:43 +00:00
if ( this . accept . call ( this . element [ 0 ] , ( draggable . currentItem || draggable . element ) ) ) {
2009-01-16 18:35:04 +00:00
if ( this . options . hoverClass ) this . element . addClass ( this . options . hoverClass ) ;
2009-01-03 15:30:23 +00:00
this . _trigger ( 'over' , event , this . ui ( draggable ) ) ;
2008-06-04 02:34:33 +00:00
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ,
2008-11-21 04:01:33 +00:00
2008-11-14 03:00:16 +00:00
_out : function ( event ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var draggable = $ . ui . ddmanager . current ;
if ( ! draggable || ( draggable . currentItem || draggable . element ) [ 0 ] == this . element [ 0 ] ) return ; // Bail if draggable and droppable are same element
2008-11-18 02:55:25 +00:00
2009-05-11 12:32:43 +00:00
if ( this . accept . call ( this . element [ 0 ] , ( draggable . currentItem || draggable . element ) ) ) {
2009-01-16 18:35:04 +00:00
if ( this . options . hoverClass ) this . element . removeClass ( this . options . hoverClass ) ;
2009-01-03 15:30:23 +00:00
this . _trigger ( 'out' , event , this . ui ( draggable ) ) ;
2008-06-04 02:34:33 +00:00
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ,
2008-11-21 04:01:33 +00:00
2008-11-14 03:00:16 +00:00
_drop : function ( event , custom ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var draggable = custom || $ . ui . ddmanager . current ;
if ( ! draggable || ( draggable . currentItem || draggable . element ) [ 0 ] == this . element [ 0 ] ) return false ; // Bail if draggable and droppable are same element
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var childrenIntersection = false ;
2009-02-02 07:18:27 +00:00
this . element . find ( ":data(droppable)" ) . not ( ".ui-draggable-dragging" ) . each ( function ( ) {
2009-01-16 02:09:45 +00:00
var inst = $ . data ( this , 'droppable' ) ;
2009-08-22 12:25:50 +00:00
if (
inst . options . greedy
&& ! inst . options . disabled
&& inst . options . scope == draggable . options . scope
&& inst . accept . call ( inst . element [ 0 ] , ( draggable . currentItem || draggable . element ) )
&& $ . ui . intersect ( draggable , $ . extend ( inst , { offset : inst . element . offset ( ) } ) , inst . options . tolerance )
) { childrenIntersection = true ; return false ; }
2008-06-04 02:34:33 +00:00
} ) ;
if ( childrenIntersection ) return false ;
2008-11-18 02:55:25 +00:00
2009-05-11 12:32:43 +00:00
if ( this . accept . call ( this . element [ 0 ] , ( draggable . currentItem || draggable . element ) ) ) {
2009-01-16 18:35:04 +00:00
if ( this . options . activeClass ) this . element . removeClass ( this . options . activeClass ) ;
if ( this . options . hoverClass ) this . element . removeClass ( this . options . hoverClass ) ;
2009-01-03 15:30:23 +00:00
this . _trigger ( 'drop' , event , this . ui ( draggable ) ) ;
2008-09-18 09:51:50 +00:00
return this . element ;
2008-06-04 02:34:33 +00:00
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
return false ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ,
2008-11-18 02:55:25 +00:00
2008-11-21 04:01:33 +00:00
ui : function ( c ) {
return {
draggable : ( c . currentItem || c . element ) ,
helper : c . helper ,
position : c . position ,
2009-01-29 12:35:38 +00:00
offset : c . positionAbs
2008-11-21 04:01:33 +00:00
} ;
2008-06-04 02:34:33 +00:00
}
2008-11-21 04:01:33 +00:00
2008-06-04 02:34:33 +00:00
} ) ;
$ . ui . intersect = function ( draggable , droppable , toleranceMode ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
if ( ! droppable . offset ) return false ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var x1 = ( draggable . positionAbs || draggable . position . absolute ) . left , x2 = x1 + draggable . helperProportions . width ,
y1 = ( draggable . positionAbs || draggable . position . absolute ) . top , y2 = y1 + draggable . helperProportions . height ;
var l = droppable . offset . left , r = l + droppable . proportions . width ,
t = droppable . offset . top , b = t + droppable . proportions . height ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
switch ( toleranceMode ) {
case 'fit' :
2010-07-06 16:15:47 +00:00
return ( l <= x1 && x2 <= r
&& t <= y1 && y2 <= b ) ;
2008-06-04 02:34:33 +00:00
break ;
case 'intersect' :
return ( l < x1 + ( draggable . helperProportions . width / 2 ) // Right Half
&& x2 - ( draggable . helperProportions . width / 2 ) < r // Left Half
&& t < y1 + ( draggable . helperProportions . height / 2 ) // Bottom Half
&& y2 - ( draggable . helperProportions . height / 2 ) < b ) ; // Top Half
break ;
case 'pointer' :
2008-11-10 06:39:52 +00:00
var draggableLeft = ( ( draggable . positionAbs || draggable . position . absolute ) . left + ( draggable . clickOffset || draggable . offset . click ) . left ) ,
draggableTop = ( ( draggable . positionAbs || draggable . position . absolute ) . top + ( draggable . clickOffset || draggable . offset . click ) . top ) ,
isOver = $ . ui . isOver ( draggableTop , draggableLeft , t , l , droppable . proportions . height , droppable . proportions . width ) ;
return isOver ;
2008-06-04 02:34:33 +00:00
break ;
case 'touch' :
return (
( y1 >= t && y1 <= b ) || // Top edge touching
( y2 >= t && y2 <= b ) || // Bottom edge touching
( y1 < t && y2 > b ) // Surrounded vertically
) && (
( x1 >= l && x1 <= r ) || // Left edge touching
( x2 >= l && x2 <= r ) || // Right edge touching
( x1 < l && x2 > r ) // Surrounded horizontally
) ;
break ;
default :
return false ;
break ;
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ;
/ *
This manager tracks offsets of draggables and droppables
* /
$ . ui . ddmanager = {
current : null ,
2008-07-28 21:06:04 +00:00
droppables : { 'default' : [ ] } ,
2008-11-14 03:00:16 +00:00
prepareOffsets : function ( t , event ) {
2009-01-16 02:09:45 +00:00
2009-08-22 11:48:48 +00:00
var m = $ . ui . ddmanager . droppables [ t . options . scope ] || [ ] ;
2008-11-14 03:00:16 +00:00
var type = event ? event . type : null ; // workaround for #2317
2009-01-16 02:09:45 +00:00
var list = ( t . currentItem || t . element ) . find ( ":data(droppable)" ) . andSelf ( ) ;
2008-11-18 02:55:25 +00:00
2008-07-28 18:34:01 +00:00
droppablesLoop : for ( var i = 0 ; i < m . length ; i ++ ) {
2008-11-18 02:55:25 +00:00
2009-05-11 12:32:43 +00:00
if ( m [ i ] . options . disabled || ( t && ! m [ i ] . accept . call ( m [ i ] . element [ 0 ] , ( t . currentItem || t . element ) ) ) ) continue ; //No disabled and non-accepted
2008-07-28 18:34:01 +00:00
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
m [ i ] . visible = m [ i ] . element . css ( "display" ) != "none" ; if ( ! m [ i ] . visible ) continue ; //If the element is not visible, continue
2008-11-18 02:55:25 +00:00
2011-03-11 14:37:52 +00:00
if ( type == "mousedown" ) m [ i ] . _activate . call ( m [ i ] , event ) ; //Activate the droppable if used directly from draggables
2008-06-04 02:34:33 +00:00
m [ i ] . offset = m [ i ] . element . offset ( ) ;
2008-07-02 17:38:34 +00:00
m [ i ] . proportions = { width : m [ i ] . element [ 0 ] . offsetWidth , height : m [ i ] . element [ 0 ] . offsetHeight } ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ,
2008-11-14 03:00:16 +00:00
drop : function ( draggable , event ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var dropped = false ;
2009-08-22 11:48:48 +00:00
$ . each ( $ . ui . ddmanager . droppables [ draggable . options . scope ] || [ ] , function ( ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
if ( ! this . options ) return ;
if ( ! this . options . disabled && this . visible && $ . ui . intersect ( draggable , this , this . options . tolerance ) )
2011-11-21 21:16:32 +00:00
dropped = this . _drop . call ( this , event ) || dropped ;
2008-11-18 02:55:25 +00:00
2009-05-11 12:32:43 +00:00
if ( ! this . options . disabled && this . visible && this . accept . call ( this . element [ 0 ] , ( draggable . currentItem || draggable . element ) ) ) {
2008-06-04 02:34:33 +00:00
this . isout = 1 ; this . isover = 0 ;
2008-11-14 03:00:16 +00:00
this . _deactivate . call ( this , event ) ;
2008-06-04 02:34:33 +00:00
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ) ;
return dropped ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
} ,
2011-05-27 17:01:42 +00:00
dragStart : function ( draggable , event ) {
//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
draggable . element . parentsUntil ( "body" ) . bind ( "scroll.droppable" , function ( ) {
if ( ! draggable . options . refreshPositions ) $ . ui . ddmanager . prepareOffsets ( draggable , event ) ;
} ) ;
} ,
2008-11-14 03:00:16 +00:00
drag : function ( draggable , event ) {
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2008-11-14 03:00:16 +00:00
if ( draggable . options . refreshPositions ) $ . ui . ddmanager . prepareOffsets ( draggable , event ) ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
//Run through all droppables and check their positions based on specific tolerance options
2009-08-22 11:48:48 +00:00
$ . each ( $ . ui . ddmanager . droppables [ draggable . options . scope ] || [ ] , function ( ) {
2008-11-18 02:55:25 +00:00
2008-06-26 10:49:47 +00:00
if ( this . options . disabled || this . greedyChild || ! this . visible ) return ;
2008-06-04 02:34:33 +00:00
var intersects = $ . ui . intersect ( draggable , this , this . options . tolerance ) ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var c = ! intersects && this . isover == 1 ? 'isout' : ( intersects && this . isover == 0 ? 'isover' : null ) ;
if ( ! c ) return ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
var parentInstance ;
if ( this . options . greedy ) {
2009-01-16 02:09:45 +00:00
var parent = this . element . parents ( ':data(droppable):eq(0)' ) ;
2008-06-04 02:34:33 +00:00
if ( parent . length ) {
2009-01-16 02:09:45 +00:00
parentInstance = $ . data ( parent [ 0 ] , 'droppable' ) ;
2008-06-04 02:34:33 +00:00
parentInstance . greedyChild = ( c == 'isover' ? 1 : 0 ) ;
}
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
// we just moved into a greedy child
if ( parentInstance && c == 'isover' ) {
parentInstance [ 'isover' ] = 0 ;
parentInstance [ 'isout' ] = 1 ;
2008-11-14 03:00:16 +00:00
parentInstance . _out . call ( parentInstance , event ) ;
2008-06-04 02:34:33 +00:00
}
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
this [ c ] = 1 ; this [ c == 'isout' ? 'isover' : 'isout' ] = 0 ;
2008-11-14 03:00:16 +00:00
this [ c == "isover" ? "_over" : "_out" ] . call ( this , event ) ;
2008-11-18 02:55:25 +00:00
2008-06-04 02:34:33 +00:00
// we just moved out of a greedy child
if ( parentInstance && c == 'isout' ) {
parentInstance [ 'isout' ] = 0 ;
parentInstance [ 'isover' ] = 1 ;
2008-11-14 03:00:16 +00:00
parentInstance . _over . call ( parentInstance , event ) ;
2008-06-04 02:34:33 +00:00
}
} ) ;
2008-11-18 02:55:25 +00:00
2011-05-27 17:01:42 +00:00
} ,
dragStop : function ( draggable , event ) {
draggable . element . parentsUntil ( "body" ) . unbind ( "scroll.droppable" ) ;
//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
if ( ! draggable . options . refreshPositions ) $ . ui . ddmanager . prepareOffsets ( draggable , event ) ;
2008-06-04 02:34:33 +00:00
}
} ;
} ) ( jQuery ) ;