summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/jquery.event.drag-2.0.min.js6
-rw-r--r--lib/jquery.event.drag-2.2.js402
-rw-r--r--lib/jquery.event.drop-2.0.min.js6
-rw-r--r--lib/jquery.event.drop-2.2.js302
4 files changed, 704 insertions, 12 deletions
diff --git a/lib/jquery.event.drag-2.0.min.js b/lib/jquery.event.drag-2.0.min.js
deleted file mode 100644
index 2cb7fee..0000000
--- a/lib/jquery.event.drag-2.0.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
- * jquery.event.drag - v 2.0.0
- * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
- * Open Source MIT License - http://threedubmedia.com/code/license
- */
-;(function(f){f.fn.drag=function(b,a,d){var e=typeof b=="string"?b:"",k=f.isFunction(b)?b:f.isFunction(a)?a:null;if(e.indexOf("drag")!==0)e="drag"+e;d=(b==k?a:d)||{};return k?this.bind(e,d,k):this.trigger(e)};var i=f.event,h=i.special,c=h.drag={defaults:{which:1,distance:0,not:":input",handle:null,relative:false,drop:true,click:false},datakey:"dragdata",livekey:"livedrag",add:function(b){var a=f.data(this,c.datakey),d=b.data||{};a.related+=1;if(!a.live&&b.selector){a.live=true;i.add(this,"draginit."+ c.livekey,c.delegate)}f.each(c.defaults,function(e){if(d[e]!==undefined)a[e]=d[e]})},remove:function(){f.data(this,c.datakey).related-=1},setup:function(){if(!f.data(this,c.datakey)){var b=f.extend({related:0},c.defaults);f.data(this,c.datakey,b);i.add(this,"mousedown",c.init,b);this.attachEvent&&this.attachEvent("ondragstart",c.dontstart)}},teardown:function(){if(!f.data(this,c.datakey).related){f.removeData(this,c.datakey);i.remove(this,"mousedown",c.init);i.remove(this,"draginit",c.delegate);c.textselect(true); this.detachEvent&&this.detachEvent("ondragstart",c.dontstart)}},init:function(b){var a=b.data,d;if(!(a.which>0&&b.which!=a.which))if(!f(b.target).is(a.not))if(!(a.handle&&!f(b.target).closest(a.handle,b.currentTarget).length)){a.propagates=1;a.interactions=[c.interaction(this,a)];a.target=b.target;a.pageX=b.pageX;a.pageY=b.pageY;a.dragging=null;d=c.hijack(b,"draginit",a);if(a.propagates){if((d=c.flatten(d))&&d.length){a.interactions=[];f.each(d,function(){a.interactions.push(c.interaction(this,a))})}a.propagates= a.interactions.length;a.drop!==false&&h.drop&&h.drop.handler(b,a);c.textselect(false);i.add(document,"mousemove mouseup",c.handler,a);return false}}},interaction:function(b,a){return{drag:b,callback:new c.callback,droppable:[],offset:f(b)[a.relative?"position":"offset"]()||{top:0,left:0}}},handler:function(b){var a=b.data;switch(b.type){case !a.dragging&&"mousemove":if(Math.pow(b.pageX-a.pageX,2)+Math.pow(b.pageY-a.pageY,2)<Math.pow(a.distance,2))break;b.target=a.target;c.hijack(b,"dragstart",a); if(a.propagates)a.dragging=true;case "mousemove":if(a.dragging){c.hijack(b,"drag",a);if(a.propagates){a.drop!==false&&h.drop&&h.drop.handler(b,a);break}b.type="mouseup"}case "mouseup":i.remove(document,"mousemove mouseup",c.handler);if(a.dragging){a.drop!==false&&h.drop&&h.drop.handler(b,a);c.hijack(b,"dragend",a)}c.textselect(true);if(a.click===false&&a.dragging){jQuery.event.triggered=true;setTimeout(function(){jQuery.event.triggered=false},20);a.dragging=false}break}},delegate:function(b){var a= [],d,e=f.data(this,"events")||{};f.each(e.live||[],function(k,j){if(j.preType.indexOf("drag")===0)if(d=f(b.target).closest(j.selector,b.currentTarget)[0]){i.add(d,j.origType+"."+c.livekey,j.origHandler,j.data);f.inArray(d,a)<0&&a.push(d)}});if(!a.length)return false;return f(a).bind("dragend."+c.livekey,function(){i.remove(this,"."+c.livekey)})},hijack:function(b,a,d,e,k){if(d){var j={event:b.originalEvent,type:b.type},n=a.indexOf("drop")?"drag":"drop",l,o=e||0,g,m;e=!isNaN(e)?e:d.interactions.length; b.type=a;b.originalEvent=null;d.results=[];do if(g=d.interactions[o])if(!(a!=="dragend"&&g.cancelled)){m=c.properties(b,d,g);g.results=[];f(k||g[n]||d.droppable).each(function(q,p){l=(m.target=p)?i.handle.call(p,b,m):null;if(l===false){if(n=="drag"){g.cancelled=true;d.propagates-=1}if(a=="drop")g[n][q]=null}else if(a=="dropinit")g.droppable.push(c.element(l)||p);if(a=="dragstart")g.proxy=f(c.element(l)||g.drag)[0];g.results.push(l);delete b.result;if(a!=="dropinit")return l});d.results[o]=c.flatten(g.results); if(a=="dropinit")g.droppable=c.flatten(g.droppable);a=="dragstart"&&!g.cancelled&&m.update()}while(++o<e);b.type=j.type;b.originalEvent=j.event;return c.flatten(d.results)}},properties:function(b,a,d){var e=d.callback;e.drag=d.drag;e.proxy=d.proxy||d.drag;e.startX=a.pageX;e.startY=a.pageY;e.deltaX=b.pageX-a.pageX;e.deltaY=b.pageY-a.pageY;e.originalX=d.offset.left;e.originalY=d.offset.top;e.offsetX=b.pageX-(a.pageX-e.originalX);e.offsetY=b.pageY-(a.pageY-e.originalY);e.drop=c.flatten((d.drop||[]).slice()); e.available=c.flatten((d.droppable||[]).slice());return e},element:function(b){if(b&&(b.jquery||b.nodeType==1))return b},flatten:function(b){return f.map(b,function(a){return a&&a.jquery?f.makeArray(a):a&&a.length?c.flatten(a):a})},textselect:function(b){f(document)[b?"unbind":"bind"]("selectstart",c.dontstart).attr("unselectable",b?"off":"on").css("MozUserSelect",b?"":"none")},dontstart:function(){return false},callback:function(){}};c.callback.prototype={update:function(){h.drop&&this.available.length&& f.each(this.available,function(b){h.drop.locate(this,b)})}};h.draginit=h.dragstart=h.dragend=c})(jQuery); \ No newline at end of file
diff --git a/lib/jquery.event.drag-2.2.js b/lib/jquery.event.drag-2.2.js
new file mode 100644
index 0000000..1cda0e2
--- /dev/null
+++ b/lib/jquery.event.drag-2.2.js
@@ -0,0 +1,402 @@
+/*!
+ * jquery.event.drag - 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
+
+;(function( $ ){
+
+// add the jquery instance method
+$.fn.drag = 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("drag") !== 0 )
+ type = "drag"+ type;
+ // were options passed
+ opts = ( str == fn ? arg : opts ) || {};
+ // trigger or bind event handler
+ return fn ? this.bind( type, opts, fn ) : this.trigger( type );
+};
+
+// local refs (increase compression)
+var $event = $.event,
+$special = $event.special,
+// configure the drag special event
+drag = $special.drag = {
+
+ // these are the default settings
+ defaults: {
+ which: 1, // mouse button pressed to start drag sequence
+ distance: 0, // distance dragged before dragstart
+ not: ':input', // selector to suppress dragging on target elements
+ handle: null, // selector to match handle target elements
+ relative: false, // true to use "position", false to use "offset"
+ drop: true, // false to suppress drop events, true or selector to allow
+ click: false // false to suppress click events after dragend (no proxy)
+ },
+
+ // the key name for stored drag data
+ datakey: "dragdata",
+
+ // prevent bubbling for better performance
+ noBubble: true,
+
+ // count bound related events
+ add: function( obj ){
+ // read the interaction data
+ var data = $.data( this, drag.datakey ),
+ // read any passed options
+ opts = obj.data || {};
+ // count another realted event
+ data.related += 1;
+ // extend data options bound with this event
+ // don't iterate "opts" in case it is a node
+ $.each( drag.defaults, function( key, def ){
+ if ( opts[ key ] !== undefined )
+ data[ key ] = opts[ key ];
+ });
+ },
+
+ // forget unbound related events
+ remove: function(){
+ $.data( this, drag.datakey ).related -= 1;
+ },
+
+ // configure interaction, capture settings
+ setup: function(){
+ // check for related events
+ if ( $.data( this, drag.datakey ) )
+ return;
+ // initialize the drag data with copied defaults
+ var data = $.extend({ related:0 }, drag.defaults );
+ // store the interaction data
+ $.data( this, drag.datakey, data );
+ // bind the mousedown event, which starts drag interactions
+ $event.add( this, "touchstart mousedown", drag.init, data );
+ // prevent image dragging in IE...
+ if ( this.attachEvent )
+ this.attachEvent("ondragstart", drag.dontstart );
+ },
+
+ // destroy configured interaction
+ teardown: function(){
+ var data = $.data( this, drag.datakey ) || {};
+ // check for related events
+ if ( data.related )
+ return;
+ // remove the stored data
+ $.removeData( this, drag.datakey );
+ // remove the mousedown event
+ $event.remove( this, "touchstart mousedown", drag.init );
+ // enable text selection
+ drag.textselect( true );
+ // un-prevent image dragging in IE...
+ if ( this.detachEvent )
+ this.detachEvent("ondragstart", drag.dontstart );
+ },
+
+ // initialize the interaction
+ init: function( event ){
+ // sorry, only one touch at a time
+ if ( drag.touched )
+ return;
+ // the drag/drop interaction data
+ var dd = event.data, results;
+ // check the which directive
+ if ( event.which != 0 && dd.which > 0 && event.which != dd.which )
+ return;
+ // check for suppressed selector
+ if ( $( event.target ).is( dd.not ) )
+ return;
+ // check for handle selector
+ if ( dd.handle && !$( event.target ).closest( dd.handle, event.currentTarget ).length )
+ return;
+
+ drag.touched = event.type == 'touchstart' ? this : null;
+ dd.propagates = 1;
+ dd.mousedown = this;
+ dd.interactions = [ drag.interaction( this, dd ) ];
+ dd.target = event.target;
+ dd.pageX = event.pageX;
+ dd.pageY = event.pageY;
+ dd.dragging = null;
+ // handle draginit event...
+ results = drag.hijack( event, "draginit", dd );
+ // early cancel
+ if ( !dd.propagates )
+ return;
+ // flatten the result set
+ results = drag.flatten( results );
+ // insert new interaction elements
+ if ( results && results.length ){
+ dd.interactions = [];
+ $.each( results, function(){
+ dd.interactions.push( drag.interaction( this, dd ) );
+ });
+ }
+ // remember how many interactions are propagating
+ dd.propagates = dd.interactions.length;
+ // locate and init the drop targets
+ if ( dd.drop !== false && $special.drop )
+ $special.drop.handler( event, dd );
+ // disable text selection
+ drag.textselect( false );
+ // bind additional events...
+ if ( drag.touched )
+ $event.add( drag.touched, "touchmove touchend", drag.handler, dd );
+ else
+ $event.add( document, "mousemove mouseup", drag.handler, dd );
+ // helps prevent text selection or scrolling
+ if ( !drag.touched || dd.live )
+ return false;
+ },
+
+ // returns an interaction object
+ interaction: function( elem, dd ){
+ var offset = $( elem )[ dd.relative ? "position" : "offset" ]() || { top:0, left:0 };
+ return {
+ drag: elem,
+ callback: new drag.callback(),
+ droppable: [],
+ offset: offset
+ };
+ },
+
+ // handle drag-releatd DOM events
+ handler: function( event ){
+ // read the data before hijacking anything
+ var dd = event.data;
+ // handle various events
+ switch ( event.type ){
+ // mousemove, check distance, start dragging
+ case !dd.dragging && 'touchmove':
+ event.preventDefault();
+ case !dd.dragging && 'mousemove':
+ // drag tolerance, x² + y² = distance²
+ if ( Math.pow( event.pageX-dd.pageX, 2 ) + Math.pow( event.pageY-dd.pageY, 2 ) < Math.pow( dd.distance, 2 ) )
+ break; // distance tolerance not reached
+ event.target = dd.target; // force target from "mousedown" event (fix distance issue)
+ drag.hijack( event, "dragstart", dd ); // trigger "dragstart"
+ if ( dd.propagates ) // "dragstart" not rejected
+ dd.dragging = true; // activate interaction
+ // mousemove, dragging
+ case 'touchmove':
+ event.preventDefault();
+ case 'mousemove':
+ if ( dd.dragging ){
+ // trigger "drag"
+ drag.hijack( event, "drag", dd );
+ if ( dd.propagates ){
+ // manage drop events
+ if ( dd.drop !== false && $special.drop )
+ $special.drop.handler( event, dd ); // "dropstart", "dropend"
+ break; // "drag" not rejected, stop
+ }
+ event.type = "mouseup"; // helps "drop" handler behave
+ }
+ // mouseup, stop dragging
+ case 'touchend':
+ case 'mouseup':
+ default:
+ if ( drag.touched )
+ $event.remove( drag.touched, "touchmove touchend", drag.handler ); // remove touch events
+ else
+ $event.remove( document, "mousemove mouseup", drag.handler ); // remove page events
+ if ( dd.dragging ){
+ if ( dd.drop !== false && $special.drop )
+ $special.drop.handler( event, dd ); // "drop"
+ drag.hijack( event, "dragend", dd ); // trigger "dragend"
+ }
+ drag.textselect( true ); // enable text selection
+ // if suppressing click events...
+ if ( dd.click === false && dd.dragging )
+ $.data( dd.mousedown, "suppress.click", new Date().getTime() + 5 );
+ dd.dragging = drag.touched = false; // deactivate element
+ break;
+ }
+ },
+
+ // re-use event object for custom events
+ hijack: function( event, type, dd, x, elem ){
+ // not configured
+ if ( !dd )
+ return;
+ // remember the original event and type
+ var orig = { event:event.originalEvent, type:event.type },
+ // is the event drag related or drog related?
+ mode = type.indexOf("drop") ? "drag" : "drop",
+ // iteration vars
+ result, i = x || 0, ia, $elems, callback,
+ len = !isNaN( x ) ? x : dd.interactions.length;
+ // modify the event type
+ event.type = type;
+ // remove the original event
+ event.originalEvent = null;
+ // initialize the results
+ dd.results = [];
+ // handle each interacted element
+ do if ( ia = dd.interactions[ i ] ){
+ // validate the interaction
+ if ( type !== "dragend" && ia.cancelled )
+ continue;
+ // set the dragdrop properties on the event object
+ callback = drag.properties( event, dd, ia );
+ // prepare for more results
+ ia.results = [];
+ // handle each element
+ $( elem || ia[ mode ] || dd.droppable ).each(function( p, subject ){
+ // identify drag or drop targets individually
+ callback.target = subject;
+ // force propagtion of the custom event
+ event.isPropagationStopped = function(){ return false; };
+ // handle the event
+ result = subject ? $event.dispatch.call( subject, event, callback ) : null;
+ // stop the drag interaction for this element
+ if ( result === false ){
+ if ( mode == "drag" ){
+ ia.cancelled = true;
+ dd.propagates -= 1;
+ }
+ if ( type == "drop" ){
+ ia[ mode ][p] = null;
+ }
+ }
+ // assign any dropinit elements
+ else if ( type == "dropinit" )
+ ia.droppable.push( drag.element( result ) || subject );
+ // accept a returned proxy element
+ if ( type == "dragstart" )
+ ia.proxy = $( drag.element( result ) || ia.drag )[0];
+ // remember this result
+ ia.results.push( result );
+ // forget the event result, for recycling
+ delete event.result;
+ // break on cancelled handler
+ if ( type !== "dropinit" )
+ return result;
+ });
+ // flatten the results
+ dd.results[ i ] = drag.flatten( ia.results );
+ // accept a set of valid drop targets
+ if ( type == "dropinit" )
+ ia.droppable = drag.flatten( ia.droppable );
+ // locate drop targets
+ if ( type == "dragstart" && !ia.cancelled )
+ callback.update();
+ }
+ while ( ++i < len )
+ // restore the original event & type
+ event.type = orig.type;
+ event.originalEvent = orig.event;
+ // return all handler results
+ return drag.flatten( dd.results );
+ },
+
+ // extend the callback object with drag/drop properties...
+ properties: function( event, dd, ia ){
+ var obj = ia.callback;
+ // elements
+ obj.drag = ia.drag;
+ obj.proxy = ia.proxy || ia.drag;
+ // starting mouse position
+ obj.startX = dd.pageX;
+ obj.startY = dd.pageY;
+ // current distance dragged
+ obj.deltaX = event.pageX - dd.pageX;
+ obj.deltaY = event.pageY - dd.pageY;
+ // original element position
+ obj.originalX = ia.offset.left;
+ obj.originalY = ia.offset.top;
+ // adjusted element position
+ obj.offsetX = obj.originalX + obj.deltaX;
+ obj.offsetY = obj.originalY + obj.deltaY;
+ // assign the drop targets information
+ obj.drop = drag.flatten( ( ia.drop || [] ).slice() );
+ obj.available = drag.flatten( ( ia.droppable || [] ).slice() );
+ return obj;
+ },
+
+ // determine is the argument is an element or jquery instance
+ element: function( arg ){
+ if ( arg && ( arg.jquery || arg.nodeType == 1 ) )
+ return arg;
+ },
+
+ // flatten nested jquery objects and arrays into a single dimension array
+ flatten: function( arr ){
+ return $.map( arr, function( member ){
+ return member && member.jquery ? $.makeArray( member ) :
+ member && member.length ? drag.flatten( member ) : member;
+ });
+ },
+
+ // toggles text selection attributes ON (true) or OFF (false)
+ textselect: function( bool ){
+ $( document )[ bool ? "unbind" : "bind" ]("selectstart", drag.dontstart )
+ .css("MozUserSelect", bool ? "" : "none" );
+ // .attr("unselectable", bool ? "off" : "on" )
+ document.unselectable = bool ? "off" : "on";
+ },
+
+ // suppress "selectstart" and "ondragstart" events
+ dontstart: function(){
+ return false;
+ },
+
+ // a callback instance contructor
+ callback: function(){}
+
+};
+
+// callback methods
+drag.callback.prototype = {
+ update: function(){
+ if ( $special.drop && this.available.length )
+ $.each( this.available, function( i ){
+ $special.drop.locate( this, i );
+ });
+ }
+};
+
+// patch $.event.$dispatch to allow suppressing clicks
+var $dispatch = $event.dispatch;
+$event.dispatch = function( event ){
+ if ( $.data( this, "suppress."+ event.type ) - new Date().getTime() > 0 ){
+ $.removeData( this, "suppress."+ event.type );
+ return;
+ }
+ return $dispatch.apply( this, arguments );
+};
+
+// event fix hooks for touch events...
+var touchHooks =
+$event.fixHooks.touchstart =
+$event.fixHooks.touchmove =
+$event.fixHooks.touchend =
+$event.fixHooks.touchcancel = {
+ props: "clientX clientY pageX pageY screenX screenY".split( " " ),
+ filter: function( event, orig ) {
+ if ( orig ){
+ var touched = ( orig.touches && orig.touches[0] )
+ || ( orig.changedTouches && orig.changedTouches[0] )
+ || null;
+ // iOS webkit: touchstart, touchmove, touchend
+ if ( touched )
+ $.each( touchHooks.props, function( i, prop ){
+ event[ prop ] = touched[ prop ];
+ });
+ }
+ return event;
+ }
+};
+
+// share the same special event configuration with related events...
+$special.draginit = $special.dragstart = $special.dragend = drag;
+
+})( jQuery ); \ No newline at end of file
diff --git a/lib/jquery.event.drop-2.0.min.js b/lib/jquery.event.drop-2.0.min.js
deleted file mode 100644
index b988575..0000000
--- a/lib/jquery.event.drop-2.0.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
- * jquery.event.drop - v 2.0.0
- * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
- * Open Source MIT License - http://threedubmedia.com/code/license
- */
-;(function(f){f.fn.drop=function(c,a,d){var g=typeof c=="string"?c:"",e=f.isFunction(c)?c:f.isFunction(a)?a:null;if(g.indexOf("drop")!==0)g="drop"+g;d=(c==e?a:d)||{};return e?this.bind(g,d,e):this.trigger(g)};f.drop=function(c){c=c||{};b.multi=c.multi===true?Infinity:c.multi===false?1:!isNaN(c.multi)?c.multi:b.multi;b.delay=c.delay||b.delay;b.tolerance=f.isFunction(c.tolerance)?c.tolerance:c.tolerance===null?null:b.tolerance;b.mode=c.mode||b.mode||"intersect"};var l=f.event,i=l.special,b=f.event.special.drop= {multi:1,delay:20,mode:"overlap",targets:[],datakey:"dropdata",livekey:"livedrop",add:function(c){var a=f.data(this,b.datakey);a.related+=1;if(!a.live&&c.selector){a.live=true;l.add(this,"dropinit."+b.livekey,b.delegate)}},remove:function(){f.data(this,b.datakey).related-=1},setup:function(){if(!f.data(this,b.datakey)){f.data(this,b.datakey,{related:0,active:[],anyactive:0,winner:0,location:{}});b.targets.push(this)}},teardown:function(){if(!f.data(this,b.datakey).related){f.removeData(this,b.datakey); l.remove(this,"dropinit",b.delegate);var c=this;b.targets=f.grep(b.targets,function(a){return a!==c})}},handler:function(c,a){var d;if(a)switch(c.type){case "mousedown":d=f(b.targets);if(typeof a.drop=="string")d=d.filter(a.drop);d.each(function(){var g=f.data(this,b.datakey);g.active=[];g.anyactive=0;g.winner=0});a.droppable=d;b.delegates=[];i.drag.hijack(c,"dropinit",a);b.delegates=f.unique(i.drag.flatten(b.delegates));break;case "mousemove":b.event=c;b.timer||b.tolerate(a);break;case "mouseup":b.timer= clearTimeout(b.timer);if(a.propagates){i.drag.hijack(c,"drop",a);i.drag.hijack(c,"dropend",a);f.each(b.delegates||[],function(){l.remove(this,"."+b.livekey)})}break}},delegate:function(c){var a=[],d,g=f.data(this,"events")||{};f.each(g.live||[],function(e,h){if(h.preType.indexOf("drop")===0){d=f(c.currentTarget).find(h.selector);d.length&&d.each(function(){l.add(this,h.origType+"."+b.livekey,h.origHandler,h.data);f.inArray(this,a)<0&&a.push(this)})}});b.delegates.push(a);return a.length?f(a):false}, locate:function(c,a){var d=f.data(c,b.datakey),g=f(c),e=g.offset()||{},h=g.outerHeight();g=g.outerWidth();e={elem:c,width:g,height:h,top:e.top,left:e.left,right:e.left+g,bottom:e.top+h};if(d){d.location=e;d.index=a;d.elem=c}return e},contains:function(c,a){return(a[0]||a.left)>=c.left&&(a[0]||a.right)<=c.right&&(a[1]||a.top)>=c.top&&(a[1]||a.bottom)<=c.bottom},modes:{intersect:function(c,a,d){return this.contains(d,[c.pageX,c.pageY])?1E9:this.modes.overlap.apply(this,arguments)},overlap:function(c, a,d){return Math.max(0,Math.min(d.bottom,a.bottom)-Math.max(d.top,a.top))*Math.max(0,Math.min(d.right,a.right)-Math.max(d.left,a.left))},fit:function(c,a,d){return this.contains(d,a)?1:0},middle:function(c,a,d){return this.contains(d,[a.left+a.width*0.5,a.top+a.height*0.5])?1:0}},sort:function(c,a){return a.winner-c.winner||c.index-a.index},tolerate:function(c){var a,d,g,e,h,m,j=0,k,p=c.interactions.length,n=[b.event.pageX,b.event.pageY],o=b.tolerance||b.modes[b.mode];do if(k=c.interactions[j]){if(!k)return; k.drop=[];h=[];m=k.droppable.length;if(o)g=b.locate(k.proxy);a=0;do if(d=k.droppable[a]){e=f.data(d,b.datakey);if(d=e.location){e.winner=o?o.call(b,b.event,g,d):b.contains(d,n)?1:0;h.push(e)}}while(++a<m);h.sort(b.sort);a=0;do if(e=h[a])if(e.winner&&k.drop.length<b.multi){if(!e.active[j]&&!e.anyactive)if(i.drag.hijack(b.event,"dropstart",c,j,e.elem)[0]!==false){e.active[j]=1;e.anyactive+=1}else e.winner=0;e.winner&&k.drop.push(e.elem)}else if(e.active[j]&&e.anyactive==1){i.drag.hijack(b.event,"dropend", c,j,e.elem);e.active[j]=0;e.anyactive-=1}while(++a<m)}while(++j<p);if(b.last&&n[0]==b.last.pageX&&n[1]==b.last.pageY)delete b.timer;else b.timer=setTimeout(function(){b.tolerate(c)},b.delay);b.last=b.event}};i.dropinit=i.dropstart=i.dropend=b})(jQuery); \ No newline at end of file
diff --git a/lib/jquery.event.drop-2.2.js b/lib/jquery.event.drop-2.2.js
new file mode 100644
index 0000000..7599ef9
--- /dev/null
+++ b/lib/jquery.event.drop-2.2.js
@@ -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