Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / grid / column / Action.js
1 /**
2  * @class Ext.grid.column.Action
3  * @extends Ext.grid.column.Column
4  * <p>A Grid header type which renders an icon, or a series of icons in a grid cell, and offers a scoped click
5  * handler for each icon.</p>
6  *
7  * {@img Ext.grid.column.Action/Ext.grid.column.Action.png Ext.grid.column.Action grid column}
8  *  
9  * ## Code
10  *     Ext.create('Ext.data.Store', {
11  *         storeId:'employeeStore',
12  *         fields:['firstname', 'lastname', 'senority', 'dep', 'hired'],
13  *         data:[
14  *             {firstname:"Michael", lastname:"Scott"},
15  *             {firstname:"Dwight", lastname:"Schrute"},
16  *             {firstname:"Jim", lastname:"Halpert"},
17  *             {firstname:"Kevin", lastname:"Malone"},
18  *             {firstname:"Angela", lastname:"Martin"}                        
19  *         ]
20  *     });
21  *     
22  *     Ext.create('Ext.grid.Panel', {
23  *         title: 'Action Column Demo',
24  *         store: Ext.data.StoreManager.lookup('employeeStore'),
25  *         columns: [
26  *             {text: 'First Name',  dataIndex:'firstname'},
27  *             {text: 'Last Name',  dataIndex:'lastname'},
28  *             {
29  *                 xtype:'actioncolumn', 
30  *                 width:50,
31  *                 items: [{
32  *                     icon: 'images/edit.png',  // Use a URL in the icon config
33  *                     tooltip: 'Edit',
34  *                     handler: function(grid, rowIndex, colIndex) {
35  *                         var rec = grid.getStore().getAt(rowIndex);
36  *                         alert("Edit " + rec.get('firstname'));
37  *                     }
38  *                 },{
39  *                     icon: 'images/delete.png',
40  *                     tooltip: 'Delete',
41  *                     handler: function(grid, rowIndex, colIndex) {
42  *                         var rec = grid.getStore().getAt(rowIndex);
43  *                         alert("Terminate " + rec.get('firstname'));
44  *                     }                
45  *                 }]
46  *             }
47  *         ],
48  *         width: 250,
49  *         renderTo: Ext.getBody()
50  *     });
51  * <p>The action column can be at any index in the columns array, and a grid can have any number of
52  * action columns. </p>
53  * @xtype actioncolumn
54  */
55 Ext.define('Ext.grid.column.Action', {
56     extend: 'Ext.grid.column.Column',
57     alias: ['widget.actioncolumn'],
58     alternateClassName: 'Ext.grid.ActionColumn',
59
60     /**
61      * @cfg {String} icon
62      * The URL of an image to display as the clickable element in the column. 
63      * Optional - defaults to <code>{@link Ext#BLANK_IMAGE_URL Ext.BLANK_IMAGE_URL}</code>.
64      */
65     /**
66      * @cfg {String} iconCls
67      * A CSS class to apply to the icon image. To determine the class dynamically, configure the Column with a <code>{@link #getClass}</code> function.
68      */
69     /**
70      * @cfg {Function} handler A function called when the icon is clicked.
71      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
72      * <li><code>view</code> : TableView<div class="sub-desc">The owning TableView.</div></li>
73      * <li><code>rowIndex</code> : Number<div class="sub-desc">The row index clicked on.</div></li>
74      * <li><code>colIndex</code> : Number<div class="sub-desc">The column index clicked on.</div></li>
75      * <li><code>item</code> : Object<div class="sub-desc">The clicked item (or this Column if multiple 
76      * {@link #items} were not configured).</div></li>
77      * <li><code>e</code> : Event<div class="sub-desc">The click event.</div></li>
78      * </ul></div>
79      */
80     /**
81      * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
82      * and <code>{@link #getClass}</code> fuctions are executed. Defaults to this Column.
83      */
84     /**
85      * @cfg {String} tooltip A tooltip message to be displayed on hover. {@link Ext.tip.QuickTipManager#init Ext.tip.QuickTipManager} must have 
86      * been initialized.
87      */
88     /**
89      * @cfg {Boolean} stopSelection Defaults to <code>true</code>. Prevent grid <i>row</i> selection upon mousedown.
90      */
91     /**
92      * @cfg {Function} getClass A function which returns the CSS class to apply to the icon image.
93      * The function is passed the following parameters:<ul>
94      *     <li><b>v</b> : Object<p class="sub-desc">The value of the column's configured field (if any).</p></li>
95      *     <li><b>metadata</b> : Object<p class="sub-desc">An object in which you may set the following attributes:<ul>
96      *         <li><b>css</b> : String<p class="sub-desc">A CSS class name to add to the cell's TD element.</p></li>
97      *         <li><b>attr</b> : String<p class="sub-desc">An HTML attribute definition string to apply to the data container element <i>within</i> the table cell
98      *         (e.g. 'style="color:red;"').</p></li>
99      *     </ul></p></li>
100      *     <li><b>r</b> : Ext.data.Record<p class="sub-desc">The Record providing the data.</p></li>
101      *     <li><b>rowIndex</b> : Number<p class="sub-desc">The row index..</p></li>
102      *     <li><b>colIndex</b> : Number<p class="sub-desc">The column index.</p></li>
103      *     <li><b>store</b> : Ext.data.Store<p class="sub-desc">The Store which is providing the data Model.</p></li>
104      * </ul>
105      */
106     /**
107      * @cfg {Array} items An Array which may contain multiple icon definitions, each element of which may contain:
108      * <div class="mdetail-params"><ul>
109      * <li><code>icon</code> : String<div class="sub-desc">The url of an image to display as the clickable element 
110      * in the column.</div></li>
111      * <li><code>iconCls</code> : String<div class="sub-desc">A CSS class to apply to the icon image.
112      * To determine the class dynamically, configure the item with a <code>getClass</code> function.</div></li>
113      * <li><code>getClass</code> : Function<div class="sub-desc">A function which returns the CSS class to apply to the icon image.
114      * The function is passed the following parameters:<ul>
115      *     <li><b>v</b> : Object<p class="sub-desc">The value of the column's configured field (if any).</p></li>
116      *     <li><b>metadata</b> : Object<p class="sub-desc">An object in which you may set the following attributes:<ul>
117      *         <li><b>css</b> : String<p class="sub-desc">A CSS class name to add to the cell's TD element.</p></li>
118      *         <li><b>attr</b> : String<p class="sub-desc">An HTML attribute definition string to apply to the data container element <i>within</i> the table cell
119      *         (e.g. 'style="color:red;"').</p></li>
120      *     </ul></p></li>
121      *     <li><b>r</b> : Ext.data.Record<p class="sub-desc">The Record providing the data.</p></li>
122      *     <li><b>rowIndex</b> : Number<p class="sub-desc">The row index..</p></li>
123      *     <li><b>colIndex</b> : Number<p class="sub-desc">The column index.</p></li>
124      *     <li><b>store</b> : Ext.data.Store<p class="sub-desc">The Store which is providing the data Model.</p></li>
125      * </ul></div></li>
126      * <li><code>handler</code> : Function<div class="sub-desc">A function called when the icon is clicked.</div></li>
127      * <li><code>scope</code> : Scope<div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the 
128      * <code>handler</code> and <code>getClass</code> functions are executed. Fallback defaults are this Column's
129      * configured scope, then this Column.</div></li>
130      * <li><code>tooltip</code> : String<div class="sub-desc">A tooltip message to be displayed on hover. 
131      * {@link Ext.tip.QuickTipManager#init Ext.tip.QuickTipManager} must have been initialized.</div></li>
132      * </ul></div>
133      */
134     header: '&#160;',
135
136     actionIdRe: /x-action-col-(\d+)/,
137
138     /**
139      * @cfg {String} altText The alt text to use for the image element. Defaults to <tt>''</tt>.
140      */
141     altText: '',
142     
143     sortable: false,
144
145     constructor: function(config) {
146         var me = this,
147             cfg = Ext.apply({}, config),
148             items = cfg.items || [me],
149             l = items.length,
150             i,
151             item;
152
153         // This is a Container. Delete the items config to be reinstated after construction.
154         delete cfg.items;
155         this.callParent([cfg]);
156
157         // Items is an array property of ActionColumns
158         me.items = items;
159
160 //      Renderer closure iterates through items creating an <img> element for each and tagging with an identifying 
161 //      class name x-action-col-{n}
162         me.renderer = function(v, meta) {
163 //          Allow a configured renderer to create initial value (And set the other values in the "metadata" argument!)
164             v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
165
166             meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
167             for (i = 0; i < l; i++) {
168                 item = items[i];
169                 v += '<img alt="' + me.altText + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
170                     '" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' +  (item.iconCls || '') + 
171                     ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || '')) + '"' +
172                     ((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
173             }
174             return v;
175         };
176     },
177
178     destroy: function() {
179         delete this.items;
180         delete this.renderer;
181         return this.callParent(arguments);
182     },
183
184     /**
185      * @private
186      * Process and refire events routed from the GridView's processEvent method.
187      * Also fires any configured click handlers. By default, cancels the mousedown event to prevent selection.
188      * Returns the event handler's status to allow canceling of GridView's bubbling process.
189      */
190     processEvent : function(type, view, cell, recordIndex, cellIndex, e){
191         var m = e.getTarget().className.match(this.actionIdRe),
192             item, fn;
193         if (m && (item = this.items[parseInt(m[1], 10)])) {
194             if (type == 'click') {
195                 fn = item.handler;
196                 if (fn || this.handler) {
197                     fn.call(item.scope||this.scope||this, view, recordIndex, cellIndex, item, e);
198                 }
199             } else if ((type == 'mousedown') && (item.stopSelection !== false)) {
200                 return false;
201             }
202         }
203         return this.callParent(arguments);
204     },
205
206     cascade: function(fn, scope) {
207         fn.call(scope||this, this);
208     },
209
210     // Private override because this cannot function as a Container, and it has an items property which is an Array, NOT a MixedCollection.
211     getRefItems: function() {
212         return [];
213     }
214 });