Upgrade to ExtJS 4.0.7 - Released 10/19/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             stateful: false,
33             id: this.id,
34             html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
35                   '<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
36             cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
37             shadow: !config || config.shadow !== false,
38             renderTo: document.body
39         });
40
41         this.el = this.proxy.el;
42         this.el.show();
43         this.el.setVisibilityMode(Ext.Element.VISIBILITY);
44         this.el.hide();
45
46         this.ghost = Ext.get(this.el.dom.childNodes[1]);
47         this.dropStatus = this.dropNotAllowed;
48     },
49     /**
50      * @cfg {String} [dropAllowed="x-dd-drop-ok"]
51      * The CSS class to apply to the status element when drop is allowed.
52      */
53     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
54     /**
55      * @cfg {String} [dropNotAllowed="x-dd-drop-nodrop"]
56      * The CSS class to apply to the status element when drop is not allowed.
57      */
58     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
59
60     /**
61      * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
62      * over the current target element.
63      * @param {String} cssClass The css class for the new drop status indicator image
64      */
65     setStatus : function(cssClass){
66         cssClass = cssClass || this.dropNotAllowed;
67         if(this.dropStatus != cssClass){
68             this.el.replaceCls(this.dropStatus, cssClass);
69             this.dropStatus = cssClass;
70         }
71     },
72
73     /**
74      * Resets the status indicator to the default dropNotAllowed value
75      * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
76      */
77     reset : function(clearGhost){
78         this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
79         this.dropStatus = this.dropNotAllowed;
80         if(clearGhost){
81             this.ghost.update("");
82         }
83     },
84
85     /**
86      * Updates the contents of the ghost element
87      * @param {String/HTMLElement} html The html that will replace the current innerHTML of the ghost element, or a
88      * DOM node to append as the child of the ghost element (in which case the innerHTML will be cleared first).
89      */
90     update : function(html){
91         if(typeof html == "string"){
92             this.ghost.update(html);
93         }else{
94             this.ghost.update("");
95             html.style.margin = "0";
96             this.ghost.dom.appendChild(html);
97         }
98         var el = this.ghost.dom.firstChild;
99         if(el){
100             Ext.fly(el).setStyle('float', 'none');
101         }
102     },
103
104     /**
105      * Returns the underlying proxy {@link Ext.Layer}
106      * @return {Ext.Layer} el
107     */
108     getEl : function(){
109         return this.el;
110     },
111
112     /**
113      * Returns the ghost element
114      * @return {Ext.Element} el
115      */
116     getGhost : function(){
117         return this.ghost;
118     },
119
120     /**
121      * Hides the proxy
122      * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
123      */
124     hide : function(clear) {
125         this.proxy.hide();
126         if (clear) {
127             this.reset(true);
128         }
129     },
130
131     /**
132      * Stops the repair animation if it's currently running
133      */
134     stop : function(){
135         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
136             this.anim.stop();
137         }
138     },
139
140     /**
141      * Displays this proxy
142      */
143     show : function() {
144         this.proxy.show();
145         this.proxy.toFront();
146     },
147
148     /**
149      * Force the Layer to sync its shadow and shim positions to the element
150      */
151     sync : function(){
152         this.proxy.el.sync();
153     },
154
155     /**
156      * Causes the proxy to return to its position of origin via an animation.  Should be called after an
157      * invalid drop operation by the item being dragged.
158      * @param {Number[]} xy The XY position of the element ([x, y])
159      * @param {Function} callback The function to call after the repair is complete.
160      * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.
161      */
162     repair : function(xy, callback, scope){
163         this.callback = callback;
164         this.scope = scope;
165         if (xy && this.animRepair !== false) {
166             this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
167             this.el.hideUnders(true);
168             this.anim = this.el.animate({
169                 duration: this.repairDuration || 500,
170                 easing: 'ease-out',
171                 to: {
172                     x: xy[0],
173                     y: xy[1]
174                 },
175                 stopAnimation: true,
176                 callback: this.afterRepair,
177                 scope: this
178             });
179         } else {
180             this.afterRepair();
181         }
182     },
183
184     // private
185     afterRepair : function(){
186         this.hide(true);
187         if(typeof this.callback == "function"){
188             this.callback.call(this.scope || this);
189         }
190         this.callback = null;
191         this.scope = null;
192     },
193
194     destroy: function(){
195         Ext.destroy(this.ghost, this.proxy, this.el);
196     }
197 });