initial import
[roojs1] / Roo / dd / DragSource.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11
12 /**
13  * @class Roo.dd.DragSource
14  * @extends Roo.dd.DDProxy
15  * A simple class that provides the basic implementation needed to make any element draggable.
16  * @constructor
17  * @param {String/HTMLElement/Element} el The container element
18  * @param {Object} config
19  */
20 Roo.dd.DragSource = function(el, config){
21     this.el = Roo.get(el);
22     this.dragData = {};
23     
24     Roo.apply(this, config);
25     
26     if(!this.proxy){
27         this.proxy = new Roo.dd.StatusProxy();
28     }
29
30     Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
31           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
32     
33     this.dragging = false;
34 };
35
36 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
37     /**
38      * @cfg {String} dropAllowed
39      * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
40      */
41     dropAllowed : "x-dd-drop-ok",
42     /**
43      * @cfg {String} dropNotAllowed
44      * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
45      */
46     dropNotAllowed : "x-dd-drop-nodrop",
47
48     /**
49      * Returns the data object associated with this drag source
50      * @return {Object} data An object containing arbitrary data
51      */
52     getDragData : function(e){
53         return this.dragData;
54     },
55
56     // private
57     onDragEnter : function(e, id){
58         var target = Roo.dd.DragDropMgr.getDDById(id);
59         this.cachedTarget = target;
60         if(this.beforeDragEnter(target, e, id) !== false){
61             if(target.isNotifyTarget){
62                 var status = target.notifyEnter(this, e, this.dragData);
63                 this.proxy.setStatus(status);
64             }else{
65                 this.proxy.setStatus(this.dropAllowed);
66             }
67             
68             if(this.afterDragEnter){
69                 /**
70                  * An empty function by default, but provided so that you can perform a custom action
71                  * when the dragged item enters the drop target by providing an implementation.
72                  * @param {Roo.dd.DragDrop} target The drop target
73                  * @param {Event} e The event object
74                  * @param {String} id The id of the dragged element
75                  * @method afterDragEnter
76                  */
77                 this.afterDragEnter(target, e, id);
78             }
79         }
80     },
81
82     /**
83      * An empty function by default, but provided so that you can perform a custom action
84      * before the dragged item enters the drop target and optionally cancel the onDragEnter.
85      * @param {Roo.dd.DragDrop} target The drop target
86      * @param {Event} e The event object
87      * @param {String} id The id of the dragged element
88      * @return {Boolean} isValid True if the drag event is valid, else false to cancel
89      */
90     beforeDragEnter : function(target, e, id){
91         return true;
92     },
93
94     // private
95     alignElWithMouse: function() {
96         Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
97         this.proxy.sync();
98     },
99
100     // private
101     onDragOver : function(e, id){
102         var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
103         if(this.beforeDragOver(target, e, id) !== false){
104             if(target.isNotifyTarget){
105                 var status = target.notifyOver(this, e, this.dragData);
106                 this.proxy.setStatus(status);
107             }
108
109             if(this.afterDragOver){
110                 /**
111                  * An empty function by default, but provided so that you can perform a custom action
112                  * while the dragged item is over the drop target by providing an implementation.
113                  * @param {Roo.dd.DragDrop} target The drop target
114                  * @param {Event} e The event object
115                  * @param {String} id The id of the dragged element
116                  * @method afterDragOver
117                  */
118                 this.afterDragOver(target, e, id);
119             }
120         }
121     },
122
123     /**
124      * An empty function by default, but provided so that you can perform a custom action
125      * while the dragged item is over the drop target and optionally cancel the onDragOver.
126      * @param {Roo.dd.DragDrop} target The drop target
127      * @param {Event} e The event object
128      * @param {String} id The id of the dragged element
129      * @return {Boolean} isValid True if the drag event is valid, else false to cancel
130      */
131     beforeDragOver : function(target, e, id){
132         return true;
133     },
134
135     // private
136     onDragOut : function(e, id){
137         var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
138         if(this.beforeDragOut(target, e, id) !== false){
139             if(target.isNotifyTarget){
140                 target.notifyOut(this, e, this.dragData);
141             }
142             this.proxy.reset();
143             if(this.afterDragOut){
144                 /**
145                  * An empty function by default, but provided so that you can perform a custom action
146                  * after the dragged item is dragged out of the target without dropping.
147                  * @param {Roo.dd.DragDrop} target The drop target
148                  * @param {Event} e The event object
149                  * @param {String} id The id of the dragged element
150                  * @method afterDragOut
151                  */
152                 this.afterDragOut(target, e, id);
153             }
154         }
155         this.cachedTarget = null;
156     },
157
158     /**
159      * An empty function by default, but provided so that you can perform a custom action before the dragged
160      * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
161      * @param {Roo.dd.DragDrop} target The drop target
162      * @param {Event} e The event object
163      * @param {String} id The id of the dragged element
164      * @return {Boolean} isValid True if the drag event is valid, else false to cancel
165      */
166     beforeDragOut : function(target, e, id){
167         return true;
168     },
169     
170     // private
171     onDragDrop : function(e, id){
172         var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
173         if(this.beforeDragDrop(target, e, id) !== false){
174             if(target.isNotifyTarget){
175                 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
176                     this.onValidDrop(target, e, id);
177                 }else{
178                     this.onInvalidDrop(target, e, id);
179                 }
180             }else{
181                 this.onValidDrop(target, e, id);
182             }
183             
184             if(this.afterDragDrop){
185                 /**
186                  * An empty function by default, but provided so that you can perform a custom action
187                  * after a valid drag drop has occurred by providing an implementation.
188                  * @param {Roo.dd.DragDrop} target The drop target
189                  * @param {Event} e The event object
190                  * @param {String} id The id of the dropped element
191                  * @method afterDragDrop
192                  */
193                 this.afterDragDrop(target, e, id);
194             }
195         }
196         delete this.cachedTarget;
197     },
198
199     /**
200      * An empty function by default, but provided so that you can perform a custom action before the dragged
201      * item is dropped onto the target and optionally cancel the onDragDrop.
202      * @param {Roo.dd.DragDrop} target The drop target
203      * @param {Event} e The event object
204      * @param {String} id The id of the dragged element
205      * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
206      */
207     beforeDragDrop : function(target, e, id){
208         return true;
209     },
210
211     // private
212     onValidDrop : function(target, e, id){
213         this.hideProxy();
214         if(this.afterValidDrop){
215             /**
216              * An empty function by default, but provided so that you can perform a custom action
217              * after a valid drop has occurred by providing an implementation.
218              * @param {Object} target The target DD 
219              * @param {Event} e The event object
220              * @param {String} id The id of the dropped element
221              * @method afterInvalidDrop
222              */
223             this.afterValidDrop(target, e, id);
224         }
225     },
226
227     // private
228     getRepairXY : function(e, data){
229         return this.el.getXY();  
230     },
231
232     // private
233     onInvalidDrop : function(target, e, id){
234         this.beforeInvalidDrop(target, e, id);
235         if(this.cachedTarget){
236             if(this.cachedTarget.isNotifyTarget){
237                 this.cachedTarget.notifyOut(this, e, this.dragData);
238             }
239             this.cacheTarget = null;
240         }
241         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
242
243         if(this.afterInvalidDrop){
244             /**
245              * An empty function by default, but provided so that you can perform a custom action
246              * after an invalid drop has occurred by providing an implementation.
247              * @param {Event} e The event object
248              * @param {String} id The id of the dropped element
249              * @method afterInvalidDrop
250              */
251             this.afterInvalidDrop(e, id);
252         }
253     },
254
255     // private
256     afterRepair : function(){
257         if(Roo.enableFx){
258             this.el.highlight(this.hlColor || "c3daf9");
259         }
260         this.dragging = false;
261     },
262
263     /**
264      * An empty function by default, but provided so that you can perform a custom action after an invalid
265      * drop has occurred.
266      * @param {Roo.dd.DragDrop} target The drop target
267      * @param {Event} e The event object
268      * @param {String} id The id of the dragged element
269      * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
270      */
271     beforeInvalidDrop : function(target, e, id){
272         return true;
273     },
274
275     // private
276     handleMouseDown : function(e){
277         if(this.dragging) {
278             return;
279         }
280         var data = this.getDragData(e);
281         if(data && this.onBeforeDrag(data, e) !== false){
282             this.dragData = data;
283             this.proxy.stop();
284             Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
285         } 
286     },
287
288     /**
289      * An empty function by default, but provided so that you can perform a custom action before the initial
290      * drag event begins and optionally cancel it.
291      * @param {Object} data An object containing arbitrary data to be shared with drop targets
292      * @param {Event} e The event object
293      * @return {Boolean} isValid True if the drag event is valid, else false to cancel
294      */
295     onBeforeDrag : function(data, e){
296         return true;
297     },
298
299     /**
300      * An empty function by default, but provided so that you can perform a custom action once the initial
301      * drag event has begun.  The drag cannot be canceled from this function.
302      * @param {Number} x The x position of the click on the dragged object
303      * @param {Number} y The y position of the click on the dragged object
304      */
305     onStartDrag : Roo.emptyFn,
306
307     // private - YUI override
308     startDrag : function(x, y){
309         this.proxy.reset();
310         this.dragging = true;
311         this.proxy.update("");
312         this.onInitDrag(x, y);
313         this.proxy.show();
314     },
315
316     // private
317     onInitDrag : function(x, y){
318         var clone = this.el.dom.cloneNode(true);
319         clone.id = Roo.id(); // prevent duplicate ids
320         this.proxy.update(clone);
321         this.onStartDrag(x, y);
322         return true;
323     },
324
325     /**
326      * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
327      * @return {Roo.dd.StatusProxy} proxy The StatusProxy
328      */
329     getProxy : function(){
330         return this.proxy;  
331     },
332
333     /**
334      * Hides the drag source's {@link Roo.dd.StatusProxy}
335      */
336     hideProxy : function(){
337         this.proxy.hide();  
338         this.proxy.reset(true);
339         this.dragging = false;
340     },
341
342     // private
343     triggerCacheRefresh : function(){
344         Roo.dd.DDM.refreshCache(this.groups);
345     },
346
347     // private - override to prevent hiding
348     b4EndDrag: function(e) {
349     },
350
351     // private - override to prevent moving
352     endDrag : function(e){
353         this.onEndDrag(this.dragData, e);
354     },
355
356     // private
357     onEndDrag : function(data, e){
358     },
359     
360     // private - pin to cursor
361     autoOffset : function(x, y) {
362         this.setDelta(-12, -20);
363     }    
364 });