app:datatable
  • Required Attributes (0)
  • Optional Attributes (11)
  • Examples (1)
  • Source code
Name Type Description Default value
There are no required attributes
Back to menuExample: Simple Example

This is a simple example that uses the <app:datatable>.

Name
Age
Height
Epidermis Showing?
$MQ('l:load.datatable',{'rows':[{'col1':'Sam','col2':'18','col3':'5.5 feet','col4':'Yes'}, {'col1':'Vanessa','col2':'22','col3':'6.5 feet','col4':'No'}, {'col1':'Joe','col2':'18','col3':'5.0 feet','col4':'Yes'}, {'col1':'Bill','col2':'40','col3':'5.2 feet','col4':'Yes'}, {'col1':'James','col2':'33','col3':'6.1 feet','col4':'No'}, {'col1':'Mary','col2':'25','col3':'5.7 feet','col4':'Yes'}]});
	<style>
	<!--
	.table_cell
	{
		padding: 3px;
		border-right: 1px solid #999;
		border-left: 1px solid #999;
	}
	.table_cell_header
	{
		padding-top: 3px;
		padding-bottom: 3px;
		padding-left: 5px;
		padding-right: 5px;
		background-color: #999;
		color:white;
		border: 1px solid #555;
		cursor: pointer;
	}
	.table_row_even
	{
		padding: 3px;
		border-right: 1px solid #999;
		border-left: 1px solid #999;
		border-bottom:1px solid #999;
		background-color: #fff;
	}
	.table_row_odd
	{
		padding: 3px;
		border-right: 1px solid #999;
		border-left: 1px solid #999;
		border-bottom:1px solid #999;
		background-color: #ddd;		
	}
	-->
	</style>
	<app:datatable on="l:load.datatable then execute" width="50%" property="rows" sort="client" 
		rowEvenClass="table_row_even" rowOddClass="table_row_odd">
		<header property="col1" align="left" width="40%">Name</header>
		<header property="col2" align="center" width="30%">Age</header>
		<header property="col3" align="center" width="30%">Height</header>
		<header property="col4" align="center" width="30%">Epidermis Showing?</header>
	</app:datatable>
	<app:script style="display:none;">
		$MQ('l:load.datatable',{'rows':[{'col1':'Sam','col2':'18','col3':'5.5 feet','col4':'Yes'},
		{'col1':'Vanessa','col2':'22','col3':'6.5 feet','col4':'No'},
		{'col1':'Joe','col2':'18','col3':'5.0 feet','col4':'Yes'},
		{'col1':'Bill','col2':'40','col3':'5.2 feet','col4':'Yes'},
		{'col1':'James','col2':'33','col3':'6.1 feet','col4':'No'},
		{'col1':'Mary','col2':'25','col3':'5.7 feet','col4':'Yes'}]});
	</app:script>
  1 /*
  2  * This file is part of Appcelerator.
  3  *
  4  * Copyright (C) 2006-2008 by Appcelerator, Inc. All Rights Reserved.
  5  * For more information, please visit http://www.appcelerator.org
  6  *
  7  * Appcelerator is free software: you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License as published by
  9  * the Free Software Foundation, either version 3 of the License, or
 10  * (at your option) any later version.
 11  *
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16  * 
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 19  *
 20  */
 21 
 22 
 23 Appcelerator.Widget.Datatable =
 24 {	
 25 	modulePath:null,
 26 	setPath: function(path)
 27 	{
 28 		this.modulePath = path;
 29 	},
 30 	getName: function()
 31 	{
 32 		return 'appcelerator datatable';
 33 	},
 34 	getDescription: function()
 35 	{
 36 		return 'datatable widget';
 37 	},
 38 	getVersion: function()
 39 	{
 40 		return 1.0;
 41 	},
 42 	getSpecVersion: function()
 43 	{
 44 		return 1.0;
 45 	},
 46 	getAuthor: function()
 47 	{
 48 		return 'Amro Mousa';
 49 	},
 50 	getModuleURL: function ()
 51 	{
 52 		return 'http://www.appcelerator.org';
 53 	},
 54 	isWidget: function ()
 55 	{
 56 		return true;
 57 	},
 58 	getWidgetName: function()
 59 	{
 60 		return 'app:datatable';
 61 	},
 62 	getActions: function()
 63 	{
 64 		return ['execute', 'stop', 'start'];
 65 	},
 66 	getAttributes: function()
 67     {
 68 		var T = Appcelerator.Types;
 69         return [{name: 'on', optional: true,
 70 		         description: "Used to populate the data table.",
 71 				 type: T.onExpr},
 72                 {name: 'sort', optional: true, defaultValue: 'client',
 73 				 description: "Where the responsibility for sorting items in the table rests"+
 74 				              "Valid values are 'client', 'server', and 'off.'",
 75 				 type: T.enumeration('client','server','off')},
 76                 {name: 'sortRequest', optional: true, defaultValue: '',
 77 				 description: "Message to be sent when the sort mode is 'server' and a column header is clicked.",
 78 				 type: T.messageSend},
 79                 {name: 'rowEvenClass', optional: true, defaultValue: '', type: T.cssClass},
 80                 {name: 'rowOddClass', optional: true, defaultValue: '', type: T.cssClass},
 81                 {name: 'width', optional: true, defaultValue: '100%',
 82 				 description: "Width of entire table.",
 83 				 type: T.cssDimension},
 84                 {name: 'property', optional: true, defaultValue: '', type: T.identifier},
 85                 {name: 'pagination', optional: true, defaultValue: 'false', type: T.bool},
 86                 {name: 'maxRows', optional: true, defaultValue: 0, type: T.naturalNumber},
 87                 {name: 'sortIndex', optional: true, defaultValue: -1, type: T.naturalNumber},
 88 				{name: 'stickySort', optional: true, defaultValue: true, type: T.bool}];
 89     },
 90 	formatShift1k: function(cell_value,column_property_name, row)
 91 	{
 92 		if (!isNaN(cell_value))
 93 			return parseInt(parseInt(cell_value)/1000);
 94 		else
 95 			return cell_value;
 96 	},
 97 	formatShift1000k: function(cell_value,column_property_name, row)
 98 	{
 99 		if (!isNaN(cell_value))
100 			return parseInt(parseInt(cell_value)/1000000);
101 		else
102 			return cell_value;
103 	},
104 	createDataTable: function (id, pagination_direction)
105 	{		
106 		//list of on attributes to be parsed and evaluated at the end of create
107 		var on_array = [];
108 
109 		var parameterMap = $(id).parameterMap;
110 		var needRecompile=false;
111 		var scope = parameterMap['scope'];
112 		
113 		//Valid values are 'client', 'server', and 'off'
114 		var sort = parameterMap['sort'];
115 		
116 		//Really applies styles to the CELLS on the even and odd rows
117 		var rowEvenClass = parameterMap['rowEvenClass'];
118 		var rowOddClass = parameterMap['rowOddClass'];
119 		
120 		//Width % of entire table
121 		var width = parameterMap['width'];
122 			
123 		//Controls whether or not to add spacers to the header (true on initial render)
124 		var add_spacers_to_header = parameterMap['add_spacers_to_header'];
125 		
126 		var header_array = parameterMap['header_array'];
127 		var array = parameterMap['array'];
128 		
129 		var pagination = parameterMap['pagination'];
130 		var maxRows = parseInt(parameterMap['maxRows']);
131 
132 		if (pagination == 'true' && !pagination_direction)
133 		{
134 			pagination_direction = 'forward';
135 			maxRows = maxRows == 0 ? 10 : maxRows;
136 		}
137 
138 		if (pagination == 'false')
139 		{
140 			maxRows = array.length;
141 		}
142 		parameterMap['maxRows'] = maxRows;
143 
144 		var html = '';
145 			
146 		//Default class names -- the only class names accepted directly by the table are rowEvenClass and rowOddClass
147 		//.table_row
148 		//.table_cell -- default IFF rowOddClass or rowEvenClass are not provided
149 		//.table_row_header
150 		//.table_cell_header
151 					
152 		var table_open = '<table cellspacing="0" border="0" width="'+width+'">';
153 		var table_close = '</table>';
154 		var table_header_content = '';
155 		var table_data_content = '';
156 		var arrow_up_img = '<img src="'+ Appcelerator.Widget.Datatable.modulePath + 'images/arrow_up.png" title="sort ascending" style="position:relative;top:-1px; left: 2px;" />';
157 		var arrow_down_img = '<img src="'+ Appcelerator.Widget.Datatable.modulePath + 'images/arrow_down.png" title="sort ascending" style="position:relative;top:-1px; left: 2px;" />';
158 		var spacer_img = '<img src="'+ Appcelerator.Widget.Datatable.modulePath + 'images/arrow_spacer.png" title="sort ascending" style="position:relative;top:-1px; left: 2px;" />';
159 	
160 		//Add spacers to the header (initially) and clear up any extra icons
161 		if (add_spacers_to_header)
162 		{
163 			for(var i = 0, len = header_array.length; i < len; i++)
164 			{
165 				header_array[i]['cell'] = header_array[i]['cell'].replace(arrow_up_img,'');
166 				header_array[i]['cell'] = header_array[i]['cell'].replace(arrow_down_img,'');
167 				header_array[i]['cell'] = header_array[i]['cell'].replace(spacer_img,'');
168 				header_array[i]['cell'] += spacer_img;
169 			}
170 		}
171 		
172 		//Create the header
173 		for (var x = 0, len = header_array.length; x < len; x++)
174 		{
175 			var header_info = header_array[x];
176 			var formatterFunction = eval(header_array[x]['formatter']);
177 			var onheader = header_array[x]['cellon'];
178 			var onTemplate = null;
179 			if (onheader)
180 			{
181 				needRecompile=true;
182 				header_info.onTemplate = new Template('on="'+onheader+'"');
183 			}
184 			if (formatterFunction) {
185 				header_info.formatterFunction = formatterFunction;
186 			}
187 			
188 			var hclass = header_info['class'];
189 			if (hclass == '' || hclass == null)
190 			{
191 				hclass='table_cell_header';
192 			}
193 			
194 			var or = '';
195 			if (header_info['on'] != '')
196 			{
197 				or = ' or ';
198 			}
199 					
200 			var sort_string = '';
201 			if (sort == 'client')
202 			{
203 				sort_string = 'click then script[Appcelerator.Widget.Datatable.sortDataTableClient(' + x + ',' + '\'' + id + '\'' + ')]';
204 			} else if (sort == 'server')
205 			{
206 				sort_string = 'click then script[Appcelerator.Widget.Datatable.sortDataTableServer(' + x + ',' + '\'' + id + '\'' + ')]';
207 				
208 				if (parameterMap['current_server_sort_column'] == header_info['property'])
209 				{
210 					if (!parameterMap['sortBy'][parameterMap['current_server_sort_column']])
211 					{
212 						header_array[x]['cell'] = header_array[x]['cell'].replace(spacer_img,'');
213 						header_array[x]['cell'] += arrow_up_img;
214 					} else
215 					{
216 						header_array[x]['cell'] = header_array[x]['cell'].replace(spacer_img,'');
217 						header_array[x]['cell'] += arrow_down_img;
218 					}	
219 				}
220 			} else
221 			{
222 				sort_string = '';
223 			}	
224 				
225 			// Pass the index of the cell in header array
226 			var hw = header_info['width'];
227 			var td = '<td id="' + id + '_header_' + x + '" align="' + header_info['align'] + '" ' +(hw?'width="'+hw+'"':'')+' class="' + hclass + '"><span>' + header_info['cell'] + '</span></td>';
228 			
229 			if (sort_string != '')
230 			{
231 				var header_on_expression = header_info['on'] + or + sort_string;
232 				on_array.push({'id': id + '_header_' + x, 'on': header_on_expression});				
233 			}
234 			
235 			
236 			table_header_content += td;
237 		}
238 		table_header_content = '<tr class="table_row_header">' + table_header_content + '</tr>';
239 	
240 		//Create the table body
241 		var x = 0;
242 		var length = maxRows;
243 
244 		if (pagination == 'true')
245 		{
246 			if (pagination_direction == 'forward')
247 			{
248 				if ($(id).initialLoad)
249 				{
250 					x = $(id).position;
251 					$(id).initialLoad = false;
252 				} else
253 				{
254 					x = $(id).position+maxRows >= array.length ? $(id).position : $(id).position+maxRows;					
255 				}
256 				length = x+maxRows > array.length ? array.length : x+maxRows;
257 			} else
258 			{
259 				if($(id).position-maxRows < 0)
260 				{
261 					x = 0;
262 					length = maxRows > array.length ? array.length : maxRows;
263 				} else
264 				{
265 					x = $(id).position-maxRows;
266 					length = x+maxRows > array.length ? array.length : x+maxRows;
267 				}
268 			}
269 			$(id).position = x;
270 		}
271 		
272 		var xrun = x;
273 		
274 		for (; xrun < length; xrun++)
275 		{
276 			table_data_content += '<tr class="table_row">';				
277 			for (var h = 0, lenH = header_array.length; h < lenH; h++)
278 			{
279 				var cell_class = (xrun % 2 == 0) ? rowEvenClass : rowOddClass;
280 				if (cell_class == '')
281 				{
282 					cell_class = 'table_cell';
283 				}
284 				
285 				//Get the column property needed to figure out what column from the current array item we need
286 				var column_property_name = header_array[h]['property'];
287 				var formatterFunction = header_array[h]['formatterFunction'];
288 				var onTemplate = header_array[h]['onTemplate'];
289 				cell_on="";
290 				if (onTemplate) 
291 				{
292 					cell_on = onTemplate.evaluate(array[xrun]);
293 				}
294 				var cell_value = (Object.getNestedProperty(array[xrun],column_property_name)||'');
295 				if (formatterFunction) {
296 					cell_value = formatterFunction(cell_value,column_property_name, array[xrun]);
297 				} else {
298 					cell_value.toString().escapeHTML();
299 				}
300 				var td ='<td align="' + header_array[h]['align'] +'" '+ cell_on+ ' class="' + cell_class + '"><span>' + cell_value +'</span></td>';
301 				table_data_content += td;
302 			}
303 			table_data_content += '</tr>';
304 		}
305 		html = table_open + table_header_content + table_data_content + table_close;	
306 		
307 		var myidback = id + "_pagination_back";
308 		var myidforward = id + "_pagination_forward";
309 
310 		if (pagination == 'true')
311 		{
312 			var pag_html = '';
313 			var myid = "'" + id + "'";
314 			var forward = '"forward"';
315 			var backward = "'backward'";
316 			
317 			pag_html = '<div style="padding-bottom: 5px;">'+
318 								 '<a class="pagination_links" id="'+myidback+'"><img style="border: 0;" src="'+Appcelerator.Widget.Datatable.modulePath+'images/resultset_previous.png"/></a> ' +
319 								 '<a class="pagination_links" id="'+myidforward+'"><img style="border: 0;" src="'+Appcelerator.Widget.Datatable.modulePath + 'images/resultset_next.png"/></a>      Showing '+(x+1)+'-'+(length)+' of '+array.length+'</div>';
320 			
321 			html = pag_html + html;
322 		}
323 		
324 		Appcelerator.Compiler.setHTML(id,html);
325 		if (needRecompile)
326 			Appcelerator.Compiler.dynamicCompile($(id));
327 
328 		if (pagination == 'true')
329 		{
330 			$(myidback).onclick = function(){Appcelerator.Widget.Datatable.createDataTable(id, 'backward');}.bind(this);
331 			$(myidforward).onclick = function(){Appcelerator.Widget.Datatable.createDataTable(id, 'forward');}.bind(this);
332 			$(myidback).onmousedown = function(){Appcelerator.Widget.Datatable.paginateContinuously(id, 'backward');}.bind(this);
333 			$(myidforward).onmousedown = function(){Appcelerator.Widget.Datatable.paginateContinuously(id, 'forward');}.bind(this);
334 			$(myidback).onmouseup = function(){Appcelerator.Widget.Datatable.stopContinuousPagination(id)}.bind(this);
335 			$(myidforward).onmouseup = function(){Appcelerator.Widget.Datatable.stopContinuousPagination(id)}.bind(this);
336 			$(myidback).onmouseout = function(){Appcelerator.Widget.Datatable.stopContinuousPagination(id)}.bind(this);
337 			$(myidforward).onmouseout = function(){Appcelerator.Widget.Datatable.stopContinuousPagination(id)}.bind(this);
338 		}
339 		var on_run_array = [];
340 		
341 		for (var i = 0, len = on_array.length; i < len; i++)
342 		{
343 			on_run_array.push(Appcelerator.Compiler.compileExpression($(on_array[i]['id']),on_array[i]['on'],false));
344 		}
345 
346 		eval(on_run_array.join(';'));
347 	},
348 	compileWidget: function (parameters, element)
349 	{		
350 	},
351 	paginateContinuously: function (id, direction)
352 	{
353 		var paginator = function()
354 		{
355 			if (direction == 'forward') Appcelerator.Widget.Datatable.createDataTable(id,'forward');
356 			else Appcelerator.Widget.Datatable.createDataTable(id,'backward');
357 		};
358 		$(id).paginationInterval = setInterval(paginator,250);
359 	},
360 	stopContinuousPagination: function (id)
361 	{
362 		clearInterval($(id).paginationInterval);
363 	},
364 	sortDataTableClient: function (index, id, maintainSortOrder)
365 	{
366 		var parameterMap = $(id).parameterMap;
367 		var header_array = parameterMap['header_array'];
368 		var array = parameterMap['array'];
369 		var column_property_name = header_array[index]['property'];
370 		parameterMap['lastSortIndex'] = index;
371 		
372 		$(id).position = 0;
373 		$(id).initialLoad = true;
374 		
375 		var sortFunction = eval(header_array[index]['sorter']);
376 		
377 		//Are we sorting numbers or strings? Check only the column we're sorting by..
378 		var num_sort = false;
379 		
380 		if (!sortFunction) {
381 			num_sort = true;
382 			for (var x = 0, len = array.length; x < len; x++) {
383 				var cell_value = (Object.getNestedProperty(array[x],column_property_name) || '');
384 				
385 				if (isNaN(parseFloat(cell_value))) {
386 					num_sort = false;
387 					break;
388 				}
389 			}
390 		}
391 	
392 		//Initialize the object holding our previous per-column sort state
393 		if (parameterMap['sortBy'] == null)
394 		{
395 			parameterMap['sortBy'] = {};
396 			parameterMap['sortBy'][column_property_name] = false;
397 		}
398 	
399 		//Flip the per column sort state for this column
400 		parameterMap['sortBy'][column_property_name] = !maintainSortOrder ? !parameterMap['sortBy'][column_property_name] :