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