]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/opac/common/js/fm_table.js
LP#1332138 Report template / field documentation
[working/Evergreen.git] / Open-ILS / web / opac / common / js / fm_table.js
1 /* 
2         Fieldmapper object table
3 */
4
5 var ID_GEN = 1;
6
7
8
9 function drawFMObjectTable( args ) {
10
11         var destination = args.dest;
12         var obj = args.obj;
13
14         if( typeof destination == 'string' ) 
15                 destination = $(destination);
16         var builder = new FMObjectBuilder(obj, args);
17
18         destination.appendChild(builder.build());
19         return builder;
20 }
21
22
23 /* Constructor for the builder object */
24 function FMObjectBuilder( obj, args ) {
25         this.obj                = obj;
26         this.table      = elem('table');
27         this.thead      = elem('thead');
28         this.tbody      = elem('tbody');
29         this.thead_tr = elem('tr');
30         this.subtables = [];
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;
37         this.rows = [];
38         if(!this.display) this.display = {};
39
40         this.table.appendChild(this.thead);
41         this.table.appendChild(this.tbody);
42         this.thead.appendChild(this.thead_tr)
43
44         addCSSClass(this.table, 'fm_table');
45         addCSSClass(this.table, 'sortable');
46         this.table.id = 'fm_table_' + (ID_GEN++);
47 }
48
49
50 FMObjectBuilder.prototype.getSelected = function() {
51         var objs = [];
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]);
56         }
57         return objs;
58 }
59
60 /* Builds the table */
61 FMObjectBuilder.prototype.build = function() {
62         var o = this.obj;
63
64         if( instanceOf(this.obj, Array) ) 
65                 o = this.obj[0];
66         else this.obj = [this.obj];
67
68         if( o ) {
69
70                 this.setKeys(o);
71                 if( this.selectCol ) {
72                         var obj = this;
73                         var td = elem('td',null,this.selectColName);
74
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);
77
78                         all.onclick = function(){obj.selectAll()};
79                         none.onclick = function(){obj.selectNone()};
80
81                         td.appendChild(all);
82                         td.appendChild(none);
83                         this.thead_tr.appendChild(td);
84                 }
85
86                 if (this.moneySummaryRow) {
87                         this.moneySummaryRow = elem('tr');
88
89                         if( this.selectCol )
90                                 this.moneySummaryRow.appendChild(elem('td'));
91
92                         for( var i = 0; i < this.keys.length; i++ ) {
93                                 var key = this.keys[i];
94
95                                 var td = elem('td');
96                                 td.setAttribute('name', this.table.id + key);
97
98                                 if (this.money && grep(this.money,function(i){return (i==key)}) )
99                                         td.appendChild(text('0.00'));
100
101                                 this.moneySummaryRow.appendChild(td);
102                         }
103
104                         this.tbody.appendChild(this.moneySummaryRow);
105                 }
106
107                 for( var i = 0; i < this.keys.length; i++ ) 
108                         this.thead_tr.appendChild(elem('td',null,this.keys[i]));
109
110                 if ( this.sortdata ) {
111                         var sortdata = this.sortdata;
112                         this.obj.sort(function(a, b){
113                                 var ret = 1;
114                                 var left = a[sortdata[0]]().toLowerCase();
115                                 var right = b[sortdata[0]]().toLowerCase();
116                                 if (left == right) return 0;
117                                 if (left < right)
118                                         ret = -1;
119                                 return ret * sortdata[1];
120                         });
121                 }
122         
123                 for( var i = 0; i < this.obj.length; i++ ) 
124                         this.buildObjectRow(this.obj[i]);
125         }
126
127         return this.table;
128 }
129
130
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;
135         }
136 }
137
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;
142         }
143 }
144
145
146 /* */
147 FMObjectBuilder.prototype.setKeys = function(o) {
148         var sortme = false;
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;
155         }
156
157         if(!this.keys && FM_TABLE_DISPLAY[o.classname])
158                 this.keys = FM_TABLE_DISPLAY[o.classname].fields;
159
160         if(!this.bold && FM_TABLE_DISPLAY[o.classname])
161                 this.bold = FM_TABLE_DISPLAY[o.classname].bold;
162
163         if(!this.money && FM_TABLE_DISPLAY[o.classname])
164                 this.money = FM_TABLE_DISPLAY[o.classname].money;
165
166         if(!this.sortdata && FM_TABLE_DISPLAY[o.classname])
167                 this.sortdata = FM_TABLE_DISPLAY[o.classname].sortdata;
168
169         if(!this.calculate && FM_TABLE_DISPLAY[o.classname])
170                 this.calculate = FM_TABLE_DISPLAY[o.classname].calculate;
171
172         if(!this.keys) {
173                 this.keys = fmclasses[o.classname];
174                 sortme = true;
175         }
176
177         if(sortme) this.keys = this.keys.sort();
178 }
179
180 /* use this method to insert object rows after the table has been rendered */
181 FMObjectBuilder.prototype.add = function(obj) {
182         this.obj.push(obj);
183         this.buildObjectRow(obj);
184 }
185
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);
191
192         if(this.selectCol) {
193                 var td = elem('td');
194                 td.appendChild(elem('input',{type:'checkbox',name:'selected'}));
195                 row.appendChild(td);
196         }
197
198         for( var i = 0; i < this.keys.length; i++ ) {
199                 var td = elem('td');    
200         var data = '';
201         if (this.caclulate[i]) { // fake data! pass the object
202             td.appendChild(this.calculate[i](obj);
203         } else {
204                     data = obj[this.keys[i]]();
205                 data = this.munge(data);
206                 this.fleshData(td, data, this.keys[i]);
207         }
208
209                 row.appendChild(td);
210         }
211         this.tbody.appendChild(row);
212         if (this.moneySummaryRow) this.tbody.appendChild(this.moneySummaryRow);
213 }
214
215 FMObjectBuilder.prototype.munge = function(data) {
216         if(!data) return;
217         if(typeof data == 'string') {
218                 if( data.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/) ) {
219                         data = data.replace(/T/,' ');
220                         data = data.replace(/:\d{2}-.*/,'');
221                 }
222         }
223
224         return data;
225 }
226
227
228 FMObjectBuilder.prototype.dataName = function(data) {
229         var name;
230         if( this.display[data.classname] ) 
231                 name = this.display[data.classname].name;
232
233         if(!name && FM_TABLE_DISPLAY[data.classname])
234                 name = FM_TABLE_DISPLAY[data.classname].name;
235
236         if(!name) name = 'id';
237
238         return data[name]();
239         return name;
240 }
241
242
243 FMObjectBuilder.prototype.fleshData = function(td, data, key) {
244         if(data == null) data = '';
245
246         if( typeof data == 'object' ) {
247                 var atext;
248
249                 if( data._isfieldmapper ) 
250                         atext = this.dataName(data);
251
252                 else if (instanceOf(data, Array) )
253                         atext = data.length;
254
255                 if( atext ) {
256
257                         var master = this;
258                         var expand = function () { 
259                                 var buildme = true;
260                                 var row = td.parentNode.nextSibling;
261                                 if( row && row.getAttribute('subrow') == key) buildme = false;
262                                 master.hideSubTables();
263                                 if(buildme) master.buildSubTable(td, data, key);
264                         };
265
266                         var a = elem('a',{href:'javascript:void(0);'});
267                         a.onclick = expand;
268                         a.appendChild(text(atext));
269                         td.appendChild(a);
270
271                 } else {
272                         td.appendChild(text(''));
273                 }
274
275         } else {
276                 if (this.money && grep(this.money,function(i){return (i==key)}) ) {
277                         td.setAttribute('align', 'right');
278                         data = parseFloat(data).toFixed(2);
279
280                         if (isNaN(data)) data = '0.00';
281
282                         if (this.moneySummaryRow) {
283                                 var summary_td = $n(this.moneySummaryRow, this.table.id + key);
284                                 summary_td.innerHTML = parseFloat(parseFloat(summary_td.innerHTML) + parseFloat(data)).toFixed(2);
285                         }
286                 }
287
288                 if( this.bold && grep(this.bold,function(i){return (i==key)}) ) {
289                         var span = elem('span',{'class':'fm_table_bold'}, data);
290                         td.appendChild(span);
291                 } else {
292                         td.appendChild(text( data ));
293                 }
294         }
295 }
296
297 FMObjectBuilder.prototype.hideSubTables = function() {
298
299         /* clear out any existing subrows */
300         for( var i = 0; i < this.tbody.childNodes.length; i++ ) {
301                 var r = this.tbody.childNodes[i];
302                 if( r.getAttribute('subrow') )
303                         this.tbody.removeChild(r);
304         }
305
306         /* un-style any selected tds */
307         var tds = this.tbody.getElementsByTagName('td');
308         for( i = 0; i < tds.length; i++ )
309                 removeCSSClass( tds[i], 'fm_selected' );
310 }
311
312 FMObjectBuilder.prototype.buildSubTable = function(td, obj, key) {
313
314         var left = parseInt(td.offsetLeft);
315         var div = elem('div');
316         var row = elem('tr');
317         var subtd= elem('td');
318
319         if( td.parentNode.nextSibling ) 
320                 this.tbody.insertBefore(row, td.parentNode.nextSibling);
321         else
322                 this.tbody.appendChild(row);
323
324         row.appendChild(subtd);
325         row.setAttribute('subrow', key);
326         subtd.appendChild(div);
327
328         addCSSClass(td, 'fm_selected');
329         subtd.setAttribute('colspan',this.keys.length);
330         if(this.selectCol)
331                 subtd.setAttribute('colspan',this.keys.length + 1);
332
333         subtd.setAttribute('style', 'width: 100%; padding-left:'+left+'px;');
334         var builder = drawFMObjectTable({dest:div, obj:obj, display:this.display});
335         builder.table.setAttribute('style', 'width: auto;');
336         addCSSClass(builder.table, 'fm_selected');
337
338         var newleft = left - (builder.table.clientWidth / 2) + (td.clientWidth / 2);
339
340         if( newleft < left ) {
341                 if( newleft < 0 ) newleft = 0;
342                 newleft = parseInt(newleft);
343                 var style = subtd.getAttribute('style');
344                 style = style.replace(new RegExp(left), newleft);
345                 subtd.setAttribute('style', style);
346         }
347 }
348
349
350
351