2 Fieldmapper object table
9 function drawFMObjectTable( args ) {
11 var destination = args.dest;
14 if( typeof destination == 'string' )
15 destination = $(destination);
16 var builder = new FMObjectBuilder(obj, args);
18 destination.appendChild(builder.build());
23 /* Constructor for the builder object */
24 function FMObjectBuilder( obj, args ) {
26 this.table = elem('table');
27 this.thead = elem('thead');
28 this.tbody = elem('tbody');
29 this.thead_tr = elem('tr');
31 this.display = args.display;
32 this.selectCol = args.selectCol;
33 this.moneySummaryRow = args.moneySummaryRow;
34 this.selectColName = args.selectColName;
35 this.selectAllName = args.selectAllName;
36 this.selectNoneName = args.selectNoneName;
38 if(!this.display) this.display = {};
40 this.table.appendChild(this.thead);
41 this.table.appendChild(this.tbody);
42 this.thead.appendChild(this.thead_tr)
44 addCSSClass(this.table, 'fm_table');
45 addCSSClass(this.table, 'sortable');
46 this.table.id = 'fm_table_' + (ID_GEN++);
50 FMObjectBuilder.prototype.getSelected = function() {
52 for( var i = 0; i < this.rows.length; i++ ) {
53 var r = $(this.rows[i]);
54 if( $n(r,'selected') && $n(r,'selected').checked )
55 objs.push(this.obj[i]);
60 /* Builds the table */
61 FMObjectBuilder.prototype.build = function() {
64 if( instanceOf(this.obj, Array) )
66 else this.obj = [this.obj];
71 if( this.selectCol ) {
73 var td = elem('td',null,this.selectColName);
75 var all = elem('a',{href:'javascript:void(0);','class':'fm_select_link' }, this.selectAllName);
76 var none = elem('a',{href:'javascript:void(0);', 'class':'fm_select_link'}, this.selectNoneName);
78 all.onclick = function(){obj.selectAll()};
79 none.onclick = function(){obj.selectNone()};
83 this.thead_tr.appendChild(td);
86 if (this.moneySummaryRow) {
87 this.moneySummaryRow = elem('tr');
90 this.moneySummaryRow.appendChild(elem('td'));
92 for( var i = 0; i < this.keys.length; i++ ) {
93 var key = this.keys[i];
96 td.setAttribute('name', this.table.id + key);
98 if (this.money && grep(this.money,function(i){return (i==key)}) )
99 td.appendChild(text('0.00'));
101 this.moneySummaryRow.appendChild(td);
104 this.tbody.appendChild(this.moneySummaryRow);
107 for( var i = 0; i < this.keys.length; i++ )
108 this.thead_tr.appendChild(elem('td',null,this.keys[i]));
110 if ( this.sortdata ) {
111 var sortdata = this.sortdata;
112 this.obj.sort(function(a, b){
114 var left = a[sortdata[0]]().toLowerCase();
115 var right = b[sortdata[0]]().toLowerCase();
116 if (left == right) return 0;
119 return ret * sortdata[1];
123 for( var i = 0; i < this.obj.length; i++ )
124 this.buildObjectRow(this.obj[i]);
131 FMObjectBuilder.prototype.selectAll = function() {
132 for( var i = 0; i < this.rows.length; i++ ) {
133 var r = $(this.rows[i]);
134 $n(r,'selected').checked = true;
138 FMObjectBuilder.prototype.selectNone = function() {
139 for( var i = 0; i < this.rows.length; i++ ) {
140 var r = $(this.rows[i]);
141 $n(r,'selected').checked = false;
147 FMObjectBuilder.prototype.setKeys = function(o) {
149 if( this.display[o.classname] ) {
150 this.keys = this.display[o.classname].fields;
151 this.bold = this.display[o.classname].bold;
152 this.money = this.display[o.classname].money;
153 this.sortdata = this.display[o.classname].sortdata;
154 this.calculate = this.display[o.classname].calculate;
157 if(!this.keys && FM_TABLE_DISPLAY[o.classname])
158 this.keys = FM_TABLE_DISPLAY[o.classname].fields;
160 if(!this.bold && FM_TABLE_DISPLAY[o.classname])
161 this.bold = FM_TABLE_DISPLAY[o.classname].bold;
163 if(!this.money && FM_TABLE_DISPLAY[o.classname])
164 this.money = FM_TABLE_DISPLAY[o.classname].money;
166 if(!this.sortdata && FM_TABLE_DISPLAY[o.classname])
167 this.sortdata = FM_TABLE_DISPLAY[o.classname].sortdata;
169 if(!this.calculate && FM_TABLE_DISPLAY[o.classname])
170 this.calculate = FM_TABLE_DISPLAY[o.classname].calculate;
173 this.keys = fmclasses[o.classname];
177 if(sortme) this.keys = this.keys.sort();
180 /* use this method to insert object rows after the table has been rendered */
181 FMObjectBuilder.prototype.add = function(obj) {
183 this.buildObjectRow(obj);
186 /* Inserts one row into the table to represent a single object */
187 FMObjectBuilder.prototype.buildObjectRow = function(obj) {
188 var row = elem('tr');
189 row.id = 'fm_table_' + (ID_GEN++);
190 this.rows.push(row.id);
194 td.appendChild(elem('input',{type:'checkbox',name:'selected'}));
198 for( var i = 0; i < this.keys.length; i++ ) {
201 var key = this.keys[i];
202 if (this.calculate && this.calculate[key]) { // fake data! pass the object
203 td.appendChild(this.calculate[key](obj));
206 data = this.munge(data);
207 this.fleshData(td, data, key);
212 this.tbody.appendChild(row);
213 if (this.moneySummaryRow) this.tbody.appendChild(this.moneySummaryRow);
216 FMObjectBuilder.prototype.munge = function(data) {
218 if(typeof data == 'string') {
219 if( data.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/) ) {
220 data = data.replace(/T/,' ');
221 data = data.replace(/:\d{2}-.*/,'');
229 FMObjectBuilder.prototype.dataName = function(data) {
231 if( this.display[data.classname] )
232 name = this.display[data.classname].name;
234 if(!name && FM_TABLE_DISPLAY[data.classname])
235 name = FM_TABLE_DISPLAY[data.classname].name;
237 if(!name) name = 'id';
244 FMObjectBuilder.prototype.fleshData = function(td, data, key) {
245 if(data == null) data = '';
247 if( typeof data == 'object' ) {
250 if( data._isfieldmapper )
251 atext = this.dataName(data);
253 else if (instanceOf(data, Array) )
259 var expand = function () {
261 var row = td.parentNode.nextSibling;
262 if( row && row.getAttribute('subrow') == key) buildme = false;
263 master.hideSubTables();
264 if(buildme) master.buildSubTable(td, data, key);
267 var a = elem('a',{href:'javascript:void(0);'});
269 a.appendChild(text(atext));
273 td.appendChild(text(''));
277 if (this.money && grep(this.money,function(i){return (i==key)}) ) {
278 td.setAttribute('align', 'right');
279 data = parseFloat(data).toFixed(2);
281 if (isNaN(data)) data = '0.00';
283 if (this.moneySummaryRow) {
284 var summary_td = $n(this.moneySummaryRow, this.table.id + key);
285 summary_td.innerHTML = parseFloat(parseFloat(summary_td.innerHTML) + parseFloat(data)).toFixed(2);
289 if( this.bold && grep(this.bold,function(i){return (i==key)}) ) {
290 var span = elem('span',{'class':'fm_table_bold'}, data);
291 td.appendChild(span);
293 td.appendChild(text( data ));
298 FMObjectBuilder.prototype.hideSubTables = function() {
300 /* clear out any existing subrows */
301 for( var i = 0; i < this.tbody.childNodes.length; i++ ) {
302 var r = this.tbody.childNodes[i];
303 if( r.getAttribute('subrow') )
304 this.tbody.removeChild(r);
307 /* un-style any selected tds */
308 var tds = this.tbody.getElementsByTagName('td');
309 for( i = 0; i < tds.length; i++ )
310 removeCSSClass( tds[i], 'fm_selected' );
313 FMObjectBuilder.prototype.buildSubTable = function(td, obj, key) {
315 var left = parseInt(td.offsetLeft);
316 var div = elem('div');
317 var row = elem('tr');
318 var subtd= elem('td');
320 if( td.parentNode.nextSibling )
321 this.tbody.insertBefore(row, td.parentNode.nextSibling);
323 this.tbody.appendChild(row);
325 row.appendChild(subtd);
326 row.setAttribute('subrow', key);
327 subtd.appendChild(div);
329 addCSSClass(td, 'fm_selected');
330 subtd.setAttribute('colspan',this.keys.length);
332 subtd.setAttribute('colspan',this.keys.length + 1);
334 subtd.setAttribute('style', 'width: 100%; padding-left:'+left+'px;');
335 var builder = drawFMObjectTable({dest:div, obj:obj, display:this.display});
336 builder.table.setAttribute('style', 'width: auto;');
337 addCSSClass(builder.table, 'fm_selected');
339 var newleft = left - (builder.table.clientWidth / 2) + (td.clientWidth / 2);
341 if( newleft < left ) {
342 if( newleft < 0 ) newleft = 0;
343 newleft = parseInt(newleft);
344 var style = subtd.getAttribute('style');
345 style = style.replace(new RegExp(left), newleft);
346 subtd.setAttribute('style', style);