]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/dd/dd-ddm-drop.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / dd / dd-ddm-drop.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('dd-ddm-drop', function(Y) {
9
10
11     /**
12      * Extends the dd-ddm Class to add support for the placement of Drop Target shims inside the viewport shim. It also handles all Drop Target related events and interactions.
13      * @module dd
14      * @submodule dd-ddm-drop
15      * @for DDM
16      * @namespace DD
17      */
18
19     //TODO CSS class name for the bestMatch..
20     Y.mix(Y.DD.DDM, {
21         /**
22         * @private
23         * @property _noShim
24         * @description This flag turns off the use of the mouseover/mouseout shim. It should not be used unless you know what you are doing.
25         * @type {Boolean}
26         */
27         _noShim: false,
28         /**
29         * @private
30         * @property _activeShims
31         * @description Placeholder for all active shims on the page
32         * @type {Array}
33         */
34         _activeShims: [],
35         /**
36         * @private
37         * @method _hasActiveShim
38         * @description This method checks the _activeShims Object to see if there is a shim active.
39         * @return {Boolean}
40         */
41         _hasActiveShim: function() {
42             if (this._noShim) {
43                 return true;
44             }
45             return this._activeShims.length;
46         },
47         /**
48         * @private
49         * @method _addActiveShim 
50         * @description Adds a Drop Target to the list of active shims
51         * @param {Object} d The Drop instance to add to the list.
52         */
53         _addActiveShim: function(d) {
54             this._activeShims[this._activeShims.length] = d;
55         },
56         /**
57         * @private
58         * @method _removeActiveShim 
59         * @description Removes a Drop Target to the list of active shims
60         * @param {Object} d The Drop instance to remove from the list.
61         */
62         _removeActiveShim: function(d) {
63             var s = [];
64             Y.each(this._activeShims, function(v, k) {
65                 if (v._yuid !== d._yuid) {
66                     s[s.length] = v;
67                 }
68                 
69             });
70             this._activeShims = s;
71         },
72         /**
73         * @method syncActiveShims
74         * @description This method will sync the position of the shims on the Drop Targets that are currently active.
75         * @param {Boolean} force Resize/sync all Targets.
76         */
77         syncActiveShims: function(force) {
78             Y.later(0, this, function(force) {
79                 var drops = ((force) ? this.targets : this._lookup());
80                 Y.each(drops, function(v, k) {
81                     v.sizeShim.call(v);
82                 }, this);
83             }, force);
84         },
85         /**
86         * @private
87         * @property mode
88         * @description The mode that the drag operations will run in 0 for Point, 1 for Intersect, 2 for Strict
89         * @type Number
90         */
91         mode: 0,
92         /**
93         * @private
94         * @property POINT
95         * @description In point mode, a Drop is targeted by the cursor being over the Target
96         * @type Number
97         */
98         POINT: 0,
99         /**
100         * @private
101         * @property INTERSECT
102         * @description In intersect mode, a Drop is targeted by "part" of the drag node being over the Target
103         * @type Number
104         */
105         INTERSECT: 1,
106         /**
107         * @private
108         * @property STRICT
109         * @description In strict mode, a Drop is targeted by the "entire" drag node being over the Target
110         * @type Number
111         */
112         STRICT: 2,
113         /**
114         * @property useHash
115         * @description Should we only check targets that are in the viewport on drags (for performance), default: true
116         * @type {Boolean}
117         */
118         useHash: true,
119         /**
120         * @property activeDrop
121         * @description A reference to the active Drop Target
122         * @type {Object}
123         */
124         activeDrop: null,
125         /**
126         * @property validDrops
127         * @description An array of the valid Drop Targets for this interaction.
128         * @type {Array}
129         */
130         //TODO Change array/object literals to be in sync..
131         validDrops: [],
132         /**
133         * @property otherDrops
134         * @description An object literal of Other Drop Targets that we encountered during this interaction (in the case of overlapping Drop Targets)
135         * @type {Object}
136         */
137         otherDrops: {},
138         /**
139         * @property targets
140         * @description All of the Targets
141         * @type {Array}
142         */
143         targets: [],
144         /**
145         * @private 
146         * @method _addValid
147         * @description Add a Drop Target to the list of Valid Targets. This list get's regenerated on each new drag operation.
148         * @param {Object} drop
149         * @return {Self}
150         * @chainable
151         */
152         _addValid: function(drop) {
153             this.validDrops[this.validDrops.length] = drop;
154             return this;
155         },
156         /**
157         * @private 
158         * @method _removeValid
159         * @description Removes a Drop Target from the list of Valid Targets. This list get's regenerated on each new drag operation.
160         * @param {Object} drop
161         * @return {Self}
162         * @chainable
163         */
164         _removeValid: function(drop) {
165             var drops = [];
166             Y.each(this.validDrops, function(v, k) {
167                 if (v !== drop) {
168                     drops[drops.length] = v;
169                 }
170             });
171
172             this.validDrops = drops;
173             return this;
174         },
175         /**
176         * @method isOverTarget
177         * @description Check to see if the Drag element is over the target, method varies on current mode
178         * @param {Object} drop The drop to check against
179         * @return {Boolean}
180         */
181         isOverTarget: function(drop) {
182             if (this.activeDrag && drop) {
183                 var xy = this.activeDrag.mouseXY, r, dMode = this.activeDrag.get('dragMode'),
184                     aRegion, node = drop.shim;
185                 if (xy && this.activeDrag) {
186                     aRegion = this.activeDrag.region;
187                     if (dMode == this.STRICT) {
188                         return this.activeDrag.get('dragNode').inRegion(drop.region, true, aRegion);
189                     } else {
190                         if (drop && drop.shim) {
191                             if ((dMode == this.INTERSECT) && this._noShim) {
192                                 r = ((aRegion) ? aRegion : this.activeDrag.get('node'));
193                                 return drop.get('node').intersect(r, drop.region).inRegion;
194                             } else {
195                                 if (this._noShim) {
196                                     node = drop.get('node');
197                                 }
198                                 return node.intersect({
199                                     top: xy[1],
200                                     bottom: xy[1],
201                                     left: xy[0], 
202                                     right: xy[0]
203                                 }, drop.region).inRegion;
204                             }
205                         } else {
206                             return false;
207                         }
208                     }
209                 } else {
210                     return false;
211                 }
212             } else {
213                 return false;
214             }
215         },
216         /**
217         * @method clearCache
218         * @description Clears the cache data used for this interaction.
219         */
220         clearCache: function() {
221             this.validDrops = [];
222             this.otherDrops = {};
223             this._activeShims = [];
224         },
225         /**
226         * @private
227         * @method _activateTargets
228         * @description Clear the cache and activate the shims of all the targets
229         */
230         _activateTargets: function() {
231             this._noShim = true;
232             this.clearCache();
233             Y.each(this.targets, function(v, k) {
234                 v._activateShim([]);
235                 if (v.get('noShim') == true) {
236                     this._noShim = false;
237                 }
238             }, this);
239             this._handleTargetOver();
240             
241         },
242         /**
243         * @method getBestMatch
244         * @description This method will gather the area for all potential targets and see which has the hightest covered area and return it.
245         * @param {Array} drops An Array of drops to scan for the best match.
246         * @param {Boolean} all If present, it returns an Array. First item is best match, second is an Array of the other items in the original Array.
247         * @return {Object or Array} 
248         */
249         getBestMatch: function(drops, all) {
250             var biggest = null, area = 0, out;
251             
252             Y.each(drops, function(v, k) {
253                 var inter = this.activeDrag.get('dragNode').intersect(v.get('node'));
254                 v.region.area = inter.area;
255
256                 if (inter.inRegion) {
257                     if (inter.area > area) {
258                         area = inter.area;
259                         biggest = v;
260                     }
261                 }
262             }, this);
263             if (all) {
264                 out = [];
265                 //TODO Sort the others in numeric order by area covered..
266                 Y.each(drops, function(v, k) {
267                     if (v !== biggest) {
268                         out[out.length] = v;
269                     }
270                 }, this);
271                 return [biggest, out];
272             } else {
273                 return biggest;
274             }
275         },
276         /**
277         * @private
278         * @method _deactivateTargets
279         * @description This method fires the drop:hit, drag:drophit, drag:dropmiss methods and deactivates the shims..
280         */
281         _deactivateTargets: function() {
282             var other = [], tmp,
283                 activeDrag = this.activeDrag,
284                 activeDrop = this.activeDrop;
285             
286             //TODO why is this check so hard??
287             if (activeDrag && activeDrop && this.otherDrops[activeDrop]) {
288                 if (!activeDrag.get('dragMode')) {
289                     //TODO otherDrops -- private..
290                     other = this.otherDrops;
291                     delete other[activeDrop];
292                 } else {
293                     tmp = this.getBestMatch(this.otherDrops, true);
294                     activeDrop = tmp[0];
295                     other = tmp[1];
296                 }
297                 activeDrag.get('node').removeClass(this.CSS_PREFIX + '-drag-over');
298                 if (activeDrop) {
299                     activeDrop.fire('drop:hit', { drag: activeDrag, drop: activeDrop, others: other });
300                     activeDrag.fire('drag:drophit', { drag: activeDrag,  drop: activeDrop, others: other });
301                 }
302             } else if (activeDrag && activeDrag.get('dragging')) {
303                 activeDrag.get('node').removeClass(this.CSS_PREFIX + '-drag-over');
304                 activeDrag.fire('drag:dropmiss', { pageX: activeDrag.lastXY[0], pageY: activeDrag.lastXY[1] });
305             } else {
306             }
307             
308             this.activeDrop = null;
309
310             Y.each(this.targets, function(v, k) {
311                 v._deactivateShim([]);
312             }, this);
313         },
314         /**
315         * @private
316         * @method _dropMove
317         * @description This method is called when the move method is called on the Drag Object.
318         */
319         _dropMove: function() {
320             if (this._hasActiveShim()) {
321                 this._handleTargetOver();
322             } else {
323                 Y.each(this.otherDrops, function(v, k) {
324                     v._handleOut.apply(v, []);
325                 });
326             }
327         },
328         /**
329         * @private
330         * @method _lookup
331         * @description Filters the list of Drops down to those in the viewport.
332         * @return {Array} The valid Drop Targets that are in the viewport.
333         */
334         _lookup: function() {
335             if (!this.useHash || this._noShim) {
336                 return this.validDrops;
337             }
338             var drops = [];
339             //Only scan drop shims that are in the Viewport
340             Y.each(this.validDrops, function(v, k) {
341                 if (v.shim && v.shim.inViewportRegion(false, v.region)) {
342                     drops[drops.length] = v;
343                 }
344             });
345             return drops;
346                 
347         },
348         /**
349         * @private
350         * @method _handleTargetOver
351         * @description This method execs _handleTargetOver on all valid Drop Targets
352         */
353         _handleTargetOver: function() {
354             var drops = this._lookup();
355             Y.each(drops, function(v, k) {
356                 v._handleTargetOver.call(v);
357             }, this);
358         },
359         /**
360         * @private
361         * @method _regTarget
362         * @description Add the passed in Target to the targets collection
363         * @param {Object} t The Target to add to the targets collection
364         */
365         _regTarget: function(t) {
366             this.targets[this.targets.length] = t;
367         },
368         /**
369         * @private
370         * @method _unregTarget
371         * @description Remove the passed in Target from the targets collection
372         * @param {Object} drop The Target to remove from the targets collection
373         */
374         _unregTarget: function(drop) {
375             var targets = [], vdrops;
376             Y.each(this.targets, function(v, k) {
377                 if (v != drop) {
378                     targets[targets.length] = v;
379                 }
380             }, this);
381             this.targets = targets;
382
383             vdrops = [];
384             Y.each(this.validDrops, function(v, k) {
385                 if (v !== drop) {
386                     vdrops[vdrops.length] = v;
387                 }
388             });
389
390             this.validDrops = vdrops;
391         },
392         /**
393         * @method getDrop
394         * @description Get a valid Drop instance back from a Node or a selector string, false otherwise
395         * @param {String/Object} node The Node instance or Selector string to check for a valid Drop Object
396         * @return {Object}
397         */
398         getDrop: function(node) {
399             var drop = false,
400                 n = Y.one(node);
401             if (n instanceof Y.Node) {
402                 Y.each(this.targets, function(v, k) {
403                     if (n.compareTo(v.get('node'))) {
404                         drop = v;
405                     }
406                 });
407             }
408             return drop;
409         }
410     }, true);
411     
412
413
414
415
416
417
418 }, '3.3.0' ,{requires:['dd-ddm'], skinnable:false});