]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/common/js/utils.js
added url param that, if present, prevents search propogation to the advanced search...
[Evergreen.git] / Open-ILS / web / opac / common / js / utils.js
1 function $(id) { return getId(id); }
2 function getId(id) {
3         return document.getElementById(id);
4 }
5
6 function swapCSSClass(obj, old, newc ) {
7         removeCSSClass(obj, old );
8         addCSSClass(obj, newc );
9 }
10
11
12 function addCSSClass(e,c) {
13         if(!e || !c) return;
14
15         var css_class_string = e.className;
16         var css_class_array;
17
18         if(css_class_string)
19                 css_class_array = css_class_string.split(/\s+/);
20
21         var string_ip = ""; /*strip out nulls*/
22         for (var css_class in css_class_array) {
23                 if (css_class_array[css_class] == c) { return; }
24                 if(css_class_array[css_class] !=null)
25                         string_ip += css_class_array[css_class] + " ";
26         }
27         string_ip += c;
28         e.className = string_ip;
29 }
30
31 function removeCSSClass(e, c) {
32         if(!e || !c) return;
33
34         var css_class_string = '';
35
36         var css_class_array = e.className;
37         if( css_class_array )
38                 css_class_array = css_class_array.split(/\s+/);
39
40         var first = 1;
41         for (var css_class in css_class_array) {
42                 if (css_class_array[css_class] != c) {
43                         if (first == 1) {
44                                 css_class_string = css_class_array[css_class];
45                                 first = 0;
46                         } else {
47                                 css_class_string = css_class_string + ' ' +
48                                         css_class_array[css_class];
49                         }
50                 }
51         }
52         e.className = css_class_string;
53 }
54
55
56 /*returns the character code pressed that caused the event */
57 function grabCharCode(evt) {
58    evt = (evt) ? evt : ((window.event) ? event : null); 
59    if( evt ) {
60       return (evt.charCode ? evt.charCode : 
61          ((evt.which) ? evt.which : evt.keyCode ));
62    } else { return -1; }
63 }       
64
65
66 /* returns true if the user pressed enter */
67 function userPressedEnter(evt) {
68    var code = grabCharCode(evt);
69    if(code==13||code==3) return true;
70    return false;
71 }   
72
73
74 function goTo(url) {
75         /* setTimeout because ie sux */
76         setTimeout( function(){ location.href = url; }, 0 );
77 }
78
79
80 function removeChildren(dom) {
81         if(!dom) return;
82         while(dom.childNodes[0])
83                 dom.removeChild(dom.childNodes[0]);
84 }
85
86 function appendClear(node, child) {
87         if(typeof child =='string') child = text(child);
88         removeChildren(node);
89         node.appendChild(child);
90 }
91
92
93 function instanceOf(object, constructorFunction) {
94
95    if(!IE) {
96       while (object != null) {
97          if (object == constructorFunction.prototype)
98             return true;
99          object = object.__proto__;
100       }
101    } else {
102       while(object != null) {
103          if( object instanceof constructorFunction )
104             return true;
105          object = object.__proto__;
106       }
107    }
108    return false;
109 }         
110
111
112 /* ------------------------------------------------------------------------------------------- */
113 /* detect my browser */
114 var isMac, NS, NS4, NS6, IE, IE4, IEmac, IE4plus, IE5, IE5plus, IE6, IEMajor, ver4, Safari;
115 function detect_browser() {       
116
117    isMac = (navigator.appVersion.indexOf("Mac")!=-1) ? true : false;
118    NS = (navigator.appName == "Netscape") ? true : false;
119    NS4 = (document.layers) ? true : false;
120    IE = (navigator.appName == "Microsoft Internet Explorer") ? true : false;
121    IEmac = ((document.all)&&(isMac)) ? true : false;
122    IE4plus = (document.all) ? true : false;
123    IE4 = ((document.all)&&(navigator.appVersion.indexOf("MSIE 4.")!=-1)) ? true : false;
124    IE5 = ((document.all)&&(navigator.appVersion.indexOf("MSIE 5.")!=-1)) ? true : false;
125    IE6 = ((document.all)&&(navigator.appVersion.indexOf("MSIE 6.")!=-1)) ? true : false;
126    ver4 = (NS4 || IE4plus) ? true : false;
127    NS6 = (!document.layers) && (navigator.userAgent.indexOf('Netscape')!=-1)?true:false;
128    Safari = navigator.userAgent.match(/Safari/);
129
130    IE5plus = IE5 || IE6;
131    IEMajor = 0;
132
133    if (IE4plus) {
134       var start = navigator.appVersion.indexOf("MSIE");
135       var end = navigator.appVersion.indexOf(".",start);
136       IEMajor = parseInt(navigator.appVersion.substring(start+5,end));
137       IE5plus = (IEMajor>=5) ? true : false;
138    }
139 }  
140 detect_browser();
141 /* ------------------------------------------------------------------------------------------- */
142
143
144 function text(t) {
145         if(t == null) t = "";
146         return document.createTextNode(t);
147 }
148
149 function elem(name, attrs, txt) {
150     var e = document.createElement(name);
151     if (attrs) {
152         for (key in attrs) {
153                           if( key == 'id') e.id = attrs[key];
154                           else e.setAttribute(key, attrs[key]);
155         }
156     }
157     if (txt) e.appendChild(text(txt));
158     return e;
159 }                   
160
161
162 /* sel is the selector object, sets selected on the 
163         option with the given value. case does not matter...*/
164 function setSelector( sel, value ) {
165         if(sel && value != null) {
166                 for( var i = 0; i!= sel.options.length; i++ ) { 
167                         if( sel.options[i] ) {
168                                 var val = sel.options[i].value;
169                                 if( val == null || val == "" ) /* for IE */
170                                         val = sel.options[i].innerHTML;
171                                 value += ""; /* in case of number */ 
172                                 if( val && val.toLowerCase() == value.toLowerCase() ) {
173                                         sel.selectedIndex = i;
174                                         sel.options[i].selected = true;
175                                         return true;
176                                 }
177                         }
178                 }
179         }
180         return false;
181 }
182
183 function setSelectorRegex( sel, regex ) {
184         if(sel && regex != null) {
185                 for( var i = 0; i!= sel.options.length; i++ ) { 
186                         if( sel.options[i] ) {
187                                 var val = sel.options[i].value;
188                                 if( val == null || val == "" ) /* for IE */
189                                         val = sel.options[i].innerHTML;
190                                 value += ""; /* in case of number */ 
191                                 if( val && val.match(regex) ) {
192                                         sel.selectedIndex = i;
193                                         sel.options[i].selected = true;
194                                         return true;
195                                 }
196                         }
197                 }
198         }
199         return false;
200 }
201
202 function getSelectorVal( sel ) {
203         if(!sel) return null;
204         var idx = sel.selectedIndex;
205         if( idx < 0 ) return null;
206         var o = sel.options[idx];
207         var v = o.value; 
208         if(v == null) v = o.innerHTML;
209         return v;
210 }
211
212 function getSelectorName( sel ) {
213         var o = sel.options[sel.selectedIndex];
214         var v = o.name;
215         if(v == null || v == undefined || v == "") v = o.innerHTML;
216         return v;
217 }
218
219 function setSelectorByName( sel, name ) {
220         for( var o in sel.options ) {
221                 var opt = sel.options[o];
222                 if( opt.name == name || opt.innerHTML == name ) {
223                         sel.selectedIndex = o;
224                         opt.selected = true;
225                 }
226         }
227 }
228
229 function findSelectorOptByValue( sel, val ) {
230         for( var i = 0; i < sel.options.length; i++ ) {
231                 var opt = sel.options[i];
232                 if( opt.value == val ) return opt;
233         }
234         return null;
235 }
236
237 function debugSelector(sel) {
238         var s = 'Selector\n';
239         for( var i = 0; i != sel.options.length; i++ ) {
240                 var o = sel.options[i];
241                 s += "\t" + o.innerHTML + "\n";
242         }
243         return s;
244 }
245
246 function findParentByNodeName(node, name) {
247         while( ( node = node.parentNode) ) 
248                 if (node.nodeName == name) return node;
249         return null;
250 }
251
252 /* returns only elements in nodes childNodes list, not sub-children */
253 function getElementsByTagNameFlat( node, name ) {
254         var elements = [];
255         for( var e in node.childNodes ) {
256                 var n = node.childNodes[e];
257                 if( n && n.nodeName == name ) elements.push(n);
258         }
259         return elements;
260 }
261
262 /* expects a tree with a id() method on each node and a 
263 children() method to get to each node */
264 function findTreeItemById( tree, id ) {
265         if( tree.id() == id ) return tree;
266         for( var c in tree.children() ) {
267                 var found = findTreeItemById( tree.children()[c], id );
268                 if(found) return found;
269         }
270         return null;
271 }
272
273 /* returns null if none of the tests are true.  returns sub-array of 
274 matching array items otherwise */
275 function grep( arr, func ) {
276         var results = [];
277         if(!arr) return null;
278         if( arr.constructor == Array ) {
279                 for( var i = 0; i < arr.length; i++ ) {
280                         if( func(arr[i]) ) 
281                                 results.push(arr[i]);
282                 }
283         } else {
284                 for( var i in arr ) {
285                         if( func(arr[i]) ) 
286                                 results.push(arr[i]);
287                 }
288         }
289         if(results.length > 0) return results;
290         return null;
291 }
292
293 function ogrep( obj, func ) {
294         var results = {};
295         var found = false;
296         for( var i in obj ) {
297                 if( func(obj[i]) ) {
298                         results[i] = obj[i];
299                         found = true;
300                 }
301         }
302         if(found) return results;
303         return null;
304 }
305
306 function doSelectorActions(sel) {
307         if((IE || Safari) && sel) { 
308                 sel.onchange = function() {
309                         var o = sel.options[sel.selectedIndex];
310                         if(o && o.onclick) o.onclick()
311                 }
312         }
313 }
314
315 /* if index < 0, the item is pushed onto the end */
316 function insertSelectorVal( selector, index, name, value, action, indent ) {
317         if( index < 0 ) index = selector.options.length;
318         var a = [];
319         for( var i = selector.options.length; i != index; i-- ) 
320                 a[i] = selector.options[i-1];
321
322         var opt = setSelectorVal( selector, index, name, value, action, indent );
323
324         for( var i = index + 1; i < a.length; i++ ) 
325                 selector.options[i] = a[i];
326
327         return opt;
328 }
329
330 /* changes the value of the option at the specified index */
331 function setSelectorVal( selector, index, name, value, action, indent ) {
332         if(!indent || indent < 0) indent = 0;
333         indent = parseInt(indent);
334
335         var option;
336
337         if(IE) {
338                 var pre = elem("pre");
339                 for( var i = 0; i != indent; i++ )
340                         pre.appendChild(text("   "));
341
342                 pre.appendChild(text(name));
343                 option = new Option("", value);
344                 selector.options[index] = option;
345                 option.appendChild(pre);
346         
347         } else {
348                 indent = indent * 14;
349                 option= new Option(name, value);
350                 option.setAttribute("style", "padding-left: "+indent+'px;');
351                 selector.options[index] = option;
352                 if(action) option.onclick = action;
353         }
354
355         if(action) option.onclick = action;
356         return option;
357 }
358
359
360 /* split on spaces.  capitalize the first /\w/ character in
361    each substring */
362 function normalize(val) {
363         return val; /* disable me for now */
364
365    if(!val) return ""; 
366
367    var newVal = '';
368    try {val = val.split(' ');} catch(E) {return val;}
369    var reg = /\w/;
370
371    for( var c = 0; c < val.length; c++) {
372
373       var string = val[c];
374       var cap = false; 
375       for(var x = 0; x != string.length; x++) {
376
377          if(!cap) {
378             var ch = string.charAt(x);
379             if(reg.exec(ch + "")) {
380                newVal += string.charAt(x).toUpperCase();
381                cap = true;
382                continue;
383             }
384          }
385
386          newVal += string.charAt(x).toLowerCase();
387       }
388       if(c < (val.length-1)) newVal += " ";
389    }
390
391    newVal = newVal.replace(/\s*\.\s*$/,'');
392    newVal = newVal.replace(/\s*\/\s*\/\s*$/,' / ');
393    newVal = newVal.replace(/\s*\/\s*$/,'');
394
395    return newVal;
396 }
397
398
399 /* returns true if n is null or stringifies to 'undefined' */
400 function isNull(n) {
401         if( n == null || n == undefined || n.toString().toLowerCase() == "undefined" 
402                 || n.toString().toLowerCase() == "null" )
403                 return true;
404         return false;
405 }
406
407
408 /* find nodes with an attribute of 'name' that equals nodeName */
409
410 function $n( root, nodeName ) { return findNodeByName(root,nodeName); }
411
412 function findNodeByName(root, nodeName) {
413         if( !root || !nodeName) return null;
414
415         if(root.nodeType != 1) return null;
416
417         if(root.getAttribute("name") == nodeName || root.name == nodeName ) 
418                 return root;
419
420         var children = root.childNodes;
421
422         for( var i = 0; i != children.length; i++ ) {
423                 var n = findNodeByName(children[i], nodeName);
424                 if(n) return n;
425         }
426
427         return null;
428 }
429
430
431 /* truncates the string at 'size' characters and appends a '...' to the end */
432 function truncate(string, size) {
433         if(string && size != null && 
434                         size > -1 && string.length > size) 
435                 return string.substr(0, size) + "... "; 
436         return string;
437 }
438
439
440 /* style sheets must have a 'name' attribute for these functions to work */
441 function setActivateStyleSheet(name) {
442         var i, a, main;
443         for (i = 0; (a = document.getElementsByTagName ("link")[i]); i++) {
444                 if (a.getAttribute ("rel").indexOf ("style") != -1 && a.getAttribute ("name")) {
445                         a.disabled = true;
446                         if (a.getAttribute ("name").indexOf(name) != -1)
447                                 a.disabled = false;
448                 }
449         }
450 }
451
452
453 /* ----------------------------------------------------- */
454 var currentFontSize;
455 function scaleFonts(type) {
456
457         var size                = "";
458         var ssize       = "";
459         var size2       = "";
460         var a;
461         
462         if(!currentFontSize) currentFontSize = 'regular';
463         if(currentFontSize == 'regular' && type == 'regular' ) return;
464         if( currentFontSize == type ) return;
465         currentFontSize = type;
466
467         switch(type) {
468                 case "large":  /* these are arbitrary.. but they seem to work ok in FF/IE */
469                         size = "142%"; 
470                         size2 = "107%"; 
471                         ssize = "94%";
472                         break;
473         }
474
475         document.getElementsByTagName('body')[0].style.fontSize = size;
476         for (i = 0; (a = document.getElementsByTagName ("td")[i]); i++) a.style.fontSize = size;;
477         for (i = 0; (a = document.getElementsByTagName ("div")[i]); i++) a.style.fontSize = ssize;
478         for (i = 0; (a = document.getElementsByTagName ("option")[i]); i++) a.style.fontSize = ssize;
479         for (i = 0; (a = document.getElementsByTagName ("li")[i]); i++) a.style.fontSize = ssize;
480         for (i = 0; (a = document.getElementsByTagName ("span")[i]); i++) a.style.fontSize = ssize;
481         for (i = 0; (a = document.getElementsByTagName ("select")[i]); i++) a.style.fontSize = ssize;
482         for (i = 0; (a = document.getElementsByTagName ("a")[i]); i++) a.style.fontSize = size2;
483 }
484
485
486 function sortWordsIgnoreCase(a, b) {
487         a = a.toLowerCase();
488         b = b.toLowerCase();
489         if(a>b) return 1;
490         if(a<b) return -1;
491         return 0;
492 }
493
494
495 function getSelectedList(sel) {
496         if(!sel) return [];
497         var vals = [];
498         for( var i = 0; i != sel.options.length; i++ ) {
499                 if(sel.options[i].selected)
500                         vals.push(sel.options[i].value);
501         }
502         return vals;
503 }
504
505
506 function setEnterFunc(node, func) {
507         if(!(node && func)) return;
508         node.onkeydown = function(evt) {
509                 if( userPressedEnter(evt)) func();
510         }
511 }
512
513 function iterate( arr, callback ) {
514         for( var i = 0; arr && i < arr.length; i++ ) 
515                 callback(arr[i]);
516 }
517
518
519
520
521 /* taken directly from the JSAN util.date library */
522 /* but changed from the util.date.interval_to_seconds invocation, 
523 because JSAN will assume the whole library is already loaded if 
524 it sees that, and the staff client uses both this file and the
525 JSAN library*/
526 function interval_to_seconds( $interval ) {
527
528         $interval = $interval.replace( /and/, ',' );
529         $interval = $interval.replace( /,/, ' ' );
530         
531         var $amount = 0;
532         var results = $interval.match( /\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/g);  
533         for( var i = 0; i < results.length; i++ ) {
534                 if(!results[i]) continue;
535                 var result = results[i].match( /\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/ );
536                 if (result[2] == 's') $amount += result[1] ;
537                 if (result[2] == 'm') $amount += 60 * result[1] ;
538                 if (result[2] == 'h') $amount += 60 * 60 * result[1] ;
539                 if (result[2] == 'd') $amount += 60 * 60 * 24 * result[1] ;
540                 if (result[2] == 'w') $amount += 60 * 60 * 24 * 7 * result[1] ;
541                 if (result[2] == 'M') $amount += ((60 * 60 * 24 * 365)/12) * result[1] ;
542                 if (result[2] == 'y') $amount += 60 * 60 * 24 * 365 * result[1] ;
543         }
544         return $amount;
545 }
546
547
548 function openWindow( data ) {
549         if( isXUL() ) {
550                 var data = window.escape(
551                         '<html><head><title></title></head><body>' + data + '</body></html>');
552
553                 xulG.window_open(
554                         'data:text/html,' + data,
555                         '', 
556                         'chrome,resizable,width=700,height=500'); 
557
558         } else {
559                 win = window.open('','', 'resizable,width=700,height=500,scrollbars=1'); 
560                 win.document.body.innerHTML = data;
561         }
562 }
563
564
565 /* alerts the innerhtml of the node with the given id */
566 function alertId(id) {
567         var node = $(id);
568         if(node) alert(node.innerHTML);
569 }
570
571 function alertIdText(id, text) {
572         var node = $(id);
573    if(!node) return;
574    if(text)
575       alert(text + '\n\n' + node.innerHTML);
576    else 
577            alert(node.innerHTML);
578 }
579
580 function confirmId(id) {
581         var node = $(id);
582         if(node) return confirm(node.innerHTML);
583 }
584
585
586 function goBack() { history.back(); }
587 function goForward() { history.forward(); }
588
589
590 function uniquify(arr) {
591         if(!arr) return [];
592         var newarr = [];
593         for( var i = 0; i < arr.length; i++ ) {
594                 var item = arr[i];
595                 if( ! grep( newarr, function(x) {return (x == item);}))
596                         newarr.push(item);
597         }
598         return newarr;
599 }
600
601 function contains(arr, item) {
602         for( var i = 0; i < arr.length; i++ ) 
603                 if( arr[i] == item ) return true;
604         return false;
605 }
606
607 function isTrue(i) {
608         return (i && !(i+'').match(/f/i) );
609 }
610
611
612 /* builds a JS date object with the given info.  The given data
613         has to be valid (e.g. months == 30 is not valid).  Returns NULL on 
614         invalid date 
615         Months are 1-12 (unlike the JS date object)
616         */
617
618 function buildDate( year, month, day, hours, minutes, seconds ) {
619
620         if(!year) year = 0;
621         if(!month) month = 1;
622         if(!day) day = 1;
623         if(!hours) hours = 0;
624         if(!minutes) minutes = 0;
625         if(!seconds) seconds = 0;
626
627         var d = new Date(year, month - 1, day, hours, minutes, seconds);
628         
629         _debug('created date with ' +
630                 (d.getYear() + 1900) +'-'+
631                 (d.getMonth() + 1) +'-'+
632                 d.getDate()+' '+
633                 d.getHours()+':'+
634                 d.getMinutes()+':'+
635                 d.getSeconds());
636
637
638         if( 
639                 (d.getYear() + 1900) == year &&
640                 d.getMonth()    == (month - 1) &&
641                 d.getDate()             == new Number(day) &&
642                 d.getHours()    == new Number(hours) &&
643                 d.getMinutes() == new Number(minutes) &&
644                 d.getSeconds() == new Number(seconds) ) {
645                 return d;
646         }
647
648         return null;
649 }
650
651 function mkYearMonDay(date) {
652         if(!date) date = new Date();
653         var y = date.getYear() + 1900;
654         var m = (date.getMonth() + 1)+'';
655         var d = date.getDate()+'';
656         if(m.length == 1) m = '0'+m;
657         if(d.length == 1) d = '0'+d;
658         return y+'-'+m+'-'+d;
659 }
660
661
662 function debugFMObject(obj) {
663         if(typeof obj != 'object' ) return obj;
664         _debug("---------------------");
665         var keys = fmclasses[obj.classname];
666         if(!keys) { _debug(formatJSON(js2JSON(obj))); return; }
667
668         keys.sort();
669         for( var i = 0; i < keys.length; i++ ) {
670                 var key = keys[i];
671                 while( key.length < 12 ) key += ' ';
672                 var val = obj[keys[i]]();
673                 if( typeof val == 'object' ) {
674                         _debug(key+' :=\n');
675                         _debugFMObject(val);
676                 } else {
677                         _debug(key+' = ' +val);
678                 }
679
680         }
681         _debug("---------------------");
682 }
683
684
685 function getTableRows(tbody) {
686     var rows = [];
687     if(!tbody) return rows;
688
689     var children = tbody.childNodes;
690     if(!children) return rows;
691
692     for(var i = 0; i < children.length; i++) {
693         var child = children[i];
694         if(child.nodeName.match(/^tr$/i)) 
695             rows.push(child);
696     }
697     return rows;
698 }
699
700 function getObjectKeys(obj) {
701     keys = []
702     for(var k in obj)
703         keys.push(k)
704     return keys;
705 }