forgotten additions to repo
[myslice.git] / third-party / slickgrid-2.1 / lib / jquery.event.drop-2.2.js
diff --git a/third-party/slickgrid-2.1/lib/jquery.event.drop-2.2.js b/third-party/slickgrid-2.1/lib/jquery.event.drop-2.2.js
new file mode 100644 (file)
index 0000000..7599ef9
--- /dev/null
@@ -0,0 +1,302 @@
+/*! 
+ * jquery.event.drop - v 2.2
+ * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
+ * Open Source MIT License - http://threedubmedia.com/code/license
+ */
+// Created: 2008-06-04 
+// Updated: 2012-05-21
+// REQUIRES: jquery 1.7.x, event.drag 2.2
+
+;(function($){ // secure $ jQuery alias
+
+// Events: drop, dropstart, dropend
+
+// add the jquery instance method
+$.fn.drop = function( str, arg, opts ){
+       // figure out the event type
+       var type = typeof str == "string" ? str : "",
+       // figure out the event handler...
+       fn = $.isFunction( str ) ? str : $.isFunction( arg ) ? arg : null;
+       // fix the event type
+       if ( type.indexOf("drop") !== 0 ) 
+               type = "drop"+ type;
+       // were options passed
+       opts = ( str == fn ? arg : opts ) || {};
+       // trigger or bind event handler
+       return fn ? this.bind( type, opts, fn ) : this.trigger( type );
+};
+
+// DROP MANAGEMENT UTILITY
+// returns filtered drop target elements, caches their positions
+$.drop = function( opts ){ 
+       opts = opts || {};
+       // safely set new options...
+       drop.multi = opts.multi === true ? Infinity : 
+               opts.multi === false ? 1 : !isNaN( opts.multi ) ? opts.multi : drop.multi;
+       drop.delay = opts.delay || drop.delay;
+       drop.tolerance = $.isFunction( opts.tolerance ) ? opts.tolerance : 
+               opts.tolerance === null ? null : drop.tolerance;
+       drop.mode = opts.mode || drop.mode || 'intersect';
+};
+
+// local refs (increase compression)
+var $event = $.event, 
+$special = $event.special,
+// configure the drop special event
+drop = $.event.special.drop = {
+
+       // these are the default settings
+       multi: 1, // allow multiple drop winners per dragged element
+       delay: 20, // async timeout delay
+       mode: 'overlap', // drop tolerance mode
+               
+       // internal cache
+       targets: [], 
+       
+       // the key name for stored drop data
+       datakey: "dropdata",
+               
+       // prevent bubbling for better performance
+       noBubble: true,
+       
+       // count bound related events
+       add: function( obj ){ 
+               // read the interaction data
+               var data = $.data( this, drop.datakey );
+               // count another realted event
+               data.related += 1;
+       },
+       
+       // forget unbound related events
+       remove: function(){
+               $.data( this, drop.datakey ).related -= 1;
+       },
+       
+       // configure the interactions
+       setup: function(){
+               // check for related events
+               if ( $.data( this, drop.datakey ) ) 
+                       return;
+               // initialize the drop element data
+               var data = { 
+                       related: 0,
+                       active: [],
+                       anyactive: 0,
+                       winner: 0,
+                       location: {}
+               };
+               // store the drop data on the element
+               $.data( this, drop.datakey, data );
+               // store the drop target in internal cache
+               drop.targets.push( this );
+       },
+       
+       // destroy the configure interaction    
+       teardown: function(){ 
+               var data = $.data( this, drop.datakey ) || {};
+               // check for related events
+               if ( data.related ) 
+                       return;
+               // remove the stored data
+               $.removeData( this, drop.datakey );
+               // reference the targeted element
+               var element = this;
+               // remove from the internal cache
+               drop.targets = $.grep( drop.targets, function( target ){ 
+                       return ( target !== element ); 
+               });
+       },
+       
+       // shared event handler
+       handler: function( event, dd ){ 
+               // local vars
+               var results, $targets;
+               // make sure the right data is available
+               if ( !dd ) 
+                       return;
+               // handle various events
+               switch ( event.type ){
+                       // draginit, from $.event.special.drag
+                       case 'mousedown': // DROPINIT >>
+                       case 'touchstart': // DROPINIT >>
+                               // collect and assign the drop targets
+                               $targets =  $( drop.targets );
+                               if ( typeof dd.drop == "string" )
+                                       $targets = $targets.filter( dd.drop );
+                               // reset drop data winner properties
+                               $targets.each(function(){
+                                       var data = $.data( this, drop.datakey );
+                                       data.active = [];
+                                       data.anyactive = 0;
+                                       data.winner = 0;
+                               });
+                               // set available target elements
+                               dd.droppable = $targets;
+                               // activate drop targets for the initial element being dragged
+                               $special.drag.hijack( event, "dropinit", dd ); 
+                               break;
+                       // drag, from $.event.special.drag
+                       case 'mousemove': // TOLERATE >>
+                       case 'touchmove': // TOLERATE >>
+                               drop.event = event; // store the mousemove event
+                               if ( !drop.timer )
+                                       // monitor drop targets
+                                       drop.tolerate( dd ); 
+                               break;
+                       // dragend, from $.event.special.drag
+                       case 'mouseup': // DROP >> DROPEND >>
+                       case 'touchend': // DROP >> DROPEND >>
+                               drop.timer = clearTimeout( drop.timer ); // delete timer        
+                               if ( dd.propagates ){
+                                       $special.drag.hijack( event, "drop", dd ); 
+                                       $special.drag.hijack( event, "dropend", dd ); 
+                               }
+                               break;
+                               
+               }
+       },
+               
+       // returns the location positions of an element
+       locate: function( elem, index ){ 
+               var data = $.data( elem, drop.datakey ),
+               $elem = $( elem ), 
+               posi = $elem.offset() || {}, 
+               height = $elem.outerHeight(), 
+               width = $elem.outerWidth(),
+               location = { 
+                       elem: elem, 
+                       width: width, 
+                       height: height,
+                       top: posi.top, 
+                       left: posi.left, 
+                       right: posi.left + width, 
+                       bottom: posi.top + height
+               };
+               // drag elements might not have dropdata
+               if ( data ){
+                       data.location = location;
+                       data.index = index;
+                       data.elem = elem;
+               }
+               return location;
+       },
+       
+       // test the location positions of an element against another OR an X,Y coord
+       contains: function( target, test ){ // target { location } contains test [x,y] or { location }
+               return ( ( test[0] || test.left ) >= target.left && ( test[0] || test.right ) <= target.right
+                       && ( test[1] || test.top ) >= target.top && ( test[1] || test.bottom ) <= target.bottom ); 
+       },
+       
+       // stored tolerance modes
+       modes: { // fn scope: "$.event.special.drop" object 
+               // target with mouse wins, else target with most overlap wins
+               'intersect': function( event, proxy, target ){
+                       return this.contains( target, [ event.pageX, event.pageY ] ) ? // check cursor
+                               1e9 : this.modes.overlap.apply( this, arguments ); // check overlap
+               },
+               // target with most overlap wins        
+               'overlap': function( event, proxy, target ){
+                       // calculate the area of overlap...
+                       return Math.max( 0, Math.min( target.bottom, proxy.bottom ) - Math.max( target.top, proxy.top ) )
+                               * Math.max( 0, Math.min( target.right, proxy.right ) - Math.max( target.left, proxy.left ) );
+               },
+               // proxy is completely contained within target bounds   
+               'fit': function( event, proxy, target ){
+                       return this.contains( target, proxy ) ? 1 : 0;
+               },
+               // center of the proxy is contained within target bounds        
+               'middle': function( event, proxy, target ){
+                       return this.contains( target, [ proxy.left + proxy.width * .5, proxy.top + proxy.height * .5 ] ) ? 1 : 0;
+               }
+       },      
+       
+       // sort drop target cache by by winner (dsc), then index (asc)
+       sort: function( a, b ){
+               return ( b.winner - a.winner ) || ( a.index - b.index );
+       },
+               
+       // async, recursive tolerance execution
+       tolerate: function( dd ){               
+               // declare local refs
+               var i, drp, drg, data, arr, len, elem,
+               // interaction iteration variables
+               x = 0, ia, end = dd.interactions.length,
+               // determine the mouse coords
+               xy = [ drop.event.pageX, drop.event.pageY ],
+               // custom or stored tolerance fn
+               tolerance = drop.tolerance || drop.modes[ drop.mode ];
+               // go through each passed interaction...
+               do if ( ia = dd.interactions[x] ){
+                       // check valid interaction
+                       if ( !ia )
+                               return; 
+                       // initialize or clear the drop data
+                       ia.drop = [];
+                       // holds the drop elements
+                       arr = []; 
+                       len = ia.droppable.length;
+                       // determine the proxy location, if needed
+                       if ( tolerance )
+                               drg = drop.locate( ia.proxy ); 
+                       // reset the loop
+                       i = 0;
+                       // loop each stored drop target
+                       do if ( elem = ia.droppable[i] ){ 
+                               data = $.data( elem, drop.datakey );
+                               drp = data.location;
+                               if ( !drp ) continue;
+                               // find a winner: tolerance function is defined, call it
+                               data.winner = tolerance ? tolerance.call( drop, drop.event, drg, drp ) 
+                                       // mouse position is always the fallback
+                                       : drop.contains( drp, xy ) ? 1 : 0; 
+                               arr.push( data );       
+                       } while ( ++i < len ); // loop 
+                       // sort the drop targets
+                       arr.sort( drop.sort );                  
+                       // reset the loop
+                       i = 0;
+                       // loop through all of the targets again
+                       do if ( data = arr[ i ] ){
+                               // winners...
+                               if ( data.winner && ia.drop.length < drop.multi ){
+                                       // new winner... dropstart
+                                       if ( !data.active[x] && !data.anyactive ){
+                                               // check to make sure that this is not prevented
+                                               if ( $special.drag.hijack( drop.event, "dropstart", dd, x, data.elem )[0] !== false ){  
+                                                       data.active[x] = 1;
+                                                       data.anyactive += 1;
+                                               }
+                                               // if false, it is not a winner
+                                               else
+                                                       data.winner = 0;
+                                       }
+                                       // if it is still a winner
+                                       if ( data.winner )
+                                               ia.drop.push( data.elem );
+                               }
+                               // losers... 
+                               else if ( data.active[x] && data.anyactive == 1 ){
+                                       // former winner... dropend
+                                       $special.drag.hijack( drop.event, "dropend", dd, x, data.elem ); 
+                                       data.active[x] = 0;
+                                       data.anyactive -= 1;
+                               }
+                       } while ( ++i < len ); // loop          
+               } while ( ++x < end ) // loop
+               // check if the mouse is still moving or is idle
+               if ( drop.last && xy[0] == drop.last.pageX && xy[1] == drop.last.pageY ) 
+                       delete drop.timer; // idle, don't recurse
+               else  // recurse
+                       drop.timer = setTimeout(function(){ 
+                               drop.tolerate( dd ); 
+                       }, drop.delay );
+               // remember event, to compare idleness
+               drop.last = drop.event; 
+       }
+       
+};
+
+// share the same special event configuration with related events...
+$special.dropinit = $special.dropstart = $special.dropend = drop;
+
+})(jQuery); // confine scope   
\ No newline at end of file