1 dump('entering util.list.js\n');
3 if (typeof main == 'undefined') main = {};
4 util.list = function (id) {
6 this.node = document.getElementById(id);
8 this.row_count = { 'total' : 0, 'fleshed' : 0 };
10 if (!this.node) throw('Could not find element ' + id);
11 switch(this.node.nodeName) {
15 throw(this.node.nodeName + ' not yet supported'); break;
16 default: throw(this.node.nodeName + ' not supported'); break;
19 JSAN.use('util.error'); this.error = new util.error();
24 util.list.prototype = {
26 'init' : function (params) {
30 JSAN.use('util.widgets');
32 if (typeof params.map_row_to_column == 'function') obj.map_row_to_column = params.map_row_to_column;
33 if (typeof params.map_row_to_columns == 'function') obj.map_row_to_columns = params.map_row_to_columns;
34 if (typeof params.retrieve_row == 'function') obj.retrieve_row = params.retrieve_row;
37 if (typeof params.prebuilt != 'undefined') obj.prebuilt = params.prebuilt;
39 if (typeof params.columns == 'undefined') throw('util.list.init: No columns');
40 obj.columns = params.columns;
42 switch(obj.node.nodeName) {
43 case 'tree' : obj._init_tree(params); break;
44 case 'listbox' : obj._init_listbox(params); break;
45 default: throw('NYI: Need ._init() for ' + obj.node.nodeName); break;
49 '_init_tree' : function (params) {
53 this.treechildren = this.node.lastChild;
56 var treecols = document.createElement('treecols');
57 this.node.appendChild(treecols);
58 this.treecols = treecols;
60 for (var i = 0; i < this.columns.length; i++) {
61 var treecol = document.createElement('treecol');
62 for (var j in this.columns[i]) {
63 treecol.setAttribute(j,this.columns[i][j]);
65 treecols.appendChild(treecol);
66 treecol.addEventListener(
70 var sortDir = ev.target.getAttribute('sortDir') || 'desc';
71 if (sortDir == 'desc') sortDir = 'asc'; else sortDir = 'desc';
72 ev.target.setAttribute('sortDir',sortDir);
73 obj._sort_tree(ev.target,sortDir);
76 if (obj.row_count.total != obj.row_count.fleshed && (obj.row_count.total - obj.row_count.fleshed) > 50) {
77 var r = window.confirm('WARNING: Only ' + obj.row_count.fleshed + ' out of ' + obj.row_count.total + ' rows in this list have been retrieved for immediate viewing. Sorting this list requires that all these rows be retrieved, and this may take some time and lag the staff client. Would you like to proceed?');
80 setTimeout( do_it, 0 );
83 setTimeout( do_it, 0 );
88 var splitter = document.createElement('splitter');
89 splitter.setAttribute('class','tree-splitter');
90 treecols.appendChild(splitter);
93 var treechildren = document.createElement('treechildren');
94 this.node.appendChild(treechildren);
95 this.treechildren = treechildren;
97 if (typeof params.on_select == 'function') {
98 this.node.addEventListener(
104 if (typeof params.on_click == 'function') {
105 this.node.addEventListener(
112 this.node.addEventListener(
114 function(ev) { obj.detect_visible(); },
118 this.node.addEventListener(
120 function(ev) { obj.auto_retrieve(); },
123 this.node.addEventListener(
125 function(ev) { obj.auto_retrieve(); },
128 window.addEventListener(
130 function(ev) { obj.auto_retrieve(); },
133 /* FIXME -- find events on scrollbar to trigger this */
134 obj.detect_visible_polling();
136 var scrollbar = document.getAnonymousNodes( document.getAnonymousNodes(this.node)[1] )[1];
137 var slider = document.getAnonymousNodes( scrollbar )[2];
138 alert('scrollbar = ' + scrollbar.nodeName + ' grippy = ' + slider.nodeName);
139 scrollbar.addEventListener('click',function(){alert('sb click');},false);
140 scrollbar.addEventListener('command',function(){alert('sb command');},false);
141 scrollbar.addEventListener('scroll',function(){alert('sb scroll');},false);
142 slider.addEventListener('click',function(){alert('slider click');},false);
143 slider.addEventListener('command',function(){alert('slider command');},false);
144 slider.addEventListener('scroll',function(){alert('slider scroll');},false);
146 this.node.addEventListener('scroll',function(){ obj.auto_retrieve(); },false);
148 this.restores_columns(params);
151 '_init_listbox' : function (params) {
154 var listhead = document.createElement('listhead');
155 this.node.appendChild(listhead);
157 var listcols = document.createElement('listcols');
158 this.node.appendChild(listcols);
160 for (var i = 0; i < this.columns.length; i++) {
161 var listheader = document.createElement('listheader');
162 listhead.appendChild(listheader);
163 var listcol = document.createElement('listcol');
164 listcols.appendChild(listcol);
165 for (var j in this.columns[i]) {
166 listheader.setAttribute(j,this.columns[i][j]);
167 listcol.setAttribute(j,this.columns[i][j]);
173 'save_columns' : function (params) {
175 switch (this.node.nodeName) {
176 case 'tree' : this._save_columns_tree(params); break;
177 default: throw('NYI: Need .save_columns() for ' + this.node.nodeName); break;
181 '_save_columns_tree' : function (params) {
184 var id = obj.node.getAttribute('id'); if (!id) {
185 alert("FIXME: The columns for this list cannot be saved because the list has no id.");
189 var nl = obj.node.getElementsByTagName('treecol');
190 for (var i = 0; i < nl.length; i++) {
192 var col_id = col.getAttribute('id');
194 alert('FIXME: A column in this list does not have an id and cannot be saved');
197 var col_hidden = col.getAttribute('hidden');
198 var col_width = col.getAttribute('width');
199 var col_ordinal = col.getAttribute('ordinal');
200 my_cols[ col_id ] = { 'hidden' : col_hidden, 'width' : col_width, 'ordinal' : col_ordinal };
202 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
203 JSAN.use('util.file'); var file = new util.file('tree_columns_for_'+window.escape(id));
204 file.set_object(my_cols);
206 alert('Columns saved.');
208 obj.error.standard_unexpected_error_alert('_save_columns_tree',E);
212 'restores_columns' : function (params) {
214 switch (this.node.nodeName) {
215 case 'tree' : this._restores_columns_tree(params); break;
216 default: throw('NYI: Need .restores_columns() for ' + this.node.nodeName); break;
220 '_restores_columns_tree' : function (params) {
223 var id = obj.node.getAttribute('id'); if (!id) {
224 alert("FIXME: The columns for this list cannot be restored because the list has no id.");
228 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
229 JSAN.use('util.file'); var file = new util.file('tree_columns_for_'+window.escape(id));
230 if (file._file.exists()) {
231 var my_cols = file.get_object(); file.close();
232 var nl = obj.node.getElementsByTagName('treecol');
233 for (var i = 0; i < nl.length; i++) {
235 var col_id = col.getAttribute('id');
237 alert('FIXME: A column in this list does not have an id and cannot be saved');
240 if (typeof my_cols[col_id] != 'undefined') {
241 col.setAttribute('hidden',my_cols[col_id].hidden);
242 col.setAttribute('width',my_cols[col_id].width);
243 col.setAttribute('ordinal',my_cols[col_id].ordinal);
245 obj.error.sdump('D_ERROR','WARNING: Column ' + col_id + ' did not have a saved state.');
250 obj.error.standard_unexpected_error_alert('_restore_columns_tree',E);
254 'clear' : function (params) {
256 switch (this.node.nodeName) {
257 case 'tree' : this._clear_tree(params); break;
258 case 'listbox' : this._clear_listbox(params); break;
259 default: throw('NYI: Need .clear() for ' + this.node.nodeName); break;
261 this.error.sdump('D_LIST','Clearing list ' + this.node.getAttribute('id') + '\n');
262 this.row_count.total = 0;
263 this.row_count.fleshed = 0;
264 setTimeout( function() { obj.exec_on_all_fleshed(); }, 0 );
267 '_clear_tree' : function(params) {
269 if (obj.error.sdump_levels.D_LIST_DUMP_ON_CLEAR) {
270 obj.error.sdump('D_LIST_DUMP_ON_CLEAR',obj.dump());
272 if (obj.error.sdump_levels.D_LIST_DUMP_WITH_KEYS_ON_CLEAR) {
273 obj.error.sdump('D_LIST_DUMP_WITH_KEYS_ON_CLEAR',obj.dump_with_keys());
275 while (obj.treechildren.lastChild) obj.treechildren.removeChild( obj.treechildren.lastChild );
278 '_clear_listbox' : function(params) {
281 var nl = this.node.getElementsByTagName('listitem');
282 for (var i = 0; i < nl.length; i++) {
285 for (var i = 0; i < items.length; i++) {
286 this.node.removeChild(items[i]);
290 'append' : function (params) {
293 switch (this.node.nodeName) {
294 case 'tree' : rparams = this._append_to_tree(params); break;
295 case 'listbox' : rparams = this._append_to_listbox(params); break;
296 default: throw('NYI: Need .append() for ' + this.node.nodeName); break;
298 if (rparams && params.attributes) {
299 for (var i in params.attributes) {
300 rparams.my_node.setAttribute(i,params.attributes[i]);
303 this.row_count.total++;
304 if (this.row_count.fleshed == this.row_count.total) {
305 setTimeout( function() { obj.exec_on_all_fleshed(); }, 0 );
310 'refresh_row' : function (params) {
313 switch (this.node.nodeName) {
314 case 'tree' : rparams = this._refresh_row_in_tree(params); break;
315 default: throw('NYI: Need .refresh_row() for ' + this.node.nodeName); break;
317 if (rparams && params.attributes) {
318 for (var i in params.attributes) {
319 rparams.my_node.setAttribute(i,params.attributes[i]);
322 this.row_count.fleshed--;
327 '_append_to_tree' : function (params) {
331 if (typeof params.row == 'undefined') throw('util.list.append: Object must contain a row');
333 var s = ('util.list.append: params = ' + (params) + '\n');
335 var treechildren_node = this.treechildren;
337 if (params.node && params.node.nodeName == 'treeitem') {
338 params.node.setAttribute('container','true'); /* params.node.setAttribute('open','true'); */
339 if (params.node.lastChild.nodeName == 'treechildren') {
340 treechildren_node = params.node.lastChild;
342 treechildren_node = document.createElement('treechildren');
343 params.node.appendChild(treechildren_node);
347 var treeitem = document.createElement('treeitem');
348 treeitem.setAttribute('retrieve_id',params.retrieve_id);
349 if (typeof params.to_bottom != 'undefined') {
350 treechildren_node.appendChild( treeitem );
351 if (typeof params.no_auto_select == 'undefined') {
352 if (!obj.auto_select_pending) {
353 obj.auto_select_pending = true;
354 setTimeout(function() {
355 dump('auto-selecting\n');
356 var idx = Number(obj.node.view.rowCount)-1;
357 try { obj.node.view.selection.select(idx); } catch(E) { obj.error.sdump('D_WARN','tree auto select: ' + E + '\n'); }
358 try { if (typeof params.on_select == 'function') params.on_select(); } catch(E) { obj.error.sdump('D_WARN','tree auto select, on_select: ' + E + '\n'); }
359 obj.auto_select_pending = false;
360 try { util.widgets.dispatch('flesh',obj.node.contentView.getItemAtIndex(idx).firstChild); } catch(E) { obj.error.sdump('D_WARN','tree auto select, flesh: ' + E + '\n'); }
365 if (treechildren_node.firstChild) {
366 treechildren_node.insertBefore( treeitem, treechildren_node.firstChild );
368 treechildren_node.appendChild( treeitem );
370 if (typeof params.no_auto_select == 'undefined') {
371 if (!obj.auto_select_pending) {
372 obj.auto_select_pending = true;
373 setTimeout(function() {
374 try { obj.node.view.selection.select(0); } catch(E) { obj.error.sdump('D_WARN','tree auto select: ' + E + '\n'); }
375 try { if (typeof params.on_select == 'function') params.on_select(); } catch(E) { obj.error.sdump('D_WARN','tree auto select, on_select: ' + E + '\n'); }
376 obj.auto_select_pending = false;
377 try { util.widgets.dispatch('flesh',obj.node.contentView.getItemAtIndex(0).firstChild); } catch(E) { obj.error.sdump('D_WARN','tree auto select, flesh: ' + E + '\n'); }
382 var treerow = document.createElement('treerow');
383 treeitem.appendChild( treerow );
384 treerow.setAttribute('retrieve_id',params.retrieve_id);
386 s += ('tree = ' + this.node + ' treechildren = ' + treechildren_node + '\n');
387 s += ('treeitem = ' + treeitem + ' treerow = ' + treerow + '\n');
389 if (typeof params.retrieve_row == 'function' || typeof this.retrieve_row == 'function') {
391 obj.put_retrieving_label(treerow);
392 treerow.addEventListener(
396 if (treerow.getAttribute('retrieved') == 'true') return; /* already running */
398 treerow.setAttribute('retrieved','true');
400 //dump('fleshing = ' + params.retrieve_id + '\n');
402 function inc_fleshed() {
403 if (treerow.getAttribute('fleshed') == 'true') return; /* already fleshed */
404 treerow.setAttribute('fleshed','true');
405 obj.row_count.fleshed++;
406 if (obj.row_count.fleshed >= obj.row_count.total) {
407 setTimeout( function() { obj.exec_on_all_fleshed(); }, 0 );
411 params.row_node = treeitem;
412 params.on_retrieve = function(p) {
415 obj._map_row_to_treecell(p,treerow);
417 var idx = obj.node.contentView.getIndexOfItem( params.row_node );
418 dump('idx = ' + idx + '\n');
419 // if current row is selected, send another select event to re-sync data that the client code fetches on selects
420 if ( obj.node.view.selection.isSelected( idx ) ) {
421 dump('dispatching select event for on_retrieve for idx = ' + idx + '\n');
422 util.widgets.dispatch('select',obj.node);
425 // Let's not alert on this for now. Getting contentView has no properties in record buckets under certain conditions
426 dump('fixme2: ' + E + '\n');
430 if (typeof params.retrieve_row == 'function') {
432 params.retrieve_row( params );
434 } else if (typeof obj.retrieve_row == 'function') {
436 obj.retrieve_row( params );
448 util.widgets.dispatch('flesh',treerow);
453 obj.put_retrieving_label(treerow);
454 treerow.addEventListener(
457 //dump('fleshing anon\n');
458 if (treerow.getAttribute('fleshed') == 'true') return; /* already fleshed */
459 obj._map_row_to_treecell(params,treerow);
460 treerow.setAttribute('retrieved','true');
461 treerow.setAttribute('fleshed','true');
462 obj.row_count.fleshed++;
463 if (obj.row_count.fleshed >= obj.row_count.total) {
464 setTimeout( function() { obj.exec_on_all_fleshed(); }, 0 );
472 util.widgets.dispatch('flesh',treerow);
477 this.error.sdump('D_LIST',s);
481 if (obj.trim_list && obj.row_count.total >= obj.trim_list) {
483 //if (typeof params.to_bottom != 'undefined')
484 if (typeof params.to_top == 'undefined') {
485 treechildren_node.removeChild( treechildren_node.firstChild );
487 treechildren_node.removeChild( treechildren_node.lastChild );
493 setTimeout( function() { obj.auto_retrieve(); }, 0 );
495 params.my_node = treeitem;
499 '_refresh_row_in_tree' : function (params) {
503 if (typeof params.row == 'undefined') throw('util.list.refresh_row: Object must contain a row');
504 if (typeof params.my_node == 'undefined') throw('util.list.refresh_row: Object must contain a my_node');
505 if (params.my_node.nodeName != 'treeitem') throw('util.list.refresh_rwo: my_node must be a treeitem');
507 var s = ('util.list.refresh_row: params = ' + (params) + '\n');
509 var treeitem = params.my_node;
510 treeitem.setAttribute('retrieve_id',params.retrieve_id);
511 if (typeof params.to_bottom != 'undefined') {
512 if (typeof params.no_auto_select == 'undefined') {
513 if (!obj.auto_select_pending) {
514 obj.auto_select_pending = true;
515 setTimeout(function() {
516 dump('auto-selecting\n');
517 var idx = Number(obj.node.view.rowCount)-1;
518 try { obj.node.view.selection.select(idx); } catch(E) { obj.error.sdump('D_WARN','tree auto select: ' + E + '\n'); }
519 try { if (typeof params.on_select == 'function') params.on_select(); } catch(E) { obj.error.sdump('D_WARN','tree auto select, on_select: ' + E + '\n'); }
520 obj.auto_select_pending = false;
521 try { util.widgets.dispatch('flesh',obj.node.contentView.getItemAtIndex(idx).firstChild); } catch(E) { obj.error.sdump('D_WARN','tree auto select, flesh: ' + E + '\n'); }
527 for (var i in treeitem.childNodes) if (treeitem.childNodes[i].nodeName == 'treerow') delete_me.push(treeitem.childNodes[i]);
528 for (var i = 0; i < delete_me.length; i++) treeitem.removeChild(delete_me[i]);
529 var treerow = document.createElement('treerow');
530 treeitem.appendChild( treerow );
531 treerow.setAttribute('retrieve_id',params.retrieve_id);
533 s += ('tree = ' + this.node + '\n');
534 s += ('treeitem = ' + treeitem + ' treerow = ' + treerow + '\n');
536 if (typeof params.retrieve_row == 'function' || typeof this.retrieve_row == 'function') {
538 obj.put_retrieving_label(treerow);
539 treerow.addEventListener(
543 if (treerow.getAttribute('retrieved') == 'true') return; /* already running */
545 treerow.setAttribute('retrieved','true');
547 //dump('fleshing = ' + params.retrieve_id + '\n');
549 function inc_fleshed() {
550 if (treerow.getAttribute('fleshed') == 'true') return; /* already fleshed */
551 treerow.setAttribute('fleshed','true');
552 obj.row_count.fleshed++;
553 if (obj.row_count.fleshed >= obj.row_count.total) {
554 setTimeout( function() { obj.exec_on_all_fleshed(); }, 0 );
558 params.row_node = treeitem;
559 params.on_retrieve = function(p) {
562 obj._map_row_to_treecell(p,treerow);
564 var idx = obj.node.contentView.getIndexOfItem( params.row_node );
565 dump('idx = ' + idx + '\n');
566 // if current row is selected, send another select event to re-sync data that the client code fetches on selects
567 if ( obj.node.view.selection.isSelected( idx ) ) {
568 dump('dispatching select event for on_retrieve for idx = ' + idx + '\n');
569 util.widgets.dispatch('select',obj.node);
572 // Let's not alert on this for now. Getting contentView has no properties in record buckets under certain conditions
573 dump('fixme2: ' + E + '\n');
577 if (typeof params.retrieve_row == 'function') {
579 params.retrieve_row( params );
581 } else if (typeof obj.retrieve_row == 'function') {
583 obj.retrieve_row( params );
595 util.widgets.dispatch('flesh',treerow);
600 obj.put_retrieving_label(treerow);
601 treerow.addEventListener(
604 //dump('fleshing anon\n');
605 if (treerow.getAttribute('fleshed') == 'true') return; /* already fleshed */
606 obj._map_row_to_treecell(params,treerow);
607 treerow.setAttribute('retrieved','true');
608 treerow.setAttribute('fleshed','true');
609 obj.row_count.fleshed++;
610 if (obj.row_count.fleshed >= obj.row_count.total) {
611 setTimeout( function() { obj.exec_on_all_fleshed(); }, 0 );
619 util.widgets.dispatch('flesh',treerow);
624 this.error.sdump('D_LIST',s);
628 if (obj.trim_list && obj.row_count.total >= obj.trim_list) {
630 //if (typeof params.to_bottom != 'undefined')
631 if (typeof params.to_top == 'undefined') {
632 treechildren_node.removeChild( treechildren_node.firstChild );
634 treechildren_node.removeChild( treechildren_node.lastChild );
640 setTimeout( function() { obj.auto_retrieve(); }, 0 );
642 JSAN.use('util.widgets'); util.widgets.dispatch('select',obj.node);
647 'put_retrieving_label' : function(treerow) {
652 dump('put_retrieving_label. columns = ' + js2JSON(obj.columns) + '\n');
653 while( obj.columns[cols_idx] && obj.columns[cols_idx].hidden && obj.columns[cols_idx].hidden == 'true') {
654 dump('\t' + cols_idx);
655 var treecell = document.createElement('treecell');
656 treerow.appendChild(treecell);
660 for (var i = 0; i < obj.columns.length; i++) {
661 var treecell = document.createElement('treecell'); treecell.setAttribute('label','Retrieving...');
662 treerow.appendChild(treecell);
665 dump('\t' + cols_idx + '\n');
672 'detect_visible' : function() {
675 //dump('detect_visible obj.node = ' + obj.node + '\n');
676 /* FIXME - this is a hack.. if the implementation of tree changes, this could break */
678 var scrollbar = document.getAnonymousNodes( document.getAnonymousNodes(obj.node)[1] )[1];
679 var curpos = scrollbar.getAttribute('curpos');
680 var maxpos = scrollbar.getAttribute('maxpos');
681 //alert('curpos = ' + curpos + ' maxpos = ' + maxpos + ' obj.curpos = ' + obj.curpos + ' obj.maxpos = ' + obj.maxpos + '\n');
682 if ((curpos != obj.curpos) || (maxpos != obj.maxpos)) {
683 if ( obj.auto_retrieve() > 0 ) {
684 obj.curpos = curpos; obj.maxpos = maxpos;
688 obj.error.sdump('D_XULRUNNER', 'List implementation changed? ' + E);
690 } catch(E) { obj.error.sdump('D_ERROR',E); }
693 'detect_visible_polling' : function() {
695 //alert('detect_visible_polling');
697 obj.detect_visible();
698 setTimeout(function() { try { obj.detect_visible_polling(); } catch(E) { alert(E); } },2000);
705 'auto_retrieve' : function(params) {
707 switch (this.node.nodeName) {
708 case 'tree' : obj._auto_retrieve_tree(params); break;
709 default: throw('NYI: Need .auto_retrieve() for ' + obj.node.nodeName); break;
713 '_auto_retrieve_tree' : function (params) {
715 if (!obj.auto_retrieve_in_progress) {
716 obj.auto_retrieve_in_progress = true;
720 //alert('auto_retrieve\n');
722 var startpos = obj.node.treeBoxObject.getFirstVisibleRow();
723 var endpos = obj.node.treeBoxObject.getLastVisibleRow();
724 if (startpos > endpos) endpos = obj.node.treeBoxObject.getPageLength();
725 //dump('startpos = ' + startpos + ' endpos = ' + endpos + '\n');
726 for (var i = startpos; i < endpos + 4; i++) {
728 //dump('trying index ' + i + '\n');
729 var item = obj.node.contentView.getItemAtIndex(i).firstChild;
730 if (item && item.getAttribute('retrieved') != 'true' ) {
731 //dump('\tgot an unfleshed item = ' + item + ' = ' + item.nodeName + '\n');
732 util.widgets.dispatch('flesh',item); count++;
735 //dump(i + ' : ' + E + '\n');
738 obj.auto_retrieve_in_progress = false;
740 } catch(E) { alert(E); }
746 'exec_on_all_fleshed' : function() {
749 if (obj.on_all_fleshed) {
750 if (typeof obj.on_all_fleshed == 'function') {
751 dump('exec_on_all_fleshed == function\n');
754 try { obj.on_all_fleshed(); } catch(E) { obj.error.standard_unexpected_error_alert('_full_retrieve_tree callback',obj.on_all_fleshed); }
757 } else if (typeof obj.on_all_fleshed.length != 'undefined') {
758 dump('exec_on_all_fleshed == array\n');
762 dump('exec_on_all_fleshed, processing on_all_fleshed array, length = ' + obj.on_all_fleshed.length + '\n');
763 var f = obj.on_all_fleshed.pop();
764 if (typeof f == 'function') {
765 try { f(); } catch(E) { obj.error.standard_unexpected_error_alert('_full_retrieve_tree callback',f); }
767 if (obj.on_all_fleshed.length > 0) arguments.callee();
769 obj.error.standard_unexpected_error_alert('exec_on_all_fleshed callback error',E);
774 obj.error.standard_unexpected_error_alert('unexpected on_all_fleshed object: ', obj.on_all_fleshed);
778 obj.error.standard_unexpected_error_alert('exec_on_all-fleshed error',E);
782 'full_retrieve' : function(params) {
784 switch (this.node.nodeName) {
785 case 'tree' : obj._full_retrieve_tree(params); break;
786 default: throw('NYI: Need .full_retrieve() for ' + obj.node.nodeName); break;
790 '_full_retrieve_tree' : function(params) {
793 if (obj.row_count.fleshed >= obj.row_count.total) {
794 dump('Full retrieve... tree seems to be in sync\n' + js2JSON(obj.row_count) + '\n');
795 obj.exec_on_all_fleshed();
797 dump('Full retrieve... syncing tree' + js2JSON(obj.row_count) + '\n');
798 JSAN.use('util.widgets');
799 var nodes = obj.treechildren.childNodes;
800 for (var i = 0; i < nodes.length; i++) {
801 util.widgets.dispatch('flesh',nodes[i].firstChild);
805 obj.error.standard_unexpected_error_alert('_full_retrieve_tree',E);
809 '_append_to_listbox' : function (params) {
813 if (typeof params.row == 'undefined') throw('util.list.append: Object must contain a row');
815 var s = ('util.list.append: params = ' + (params) + '\n');
817 var listitem = document.createElement('listitem');
819 s += ('listbox = ' + this.node + ' listitem = ' + listitem + '\n');
821 if (typeof params.retrieve_row == 'function' || typeof this.retrieve_row == 'function') {
825 listitem.setAttribute('retrieve_id',params.retrieve_id);
826 //FIXME//Make async and fire when row is visible in list
829 params.row_node = listitem;
830 params.on_retrieve = function(row) {
832 obj._map_row_to_listcell(params,listitem);
833 obj.node.appendChild( listitem );
834 util.widgets.dispatch('select',obj.node);
837 if (typeof params.retrieve_row == 'function') {
839 row = params.retrieve_row( params );
843 if (typeof obj.retrieve_row == 'function') {
845 row = obj.retrieve_row( params );
852 this._map_row_to_listcell(params,listitem);
853 this.node.appendChild( listitem );
856 this.error.sdump('D_LIST',s);
857 params.my_node = listitem;
862 '_map_row_to_treecell' : function(params,treerow) {
865 util.widgets.remove_children(treerow);
867 if (typeof params.map_row_to_column == 'function' || typeof this.map_row_to_column == 'function') {
869 for (var i = 0; i < this.columns.length; i++) {
870 var treecell = document.createElement('treecell');
872 if (params.skip_columns && (params.skip_columns.indexOf(i) != -1)) {
873 treecell.setAttribute('label',label);
874 treerow.appendChild( treecell );
875 s += ('treecell = ' + treecell + ' with label = ' + label + '\n');
878 if (params.skip_all_columns_except && (params.skip_all_columns_except.indexOf(i) == -1)) {
879 treecell.setAttribute('label',label);
880 treerow.appendChild( treecell );
881 s += ('treecell = ' + treecell + ' with label = ' + label + '\n');
885 if (typeof params.map_row_to_column == 'function') {
887 label = params.map_row_to_column(params.row,this.columns[i]);
889 } else if (typeof this.map_row_to_column == 'function') {
891 label = this.map_row_to_column(params.row,this.columns[i]);
894 treecell.setAttribute('label',label ? label : '');
895 treerow.appendChild( treecell );
896 s += ('treecell = ' + treecell + ' with label = ' + label + '\n');
898 } else if (typeof params.map_row_to_columns == 'function' || typeof this.map_row_to_columns == 'function') {
902 if (typeof params.map_row_to_columns == 'function') {
904 labels = params.map_row_to_columns(params.row,this.columns);
906 } else if (typeof this.map_row_to_columns == 'function') {
908 labels = this.map_row_to_columns(params.row,this.columns);
911 for (var i = 0; i < labels.length; i++) {
912 var treecell = document.createElement('treecell');
913 treecell.setAttribute('label',typeof labels[i] == 'string' || typeof labels[i] == 'number' ? labels[i] : '');
914 treerow.appendChild( treecell );
915 s += ('treecell = ' + treecell + ' with label = ' + labels[i] + '\n');
920 throw('No row to column mapping function.');
922 this.error.sdump('D_LIST',s);
925 '_map_row_to_listcell' : function(params,listitem) {
928 for (var i = 0; i < this.columns.length; i++) {
930 if (typeof params.map_row_to_column == 'function') {
932 value = params.map_row_to_column(params.row,this.columns[i]);
936 if (typeof this.map_row_to_column == 'function') {
938 value = this.map_row_to_column(params.row,this.columns[i]);
941 if (typeof value == 'string' || typeof value == 'number') {
942 var listcell = document.createElement('listcell');
943 listcell.setAttribute('label',value);
944 listitem.appendChild(listcell);
945 s += ('listcell = ' + listcell + ' with label = ' + value + '\n');
947 listitem.appendChild(value);
948 s += ('listcell = ' + value + ' is really a ' + value.nodeName + '\n');
951 this.error.sdump('D_LIST',s);
954 'select_all' : function(params) {
956 switch(this.node.nodeName) {
957 case 'tree' : return this._select_all_from_tree(params); break;
958 default: throw('NYI: Need ._select_all_from_() for ' + this.node.nodeName); break;
962 '_select_all_from_tree' : function(params) {
964 this.node.view.selection.selectAll();
967 'retrieve_selection' : function(params) {
969 switch(this.node.nodeName) {
970 case 'tree' : return this._retrieve_selection_from_tree(params); break;
971 default: throw('NYI: Need ._retrieve_selection_from_() for ' + this.node.nodeName); break;
975 '_retrieve_selection_from_tree' : function(params) {
978 var start = new Object();
979 var end = new Object();
980 var numRanges = this.node.view.selection.getRangeCount();
981 for (var t=0; t<numRanges; t++){
982 this.node.view.selection.getRangeAt(t,start,end);
983 for (var v=start.value; v<=end.value; v++){
984 var i = this.node.contentView.getItemAtIndex(v);
991 'dump' : function(params) {
993 switch(this.node.nodeName) {
994 case 'tree' : return this._dump_tree(params); break;
995 default: throw('NYI: Need .dump() for ' + this.node.nodeName); break;
999 '_dump_tree' : function(params) {
1002 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
1004 var treeitem = this.treechildren.childNodes[i];
1005 var treerow = treeitem.firstChild;
1006 for (var j = 0; j < treerow.childNodes.length; j++) {
1007 row.push( treerow.childNodes[j].getAttribute('label') );
1014 'dump_with_keys' : function(params) {
1016 switch(this.node.nodeName) {
1017 case 'tree' : return this._dump_tree_with_keys(params); break;
1018 default: throw('NYI: Need .dump_with_keys() for ' + this.node.nodeName); break;
1023 '_dump_tree_with_keys' : function(params) {
1026 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
1028 var treeitem = this.treechildren.childNodes[i];
1029 var treerow = treeitem.firstChild;
1030 for (var j = 0; j < treerow.childNodes.length; j++) {
1031 row[ obj.columns[j].id ] = treerow.childNodes[j].getAttribute('label');
1038 'dump_csv' : function(params) {
1040 switch(this.node.nodeName) {
1041 case 'tree' : return this._dump_tree_csv(params); break;
1042 default: throw('NYI: Need .dump_csv() for ' + this.node.nodeName); break;
1047 '_dump_tree_csv' : function(params) {
1050 for (var j = 0; j < obj.columns.length; j++) {
1051 if (obj.node.treeBoxObject.columns.getColumnAt(j).element.getAttribute('hidden') == 'true') {
1054 if (dump) dump += ',';
1055 dump += '"' + obj.columns[j].label.replace(/"/g, '""') + '"';
1059 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
1061 var treeitem = this.treechildren.childNodes[i];
1062 var treerow = treeitem.firstChild;
1063 for (var j = 0; j < treerow.childNodes.length; j++) {
1064 if (obj.node.treeBoxObject.columns.getColumnAt(j).element.getAttribute('hidden') == 'true') {
1067 if (row) row += ',';
1068 row += '"' + treerow.childNodes[j].getAttribute('label').replace(/"/g, '""') + '"';
1071 dump += row + '\r\n';
1076 'dump_csv_to_clipboard' : function(params) {
1078 if (typeof params == 'undefined') params = {};
1079 if (params.no_full_retrieve) {
1080 copy_to_clipboard( obj.dump_csv( params ) );
1082 obj.wrap_in_full_retrieve( function() { copy_to_clipboard( obj.dump_csv( params ) ); } );
1086 'dump_csv_to_printer' : function(params) {
1088 JSAN.use('util.print'); var print = new util.print();
1089 if (typeof params == 'undefined') params = {};
1090 if (params.no_full_retrieve) {
1091 print.simple( obj.dump_csv( params ), {'content_type':'text/plain'} );
1093 obj.wrap_in_full_retrieve(
1095 print.simple( obj.dump_csv( params ), {'content_type':'text/plain'} );
1101 'dump_csv_to_file' : function(params) {
1103 JSAN.use('util.file'); var f = new util.file();
1104 if (typeof params == 'undefined') params = {};
1105 if (params.no_full_retrieve) {
1106 params.data = obj.dump_csv( params );
1107 params.not_json = true;
1108 if (!params.title) params.title = 'Save List CSV As';
1109 f.export_file( params );
1111 obj.wrap_in_full_retrieve(
1113 params.data = obj.dump_csv( params );
1114 params.not_json = true;
1115 if (!params.title) params.title = 'Save List CSV As';
1116 f.export_file( params );
1122 'print' : function(params) {
1123 if (!params) params = {};
1124 switch(this.node.nodeName) {
1125 case 'tree' : return this._print_tree(params); break;
1126 default: throw('NYI: Need ._print() for ' + this.node.nodeName); break;
1130 '_print_tree' : function(params) {
1133 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
1134 if (!params.staff && data.list.au && data.list.au[0]) {
1135 params.staff = data.list.au[0];
1137 if (!params.lib && data.list.au && data.list.au[0] && data.list.au[0].ws_ou() && data.hash.aou && data.hash.aou[ data.list.au[0].ws_ou() ]) {
1138 params.lib = data.hash.aou[ data.list.au[0].ws_ou() ];
1139 params.lib.children(null);
1141 if (params.template && data.print_list_templates[ params.template ]) {
1142 var template = data.print_list_templates[ params.template ];
1143 for (var i in template) params[i] = template[i];
1145 obj.wrap_in_full_retrieve(
1148 if (!params.list) params.list = obj.dump_with_keys();
1149 JSAN.use('util.print'); var print = new util.print();
1150 print.tree_list( params );
1151 if (typeof params.callback == 'function') params.callback();
1153 obj.error.standard_unexpected_error_alert('inner _print_tree',E);
1159 obj.error.standard_unexpected_error_alert('_print_tree',E);
1163 'dump_selected_with_keys' : function(params) {
1165 switch(this.node.nodeName) {
1166 case 'tree' : return this._dump_tree_selection_with_keys(params); break;
1167 default: throw('NYI: Need .dump_selection_with_keys() for ' + this.node.nodeName); break;
1172 '_dump_tree_selection_with_keys' : function(params) {
1175 var list = obj._retrieve_selection_from_tree();
1176 for (var i = 0; i < list.length; i++) {
1178 var treeitem = list[i];
1179 var treerow = treeitem.firstChild;
1180 for (var j = 0; j < treerow.childNodes.length; j++) {
1181 var value = treerow.childNodes[j].getAttribute('label');
1182 if (params.skip_hidden_columns) if (obj.node.treeBoxObject.columns.getColumnAt(j).element.getAttribute('hidden') == 'true') continue;
1183 var id = obj.columns[j].id; if (params.labels_instead_of_ids) id = obj.columns[j].label;
1191 'clipboard' : function() {
1194 var dump = obj.dump_selected_with_keys({'skip_hidden_columns':true,'labels_instead_of_ids':true});
1195 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
1196 data.list_clipboard = dump; data.stash('list_clipboard');
1197 JSAN.use('util.window'); var win = new util.window();
1198 win.open(urls.XUL_LIST_CLIPBOARD,'list_clipboard','chrome,resizable,modal');
1199 window.focus(); // sometimes the main window will lower after a clipboard action
1201 this.error.standard_unexpected_error_alert('clipboard',E);
1205 'dump_retrieve_ids' : function(params) {
1207 switch(this.node.nodeName) {
1208 case 'tree' : return this._dump_retrieve_ids_tree(params); break;
1209 default: throw('NYI: Need .dump_retrieve_ids() for ' + this.node.nodeName); break;
1213 '_dump_retrieve_ids_tree' : function(params) {
1216 for (var i = 0; i < this.treechildren.childNodes.length; i++) {
1217 var treeitem = this.treechildren.childNodes[i];
1218 dump.push( treeitem.getAttribute('retrieve_id') );
1223 'wrap_in_full_retrieve' : function(f) {
1225 if (typeof obj.on_all_fleshed == 'function') { // legacy
1226 obj.on_all_fleshed = [ obj.on_all_fleshed ];
1228 if (! obj.on_all_fleshed) obj.on_all_fleshed = [];
1229 obj.on_all_fleshed.push(f);
1230 obj.full_retrieve();
1233 '_sort_tree' : function(col,sortDir) {
1236 if (obj.node.getAttribute('no_sort')) {
1240 for (var i = 0; i < obj.columns.length; i++) {
1241 if (obj.columns[i].id == col.id) col_pos = function(a){return a;}(i);
1243 obj.wrap_in_full_retrieve(
1246 JSAN.use('util.money');
1248 var treeitems = obj.treechildren.childNodes;
1249 for (var i = 0; i < treeitems.length; i++) {
1250 var treeitem = treeitems[i];
1251 var treerow = treeitem.firstChild;
1252 var treecell = treerow.childNodes[ col_pos ];
1253 value = ( { 'value' : treecell ? treecell.getAttribute('label') : '', 'node' : treeitem } );
1256 rows = rows.sort( function(a,b) {
1257 a = a.value; b = b.value;
1258 if (col.getAttribute('sort_type')) {
1259 switch(col.getAttribute('sort_type')) {
1261 a = Number(a); b = Number(b);
1264 a = util.money.dollars_float_to_cents_integer(a);
1265 b = util.money.dollars_float_to_cents_integer(b);
1267 case 'title' : /* special case for "a" and "the". doesn't use marc 245 indicator */
1268 a = String( a ).toUpperCase().replace( /^\s*(THE|A|AN)\s+/, '' );
1269 b = String( b ).toUpperCase().replace( /^\s*(THE|A|AN)\s+/, '' );
1272 a = String( a ).toUpperCase();
1273 b = String( b ).toUpperCase();
1277 if (typeof a == 'string' || typeof b == 'string') {
1278 a = String( a ).toUpperCase();
1279 b = String( b ).toUpperCase();
1282 if (a < b) return -1;
1283 if (a > b) return 1;
1286 if (sortDir == 'asc') rows = rows.reverse();
1287 while(obj.treechildren.lastChild) obj.treechildren.removeChild( obj.treechildren.lastChild );
1288 for (var i = 0; i < rows.length; i++) {
1289 obj.treechildren.appendChild( rows[i].node );
1292 obj.error.standard_unexpected_error_alert('sorting',E);
1297 obj.error.standard_unexpected_error_alert('pre sorting', E);
1302 dump('exiting util.list.js\n');