/ext-4.1.0_b3/docs/source/RowExpander.html
HTML | 250 lines | 220 code | 30 blank | 0 comment | 0 complexity | bdcc43cb14efa6c8b4da1bddfc7974dd MD5 | raw file
1<!DOCTYPE html>
2<html>
3<head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
10 </style>
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14 }
15 </script>
16</head>
17<body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js">// feature idea to enable Ajax loading and then the content
19// cache would actually make sense. Should we dictate that they use
20// data or support raw html as well?
21
22<span id='Ext-ux-RowExpander'>/**
23</span> * @class Ext.ux.RowExpander
24 * @extends Ext.AbstractPlugin
25 * Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables
26 * a second row body which expands/contracts. The expand/contract behavior is configurable to react
27 * on clicking of the column, double click of the row, and/or hitting enter while a row is selected.
28 *
29 * @ptype rowexpander
30 */
31Ext.define('Ext.ux.RowExpander', {
32 extend: 'Ext.AbstractPlugin',
33
34 requires: [
35 'Ext.grid.feature.RowBody',
36 'Ext.grid.feature.RowWrap'
37 ],
38
39 alias: 'plugin.rowexpander',
40
41 rowBodyTpl: null,
42
43<span id='Ext-ux-RowExpander-cfg-expandOnEnter'> /**
44</span> * @cfg {Boolean} expandOnEnter
45 * <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter
46 * key is pressed (defaults to <tt>true</tt>).
47 */
48 expandOnEnter: true,
49
50<span id='Ext-ux-RowExpander-cfg-expandOnDblClick'> /**
51</span> * @cfg {Boolean} expandOnDblClick
52 * <tt>true</tt> to toggle a row between expanded/collapsed when double clicked
53 * (defaults to <tt>true</tt>).
54 */
55 expandOnDblClick: true,
56
57<span id='Ext-ux-RowExpander-cfg-selectRowOnExpand'> /**
58</span> * @cfg {Boolean} selectRowOnExpand
59 * <tt>true</tt> to select a row when clicking on the expander icon
60 * (defaults to <tt>false</tt>).
61 */
62 selectRowOnExpand: false,
63
64 rowBodyTrSelector: '.x-grid-rowbody-tr',
65 rowBodyHiddenCls: 'x-grid-row-body-hidden',
66 rowCollapsedCls: 'x-grid-row-collapsed',
67
68
69
70 renderer: function(value, metadata, record, rowIdx, colIdx) {
71 if (colIdx === 0) {
72 metadata.tdCls = 'x-grid-td-expander';
73 }
74 return '<div class="x-grid-row-expander">&#160;</div>';
75 },
76
77<span id='Ext-ux-RowExpander-event-expandbody'> /**
78</span> * @event expandbody
79 * <b<Fired through the grid's View</b>
80 * @param {HTMLElement} rowNode The &lt;tr> element which owns the expanded row.
81 * @param {Ext.data.Model} record The record providing the data.
82 * @param {HTMLElement} expandRow The &lt;tr> element containing the expanded data.
83 */
84<span id='Ext-ux-RowExpander-event-collapsebody'> /**
85</span> * @event collapsebody
86 * <b<Fired through the grid's View.</b>
87 * @param {HTMLElement} rowNode The &lt;tr> element which owns the expanded row.
88 * @param {Ext.data.Model} record The record providing the data.
89 * @param {HTMLElement} expandRow The &lt;tr> element containing the expanded data.
90 */
91
92 constructor: function() {
93 this.callParent(arguments);
94 var grid = this.getCmp();
95 this.recordsExpanded = {};
96 // <debug>
97 if (!this.rowBodyTpl) {
98 Ext.Error.raise("The 'rowBodyTpl' config is required and is not defined.");
99 }
100 // </debug>
101 // TODO: if XTemplate/Template receives a template as an arg, should
102 // just return it back!
103 var rowBodyTpl = Ext.create('Ext.XTemplate', this.rowBodyTpl),
104 features = [{
105 ftype: 'rowbody',
106 columnId: this.getHeaderId(),
107 recordsExpanded: this.recordsExpanded,
108 rowBodyHiddenCls: this.rowBodyHiddenCls,
109 rowCollapsedCls: this.rowCollapsedCls,
110 getAdditionalData: this.getRowBodyFeatureData,
111 getRowBodyContents: function(data) {
112 return rowBodyTpl.applyTemplate(data);
113 }
114 },{
115 ftype: 'rowwrap'
116 }];
117
118 if (grid.features) {
119 grid.features = features.concat(grid.features);
120 } else {
121 grid.features = features;
122 }
123
124 // NOTE: features have to be added before init (before Table.initComponent)
125 },
126
127 init: function(grid) {
128 this.callParent(arguments);
129
130 // Columns have to be added in init (after columns has been used to create the
131 // headerCt). Otherwise, shared column configs get corrupted, e.g., if put in the
132 // prototype.
133 grid.headerCt.insert(0, this.getHeaderConfig());
134 grid.on('render', this.bindView, this, {single: true});
135 },
136
137 getHeaderId: function() {
138 if (!this.headerId) {
139 this.headerId = Ext.id();
140 }
141 return this.headerId;
142 },
143
144 getRowBodyFeatureData: function(data, idx, record, orig) {
145 var o = Ext.grid.feature.RowBody.prototype.getAdditionalData.apply(this, arguments),
146 id = this.columnId;
147 o.rowBodyColspan = o.rowBodyColspan - 1;
148 o.rowBody = this.getRowBodyContents(data);
149 o.rowCls = this.recordsExpanded[record.internalId] ? '' : this.rowCollapsedCls;
150 o.rowBodyCls = this.recordsExpanded[record.internalId] ? '' : this.rowBodyHiddenCls;
151 o[id + '-tdAttr'] = ' valign="top" rowspan="2" ';
152 if (orig[id+'-tdAttr']) {
153 o[id+'-tdAttr'] += orig[id+'-tdAttr'];
154 }
155 return o;
156 },
157
158 bindView: function() {
159 var view = this.getCmp().getView(),
160 viewEl;
161
162 if (!view.rendered) {
163 view.on('render', this.bindView, this, {single: true});
164 } else {
165 viewEl = view.getEl();
166 if (this.expandOnEnter) {
167 this.keyNav = Ext.create('Ext.KeyNav', viewEl, {
168 'enter' : this.onEnter,
169 scope: this
170 });
171 }
172 if (this.expandOnDblClick) {
173 view.on('itemdblclick', this.onDblClick, this);
174 }
175 this.view = view;
176 }
177 },
178
179 onEnter: function(e) {
180 var view = this.view,
181 ds = view.store,
182 sm = view.getSelectionModel(),
183 sels = sm.getSelection(),
184 ln = sels.length,
185 i = 0,
186 rowIdx;
187
188 for (; i < ln; i++) {
189 rowIdx = ds.indexOf(sels[i]);
190 this.toggleRow(rowIdx);
191 }
192 },
193
194 toggleRow: function(rowIdx) {
195 var rowNode = this.view.getNode(rowIdx),
196 row = Ext.get(rowNode),
197 nextBd = Ext.get(row).down(this.rowBodyTrSelector),
198 record = this.view.getRecord(rowNode),
199 grid = this.getCmp();
200
201 if (row.hasCls(this.rowCollapsedCls)) {
202 row.removeCls(this.rowCollapsedCls);
203 nextBd.removeCls(this.rowBodyHiddenCls);
204 this.recordsExpanded[record.internalId] = true;
205 this.view.fireEvent('expandbody', rowNode, record, nextBd.dom);
206 } else {
207 row.addCls(this.rowCollapsedCls);
208 nextBd.addCls(this.rowBodyHiddenCls);
209 this.recordsExpanded[record.internalId] = false;
210 this.view.fireEvent('collapsebody', rowNode, record, nextBd.dom);
211 }
212 },
213
214 onDblClick: function(view, cell, rowIdx, cellIndex, e) {
215
216 this.toggleRow(rowIdx);
217 },
218
219 getHeaderConfig: function() {
220 var me = this,
221 toggleRow = Ext.Function.bind(me.toggleRow, me),
222 selectRowOnExpand = me.selectRowOnExpand;
223
224 return {
225 id: this.getHeaderId(),
226 width: 24,
227 sortable: false,
228 resizable: false,
229 draggable: false,
230 hideable: false,
231 menuDisabled: true,
232 cls: Ext.baseCSSPrefix + 'grid-header-special',
233 renderer: function(value, metadata) {
234 metadata.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
235
236 return '<div class="' + Ext.baseCSSPrefix + 'grid-row-expander">&#160;</div>';
237 },
238 processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
239 if (type == "mousedown" && e.getTarget('.x-grid-row-expander')) {
240 var row = e.getTarget('.x-grid-row');
241 toggleRow(row);
242 return selectRowOnExpand;
243 }
244 }
245 };
246 }
247});
248</pre>
249</body>
250</html>