]> git.evergreen-ils.org Git - Evergreen.git/blob - Evergreen/staff_client/chrome/content/evergreen/util/util.js
some refactoring and comments
[Evergreen.git] / Evergreen / staff_client / chrome / content / evergreen / util / util.js
1 sdump('D_TRACE','Loading util.js\n');
2
3 var timer = {};
4 var counter = {};
5 var treeitem_id = 0;
6
7 var sdump_levels = {
8         'D_TRACE' :  true,
9         'D_AUTH' : false,
10         'D_UTIL' : false,
11         'D_EXPLODE' : false,
12         'D_PRINT' : false,
13         'D_SES' : true
14 };
15
16 function sdump(level,msg) {
17         try {
18                 if (sdump_levels[level])
19                         debug(msg);
20         } catch(E) {}
21 }
22
23 function snd_bad() {
24         mw.G.sound.play( xp_url_init('chrome://evergreen/content/media/redalert.wav') );
25 }
26
27 function snd_really_bad() {
28         mw.G.sound.play( xp_url_init('chrome://evergreen/content/media/die.wav') );
29 }
30
31 function snd_good() {
32         mw.G.sound.play( xp_url_init('chrome://evergreen/content/media/turn.wav') );
33 }
34
35 function snd_circ_good() {
36         mw.G.sound.play( xp_url_init('chrome://evergreen/content/media/clicked.wav') );
37 }
38
39 function snd_circ_bad() {
40         mw.G.sound.play( xp_url_init('chrome://evergreen/content/media/cow.wav') );
41 }
42
43 function snd_logon() {
44
45 }
46
47 function snd_logoff() {
48
49 }
50
51 function snd_exit() {
52
53 }
54
55 function handle_error(E) {
56         var s = '';
57         if (instanceOf(E,ex)) {
58                 s += E.err_msg();
59                 //s += '\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n';
60                 //s += 'This error was anticipated.\n\n';
61                 //s += js2JSON(E).substr(0,200) + '...\n\n';
62                 snd_bad()
63         } else {
64                 s += '\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n';
65                 s += 'This is a bug that we will fix later.\n\n';
66                 s += js2JSON(E).substr(0,200) + '\n\n';
67                 snd_really_bad();
68         }
69         s_alert(s);
70 }
71
72 function string_to_array(s) {
73         var my_array = [];
74         for (var i = 0; i < s.length; i++ ) {
75                 my_array.push( s.charAt(i) );
76         }
77         return my_array;
78 }
79
80 function textbox_checkdigit(ev) {
81         if ( check_checkdigit( ev.target.value ) ) {
82                 sdump('D_UTIL', 'success\n');
83                 return true;
84         } else {
85                 sdump('D_UTIL', 'failure\n');
86                 ev.preventDefault();
87                 ev.stopPropagation();
88                 return false;
89         }
90 }
91
92 function check_checkdigit(barcode) {
93
94         var stripped_barcode = barcode.slice(0,-1);
95         var checkdigit = barcode.slice(-1);
96
97         sdump('D_UTIL', '\n\n=-=***=-=\n\ncheck_checkdigit: barcode = ' + barcode + ' barcode stripped = ' + stripped_barcode + ' checkdigit = ' + checkdigit + '\n');
98
99         var sum = 0; var mul = 2;
100
101         var b_array = string_to_array( stripped_barcode ).reverse();
102         sdump('D_UTIL', '\tb_array = ' + b_array + '\n');
103
104         for (var i in b_array) {
105                 var digit = parseInt( b_array[i] );
106                 sdump('D_UTIL', '\t\tdigit = ' + digit + '\n');
107
108                 var product = digit * mul;
109                 if (mul == 2) { mul = 1; } else { mul = 2; }
110
111                 var p_array = string_to_array( product.toString() );
112                 sdump('D_UTIL', '\t\tp_array = ' + p_array + '\n');
113
114                 for (var j in p_array) { 
115                         var n = parseInt( p_array[j] );
116                         sdump('D_UTIL', '\t\t\tn = ' + n + '\n');
117                         sum += n;
118                 }
119         }
120
121         sdump('D_UTIL', '\tsum = ' + sum + '\n');
122
123         var s_array = string_to_array( sum.toString() );
124         var calculated_checkdigit = s_array.pop();
125         if (calculated_checkdigit > 0) calculated_checkdigit = 10 - calculated_checkdigit;
126         sdump('D_UTIL', '\tcalculated checkdigit = ' + calculated_checkdigit + '\n\n=-=***=-=\n\n');
127
128         return ( calculated_checkdigit == checkdigit );
129 }
130
131 function fake_tab_for_textboxes(w,current) {
132         var flag = false; var next_one;
133         if (typeof(w)!='object') {
134                 w = document.getElementById(w);
135         }
136         sdump('D_UTIL', 'fake_tab_for_textboxes: Current ' + current + '\n');
137         var nl = w.getElementsByTagName('textbox');
138         //var nl = document.getElementsByTagName('textbox');
139         sdump('D_UTIL', 'fake_tab_for_textboxes: nl.length = ' + nl.length + '\n');
140         for (var i = 0; i < nl.length; i++) {
141                 sdump('D_UTIL', 'fake_tab_for_textboxes: Considering ' + nl[i] + '...\n');
142                 if (flag && !next_one) {
143                         sdump('D_UTIL', 'fake_tab_for_textboxes: Setting next_one ' + nl[i] + '\n');    
144                         next_one = nl[i];
145                 }
146                 if (nl[i] === current) {
147                         sdump('D_UTIL','fake_tab_for_textboxes: Found current\n');
148                         flag = true;
149                 }
150         }
151         if (!next_one) {
152                 sdump('D_UTIL','fake_tab_for_textboxes: Out of loop, Setting next_one ' + nl[0] + '\n');        
153                 next_one = nl[0];
154         }
155         if (next_one) {
156                 next_one.focus(); next_one.select();
157         } else {
158                 sdump('D_UTIL','fake_tab_for_textboxes: next_one not set\n');
159         }
160 }
161
162 function get_list_from_tree_selection(tree_w) {
163         sdump('D_UTIL','entering get_list_from_tree...\n');
164         var hitlist;
165         if (typeof(tree_w) != 'object') {
166                 hitlist = document.getElementById(tree_w);
167         } else {
168                 hitlist = tree_w;
169         }
170         var list = [];
171         var start = new Object();
172         var end = new Object();
173         var numRanges = hitlist.view.selection.getRangeCount();
174         for (var t=0; t<numRanges; t++){
175                 hitlist.view.selection.getRangeAt(t,start,end);
176                 for (var v=start.value; v<=end.value; v++){
177                         var i = hitlist.contentView.getItemAtIndex(v);
178                         //sdump('D_UTIL',i.tagName + '\n');
179                         list.push( i );
180                 }
181         }
182         sdump('D_UTIL','leaving get_list_from_tree...\n');
183         return list;
184 }
185
186 function yesno(value) {
187         switch(value) {
188                 case true: case 'true': case '1': case 'on':
189                         return 'Yes';
190                 default: 
191                         return 'No';
192         }
193 }
194
195 function formatted_date(date,format) {
196         // pass in a Date object or epoch seconds
197         if (typeof(date) == 'string') {
198                 date = new Date( parseInt( date + '000' ) );
199         }
200         var mm = date.getMonth() + 1;
201         mm = mm.toString();
202         if (mm.length == 1) mm = '0' +mm;
203         var dd = date.getDate().toString();
204         if (dd.length == 1) dd = '0' +dd;
205         var yyyy = date.getFullYear().toString();
206         var s = format.replace( /%m/g, mm );
207         s = s.replace( /%d/g, dd );
208         s = s.replace( /%Y/g, yyyy );
209         return s;
210 }
211
212 function interval_to_seconds ( $interval ) {
213
214         $interval = $interval.replace( /and/, ',' );
215         $interval = $interval.replace( /,/, ' ' );
216
217         var $amount = 0;
218         var results = $interval.match( /\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/g);  
219         for (var i in results) {
220                 var result = results[i].match( /\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/ );
221                 if (result[2] == 's') $amount += result[1] ;
222                 if (result[2] == 'm') $amount += 60 * result[1] ;
223                 if (result[2] == 'h') $amount += 60 * 60 * result[1] ;
224                 if (result[2] == 'd') $amount += 60 * 60 * 24 * result[1] ;
225                 if (result[2] == 'w') $amount += 60 * 60 * 24 * 7 * result[1] ;
226                 if (result[2] == 'M') $amount += ((60 * 60 * 24 * 365)/12) * result[1] ;
227                 if (result[2] == 'y') $amount += 60 * 60 * 24 * 365 * result[1] ;
228         }
229         return $amount;
230 }
231
232 /*
233 function debug() {
234         var s = '';
235         for (var i = 0; i < arguments.length; i++) {
236                 s = s + arguments[i];
237         }
238         //sdump('D_UTIL','debug:' + s + '\n');
239 }
240 */
241
242 function counter_init(id) {
243         counter[id] = 0;
244 }
245
246 function counter_incr(id) {
247         if (! counter[id]) { counter_init(id); }
248         return ++counter[id];
249 }
250
251 function counter_peek(id) {
252         if (! counter[id]) { return 0; }
253         return counter[id];
254 }
255
256 function timer_init(id) {
257         timer[id] = (new Date).getTime();
258 }
259
260 function timer_elapsed(id) {
261         if (! timer[id]) { timer_init(id); }
262         var ms = (new Date).getTime() - timer[id];
263         return( ms + 'ms (' + ms/1000 + 's)' );
264 }
265
266 function dump_ns_node( node ) {
267         return (
268         'id=<' + 
269         node[fieldmap["Fieldmapper::biblio::record_node"].fields.id.position] 
270         + '>  intra-id=<' + 
271         node[fieldmap["Fieldmapper::biblio::record_node"].fields.intra_doc_id.position]
272         + '>  name=<' + 
273         node[fieldmap["Fieldmapper::biblio::record_node"].fields.name.position]
274         + '>  node_type=<' + 
275         node[fieldmap["Fieldmapper::biblio::record_node"].fields.type.position]
276         + '>  parent_node=<' + 
277         node[fieldmap["Fieldmapper::biblio::record_node"].fields.parent_node.position]
278         + '>  '
279         );
280 }
281
282 function nodeset2tree(ns) {
283         for (var i in ns) {
284                 if (ns[i].parent_node) {
285                         ns_addChild( 
286                                 ns, 
287                                 ns[i].parent_node, 
288                                 ns[i].intra_doc_id 
289                         );
290                 }
291         }
292         return ns;
293 }
294
295 function ns_addChild(ns,p,c) {
296         if (! ns[p].children ) { ns[p].children = []; }
297         ns[p].children.push(ns[c]);
298 }
299
300 function print_tabs(t) {
301         var r = '';
302         for (var j = 0; j < t; j++ ) { r = r + "\t"; }
303         return r;
304 }
305
306 function pretty_print(s) {
307         var r = ''; var t = 0;
308         for (var i in s) {
309                 if (s[i] == '{') {
310                         r = r + "\n" + print_tabs(t) + s[i]; t++;
311                         r = r + "\n" + print_tabs(t);
312                 } else if (s[i] == '[') {
313                         r = r + "\n" + print_tabs(t) + s[i]; t++;
314                         r = r + "\n" + print_tabs(t);
315                 } else if (s[i] == '}') {
316                         t--; r = r + "\n" + print_tabs(t) + s[i]; 
317                         r = r + "\n" + print_tabs(t);
318                 } else if (s[i] == ']') { 
319                         t--; r = r + "\n" + print_tabs(t) + s[i];
320                         r = r + "\n" + print_tabs(t);
321                 } else if (s[i] == ',') {
322                         r = r + s[i]; 
323                         r = r + "\n" + print_tabs(t);
324                 } else {
325                         r = r + s[i];
326                 }
327         }
328         return r;
329 }
330
331 function enable_widgets() {
332         for (var i = 0; i < arguments.length; i++) {
333                 if (typeof(arguments[i]) == 'object') {
334                         sdump('D_UTIL',arguments[i] + '.disabled = false;\n');
335                         arguments[i].disabled = false;
336                 } else {
337                         var w = document.getElementById( arguments[i] );
338                         if (w) { 
339                                 sdump('D_UTIL',w + '.disabled = false;\n');
340                                 w.disabled = false; 
341                         }
342                 }
343         }
344 }
345
346 function disable_widgets() {
347         for (var i = 0; i < arguments.length; i++) {
348                 if (typeof(arguments[i]) == 'object') {
349                         sdump('D_UTIL',arguments[i] + '.disabled = true;\n');
350                         arguments[i].disabled = true;
351                 } else {
352                         var w = document.getElementById( arguments[i] );
353                         if (w) { 
354                                 sdump('D_UTIL',w + '.disabled = true;\n');
355                                 w.disabled = true; 
356                         }
357                 }
358         }
359 }
360
361 function focus_widget(e) {
362         if (typeof(e) == 'object') {
363                 e.focus();
364         } else {
365                 var w = document.getElementById(e);
366                 if (w) { w.focus(); }
367         }
368 }
369
370 function empty_widget(e) {
371         if (typeof(e) != 'object') { e = document.getElementById(e); }
372         if (typeof(e) != 'object') { sdump('D_UTIL','Failed on empty_widget\n'); return; }
373         while (e.lastChild) { e.removeChild(e.lastChild); }
374 }
375
376 function empty_listbox(e) {
377         if (typeof(e) != 'object') { e = document.getElementById(e); }
378         if (typeof(e) != 'object') { sdump('D_UTIL','Failed on empty_listbox\n'); return; }
379         var nl = e.getElementsByTagName('listitem');
380         for (var i = 0; i < nl.length; i++) {
381                 e.removeChild(nl[i]);
382         }
383 }
384
385 function swap_attributes(e,a1,a2) {
386         if (typeof(e) != 'object') { e = document.getElementById(e); }
387         if (typeof(e) != 'object') { sdump('D_UTIL','Failed on swap_attributes\n'); return; }
388         var a1_v = e.getAttribute(a1);
389         var a2_v = e.getAttribute(a2);
390         e.setAttribute(a1,a2_v);
391         e.setAttribute(a2, a1_v);
392         sdump('D_UTIL','before: a1 = ' + a1_v + ' a2 = ' + a2_v + ' and ');
393         sdump('D_UTIL','after: a1 = ' + a2_v + ' a2 = ' + a1_v + '\n');
394 }
395
396 function cycle_attribute(e,a,v) {
397         try {
398                 if (typeof(e) != 'object') { e = document.getElementById(e); }
399                 if (typeof(e) != 'object') { throw('typeof e != object : typeof e = ' + typeof(e)); }
400                 if (!a) { throw('!a : a = ' + a); }
401                 if (! e.getAttribute(a) ) { throw(' ! e.getAttribute(a) : a = ' + a); }
402                 if (typeof(v) != 'object') { throw('typeof v != object : typeof v = ' + typeof(v)); }
403
404                 var toggle = e.getAttribute(a);
405                 var next_one = false;
406                 sdump('D_UTIL','cycling ' + a + ' on ' + e.getAttribute('id') + ' to ');
407                 for (var i = 0; i < v.length; i++) {
408                         if (next_one) {
409                                 e.setAttribute(a,v[i]);
410                                 sdump('D_UTIL',v[i] + '\n');
411                                 return v[i];
412                         }
413                         if (toggle == v[i]) {
414                                 next_one = true;
415                         }
416                 }
417                 if (next_one) {
418                         e.setAttribute(a,v[0]);
419                         sdump('D_UTIL',v[0] + '\n');
420                         return v[0];
421                 } else {
422                         throw('current value not in list');
423                 }
424         } catch(E) {
425                 sdump('D_UTIL','cycle_attribute error: ' + js2JSON(E) + '\n');
426                 sdump('D_UTIL','null\n');
427                 return null;
428         }
429 }
430
431
432 function radio_checkbox(ev) {
433         var target = ev.target;
434         var group = target.getAttribute('group');
435         if (group) {
436                 var nl = document.getElementsByTagName('checkbox');
437                 for (var i in nl) {
438                         if (typeof(nl[i])=='object') {
439                                 var c = nl[i];
440                                 var cgroup = c.getAttribute('group');
441                                 if (cgroup == group) {
442                                         c.checked = false;
443                                 }
444                         }
445                 }
446                 target.checked = true;
447         } else {
448                 sdump('D_UTIL','radio_checkbox: Checkbox must have a group attribute to find peers');
449         }
450 }
451
452 function toggle_hidden_grid_rows(grid) {
453         if (typeof(grid) != 'object') {
454                 grid = document.getElementById(grid);
455         }
456         if (!grid) { return; }
457         var rows = grid.lastChild; if (!rows) { return; }
458         for (var r = 0; r < rows.childNodes.length; r++ ) {
459                 var row = rows.childNodes[r];
460                 if (typeof(row) == 'object') {
461                         //sdump('D_UTIL','toggle row = ' + row + '\n');
462                         var hidden = row.getAttribute('hidden');
463                         if (hidden == 'true') {
464                                 row.setAttribute('hidden','false');
465                         } else {
466                                 row.setAttribute('hidden','true');
467                         }
468                 }
469         }
470 }
471
472 /* The first parameter is the id of the element to set, or an array of ids for elements to set in batch.  The second parameter is an object containing the attribute/value pairs to assign to the element or elements */
473 function xul_setAttributes(el,attrs) {
474         if (typeof(el) == 'object') {
475                 for (var e in el) {
476                         var w = document.getElementById(e);
477                         for (var a in attrs) {
478                                 w.setAttribute(a,attrs[a]);
479                         }
480                 }
481         } else {
482                 var w = document.getElementById(el);
483                 for (var a in attrs) {
484                         w.setAttribute(a,attrs[a]);
485                 }
486         }
487 }
488
489 function append_treeitem() {
490         var id = arguments[0];
491         var treechildren = document.getElementById(id);
492         if (!treechildren) { sdump('D_UTIL','No ' + id + ' to append to\n'); return; }
493         var treeitem = document.createElement('treeitem'); treechildren.appendChild(treeitem);
494         var treerow = document.createElement('treerow'); treeitem.appendChild(treerow);
495         for (var i = 1; i < arguments.length ; i++ ) {
496                 var treecell = document.createElement('treecell'); treerow.appendChild(treecell);
497                 treecell.setAttribute('label',arguments[i]);
498                         treecell.setAttribute('id', 'treeitem_' + treeitem_id + '_' + i);
499                 //sdump('D_UTIL','treecell.label = ' + arguments[i] + '\n');
500         }
501         return treeitem_id++;
502 }
503
504 function set_decks(params) {
505         for (var deck_id in params) {
506                 var deck = document.getElementById( deck_id )
507                 if (deck) deck.setAttribute( 'selectedIndex', params[deck_id] );
508         }
509 }
510
511 function super_dump(o,t) {
512         var s = "\n";
513         for (var ii = 0; ii < t; ii++) { s = s + '\t'; }
514         s = s + "=-=-=\n";
515         s = s + 'o.constructor == Array = ' + (o.constructor == Array) + '\n';
516         for (var ii = 0; ii < t; ii++) { s = s + '\t'; }
517         s = s + "typeof = " + typeof(o) + "\n";
518         try {
519                 var string = new XMLSerializer().serializeToString(o);
520                 return( string + "\n" );
521         } catch( E ) {
522                 var i;
523                 var c = 0;
524                 for (i in o) {
525                         switch(typeof(i)) {
526                                 case 'object':
527                                         s = s + super_dump(i,t+1);
528                                         break;
529                                 default :
530                                         var value = o[i];
531                                         for (var ii = 0; ii < t; ii++) { s = s + '\t'; }
532                                         s = s + "\tMember#" + c++ + "\tType:" + typeof(value);
533                                         if (typeof(value) == 'object') {
534                                                 value = super_dump(value,t+1);
535                                         }
536                                         s = s + "\ttoString:" + i.toString() + "\tvalue:" + value + "\n";
537                                         break;
538                         }
539                 }
540                 return( s + "\n" );
541         }
542 }
543
544 function super_dump_norecurse(o,t) {
545         var s = "\n";
546         for (var ii = 0; ii < t; ii++) { s = s + '\t'; }
547         s = s + "=-=-=\n";
548         s = s + 'o.constructor == Array = ' + (o.constructor == Array) + '\n';
549         for (var ii = 0; ii < t; ii++) { s = s + '\t'; }
550         s = s + "typeof = " + typeof(o) + "\n";
551         try {
552                 var string = new XMLSerializer().serializeToString(o);
553                 return( string + "\n" );
554         } catch( E ) {
555                 var i;
556                 var c = 0;
557                 for (i in o) {
558                         switch(typeof(i)) {
559                                 default :
560                                         var value = o[i];
561                                         for (var ii = 0; ii < t; ii++) { s = s + '\t'; }
562                                         s = s + "\tMember#" + c++ + "\tType:" + typeof(value);
563                                         s = s + "\ttoString:" + i.toString() + "\n";
564                                         break;
565                         }
566                 }
567                 return( s + "\n" );
568         }
569 }
570
571 function get_my_orgs(user_ou) {
572
573         // self and ancestors
574         var current_item_id = user_ou.id();
575         //sdump('D_UTIL','mw.G[user_ou] = ' + js2JSON(mw.G['user_ou']) + '\n');
576         //sdump('D_UTIL','current_item_id = ' + current_item_id + '\n');
577         var item_ou; var my_orgs = {}; var other_orgs = {};
578         while( item_ou = find_ou(mw.G['org_tree'],current_item_id) ) {
579                 //sdump('D_UTIL','\titem_ou = ' + js2JSON(item_ou) + '\n');
580                 my_orgs[ item_ou.id() ] = item_ou;
581                 current_item_id = item_ou.parent_ou();
582                 if (!current_item_id) { break; }
583         }
584
585         current_item_id = user_ou.id();
586         //sdump('D_UTIL','self & ancestors : my_orgs = <<<'+js2JSON(my_orgs)+'>>>\n');
587         // descendants
588         var my_children;
589         var find_ou_result = find_ou(mw.G['org_tree'],current_item_id);
590         if (find_ou_result) { 
591                 my_children = find_ou_result.children() } 
592         else {
593                 sdump('D_UTIL','ERROR: find_ou(org_tree,'+current_item_id+') returned with no properties\n');
594         };
595         //sdump('D_UTIL','my_children: ' + my_children + ' : ' + js2JSON(my_children) + '\n');
596         if (my_children) {
597                 for (var i = 0; i < my_children.length; i++) {
598                         var my_child = my_children[i];
599                         my_orgs[ my_child.id() ] = my_child;
600                         //sdump('D_UTIL','my_child.children(): ' + my_child.children() + ' : ' + js2JSON(my_child.children()) + '\n');
601                         if (my_child.children() != null) {
602                                 for (var j = 0; j < my_child.children().length; j++) {
603                                         var my_gchild = my_child.children()[j];
604                                         my_orgs[ my_gchild.id() ] = my_gchild;
605                                 }
606                         }
607                 }
608         }
609         //sdump('D_UTIL','& descendants : my_orgs = <<<'+js2JSON(my_orgs)+'>>>\n');
610         return my_orgs;
611 }
612
613 function get_other_orgs(org,other_orgs) {
614 }
615
616 function flatten_ou_branch(branch) {
617         //sdump('D_UTIL','flatten: branch = ' + js2JSON(branch) + '\n');
618         var my_array = new Array();
619         my_array.push( branch );
620         for (var i in branch.children() ) {
621                 var child = branch.children()[i];
622                 if (child != null) {
623                         var temp_array = flatten_ou_branch(child);
624                         for (var j in temp_array) {
625                                 my_array.push( temp_array[j] );
626                         }
627                 }
628         }
629         return my_array;
630 }
631
632 function find_ou(tree,id) {
633         if (typeof(id)=='object') { id = id.id(); }
634         if (tree.id()==id) {
635                 return tree;
636         }
637         for (var i in tree.children()) {
638                 var child = tree.children()[i];
639                 ou = find_ou( child, id );
640                 if (ou) { return ou; }
641         }
642         return null;
643 }
644
645 function find_tree_via_children(tree,children_func,find_func) {
646         if (typeof(tree)!='object') tree = document.getElementById(tree);
647
648         var t = find_func(tree); if (t) return t;
649
650         var c = children_func(tree);
651
652         for (var i = 0; i < c.length; i++) {
653                 t = find_func( c[i] );
654                 if (t) return t;
655         }
656 }
657
658 function filter_list(list,f) {
659         var new_list = [];
660         for (var i in list) {
661                 var t = f( list[i] );
662                 if (t) new_list.push( list[i] );
663         }
664         return new_list;
665 }
666
667 function find_list(list,f) {
668         for (var i in list) {
669                 var t = f( list[i] );
670                 if (t) return list[i];
671         }
672         return null;
673 }
674
675 function map_list(list,f) {
676         var new_list = [];
677         for (var i in list) {
678                 new_list.push( f( list[i] ) );
679         }
680         return new_list;
681 }
682
683 function map_object_to_list(obj,f) {
684         var new_list = [];
685         for (var i in obj) {
686                 new_list.push( f( obj, i ) );
687         }
688         return new_list;
689 }
690
691 function convert_object_list_to_hash(list) {
692         var my_hash = new Object();
693         if (list) {
694                 for (var i = 0; i < list.length; i++) {
695                         my_hash[ list[i].id() ] = list[i];
696                 }
697         }
698         return my_hash;
699 }
700
701 function find_id_object_in_list(list,id) {
702         //sdump('D_UTIL','find_id_object_in_list(' + js2JSON(list).substr(0,20) + '... ,' + id + ')\n');
703         if (list) {
704                 for (var i = 0; i < list.length; i++ ) {
705                         try {
706                                 if ( list[i].id() == id ) {
707                                         return list[i];
708                                 }
709                         } catch(E) {
710                                 sdump('D_UTIL','find_id_object_in_list error, i = ' + i + '  typeof(list[i]) = ' + typeof(list[i]) + '  list[i] = ' + js2JSON(list[i]) + ' : ' + js2JSON(E) + '\n');
711                         }
712                 }
713         }
714         //sdump('D_UTIL','not found\n');
715         return null;
716 }
717
718 function find_attr_object_in_list(list,attr,value) {
719         if (list) {
720                 for (var i = 0; i < list.length; i++ ) {
721                         sdump('D_UTIL','find_attr_object_in_list: i = ' + i + '  id = ' + list[i].id() + '\n');
722                         try {
723                                 var command = 'list[' + i + '].'+attr+'() == ' + value;
724                                 if ( eval(command) ) {
725                                         return list[i];
726                                 }
727                         } catch(E) {
728                                 sdump('D_UTIL','find_attr_object_in_list error, i = ' + i + '  typeof(list[i]) = ' + typeof(list[i]) + '  list[i] = ' + js2JSON(list[i]) + ' :   list = ' + js2JSON(list) + ' : ' + js2JSON(E) + '\n');
729                         }
730                 }
731         }
732         return null;
733 }
734
735 function find_ou_by_shortname(tree,sn) {
736         var ou = new aou();
737         if (tree.shortname()==sn) {
738                 return tree;
739         }
740         for (var i in tree.children()) {
741                 var child = tree.children()[i];
742                 ou = find_ou_by_shortname( child, sn );
743                 if (ou) { return ou; }
744         }
745         return null;
746 }
747
748