Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / Action.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.Action
17  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
18  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI
19  * updates across any components that support the Action interface (primarily {@link Ext.toolbar.Toolbar}, {@link Ext.button.Button}
20  * and {@link Ext.menu.Menu} components).</p>
21  * <p>Use a single Action instance as the config object for any number of UI Components which share the same configuration. The
22  * Action not only supplies the configuration, but allows all Components based upon it to have a common set of methods
23  * called at once through a single call to the Action.</p>
24  * <p>Any Component that is to be configured with an Action must also support
25  * the following methods:<ul>
26  * <li><code>setText(string)</code></li>
27  * <li><code>setIconCls(string)</code></li>
28  * <li><code>setDisabled(boolean)</code></li>
29  * <li><code>setVisible(boolean)</code></li>
30  * <li><code>setHandler(function)</code></li></ul>.</p>
31  * <p>This allows the Action to control its associated Components.</p>
32  * Example usage:<br>
33  * <pre><code>
34 // Define the shared Action.  Each Component below will have the same
35 // display text and icon, and will display the same message on click.
36 var action = new Ext.Action({
37     {@link #text}: 'Do something',
38     {@link #handler}: function(){
39         Ext.Msg.alert('Click', 'You did something.');
40     },
41     {@link #iconCls}: 'do-something',
42     {@link #itemId}: 'myAction'
43 });
44
45 var panel = new Ext.panel.Panel({
46     title: 'Actions',
47     width: 500,
48     height: 300,
49     tbar: [
50         // Add the Action directly to a toolbar as a menu button
51         action,
52         {
53             text: 'Action Menu',
54             // Add the Action to a menu as a text item
55             menu: [action]
56         }
57     ],
58     items: [
59         // Add the Action to the panel body as a standard button
60         new Ext.button.Button(action)
61     ],
62     renderTo: Ext.getBody()
63 });
64
65 // Change the text for all components using the Action
66 action.setText('Something else');
67
68 // Reference an Action through a container using the itemId
69 var btn = panel.getComponent('myAction');
70 var aRef = btn.baseAction;
71 aRef.setText('New text');
72 </code></pre>
73  */
74 Ext.define('Ext.Action', {
75
76     /* Begin Definitions */
77
78     /* End Definitions */
79
80     /**
81      * @cfg {String} text The text to set for all components configured by this Action (defaults to '').
82      */
83     /**
84      * @cfg {String} iconCls
85      * The CSS class selector that specifies a background image to be used as the header icon for
86      * all components configured by this Action (defaults to '').
87      * <p>An example of specifying a custom icon class would be something like:
88      * </p><pre><code>
89 // specify the property in the config for the class:
90      ...
91      iconCls: 'do-something'
92
93 // css class that specifies background image to be used as the icon image:
94 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
95 </code></pre>
96      */
97     /**
98      * @cfg {Boolean} disabled True to disable all components configured by this Action, false to enable them (defaults to false).
99      */
100     /**
101      * @cfg {Boolean} hidden True to hide all components configured by this Action, false to show them (defaults to false).
102      */
103     /**
104      * @cfg {Function} handler The function that will be invoked by each component tied to this Action
105      * when the component's primary event is triggered (defaults to undefined).
106      */
107     /**
108      * @cfg {String} itemId
109      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
110      */
111     /**
112      * @cfg {Object} scope The scope (<code><b>this</b></code> reference) in which the
113      * <code>{@link #handler}</code> is executed. Defaults to the browser window.
114      */
115
116     /**
117      * Creates new Action.
118      * @param {Object} config Config object.
119      */
120     constructor : function(config){
121         this.initialConfig = config;
122         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
123         this.items = [];
124     },
125
126     // private
127     isAction : true,
128
129     /**
130      * Sets the text to be displayed by all components configured by this Action.
131      * @param {String} text The text to display
132      */
133     setText : function(text){
134         this.initialConfig.text = text;
135         this.callEach('setText', [text]);
136     },
137
138     /**
139      * Gets the text currently displayed by all components configured by this Action.
140      */
141     getText : function(){
142         return this.initialConfig.text;
143     },
144
145     /**
146      * Sets the icon CSS class for all components configured by this Action.  The class should supply
147      * a background image that will be used as the icon image.
148      * @param {String} cls The CSS class supplying the icon image
149      */
150     setIconCls : function(cls){
151         this.initialConfig.iconCls = cls;
152         this.callEach('setIconCls', [cls]);
153     },
154
155     /**
156      * Gets the icon CSS class currently used by all components configured by this Action.
157      */
158     getIconCls : function(){
159         return this.initialConfig.iconCls;
160     },
161
162     /**
163      * Sets the disabled state of all components configured by this Action.  Shortcut method
164      * for {@link #enable} and {@link #disable}.
165      * @param {Boolean} disabled True to disable the component, false to enable it
166      */
167     setDisabled : function(v){
168         this.initialConfig.disabled = v;
169         this.callEach('setDisabled', [v]);
170     },
171
172     /**
173      * Enables all components configured by this Action.
174      */
175     enable : function(){
176         this.setDisabled(false);
177     },
178
179     /**
180      * Disables all components configured by this Action.
181      */
182     disable : function(){
183         this.setDisabled(true);
184     },
185
186     /**
187      * Returns true if the components using this Action are currently disabled, else returns false.  
188      */
189     isDisabled : function(){
190         return this.initialConfig.disabled;
191     },
192
193     /**
194      * Sets the hidden state of all components configured by this Action.  Shortcut method
195      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
196      * @param {Boolean} hidden True to hide the component, false to show it
197      */
198     setHidden : function(v){
199         this.initialConfig.hidden = v;
200         this.callEach('setVisible', [!v]);
201     },
202
203     /**
204      * Shows all components configured by this Action.
205      */
206     show : function(){
207         this.setHidden(false);
208     },
209
210     /**
211      * Hides all components configured by this Action.
212      */
213     hide : function(){
214         this.setHidden(true);
215     },
216
217     /**
218      * Returns true if the components configured by this Action are currently hidden, else returns false.
219      */
220     isHidden : function(){
221         return this.initialConfig.hidden;
222     },
223
224     /**
225      * Sets the function that will be called by each Component using this action when its primary event is triggered.
226      * @param {Function} fn The function that will be invoked by the action's components.  The function
227      * will be called with no arguments.
228      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.
229      */
230     setHandler : function(fn, scope){
231         this.initialConfig.handler = fn;
232         this.initialConfig.scope = scope;
233         this.callEach('setHandler', [fn, scope]);
234     },
235
236     /**
237      * Executes the specified function once for each Component currently tied to this Action.  The function passed
238      * in should accept a single argument that will be an object that supports the basic Action config/method interface.
239      * @param {Function} fn The function to execute for each component
240      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.
241      */
242     each : function(fn, scope){
243         Ext.each(this.items, fn, scope);
244     },
245
246     // private
247     callEach : function(fnName, args){
248         var items = this.items,
249             i = 0,
250             len = items.length;
251             
252         for(; i < len; i++){
253             items[i][fnName].apply(items[i], args);
254         }
255     },
256
257     // private
258     addComponent : function(comp){
259         this.items.push(comp);
260         comp.on('destroy', this.removeComponent, this);
261     },
262
263     // private
264     removeComponent : function(comp){
265         Ext.Array.remove(this.items, comp);
266     },
267
268     /**
269      * Executes this Action manually using the handler function specified in the original config object
270      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this
271      * function will be passed on to the handler function.
272      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
273      * @param {Mixed} arg2 (optional)
274      * @param {Mixed} etc... (optional)
275      */
276     execute : function(){
277         this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
278     }
279 });
280