Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / dd / StatusProxy.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.dd.StatusProxy
17  * A specialized drag proxy that supports a drop status icon, {@link Ext.Layer} styles and auto-repair.  This is the
18  * default drag proxy used by all Ext.dd components.
19  */
20 Ext.define('Ext.dd.StatusProxy', {
21     animRepair: false,
22
23     /**
24      * Creates new StatusProxy.
25      * @param {Object} config (optional) Config object.
26      */
27     constructor: function(config){
28         Ext.apply(this, config);
29         this.id = this.id || Ext.id();
30         this.proxy = Ext.createWidget('component', {
31             floating: true,
32             id: this.id,
33             html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
34                   '<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
35             cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
36             shadow: !config || config.shadow !== false,
37             renderTo: document.body
38         });
39
40         this.el = this.proxy.el;
41         this.el.show();
42         this.el.setVisibilityMode(Ext.core.Element.VISIBILITY);
43         this.el.hide();
44
45         this.ghost = Ext.get(this.el.dom.childNodes[1]);
46         this.dropStatus = this.dropNotAllowed;
47     },
48     /**
49      * @cfg {String} dropAllowed
50      * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
51      */
52     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
53     /**
54      * @cfg {String} dropNotAllowed
55      * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
56      */
57     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
58
59     /**
60      * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
61      * over the current target element.
62      * @param {String} cssClass The css class for the new drop status indicator image
63      */
64     setStatus : function(cssClass){
65         cssClass = cssClass || this.dropNotAllowed;
66         if(this.dropStatus != cssClass){
67             this.el.replaceCls(this.dropStatus, cssClass);
68             this.dropStatus = cssClass;
69         }
70     },
71
72     /**
73      * Resets the status indicator to the default dropNotAllowed value
74      * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
75      */
76     reset : function(clearGhost){
77         this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
78         this.dropStatus = this.dropNotAllowed;
79         if(clearGhost){
80             this.ghost.update("");
81         }
82     },
83
84     /**
85      * Updates the contents of the ghost element
86      * @param {String/HTMLElement} html The html that will replace the current innerHTML of the ghost element, or a
87      * DOM node to append as the child of the ghost element (in which case the innerHTML will be cleared first).
88      */
89     update : function(html){
90         if(typeof html == "string"){
91             this.ghost.update(html);
92         }else{
93             this.ghost.update("");
94             html.style.margin = "0";
95             this.ghost.dom.appendChild(html);
96         }
97         var el = this.ghost.dom.firstChild; 
98         if(el){
99             Ext.fly(el).setStyle('float', 'none');
100         }
101     },
102
103     /**
104      * Returns the underlying proxy {@link Ext.Layer}
105      * @return {Ext.Layer} el
106     */
107     getEl : function(){
108         return this.el;
109     },
110
111     /**
112      * Returns the ghost element
113      * @return {Ext.core.Element} el
114      */
115     getGhost : function(){
116         return this.ghost;
117     },
118
119     /**
120      * Hides the proxy
121      * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
122      */
123     hide : function(clear) {
124         this.proxy.hide();
125         if (clear) {
126             this.reset(true);
127         }
128     },
129
130     /**
131      * Stops the repair animation if it's currently running
132      */
133     stop : function(){
134         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
135             this.anim.stop();
136         }
137     },
138
139     /**
140      * Displays this proxy
141      */
142     show : function() {
143         this.proxy.show();
144         this.proxy.toFront();
145     },
146
147     /**
148      * Force the Layer to sync its shadow and shim positions to the element
149      */
150     sync : function(){
151         this.proxy.el.sync();
152     },
153
154     /**
155      * Causes the proxy to return to its position of origin via an animation.  Should be called after an
156      * invalid drop operation by the item being dragged.
157      * @param {Array} xy The XY position of the element ([x, y])
158      * @param {Function} callback The function to call after the repair is complete.
159      * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.
160      */
161     repair : function(xy, callback, scope){
162         this.callback = callback;
163         this.scope = scope;
164         if (xy && this.animRepair !== false) {
165             this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
166             this.el.hideUnders(true);
167             this.anim = this.el.animate({
168                 duration: this.repairDuration || 500,
169                 easing: 'ease-out',
170                 to: {
171                     x: xy[0],
172                     y: xy[1]
173                 },
174                 stopAnimation: true,
175                 callback: this.afterRepair,
176                 scope: this
177             });
178         } else {
179             this.afterRepair();
180         }
181     },
182
183     // private
184     afterRepair : function(){
185         this.hide(true);
186         if(typeof this.callback == "function"){
187             this.callback.call(this.scope || this);
188         }
189         this.callback = null;
190         this.scope = null;
191     },
192
193     destroy: function(){
194         Ext.destroy(this.ghost, this.proxy, this.el);
195     }
196 });