/* * jQuery UI Droppable * * Copyright (c) 2008 Paul Bakaus * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. *  * http://docs.jquery.com/UI/Droppables * * Depends: *	ui.core.js *	ui.draggable.js */(function($) {$.widget("ui.droppable", {init: function() {var o = this.options, accept = o.accept;this.isover = 0; this.isout = 1;this.options.accept = this.options.accept && this.options.accept.constructor == Function ? this.options.accept : function(d) {return d.is(accept);};//Store the droppable's proportionsthis.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };// Add the reference and positions to the manager$.ui.ddmanager.droppables[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];$.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.cssNamespace && this.element.addClass(this.options.cssNamespace+"-droppable"));},plugins: {},ui: function(c) {return {draggable: (c.currentItem || c.element),helper: c.helper,position: c.position,absolutePosition: c.positionAbs,options: this.options,element: this.element};},destroy: function() {var drop = $.ui.ddmanager.droppables[this.options.scope];for ( var i = 0; i < drop.length; i++ )if ( drop[i] == this )drop.splice(i, 1);this.element.removeClass("ui-droppable-disabled").removeData("droppable").unbind(".droppable");},over: function(e) {var draggable = $.ui.ddmanager.current;if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same elementif (this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {$.ui.plugin.call(this, 'over', [e, this.ui(draggable)]);this.element.triggerHandler("dropover", [e, this.ui(draggable)], this.options.over);}},out: function(e) {var draggable = $.ui.ddmanager.current;if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same elementif (this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {$.ui.plugin.call(this, 'out', [e, this.ui(draggable)]);this.element.triggerHandler("dropout", [e, this.ui(draggable)], this.options.out);}},drop: function(e,custom) {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var childrenIntersection = false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {var inst = $.data(this, 'droppable');if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {childrenIntersection = true; return false;}});if(childrenIntersection) return false;if(this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {$.ui.plugin.call(this, 'drop', [e, this.ui(draggable)]);this.element.triggerHandler("drop", [e, this.ui(draggable)], this.options.drop);return true;}return false;},activate: function(e) {var draggable = $.ui.ddmanager.current;$.ui.plugin.call(this, 'activate', [e, this.ui(draggable)]);if(draggable) this.element.triggerHandler("dropactivate", [e, this.ui(draggable)], this.options.activate);},deactivate: function(e) {var draggable = $.ui.ddmanager.current;$.ui.plugin.call(this, 'deactivate', [e, this.ui(draggable)]);if(draggable) this.element.triggerHandler("dropdeactivate", [e, this.ui(draggable)], this.options.deactivate);}});$.extend($.ui.droppable, {defaults: {disabled: false,tolerance: 'intersect',scope: 'default',cssNamespace: 'ui'}});$.ui.intersect = function(draggable, droppable, toleranceMode) {if (!droppable.offset) return false;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;switch (toleranceMode) {case 'fit':return (l < x1 && x2 < r&& t < y1 && y2 < b);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':return (l < ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left) && ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left) < r&& t < ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top) && ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top) < b);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;}};/*This manager tracks offsets of draggables and droppables*/$.ui.ddmanager = {current: null,droppables: { 'default': [] },prepareOffsets: function(t, e) {var m = $.ui.ddmanager.droppables[t.options.scope];var type = e ? e.type : null; // workaround for #2317var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();	droppablesLoop: for (var i = 0; i < m.length; i++) {if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element,(t.currentItem || t.element)))) continue;	//No disabled and non-accepted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m[i].offset = m[i].element.offset();m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };if(type == "dragstart" || type == "sortactivate") m[i].activate.call(m[i], e); 										//Activate the droppable if used directly from draggables}},drop: function(draggable, e) {var dropped = false;$.each($.ui.ddmanager.droppables[draggable.options.scope], function() {if(!this.options) return;if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))dropped = this.drop.call(this, e);if (!this.options.disabled && this.visible && this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {this.isout = 1; this.isover = 0;this.deactivate.call(this, e);}});return dropped;},drag: function(draggable, e) {//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, e);//Run through all droppables and check their positions based on specific tolerance options$.each($.ui.ddmanager.droppables[draggable.options.scope], function() {if(this.options.disabled || this.greedyChild || !this.visible) return;var intersects = $.ui.intersect(draggable, this, this.options.tolerance);var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);if(!c) return;var parentInstance;if (this.options.greedy) {var parent = this.element.parents(':data(droppable):eq(0)');if (parent.length) {parentInstance = $.data(parent[0], 'droppable');parentInstance.greedyChild = (c == 'isover' ? 1 : 0);}}// we just moved into a greedy childif (parentInstance && c == 'isover') {parentInstance['isover'] = 0;parentInstance['isout'] = 1;parentInstance.out.call(parentInstance, e);}this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;this[c == "isover" ? "over" : "out"].call(this, e);// we just moved out of a greedy childif (parentInstance && c == 'isout') {parentInstance['isout'] = 0;parentInstance['isover'] = 1;parentInstance.over.call(parentInstance, e);}});}};/* * Droppable Extensions */$.ui.plugin.add("droppable", "activeClass", {activate: function(e, ui) {$(this).addClass(ui.options.activeClass);},deactivate: function(e, ui) {$(this).removeClass(ui.options.activeClass);},drop: function(e, ui) {$(this).removeClass(ui.options.activeClass);}});$.ui.plugin.add("droppable", "hoverClass", {over: function(e, ui) {$(this).addClass(ui.options.hoverClass);},out: function(e, ui) {$(this).removeClass(ui.options.hoverClass);},drop: function(e, ui) {$(this).removeClass(ui.options.hoverClass);}});})(jQuery);