]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/chrome/content/util/list.js
put retrieve_id on listitem as soon as possible.. and support for full_retrieve befor...
[Evergreen.git] / Open-ILS / xul / staff_client / chrome / content / util / list.js
1 dump('entering util.list.js\n');
2
3 if (typeof main == 'undefined') main = {};
4 util.list = function (id) {
5
6         this.node = document.getElementById(id);
7
8         if (!this.node) throw('Could not find element ' + id);
9         switch(this.node.nodeName) {
10                 case 'listbox' : 
11                 case 'tree' : break;
12                 case 'richlistbox' :
13                         throw(this.node.nodeName + ' not yet supported'); break;
14                 default: throw(this.node.nodeName + ' not supported'); break;
15         }
16
17         JSAN.use('util.error'); this.error = new util.error();
18
19         return this;
20 };
21
22 util.list.prototype = {
23
24         'row_count' : { 'total' : 0, 'fleshed' : 0, 'all_fleshed' : true },
25
26         'init' : function (params) {
27
28                 var obj = this;
29
30                 JSAN.use('util.widgets');
31
32                 if (typeof params.map_row_to_column == 'function') obj.map_row_to_column = params.map_row_to_column;
33                 if (typeof params.retrieve_row == 'function') obj.retrieve_row = params.retrieve_row;
34
35                 obj.prebuilt = false;
36                 if (typeof params.prebuilt != 'undefined') obj.prebuilt = params.prebuilt;
37
38                 if (typeof params.columns == 'undefined') throw('util.list.init: No columns');
39                 obj.columns = params.columns;
40
41                 switch(obj.node.nodeName) {
42                         case 'tree' : obj._init_tree(params); break;
43                         case 'listbox' : obj._init_listbox(params); break;
44                         default: throw('NYI: Need ._init() for ' + obj.node.nodeName); break;
45                 }
46
47                 obj.row_count.watch(
48                         'all_fleshed',
49                         function(a,b,c) {
50                                 if (c) {
51                                         if (typeof obj.on_all_fleshed == 'function') {
52                                                 obj.on_all_fleshed(a,b,c);
53                                         }
54                                 }
55                         }
56                 );
57         },
58
59         '_init_tree' : function (params) {
60                 var obj = this;
61                 if (this.prebuilt) {
62                 
63                         this.treechildren = this.node.lastChild;        
64                 
65                 } else {
66                         var treecols = document.createElement('treecols');
67                         this.node.appendChild(treecols);
68
69                         for (var i = 0; i < this.columns.length; i++) {
70                                 var treecol = document.createElement('treecol');
71                                 for (var j in this.columns[i]) {
72                                         treecol.setAttribute(j,this.columns[i][j]);
73                                 }
74                                 treecols.appendChild(treecol);
75                                 var splitter = document.createElement('splitter');
76                                 splitter.setAttribute('class','tree-splitter');
77                                 treecols.appendChild(splitter);
78                         }
79
80                         var treechildren = document.createElement('treechildren');
81                         this.node.appendChild(treechildren);
82                         this.treechildren = treechildren;
83                 }
84                 if (typeof params.on_select == 'function') {
85                         this.node.addEventListener(
86                                 'select',
87                                 params.on_select,
88                                 false
89                         );
90                 }
91                 if (typeof params.on_click == 'function') {
92                         this.node.addEventListener(
93                                 'click',
94                                 params.on_click,
95                                 false
96                         );
97                 }
98                 /*
99                 this.node.addEventListener(
100                         'mousemove',
101                         function(ev) { obj.detect_visible(); },
102                         false
103                 );
104                 */
105                 this.node.addEventListener(
106                         'keypress',
107                         function(ev) { obj.auto_retrieve(); },
108                         false
109                 );
110                 this.node.addEventListener(
111                         'click',
112                         function(ev) { obj.auto_retrieve(); },
113                         false
114                 );
115                 window.addEventListener(
116                         'resize',
117                         function(ev) { obj.auto_retrieve(); },
118                         false
119                 );
120                 /* FIXME -- find events on scrollbar to trigger this */
121                 //obj.detect_visible_polling(); 
122                 /*
123                 var scrollbar = document.getAnonymousNodes( document.getAnonymousNodes(this.node)[1] )[1];
124                 var slider = document.getAnonymousNodes( scrollbar )[2];
125                 alert('scrollbar = ' + scrollbar.nodeName + ' grippy = ' + slider.nodeName);
126                 scrollbar.addEventListener('click',function(){alert('sb click');},false);
127                 scrollbar.addEventListener('command',function(){alert('sb command');},false);
128                 scrollbar.addEventListener('scroll',function(){alert('sb scroll');},false);
129                 slider.addEventListener('click',function(){alert('slider click');},false);
130                 slider.addEventListener('command',function(){alert('slider command');},false);
131                 slider.addEventListener('scroll',function(){alert('slider scroll');},false);
132                 */
133                 this.node.addEventListener('scroll',function(){ obj.auto_retrieve(); },false);
134         },
135
136         '_init_listbox' : function (params) {
137                 if (this.prebuilt) {
138                 } else {
139                         var listhead = document.createElement('listhead');
140                         this.node.appendChild(listhead);
141
142                         var listcols = document.createElement('listcols');
143                         this.node.appendChild(listcols);
144
145                         for (var i = 0; i < this.columns.length; i++) {
146                                 var listheader = document.createElement('listheader');
147                                 listhead.appendChild(listheader);
148                                 var listcol = document.createElement('listcol');
149                                 listcols.appendChild(listcol);
150                                 for (var j in this.columns[i]) {
151                                         listheader.setAttribute(j,this.columns[i][j]);
152                                         listcol.setAttribute(j,this.columns[i][j]);
153                                 };
154                         }
155                 }
156         },
157
158         'clear' : function (params) {
159                 switch (this.node.nodeName) {
160                         case 'tree' : this._clear_tree(params); break;
161                         case 'listbox' : this._clear_listbox(params); break;
162                         default: throw('NYI: Need .clear() for ' + this.node.nodeName); break;
163                 }
164                 this.error.sdump('D_LIST','Clearing list ' + this.node.getAttribute('id') + '\n');
165                 this.row_count.total = 0;
166                 this.row_count.fleshed = 0;
167                 this.row_count.all_fleshed = true;
168         },
169
170         '_clear_tree' : function(params) {
171                 var obj = this;
172                 if (obj.error.sdump_levels.D_LIST_DUMP_ON_CLEAR) {
173                         obj.error.sdump('D_LIST_DUMP_ON_CLEAR',obj.dump());
174                 }
175                 if (obj.error.sdump_levels.D_LIST_DUMP_WITH_KEYS_ON_CLEAR) {
176                         obj.error.sdump('D_LIST_DUMP_WITH_KEYS_ON_CLEAR',obj.dump_with_keys());
177                 }
178                 while (obj.treechildren.lastChild) obj.treechildren.removeChild( obj.treechildren.lastChild );
179         },
180
181         '_clear_listbox' : function(params) {
182                 var items = [];
183                 var nl = this.node.getElementsByTagName('listitem');
184                 for (var i = 0; i < nl.length; i++) {
185                         items.push( nl[i] );
186                 }
187                 for (var i = 0; i < items.length; i++) {
188                         this.node.removeChild(items[i]);
189                 }
190         },
191
192         'append' : function (params) {
193                 var rnode;
194                 switch (this.node.nodeName) {
195                         case 'tree' : rnode = this._append_to_tree(params); break;
196                         case 'listbox' : rnode = this._append_to_listbox(params); break;
197                         default: throw('NYI: Need .append() for ' + this.node.nodeName); break;
198                 }
199                 if (rnode && params.attributes) {
200                         for (var i in params.attributes) {
201                                 rnode.setAttribute(i,params.attributes[i]);
202                         }
203                 }
204                 this.row_count.total++;
205                 if (this.row_count.fleshed == this.row_count.total) {
206                         this.row_count.all_fleshed = true;
207                 } else {
208                         this.row_count.all_fleshed = false;
209                 }
210                 return rnode;
211         },
212
213         '_append_to_tree' : function (params) {
214
215                 var obj = this;
216
217                 if (typeof params.row == 'undefined') throw('util.list.append: Object must contain a row');
218
219                 var s = ('util.list.append: params = ' + (params) + '\n');
220
221                 var treechildren_node = this.treechildren;
222
223                 if (params.node && params.node.nodeName == 'treeitem') {
224                         params.node.setAttribute('container','true'); /* params.node.setAttribute('open','true'); */
225                         if (params.node.lastChild.nodeName == 'treechildren') {
226                                 treechildren_node = params.node.lastChild;
227                         } else {
228                                 treechildren_node = document.createElement('treechildren');
229                                 params.node.appendChild(treechildren_node);
230                         }
231                 }
232
233                 var treeitem = document.createElement('treeitem');
234                 treeitem.setAttribute('retrieve_id',params.retrieve_id);
235                 treechildren_node.appendChild( treeitem );
236                 var treerow = document.createElement('treerow');
237                 treeitem.appendChild( treerow );
238                 treerow.setAttribute('retrieve_id',params.retrieve_id);
239
240                 s += ('tree = ' + this.node + '  treechildren = ' + treechildren_node + '\n');
241                 s += ('treeitem = ' + treeitem + '  treerow = ' + treerow + '\n');
242
243                 if (typeof params.retrieve_row == 'function' || typeof this.retrieve_row == 'function') {
244
245                         obj.put_retrieving_label(treerow);
246                         treerow.addEventListener(
247                                 'flesh',
248                                 function() {
249                                         //dump('fleshing = ' + params.retrieve_id + '\n');
250
251                                         params.row_node = treeitem;
252                                         params.on_retrieve = function(p) {
253                                                 try {
254                                                         p.row = params.row;
255                                                         obj._map_row_to_treecell(p,treerow);
256                                                         treerow.setAttribute('fleshed','true');
257                                                         obj.row_count.fleshed++;
258                                                         if (obj.row_count.fleshed == obj.row_count.total) {
259                                                                 obj.row_count.all_fleshed = true;
260                                                         } else {
261                                                                 obj.row_count.all_fleshed = false;
262                                                         }
263                                                 } catch(E) {
264                                                         alert('fixme2: ' + E);
265                                                 }
266                                         }
267
268                                         if (typeof params.retrieve_row == 'function') {
269
270                                                 params.retrieve_row( params );
271
272                                         } else {
273
274                                                 if (typeof obj.retrieve_row == 'function') {
275
276                                                         obj.retrieve_row( params );
277
278                                                 }
279                                         }
280
281                                         treerow.setAttribute('retrieved','true');
282                                 },
283                                 false
284                         );
285                         /*
286                         setTimeout(
287                                 function() {
288                                         util.widgets.dispatch('flesh',treerow);
289                                 }, 0
290                         );
291                         */
292                 } else {
293                         obj.put_retrieving_label(treerow);
294                         treerow.addEventListener(
295                                 'flesh',
296                                 function() {
297                                         //dump('fleshing anon\n');
298                                         obj._map_row_to_treecell(params,treerow);
299                                         treerow.setAttribute('retrieved','true');
300                                         treerow.setAttribute('fleshed','true');
301                                         obj.row_count.fleshed++;
302                                         if (obj.row_count.fleshed == obj.row_count.total) {
303                                                 obj.row_count.all_fleshed = true;
304                                         } else {
305                                                 obj.row_count.all_fleshed = false;
306                                         }
307                                 },
308                                 false
309                         );
310                         /*
311                         setTimeout(
312                                 function() {
313                                         util.widgets.dispatch('flesh',treerow);
314                                 }, 0
315                         );
316                         */
317                 }
318                 this.error.sdump('D_LIST',s);
319
320                 setTimeout( function() { obj.auto_retrieve(); }, 0 );
321
322                 return treeitem;
323         },
324
325         'put_retrieving_label' : function(treerow) {
326                 var obj = this;
327                 try {
328                         /*
329                         var cols_idx = 0;
330                         dump('put_retrieving_label.  columns = ' + js2JSON(obj.columns) + '\n');
331                         while( obj.columns[cols_idx] && obj.columns[cols_idx].hidden && obj.columns[cols_idx].hidden == 'true') {
332                                 dump('\t' + cols_idx);
333                                 var treecell = document.createElement('treecell');
334                                 treerow.appendChild(treecell);
335                                 cols_idx++;
336                         }
337                         */
338                         for (var i = 0; i < obj.columns.length; i++) {
339                         var treecell = document.createElement('treecell'); treecell.setAttribute('label','Retrieving...');
340                         treerow.appendChild(treecell);
341                         }
342                         /*
343                         dump('\t' + cols_idx + '\n');
344                         */
345                 } catch(E) {
346                         alert(E);
347                 }
348         },
349
350         'detect_visible' : function() {
351                 try {
352                         var obj = this;
353                         //dump('detect_visible  obj.node = ' + obj.node + '\n');
354                         /* FIXME - this is a hack.. if the implementation of tree changes, this could break */
355                         var scrollbar = document.getAnonymousNodes( document.getAnonymousNodes(obj.node)[1] )[1];
356                         var curpos = scrollbar.getAttribute('curpos');
357                         var maxpos = scrollbar.getAttribute('maxpos');
358                         //alert('curpos = ' + curpos + ' maxpos = ' + maxpos + ' obj.curpos = ' + obj.curpos + ' obj.maxpos = ' + obj.maxpos + '\n');
359                         if ((curpos != obj.curpos) || (maxpos != obj.maxpos)) {
360                                 if ( obj.auto_retrieve() > 0 ) {
361                                         obj.curpos = curpos; obj.maxpos = maxpos;
362                                 }
363                         }
364                 } catch(E) { alert(E); }
365         },
366
367         'detect_visible_polling' : function() {
368                 try {
369                         //alert('detect_visible_polling');
370                         var obj = this;
371                         obj.detect_visible();
372                         setTimeout(function() { try { obj.detect_visible_polling(); } catch(E) { alert(E); } },2000);
373                 } catch(E) {
374                         alert(E);
375                 }
376         },
377
378
379         'auto_retrieve' : function(params) {
380                 var obj = this;
381                 switch (this.node.nodeName) {
382                         case 'tree' : obj._auto_retrieve_tree(params); break;
383                         default: throw('NYI: Need .auto_retrieve() for ' + obj.node.nodeName); break;
384                 }
385         },
386
387         '_auto_retrieve_tree' : function (params) {
388                 var obj = this;
389                 if (!obj.auto_retrieve_in_progress) {
390                         obj.auto_retrieve_in_progress = true;
391                         setTimeout(
392                                 function() {
393                                         try {
394                                                         //alert('auto_retrieve\n');
395                                                         var count = 0;
396                                                         var startpos = obj.node.treeBoxObject.getFirstVisibleRow();
397                                                         var endpos = obj.node.treeBoxObject.getLastVisibleRow();
398                                                         if (startpos > endpos) endpos = obj.node.treeBoxObject.getPageLength();
399                                                         //dump('startpos = ' + startpos + ' endpos = ' + endpos + '\n');
400                                                         for (var i = startpos; i < endpos + 2; i++) {
401                                                                 try {
402                                                                         //dump('trying index ' + i + '\n');
403                                                                         var item = obj.node.contentView.getItemAtIndex(i).firstChild;
404                                                                         if (item && item.getAttribute('retrieved') != 'true' ) {
405                                                                                 //dump('\tgot an unfleshed item = ' + item + ' = ' + item.nodeName + '\n');
406                                                                                 util.widgets.dispatch('flesh',item); count++;
407                                                                         }
408                                                                 } catch(E) {
409                                                                         //dump(i + ' : ' + E + '\n');
410                                                                 }
411                                                         }
412                                                         obj.auto_retrieve_in_progress = false;
413                                                         return count;
414                                         } catch(E) { alert(E); }
415                                 }, 1
416                         );
417                 }
418         },
419
420         'full_retrieve' : function(params) {
421                 var obj = this;
422                 switch (this.node.nodeName) {
423                         case 'tree' : obj._full_retrieve_tree(params); break;
424                         default: throw('NYI: Need .full_retrieve() for ' + obj.node.nodeName); break;
425                 }
426         },
427
428         '_full_retrieve_tree' : function(params) {
429                 var obj = this;
430                 var nodes = obj.treechildren.childNodes;
431                 for (var i = 0; i < nodes.length; i++) util.widgets.dispatch('flesh',nodes[i]);
432         },
433
434         '_append_to_listbox' : function (params) {
435
436                 var obj = this;
437
438                 if (typeof params.row == 'undefined') throw('util.list.append: Object must contain a row');
439
440                 var s = ('util.list.append: params = ' + (params) + '\n');
441
442                 var listitem = document.createElement('listitem');
443
444                 s += ('listbox = ' + this.node + '  listitem = ' + listitem + '\n');
445
446                 if (typeof params.retrieve_row == 'function' || typeof this.retrieve_row == 'function') {
447
448                         setTimeout(
449                                 function() {
450                                         listitem.setAttribute('retrieve_id',params.retrieve_id);
451                                         //FIXME//Make async and fire when row is visible in list
452                                         var row;
453
454                                         params.row_node = listitem;
455                                         params.on_retrieve = function(row) {
456                                                 params.row = row;
457                                                 obj._map_row_to_listcell(params,listitem);
458                                                 obj.node.appendChild( listitem );
459                                         }
460
461                                         if (typeof params.retrieve_row == 'function') {
462
463                                                 row = params.retrieve_row( params );
464
465                                         } else {
466
467                                                 if (typeof obj.retrieve_row == 'function') {
468
469                                                         row = obj.retrieve_row( params );
470
471                                                 }
472                                         }
473                                 }, 0
474                         );
475                 } else {
476                         this._map_row_to_listcell(params,listitem);
477                         this.node.appendChild( listitem );
478                 }
479
480                 this.error.sdump('D_LIST',s);
481                 return listitem;
482
483         },
484
485         '_map_row_to_treecell' : function(params,treerow) {
486                 var s = '';
487                 util.widgets.remove_children(treerow);
488                 for (var i = 0; i < this.columns.length; i++) {
489                         var treecell = document.createElement('treecell');
490                         var label = '';
491                         if (params.skip_columns && (params.skip_columns.indexOf(i) != -1)) {
492                                 treecell.setAttribute('label',label);
493                                 treerow.appendChild( treecell );
494                                 s += ('treecell = ' + treecell + ' with label = ' + label + '\n');
495                                 continue;
496                         }
497                         if (params.skip_all_columns_except && (params.skip_all_columns_except.indexOf(i) == -1)) {
498                                 treecell.setAttribute('label',label);
499                                 treerow.appendChild( treecell );
500                                 s += ('treecell = ' + treecell + ' with label = ' + label + '\n');
501                                 continue;
502                         }
503                         if (typeof params.map_row_to_column == 'function')  {
504
505                                 label = params.map_row_to_column(params.row,this.columns[i]);
506
507                         } else {
508
509                                 if (typeof this.map_row_to_column == 'function') {
510
511                                         label = this.map_row_to_column(params.row,this.columns[i]);
512
513                                 } else {
514
515                                         throw('No map_row_to_column function');
516
517                                 }
518                         }
519                         treecell.setAttribute('label',label);
520                         treerow.appendChild( treecell );
521                         s += ('treecell = ' + treecell + ' with label = ' + label + '\n');
522                 }
523                 this.error.sdump('D_LIST',s);
524         },
525
526         '_map_row_to_listcell' : function(params,listitem) {
527                 var s = '';
528                 for (var i = 0; i < this.columns.length; i++) {
529                         var value = '';
530                         if (typeof params.map_row_to_column == 'function')  {
531
532                                 value = params.map_row_to_column(params.row,this.columns[i]);
533
534                         } else {
535
536                                 if (typeof this.map_row_to_column == 'function') {
537
538                                         value = this.map_row_to_column(params.row,this.columns[i]);
539                                 }
540                         }
541                         if (typeof value == 'string' || typeof value == 'number') {
542                                 var listcell = document.createElement('listcell');
543                                 listcell.setAttribute('label',value);
544                                 listitem.appendChild(listcell);
545                                 s += ('listcell = ' + listcell + ' with label = ' + value + '\n');
546                         } else {
547                                 listitem.appendChild(value);
548                                 s += ('listcell = ' + value + ' is really a ' + value.nodeName + '\n');
549                         }
550                 }
551                 this.error.sdump('D_LIST',s);
552         },
553
554         'retrieve_selection' : function(params) {
555                 switch(this.node.nodeName) {
556                         case 'tree' : return this._retrieve_selection_from_tree(params); break;
557                         default: throw('NYI: Need ._retrieve_selection_from_() for ' + this.node.nodeName); break;
558                 }
559         },
560
561         '_retrieve_selection_from_tree' : function(params) {
562                 var list = [];
563                 var start = new Object();
564                 var end = new Object();
565                 var numRanges = this.node.view.selection.getRangeCount();
566                 for (var t=0; t<numRanges; t++){
567                         this.node.view.selection.getRangeAt(t,start,end);
568                         for (var v=start.value; v<=end.value; v++){
569                                 var i = this.node.contentView.getItemAtIndex(v);
570                                 list.push( i );
571                         }
572                 }
573                 return list;
574         },
575
576         'dump' : function(params) {
577                 switch(this.node.nodeName) {
578                         case 'tree' : return this._dump_tree(params); break;
579                         default: throw('NYI: Need .dump() for ' + this.node.nodeName); break;
580                 }
581         },
582
583         '_dump_tree' : function(params) {
584                 var dump = [];
585                 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
586                         var row = [];
587                         var treeitem = this.treechildren.childNodes[i];
588                         var treerow = treeitem.firstChild;
589                         for (var j = 0; j < treerow.childNodes.length; j++) {
590                                 row.push( treerow.childNodes[j].getAttribute('label') );
591                         }
592                         dump.push( row );
593                 }
594                 return dump;
595         },
596
597         'dump_with_keys' : function(params) {
598                 switch(this.node.nodeName) {
599                         case 'tree' : return this._dump_tree_with_keys(params); break;
600                         default: throw('NYI: Need .dump_with_keys() for ' + this.node.nodeName); break;
601                 }
602
603         },
604
605         '_dump_tree_with_keys' : function(params) {
606                 var obj = this;
607                 var dump = [];
608                 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
609                         var row = {};
610                         var treeitem = this.treechildren.childNodes[i];
611                         var treerow = treeitem.firstChild;
612                         for (var j = 0; j < treerow.childNodes.length; j++) {
613                                 row[ obj.columns[j].id ] = treerow.childNodes[j].getAttribute('label');
614                         }
615                         dump.push( row );
616                 }
617                 return dump;
618         },
619
620         'dump_retrieve_ids' : function(params) {
621                 switch(this.node.nodeName) {
622                         case 'tree' : return this._dump_retrieve_ids_tree(params); break;
623                         default: throw('NYI: Need .dump_retrieve_ids() for ' + this.node.nodeName); break;
624                 }
625         },
626
627         '_dump_retrieve_ids_tree' : function(params) {
628                 var dump = [];
629                 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
630                         var treeitem = this.treechildren.childNodes[i];
631                         dump.push( treeitem.getAttribute('retrieve_id') );
632                 }
633                 return dump;
634         },
635
636 }
637 dump('exiting util.list.js\n');