|
1 /** |
|
2 * Interface Elements for jQuery |
|
3 * Droppables |
|
4 * |
|
5 * http://interface.eyecon.ro |
|
6 * |
|
7 * Copyright (c) 2006 Stefan Petre |
|
8 * Dual licensed under the MIT (MIT-LICENSE.txt) |
|
9 * and GPL (GPL-LICENSE.txt) licenses. |
|
10 * |
|
11 * |
|
12 */ |
|
13 |
|
14 /** |
|
15 * With the Draggables plugin, Droppable allows you to create drop zones for draggable elements. |
|
16 * |
|
17 * @name Droppable |
|
18 * @cat Plugins/Interface |
|
19 * @param Hash options A hash of options |
|
20 * @option String accept The class name for draggables to get accepted by the droppable (mandatory) |
|
21 * @option String activeclass When an acceptable draggable is moved, the droppable gets this class |
|
22 * @option String hoverclass When an acceptable draggable is inside the droppable, the droppable gets |
|
23 * this class |
|
24 * @option String tolerance Choose from 'pointer', 'intersect', or 'fit'. The pointer options means |
|
25 * that the pointer must be inside the droppable in order for the draggable |
|
26 * to be dropped. The intersect option means that the draggable must intersect |
|
27 * the droppable. The fit option means that the entire draggable must be |
|
28 * inside the droppable. |
|
29 * @option Function onDrop When an acceptable draggable is dropped on a droppable, this callback is |
|
30 * called. It passes the draggable DOMElement as a parameter. |
|
31 * @option Function onHover When an acceptable draggable is hovered over a droppable, this callback |
|
32 * is called. It passes the draggable DOMElement as a parameter. |
|
33 * @option Function onOut When an acceptable draggable leaves a droppable, this callback is called. |
|
34 * It passes the draggable DOMElement as a parameter. |
|
35 * @example $('#dropzone1').Droppable( |
|
36 * { |
|
37 * accept : 'dropaccept', |
|
38 * activeclass: 'dropzoneactive', |
|
39 * hoverclass: 'dropzonehover', |
|
40 * ondrop: function (drag) { |
|
41 * alert(this); //the droppable |
|
42 * alert(drag); //the draggable |
|
43 * }, |
|
44 * fit: true |
|
45 * } |
|
46 * ) |
|
47 */ |
|
48 |
|
49 jQuery.iDrop = { |
|
50 fit : function (zonex, zoney, zonew, zoneh) |
|
51 { |
|
52 return zonex <= jQuery.iDrag.dragged.dragCfg.nx && |
|
53 (zonex + zonew) >= (jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.w) && |
|
54 zoney <= jQuery.iDrag.dragged.dragCfg.ny && |
|
55 (zoney + zoneh) >= (jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.h) ? true :false; |
|
56 }, |
|
57 intersect : function (zonex, zoney, zonew, zoneh) |
|
58 { |
|
59 return ! ( zonex > (jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.w) |
|
60 || (zonex + zonew) < jQuery.iDrag.dragged.dragCfg.nx |
|
61 || zoney > (jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.h) |
|
62 || (zoney + zoneh) < jQuery.iDrag.dragged.dragCfg.ny |
|
63 ) ? true :false; |
|
64 }, |
|
65 pointer : function (zonex, zoney, zonew, zoneh) |
|
66 { |
|
67 return zonex < jQuery.iDrag.dragged.dragCfg.currentPointer.x |
|
68 && (zonex + zonew) > jQuery.iDrag.dragged.dragCfg.currentPointer.x |
|
69 && zoney < jQuery.iDrag.dragged.dragCfg.currentPointer.y |
|
70 && (zoney + zoneh) > jQuery.iDrag.dragged.dragCfg.currentPointer.y |
|
71 ? true :false; |
|
72 }, |
|
73 overzone : false, |
|
74 highlighted : {}, |
|
75 count : 0, |
|
76 zones : {}, |
|
77 |
|
78 highlight : function (elm) |
|
79 { |
|
80 if (jQuery.iDrag.dragged == null) { |
|
81 return; |
|
82 } |
|
83 var i; |
|
84 jQuery.iDrop.highlighted = {}; |
|
85 var oneIsSortable = false; |
|
86 for (i in jQuery.iDrop.zones) { |
|
87 if (jQuery.iDrop.zones[i] != null) { |
|
88 var iEL = jQuery.iDrop.zones[i].get(0); |
|
89 if (jQuery(jQuery.iDrag.dragged).is('.' + iEL.dropCfg.a)) { |
|
90 if (iEL.dropCfg.m == false) { |
|
91 iEL.dropCfg.p = jQuery.extend( |
|
92 jQuery.iUtil.getPositionLite(iEL), |
|
93 jQuery.iUtil.getSizeLite(iEL) |
|
94 );//jQuery.iUtil.getPos(iEL); |
|
95 iEL.dropCfg.m = true; |
|
96 } |
|
97 if (iEL.dropCfg.ac) { |
|
98 jQuery.iDrop.zones[i].addClass(iEL.dropCfg.ac); |
|
99 } |
|
100 jQuery.iDrop.highlighted[i] = jQuery.iDrop.zones[i]; |
|
101 //if (jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) { |
|
102 if (jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) { |
|
103 iEL.dropCfg.el = jQuery('.' + iEL.dropCfg.a, iEL); |
|
104 elm.style.display = 'none'; |
|
105 jQuery.iSort.measure(iEL); |
|
106 iEL.dropCfg.os = jQuery.iSort.serialize(jQuery.attr(iEL, 'id')).hash; |
|
107 elm.style.display = elm.dragCfg.oD; |
|
108 oneIsSortable = true; |
|
109 } |
|
110 if (iEL.dropCfg.onActivate) { |
|
111 iEL.dropCfg.onActivate.apply(jQuery.iDrop.zones[i].get(0), [jQuery.iDrag.dragged]); |
|
112 } |
|
113 } |
|
114 } |
|
115 } |
|
116 //if (jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) { |
|
117 if (oneIsSortable) { |
|
118 jQuery.iSort.start(); |
|
119 } |
|
120 }, |
|
121 /** |
|
122 * remeasure the droppable |
|
123 * |
|
124 * useful when the positions/dimensions for droppables |
|
125 * are changed while dragging a element |
|
126 * |
|
127 * this works for sortables too but with a greate processor |
|
128 * penality because remeasures each sort items too |
|
129 */ |
|
130 remeasure : function() |
|
131 { |
|
132 jQuery.iDrop.highlighted = {}; |
|
133 for (i in jQuery.iDrop.zones) { |
|
134 if (jQuery.iDrop.zones[i] != null) { |
|
135 var iEL = jQuery.iDrop.zones[i].get(0); |
|
136 if (jQuery(jQuery.iDrag.dragged).is('.' + iEL.dropCfg.a)) { |
|
137 iEL.dropCfg.p = jQuery.extend( |
|
138 jQuery.iUtil.getPositionLite(iEL), |
|
139 jQuery.iUtil.getSizeLite(iEL) |
|
140 ); |
|
141 if (iEL.dropCfg.ac) { |
|
142 jQuery.iDrop.zones[i].addClass(iEL.dropCfg.ac); |
|
143 } |
|
144 jQuery.iDrop.highlighted[i] = jQuery.iDrop.zones[i]; |
|
145 |
|
146 if (jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) { |
|
147 iEL.dropCfg.el = jQuery('.' + iEL.dropCfg.a, iEL); |
|
148 elm.style.display = 'none'; |
|
149 jQuery.iSort.measure(iEL); |
|
150 elm.style.display = elm.dragCfg.oD; |
|
151 } |
|
152 } |
|
153 } |
|
154 } |
|
155 }, |
|
156 |
|
157 checkhover : function (e) |
|
158 { |
|
159 if (jQuery.iDrag.dragged == null) { |
|
160 return; |
|
161 } |
|
162 jQuery.iDrop.overzone = false; |
|
163 var i; |
|
164 var applyOnHover = false; |
|
165 var hlt = 0; |
|
166 for (i in jQuery.iDrop.highlighted) |
|
167 { |
|
168 var iEL = jQuery.iDrop.highlighted[i].get(0); |
|
169 if ( |
|
170 jQuery.iDrop.overzone == false |
|
171 && |
|
172 jQuery.iDrop[iEL.dropCfg.t]( |
|
173 iEL.dropCfg.p.x, |
|
174 iEL.dropCfg.p.y, |
|
175 iEL.dropCfg.p.wb, |
|
176 iEL.dropCfg.p.hb |
|
177 ) |
|
178 |
|
179 ) { |
|
180 if (iEL.dropCfg.hc && iEL.dropCfg.h == false) { |
|
181 jQuery.iDrop.highlighted[i].addClass(iEL.dropCfg.hc); |
|
182 } |
|
183 //chec if onHover function has to be called |
|
184 if (iEL.dropCfg.h == false &&iEL.dropCfg.onHover) { |
|
185 applyOnHover = true; |
|
186 } |
|
187 iEL.dropCfg.h = true; |
|
188 jQuery.iDrop.overzone = iEL; |
|
189 //if(jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) { |
|
190 if(jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) { |
|
191 jQuery.iSort.helper.get(0).className = iEL.dropCfg.shc; |
|
192 jQuery.iSort.checkhover(iEL); |
|
193 } |
|
194 hlt ++; |
|
195 } else if(iEL.dropCfg.h == true) { |
|
196 //onOut function |
|
197 if (iEL.dropCfg.onOut) { |
|
198 iEL.dropCfg.onOut.apply(iEL, [e, jQuery.iDrag.helper.get(0).firstChild, iEL.dropCfg.fx]); |
|
199 } |
|
200 if (iEL.dropCfg.hc) { |
|
201 jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.hc); |
|
202 } |
|
203 iEL.dropCfg.h = false; |
|
204 } |
|
205 } |
|
206 if (jQuery.iSort && !jQuery.iDrop.overzone && jQuery.iDrag.dragged.so) { |
|
207 jQuery.iSort.helper.get(0).style.display = 'none'; |
|
208 //jQuery('body').append(jQuery.iSort.helper.get(0)); |
|
209 } |
|
210 //call onhover |
|
211 if(applyOnHover) { |
|
212 jQuery.iDrop.overzone.dropCfg.onHover.apply(jQuery.iDrop.overzone, [e, jQuery.iDrag.helper.get(0).firstChild]); |
|
213 } |
|
214 }, |
|
215 checkdrop : function (e) |
|
216 { |
|
217 var i; |
|
218 for (i in jQuery.iDrop.highlighted) { |
|
219 var iEL = jQuery.iDrop.highlighted[i].get(0); |
|
220 if (iEL.dropCfg.ac) { |
|
221 jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.ac); |
|
222 } |
|
223 if (iEL.dropCfg.hc) { |
|
224 jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.hc); |
|
225 } |
|
226 if(iEL.dropCfg.s) { |
|
227 jQuery.iSort.changed[jQuery.iSort.changed.length] = i; |
|
228 } |
|
229 if (iEL.dropCfg.onDrop && iEL.dropCfg.h == true) { |
|
230 iEL.dropCfg.h = false; |
|
231 iEL.dropCfg.onDrop.apply(iEL, [e, iEL.dropCfg.fx]); |
|
232 } |
|
233 iEL.dropCfg.m = false; |
|
234 iEL.dropCfg.h = false; |
|
235 } |
|
236 jQuery.iDrop.highlighted = {}; |
|
237 }, |
|
238 destroy : function() |
|
239 { |
|
240 return this.each( |
|
241 function() |
|
242 { |
|
243 if (this.isDroppable) { |
|
244 if (this.dropCfg.s) { |
|
245 id = jQuery.attr(this,'id'); |
|
246 jQuery.iSort.collected[id] = null; |
|
247 jQuery('.' + this.dropCfg.a, this).DraggableDestroy(); |
|
248 } |
|
249 jQuery.iDrop.zones['d' + this.idsa] = null; |
|
250 this.isDroppable = false; |
|
251 this.f = null; |
|
252 } |
|
253 } |
|
254 ); |
|
255 }, |
|
256 build : function (o) |
|
257 { |
|
258 return this.each( |
|
259 function() |
|
260 { |
|
261 if (this.isDroppable == true || !o.accept || !jQuery.iUtil || !jQuery.iDrag){ |
|
262 return; |
|
263 } |
|
264 this.dropCfg = { |
|
265 a : o.accept, |
|
266 ac: o.activeclass||false, |
|
267 hc: o.hoverclass||false, |
|
268 shc: o.helperclass||false, |
|
269 onDrop: o.ondrop||o.onDrop||false, |
|
270 onHover: o.onHover||o.onhover||false, |
|
271 onOut: o.onOut||o.onout||false, |
|
272 onActivate: o.onActivate||false, |
|
273 t: o.tolerance && ( o.tolerance == 'fit' || o.tolerance == 'intersect') ? o.tolerance : 'pointer', |
|
274 fx: o.fx ? o.fx : false, |
|
275 m: false, |
|
276 h: false |
|
277 }; |
|
278 if (o.sortable == true && jQuery.iSort) { |
|
279 id = jQuery.attr(this,'id'); |
|
280 jQuery.iSort.collected[id] = this.dropCfg.a; |
|
281 this.dropCfg.s = true; |
|
282 if(o.onChange) { |
|
283 this.dropCfg.onChange = o.onChange; |
|
284 this.dropCfg.os = jQuery.iSort.serialize(id).hash; |
|
285 } |
|
286 } |
|
287 this.isDroppable = true; |
|
288 this.idsa = parseInt(Math.random() * 10000); |
|
289 jQuery.iDrop.zones['d' + this.idsa] = jQuery(this); |
|
290 jQuery.iDrop.count ++; |
|
291 } |
|
292 ); |
|
293 } |
|
294 }; |
|
295 |
|
296 /** |
|
297 * Destroy an existing droppable on a collection of elements |
|
298 * |
|
299 * @name DroppableDestroy |
|
300 * @descr Destroy a droppable |
|
301 * @type jQuery |
|
302 * @cat Plugins/Interface |
|
303 * @example $('#drag2').DroppableDestroy(); |
|
304 */ |
|
305 |
|
306 jQuery.fn.extend( |
|
307 { |
|
308 DroppableDestroy : jQuery.iDrop.destroy, |
|
309 Droppable : jQuery.iDrop.build |
|
310 } |
|
311 ); |
|
312 |
|
313 |
|
314 /** |
|
315 * Recalculate all Droppables |
|
316 * |
|
317 * @name $.recallDroppables |
|
318 * @type jQuery |
|
319 * @cat Plugins/Interface |
|
320 * @example $.recallDroppable(); |
|
321 */ |
|
322 |
|
323 jQuery.recallDroppables = jQuery.iDrop.remeasure; |