/**
* Interface Elements for jQuery
* Droppables
*
* http://interface.eyecon.ro
*
* Copyright (c) 2006 Stefan Petre
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
*
*/
/**
* With the Draggables plugin, Droppable allows you to create drop zones for draggable elements.
*
* @name Droppable
* @cat Plugins/Interface
* @param Hash options A hash of options
* @option String accept The class name for draggables to get accepted by the droppable (mandatory)
* @option String activeclass When an acceptable draggable is moved, the droppable gets this class
* @option String hoverclass When an acceptable draggable is inside the droppable, the droppable gets
* this class
* @option String tolerance Choose from 'pointer', 'intersect', or 'fit'. The pointer options means
* that the pointer must be inside the droppable in order for the draggable
* to be dropped. The intersect option means that the draggable must intersect
* the droppable. The fit option means that the entire draggable must be
* inside the droppable.
* @option Function onDrop When an acceptable draggable is dropped on a droppable, this callback is
* called. It passes the draggable DOMElement as a parameter.
* @option Function onHover When an acceptable draggable is hovered over a droppable, this callback
* is called. It passes the draggable DOMElement as a parameter.
* @option Function onOut When an acceptable draggable leaves a droppable, this callback is called.
* It passes the draggable DOMElement as a parameter.
* @example $('#dropzone1').Droppable(
* {
* accept : 'dropaccept',
* activeclass: 'dropzoneactive',
* hoverclass: 'dropzonehover',
* ondrop: function (drag) {
* alert(this); //the droppable
* alert(drag); //the draggable
* },
* fit: true
* }
* )
*/
jQuery.iDrop = {
fit : function (zonex, zoney, zonew, zoneh)
{
return zonex <= jQuery.iDrag.dragged.dragCfg.nx &&
(zonex + zonew) >= (jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.w) &&
zoney <= jQuery.iDrag.dragged.dragCfg.ny &&
(zoney + zoneh) >= (jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.h) ? true :false;
},
intersect : function (zonex, zoney, zonew, zoneh)
{
return ! ( zonex > (jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.w)
|| (zonex + zonew) < jQuery.iDrag.dragged.dragCfg.nx
|| zoney > (jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.h)
|| (zoney + zoneh) < jQuery.iDrag.dragged.dragCfg.ny
) ? true :false;
},
pointer : function (zonex, zoney, zonew, zoneh)
{
return zonex < jQuery.iDrag.dragged.dragCfg.currentPointer.x
&& (zonex + zonew) > jQuery.iDrag.dragged.dragCfg.currentPointer.x
&& zoney < jQuery.iDrag.dragged.dragCfg.currentPointer.y
&& (zoney + zoneh) > jQuery.iDrag.dragged.dragCfg.currentPointer.y
? true :false;
},
overzone : false,
highlighted : {},
count : 0,
zones : {},
highlight : function (elm)
{
if (jQuery.iDrag.dragged == null) {
return;
}
var i;
jQuery.iDrop.highlighted = {};
var oneIsSortable = false;
for (i in jQuery.iDrop.zones) {
if (jQuery.iDrop.zones[i] != null) {
var iEL = jQuery.iDrop.zones[i].get(0);
if (jQuery(jQuery.iDrag.dragged).is('.' + iEL.dropCfg.a)) {
if (iEL.dropCfg.m == false) {
iEL.dropCfg.p = jQuery.extend(
jQuery.iUtil.getPositionLite(iEL),
jQuery.iUtil.getSizeLite(iEL)
);//jQuery.iUtil.getPos(iEL);
iEL.dropCfg.m = true;
}
if (iEL.dropCfg.ac) {
jQuery.iDrop.zones[i].addClass(iEL.dropCfg.ac);
}
jQuery.iDrop.highlighted[i] = jQuery.iDrop.zones[i];
//if (jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) {
if (jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) {
iEL.dropCfg.el = jQuery('.' + iEL.dropCfg.a, iEL);
elm.style.display = 'none';
jQuery.iSort.measure(iEL);
iEL.dropCfg.os = jQuery.iSort.serialize(jQuery.attr(iEL, 'id')).hash;
elm.style.display = elm.dragCfg.oD;
oneIsSortable = true;
}
if (iEL.dropCfg.onActivate) {
iEL.dropCfg.onActivate.apply(jQuery.iDrop.zones[i].get(0), [jQuery.iDrag.dragged]);
}
}
}
}
//if (jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) {
if (oneIsSortable) {
jQuery.iSort.start();
}
},
/**
* remeasure the droppable
*
* useful when the positions/dimensions for droppables
* are changed while dragging a element
*
* this works for sortables too but with a greate processor
* penality because remeasures each sort items too
*/
remeasure : function()
{
jQuery.iDrop.highlighted = {};
for (i in jQuery.iDrop.zones) {
if (jQuery.iDrop.zones[i] != null) {
var iEL = jQuery.iDrop.zones[i].get(0);
if (jQuery(jQuery.iDrag.dragged).is('.' + iEL.dropCfg.a)) {
iEL.dropCfg.p = jQuery.extend(
jQuery.iUtil.getPositionLite(iEL),
jQuery.iUtil.getSizeLite(iEL)
);
if (iEL.dropCfg.ac) {
jQuery.iDrop.zones[i].addClass(iEL.dropCfg.ac);
}
jQuery.iDrop.highlighted[i] = jQuery.iDrop.zones[i];
if (jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) {
iEL.dropCfg.el = jQuery('.' + iEL.dropCfg.a, iEL);
elm.style.display = 'none';
jQuery.iSort.measure(iEL);
elm.style.display = elm.dragCfg.oD;
}
}
}
}
},
checkhover : function (e)
{
if (jQuery.iDrag.dragged == null) {
return;
}
jQuery.iDrop.overzone = false;
var i;
var applyOnHover = false;
var hlt = 0;
for (i in jQuery.iDrop.highlighted)
{
var iEL = jQuery.iDrop.highlighted[i].get(0);
if (
jQuery.iDrop.overzone == false
&&
jQuery.iDrop[iEL.dropCfg.t](
iEL.dropCfg.p.x,
iEL.dropCfg.p.y,
iEL.dropCfg.p.wb,
iEL.dropCfg.p.hb
)
) {
if (iEL.dropCfg.hc && iEL.dropCfg.h == false) {
jQuery.iDrop.highlighted[i].addClass(iEL.dropCfg.hc);
}
//chec if onHover function has to be called
if (iEL.dropCfg.h == false &&iEL.dropCfg.onHover) {
applyOnHover = true;
}
iEL.dropCfg.h = true;
jQuery.iDrop.overzone = iEL;
//if(jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) {
if(jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) {
jQuery.iSort.helper.get(0).className = iEL.dropCfg.shc;
jQuery.iSort.checkhover(iEL);
}
hlt ++;
} else if(iEL.dropCfg.h == true) {
//onOut function
if (iEL.dropCfg.onOut) {
iEL.dropCfg.onOut.apply(iEL, [e, jQuery.iDrag.helper.get(0).firstChild, iEL.dropCfg.fx]);
}
if (iEL.dropCfg.hc) {
jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.hc);
}
iEL.dropCfg.h = false;
}
}
if (jQuery.iSort && !jQuery.iDrop.overzone && jQuery.iDrag.dragged.so) {
jQuery.iSort.helper.get(0).style.display = 'none';
//jQuery('body').append(jQuery.iSort.helper.get(0));
}
//call onhover
if(applyOnHover) {
jQuery.iDrop.overzone.dropCfg.onHover.apply(jQuery.iDrop.overzone, [e, jQuery.iDrag.helper.get(0).firstChild]);
}
},
checkdrop : function (e)
{
var i;
for (i in jQuery.iDrop.highlighted) {
var iEL = jQuery.iDrop.highlighted[i].get(0);
if (iEL.dropCfg.ac) {
jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.ac);
}
if (iEL.dropCfg.hc) {
jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.hc);
}
if(iEL.dropCfg.s) {
jQuery.iSort.changed[jQuery.iSort.changed.length] = i;
}
if (iEL.dropCfg.onDrop && iEL.dropCfg.h == true) {
iEL.dropCfg.h = false;
iEL.dropCfg.onDrop.apply(iEL, [e, iEL.dropCfg.fx]);
}
iEL.dropCfg.m = false;
iEL.dropCfg.h = false;
}
jQuery.iDrop.highlighted = {};
},
destroy : function()
{
return this.each(
function()
{
if (this.isDroppable) {
if (this.dropCfg.s) {
id = jQuery.attr(this,'id');
jQuery.iSort.collected[id] = null;
jQuery('.' + this.dropCfg.a, this).DraggableDestroy();
}
jQuery.iDrop.zones['d' + this.idsa] = null;
this.isDroppable = false;
this.f = null;
}
}
);
},
build : function (o)
{
return this.each(
function()
{
if (this.isDroppable == true || !o.accept || !jQuery.iUtil || !jQuery.iDrag){
return;
}
this.dropCfg = {
a : o.accept,
ac: o.activeclass||false,
hc: o.hoverclass||false,
shc: o.helperclass||false,
onDrop: o.ondrop||o.onDrop||false,
onHover: o.onHover||o.onhover||false,
onOut: o.onOut||o.onout||false,
onActivate: o.onActivate||false,
t: o.tolerance && ( o.tolerance == 'fit' || o.tolerance == 'intersect') ? o.tolerance : 'pointer',
fx: o.fx ? o.fx : false,
m: false,
h: false
};
if (o.sortable == true && jQuery.iSort) {
id = jQuery.attr(this,'id');
jQuery.iSort.collected[id] = this.dropCfg.a;
this.dropCfg.s = true;
if(o.onChange) {
this.dropCfg.onChange = o.onChange;
this.dropCfg.os = jQuery.iSort.serialize(id).hash;
}
}
this.isDroppable = true;
this.idsa = parseInt(Math.random() * 10000);
jQuery.iDrop.zones['d' + this.idsa] = jQuery(this);
jQuery.iDrop.count ++;
}
);
}
};
/**
* Destroy an existing droppable on a collection of elements
*
* @name DroppableDestroy
* @descr Destroy a droppable
* @type jQuery
* @cat Plugins/Interface
* @example $('#drag2').DroppableDestroy();
*/
jQuery.fn.extend(
{
DroppableDestroy : jQuery.iDrop.destroy,
Droppable : jQuery.iDrop.build
}
);
/**
* Recalculate all Droppables
*
* @name $.recallDroppables
* @type jQuery
* @cat Plugins/Interface
* @example $.recallDroppable();
*/
jQuery.recallDroppables = jQuery.iDrop.remeasure;