A demonstration of the DataTable's row expansion feature to display a list of "Interestingness" from Flickr. When the table first loads, it displays a list of image titles. When a row is expanded the photo is displayed in the expansion area along with a link to the Flickr user's photostream. This example uses a simple string-based template to format the row expansion area.
Interestingness | |
---|---|
Custom CSS for this example:
1 | /** |
2 | * |
3 | * Style the yui-dt-expandablerow-trigger column |
4 | * |
5 | **/ |
6 | .yui-dt-expandablerow-trigger{ |
7 | width:18px; |
8 | height:22px; |
9 | cursor:pointer; |
10 | } |
11 | .yui-dt-expanded .yui-dt-expandablerow-trigger{ |
12 | background:url(arrow_open.png) 4px 4px no-repeat; |
13 | } |
14 | .yui-dt-expandablerow-trigger, .yui-dt-collapsed .yui-dt-expandablerow-trigger{ |
15 | background:url(arrow_closed.png) 4px 4px no-repeat; |
16 | } |
17 | .yui-dt-expanded .yui-dt-expandablerow-trigger.spinner{ |
18 | background:url(spinner.gif) 1px 4px no-repeat; |
19 | } |
20 | |
21 | /** |
22 | * |
23 | * Style the expansion row |
24 | * |
25 | **/ |
26 | .yui-dt-expansion .yui-dt-liner{ |
27 | padding:0; |
28 | border:solid 0 #bbb; |
29 | border-width: 0 0 2px 0; |
30 | } |
31 | .yui-dt-expansion .yui-dt-liner th, .yui-dt-expansion .yui-dt-liner table{ |
32 | border:none; |
33 | background-color:#fff; |
34 | } |
35 | .yui-dt-expansion .yui-dt-liner th, .yui-dt-expansion .yui-dt-liner table th{ |
36 | background-image:none; |
37 | background-color:#eee; |
38 | } |
39 | .yui-dt-expansion .yui-dt-liner th, .yui-dt-expansion .yui-dt-liner table td{ |
40 | border:solid 0 #eee; |
41 | border-width: 0 0 1px 1px; |
42 | } |
43 | .yui-dt-expansion .yui-dt-liner th, .yui-dt-expansion .yui-dt-liner table td div{ |
44 | padding:3px; |
45 | overflow:hidden; |
46 | width:100px; |
47 | } |
48 | .yui-dt-expansion .yui-dt-liner th, .yui-dt-expansion .yui-dt-liner table td.big div{ |
49 | width:300px; |
50 | } |
51 | .yui-dt-expansion .yui-dt-liner th, .yui-dt-expansion .yui-dt-liner table td ul{ padding:0;margin:0; } |
view plain | print | ? |
DataTable RowExpansion extension code:
1 | /* This code should not be modified */ |
2 | |
3 | (function(){ |
4 | |
5 | var Dom = YAHOO.util.Dom, |
6 | |
7 | STRING_STATENAME = 'yui_dt_state', |
8 | |
9 | CLASS_EXPANDED = 'yui-dt-expanded', |
10 | CLASS_COLLAPSED = 'yui-dt-collapsed', |
11 | CLASS_EXPANSION = 'yui-dt-expansion', |
12 | CLASS_LINER = 'yui-dt-liner', |
13 | |
14 | //From YUI 3 |
15 | indexOf = function(a, val) { |
16 | for (var i=0; i<a.length; i=i+1) { |
17 | if (a[i] === val) { |
18 | return i; |
19 | } |
20 | } |
21 | |
22 | return -1; |
23 | }; |
24 | |
25 | YAHOO.lang.augmentObject( |
26 | YAHOO.widget.DataTable.prototype , { |
27 | |
28 | //////////////////////////////////////////////////////////////////// |
29 | // |
30 | // Private members |
31 | // |
32 | //////////////////////////////////////////////////////////////////// |
33 | |
34 | /** |
35 | * Gets state object for a specific record associated with the |
36 | * DataTable. |
37 | * @method _getRecordState |
38 | * @param {Mixed} record_id Record / Row / or Index id |
39 | * @param {String} key Key to return within the state object. |
40 | * Default is to return all as a map |
41 | * @return {Object} State data object |
42 | * @type mixed |
43 | * @private |
44 | **/ |
45 | _getRecordState : function( record_id, key ){ |
46 | var row_data = this.getRecord( record_id ), |
47 | row_state = row_data.getData( STRING_STATENAME ), |
48 | state_data = (row_state && key) ? row_state[ key ]:row_state; |
49 | |
50 | return state_data || {}; |
51 | }, |
52 | |
53 | /** |
54 | * Sets a value to a state object with a unique id for a record |
55 | * which is associated with the DataTable |
56 | * @method _setRecordState |
57 | * @param {Mixed} record_id Record / Row / or Index id |
58 | * @param {String} key Key to use in map |
59 | * @param {Mixed} value Value to assign to the key |
60 | * @return {Object} State data object |
61 | * @type mixed |
62 | * @private |
63 | **/ |
64 | _setRecordState : function( record_id, key, value ){ |
65 | var row_data = this.getRecord( record_id ).getData(), |
66 | merged_data = row_data[ STRING_STATENAME ] || {}; |
67 | |
68 | merged_data[ key ] = value; |
69 | |
70 | this.getRecord(record_id).setData(STRING_STATENAME, merged_data); |
71 | |
72 | return merged_data; |
73 | |
74 | }, |
75 | |
76 | ////////////////////////////////////////////////////////////////////// |
77 | // |
78 | // Public methods |
79 | // |
80 | ////////////////////////////////////////////////////////////////////// |
81 | |
82 | /** |
83 | * Over-ridden initAttributes method from DataTable |
84 | * @method initAttributes |
85 | * @param {Mixed} record_id Record / Row / or Index id |
86 | * @param {String} key Key to use in map |
87 | * @param {Mixed} value Value to assign to the key |
88 | * @return {Object} State data object |
89 | * @type mixed |
90 | **/ |
91 | initAttributes : function( oConfigs ) { |
92 | |
93 | oConfigs = oConfigs || {}; |
94 | |
95 | YAHOO.widget.DataTable.superclass.initAttributes.call(this, |
96 | oConfigs); |
97 | |
98 | /** |
99 | * @attribute rowExpansionTemplate |
100 | * @description Value for the rowExpansionTemplate attribute. |
101 | * @type {Mixed} |
102 | * @default "" |
103 | **/ |
104 | this.setAttributeConfig("rowExpansionTemplate", { |
105 | value: "", |
106 | validator: function( template ){ |
107 | return ( |
108 | YAHOO.lang.isString( template ) || |
109 | YAHOO.lang.isFunction( template ) |
110 | ); |
111 | }, |
112 | method: this.initRowExpansion |
113 | }); |
114 | |
115 | }, |
116 | |
117 | /** |
118 | * Initializes row expansion on the DataTable instance |
119 | * @method initRowExpansion |
120 | * @param {Mixed} template a string template or function to be |
121 | * called when Row is expanded |
122 | * @type mixed |
123 | **/ |
124 | initRowExpansion : function( template ){ |
125 | //Set subscribe restore method |
126 | this.subscribe('postRenderEvent', |
127 | this.onEventRestoreRowExpansion); |
128 | |
129 | //Setup template |
130 | this.rowExpansionTemplate = template; |
131 | |
132 | //Set table level state |
133 | this.a_rowExpansions = []; |
134 | }, |
135 | |
136 | /** |
137 | * Toggles the expansion state of a row |
138 | * @method toggleRowExpansion |
139 | * @param {Mixed} record_id Record / Row / or Index id |
140 | * @type mixed |
141 | **/ |
142 | toggleRowExpansion : function( record_id ){ |
143 | var state = this._getRecordState( record_id ); |
144 | |
145 | if( state && state.expanded ){ |
146 | this.collapseRow( record_id ); |
147 | } else { |
148 | this.expandRow( record_id ); |
149 | } |
150 | }, |
151 | |
152 | /** |
153 | * Sets the expansion state of a row to expanded |
154 | * @method expandRow |
155 | * @param {Mixed} record_id Record / Row / or Index id |
156 | * @param {Boolean} restore will restore an exisiting state for a |
157 | * row that has been collapsed by a non user action |
158 | * @return {Boolean} successful |
159 | * @type mixed |
160 | **/ |
161 | expandRow : function( record_id, restore ){ |
162 | |
163 | var state = this._getRecordState( record_id ); |
164 | |
165 | if( !state.expanded || restore ){ |
166 | |
167 | var row_data = this.getRecord( record_id ), |
168 | row = this.getRow( row_data ), |
169 | new_row = document.createElement('tr'), |
170 | column_length = this.getFirstTrEl().childNodes.length, |
171 | expanded_data = row_data.getData(), |
172 | expanded_content = null, |
173 | template = this.rowExpansionTemplate, |
174 | next_sibling = Dom.getNextSibling( row ); |
175 | |
176 | //Construct expanded row body |
177 | new_row.className = CLASS_EXPANSION; |
178 | var new_column = document.createElement( 'td' ); |
179 | new_column.colSpan = column_length; |
180 | |
181 | new_column.innerHTML = '<div class="'+CLASS_LINER+'"></div>'; |
182 | new_row.appendChild( new_column ); |
183 | |
184 | var liner_element = new_row.firstChild.firstChild; |
185 | |
186 | if( YAHOO.lang.isString( template ) ){ |
187 | |
188 | liner_element.innerHTML = YAHOO.lang.substitute( |
189 | template, |
190 | expanded_data |
191 | ); |
192 | |
193 | } else if( YAHOO.lang.isFunction( template ) ) { |
194 | |
195 | template( { |
196 | row_element : new_row, |
197 | liner_element : liner_element, |
198 | data : row_data, |
199 | state : state |
200 | |
201 | } ); |
202 | |
203 | } else { |
204 | return false; |
205 | } |
206 | |
207 | //Insert new row |
208 | newRow = Dom.insertAfter( new_row, row ); |
209 | |
210 | if (newRow.innerHTML.length) { |
211 | |
212 | this._setRecordState( record_id, 'expanded', true ); |
213 | |
214 | if( !restore ){ |
215 | this.a_rowExpansions.push( |
216 | this.getRecord(record_id).getId() |
217 | ); |
218 | } |
219 | |
220 | Dom.removeClass( row, CLASS_COLLAPSED ); |
221 | Dom.addClass( row, CLASS_EXPANDED ); |
222 | |
223 | //Fire custom event |
224 | this.fireEvent( "rowExpandEvent", |
225 | { record_id : row_data.getId() } ); |
226 | |
227 | return true; |
228 | } else { |
229 | return false; |
230 | } |
231 | } |
232 | }, |
233 | |
234 | /** |
235 | * Sets the expansion state of a row to collapsed |
236 | * @method collapseRow |
237 | * @param {Mixed} record_id Record / Row / or Index id |
238 | * @return {Boolean} successful |
239 | * @type mixed |
240 | **/ |
241 | collapseRow : function( record_id ){ |
242 | var row_data = this.getRecord( record_id ), |
243 | row = Dom.get( row_data.getId() ), |
244 | state = row_data.getData( STRING_STATENAME ); |
245 | |
246 | if( state && state.expanded ){ |
247 | var next_sibling = Dom.getNextSibling( row ), |
248 | hash_index = indexOf(this.a_rowExpansions, record_id); |
249 | |
250 | if( Dom.hasClass( next_sibling, CLASS_EXPANSION ) ) { |
251 | next_sibling.parentNode.removeChild( next_sibling ); |
252 | this.a_rowExpansions.splice( hash_index, 1 ); |
253 | this._setRecordState( record_id, 'expanded', false ); |
254 | |
255 | Dom.addClass( row, CLASS_COLLAPSED ); |
256 | Dom.removeClass( row, CLASS_EXPANDED ); |
257 | |
258 | //Fire custom event |
259 | this.fireEvent("rowCollapseEvent", |
260 | {record_id:row_data.getId()}); |
261 | |
262 | return true; |
263 | } else { |
264 | return false; |
265 | } |
266 | } |
267 | }, |
268 | |
269 | /** |
270 | * Collapses all expanded rows. This should be called before any |
271 | * action where the row expansion markup would interfere with |
272 | * normal DataTable markup handling. This method does not remove |
273 | * events attached during implementation. All event handlers should |
274 | * be removed separately. |
275 | * @method collapseAllRows |
276 | * @type mixed |
277 | **/ |
278 | collapseAllRows : function(){ |
279 | var rows = this.a_rowExpansions; |
280 | |
281 | for( var i = 0, l = rows.length; l > i; i++ ){ |
282 | //Always pass 0 since collapseRow |
283 | //removes item from the a_rowExpansions array |
284 | this.collapseRow( rows[ 0 ] ); |
285 | |
286 | } |
287 | |
288 | a_rowExpansions = []; |
289 | |
290 | }, |
291 | |
292 | /** |
293 | * Restores rows which have an expanded state but no markup. This |
294 | * is to be called to restore row expansions after the DataTable |
295 | * renders or the collapseAllRows is called. |
296 | * @method collapseAllRows |
297 | * @type mixed |
298 | **/ |
299 | restoreExpandedRows : function(){ |
300 | var expanded_rows = this.a_rowExpansions; |
301 | |
302 | if( !expanded_rows.length ){ |
303 | return; |
304 | } |
305 | |
306 | if( this.a_rowExpansions.length ){ |
307 | for( var i = 0, l = expanded_rows.length; l > i; i++ ){ |
308 | this.expandRow( expanded_rows[ i ] , true ); |
309 | } |
310 | } |
311 | }, |
312 | |
313 | /** |
314 | * Abstract method which restores row expansion for subscribing to |
315 | * the DataTable postRenderEvent. |
316 | * @method onEventRestoreRowExpansion |
317 | * @param {Object} oArgs context of a subscribed event |
318 | * @type mixed |
319 | **/ |
320 | onEventRestoreRowExpansion : function( oArgs ){ |
321 | this.restoreExpandedRows(); |
322 | }, |
323 | |
324 | /** |
325 | * Abstract method which toggles row expansion for subscribing to |
326 | * the DataTable postRenderEvent. |
327 | * @method onEventToggleRowExpansion |
328 | * @param {Object} oArgs context of a subscribed event |
329 | * @type mixed |
330 | **/ |
331 | onEventToggleRowExpansion : function( oArgs ){ |
332 | if(YAHOO.util.Dom.hasClass(oArgs.target, |
333 | 'yui-dt-expandablerow-trigger')){ |
334 | this.toggleRowExpansion( oArgs.target ); |
335 | } |
336 | } |
337 | |
338 | }, true //This boolean needed to override members of the original object |
339 | ); |
340 | |
341 | })(); |
view plain | print | ? |
JavaScript to run this example:
1 | /* Modify as needed */ |
2 | |
3 | YAHOO.util.Event.onDOMReady( function() { |
4 | YAHOO.example.Basic = function() { |
5 | var expansionFormatter = function(el, oRecord, oColumn, oData) { |
6 | var cell_element = el.parentNode; |
7 | |
8 | //Set trigger |
9 | if( oData ){ //Row is closed |
10 | YAHOO.util.Dom.addClass( cell_element, |
11 | "yui-dt-expandablerow-trigger" ); |
12 | } |
13 | |
14 | }; |
15 | |
16 | var myDataSource = new |
17 | YAHOO.util.DataSource(YAHOO.example.interestingness); |
18 | myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY; |
19 | myDataSource.responseSchema = { |
20 | fields: ["title","farm","server","id","secret","owner"] |
21 | }; |
22 | |
23 | var myDataTable = new YAHOO.widget.DataTable( |
24 | "event_table", |
25 | [ |
26 | { |
27 | key:"farm", |
28 | label:"", |
29 | formatter:expansionFormatter |
30 | }, |
31 | { |
32 | key:"title", |
33 | label:"Interestingness", |
34 | width : '200px', |
35 | sortable:true |
36 | } |
37 | ], |
38 | myDataSource, |
39 | { rowExpansionTemplate : |
40 | '<img src="http://farm{farm}.static.flickr.com/'+ |
41 | '{server}/{id}_{secret}_m_d.jpg" />' } |
42 | ); |
43 | |
44 | //Subscribe to a click event to bind to |
45 | myDataTable.subscribe( 'cellClickEvent', |
46 | myDataTable.onEventToggleRowExpansion ); |
47 | |
48 | return { |
49 | oDS: myDataSource, |
50 | oDT: myDataTable |
51 | }; |
52 | }(); |
53 | }); |
view plain | print | ? |
You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.
Note: Logging and debugging is currently turned off for this example.
Copyright © 2009 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Copyright Policy - Job Openings