1 function $(id) { return getId(id); }
3 return document.getElementById(id);
6 function swapCSSClass(obj, old, newc ) {
7 removeCSSClass(obj, old );
8 addCSSClass(obj, newc );
12 function addCSSClass(e,c) {
15 var css_class_string = e.className;
19 css_class_array = css_class_string.split(/\s+/);
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] + " ";
28 e.className = string_ip;
31 function removeCSSClass(e, c) {
34 var css_class_string = '';
36 var css_class_array = e.className;
38 css_class_array = css_class_array.split(/\s+/);
41 for (var css_class in css_class_array) {
42 if (css_class_array[css_class] != c) {
44 css_class_string = css_class_array[css_class];
47 css_class_string = css_class_string + ' ' +
48 css_class_array[css_class];
52 e.className = css_class_string;
56 /*returns the character code pressed that caused the event */
57 function grabCharCode(evt) {
58 evt = (evt) ? evt : ((window.event) ? event : null);
60 return (evt.charCode ? evt.charCode :
61 ((evt.which) ? evt.which : evt.keyCode ));
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;
75 /* setTimeout because ie sux */
76 setTimeout( function(){ location.href = url; }, 0 );
80 function removeChildren(dom) {
82 while(dom.childNodes[0])
83 dom.removeChild(dom.childNodes[0]);
86 function appendClear(node, child) {
87 if(typeof child =='string') child = text(child);
89 node.appendChild(child);
93 function instanceOf(object, constructorFunction) {
96 while (object != null) {
97 if (object == constructorFunction.prototype)
99 object = object.__proto__;
102 while(object != null) {
103 if( object instanceof constructorFunction )
105 object = object.__proto__;
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() {
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/);
130 IE5plus = IE5 || IE6;
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;
141 /* ------------------------------------------------------------------------------------------- */
145 if(t == null) t = "";
146 return document.createTextNode(t);
149 function elem(name, attrs, txt) {
150 var e = document.createElement(name);
153 if( key == 'id') e.id = attrs[key];
154 else e.setAttribute(key, attrs[key]);
157 if (txt) e.appendChild(text(txt));
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;
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;
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];
208 if(v == null) v = o.innerHTML;
212 function getSelectorName( sel ) {
213 var o = sel.options[sel.selectedIndex];
215 if(v == null || v == undefined || v == "") v = o.innerHTML;
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;
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;
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";
246 function findParentByNodeName(node, name) {
247 while( ( node = node.parentNode) )
248 if (node.nodeName == name) return node;
252 /* returns only elements in nodes childNodes list, not sub-children */
253 function getElementsByTagNameFlat( node, name ) {
255 for( var e in node.childNodes ) {
256 var n = node.childNodes[e];
257 if( n && n.nodeName == name ) elements.push(n);
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;
273 /* returns null if none of the tests are true. returns sub-array of
274 matching array items otherwise */
275 function grep( arr, func ) {
277 if(!arr) return null;
278 if( arr.constructor == Array ) {
279 for( var i = 0; i < arr.length; i++ ) {
281 results.push(arr[i]);
284 for( var i in arr ) {
286 results.push(arr[i]);
289 if(results.length > 0) return results;
293 function ogrep( obj, func ) {
296 for( var i in obj ) {
302 if(found) return results;
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()
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;
319 for( var i = selector.options.length; i != index; i-- )
320 a[i] = selector.options[i-1];
322 var opt = setSelectorVal( selector, index, name, value, action, indent );
324 for( var i = index + 1; i < a.length; i++ )
325 selector.options[i] = a[i];
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);
338 var pre = elem("pre");
339 for( var i = 0; i != indent; i++ )
340 pre.appendChild(text(" "));
342 pre.appendChild(text(name));
343 option = new Option("", value);
344 selector.options[index] = option;
345 option.appendChild(pre);
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;
355 if(action) option.onclick = action;
360 /* split on spaces. capitalize the first /\w/ character in
362 function normalize(val) {
363 return val; /* disable me for now */
368 try {val = val.split(' ');} catch(E) {return val;}
371 for( var c = 0; c < val.length; c++) {
375 for(var x = 0; x != string.length; x++) {
378 var ch = string.charAt(x);
379 if(reg.exec(ch + "")) {
380 newVal += string.charAt(x).toUpperCase();
386 newVal += string.charAt(x).toLowerCase();
388 if(c < (val.length-1)) newVal += " ";
391 newVal = newVal.replace(/\s*\.\s*$/,'');
392 newVal = newVal.replace(/\s*\/\s*\/\s*$/,' / ');
393 newVal = newVal.replace(/\s*\/\s*$/,'');
399 /* returns true if n is null or stringifies to 'undefined' */
401 if( n == null || n == undefined || n.toString().toLowerCase() == "undefined"
402 || n.toString().toLowerCase() == "null" )
408 /* find nodes with an attribute of 'name' that equals nodeName */
410 function $n( root, nodeName ) { return findNodeByName(root,nodeName); }
412 function findNodeByName(root, nodeName) {
413 if( !root || !nodeName) return null;
415 if(root.nodeType != 1) return null;
417 if(root.getAttribute("name") == nodeName || root.name == nodeName )
420 var children = root.childNodes;
422 for( var i = 0; i != children.length; i++ ) {
423 var n = findNodeByName(children[i], nodeName);
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) + "... ";
440 /* style sheets must have a 'name' attribute for these functions to work */
441 function setActivateStyleSheet(name) {
443 for (i = 0; (a = document.getElementsByTagName ("link")[i]); i++) {
444 if (a.getAttribute ("rel").indexOf ("style") != -1 && a.getAttribute ("name")) {
446 if (a.getAttribute ("name").indexOf(name) != -1)
453 /* ----------------------------------------------------- */
455 function scaleFonts(type) {
462 if(!currentFontSize) currentFontSize = 'regular';
463 if(currentFontSize == 'regular' && type == 'regular' ) return;
464 if( currentFontSize == type ) return;
465 currentFontSize = type;
468 case "large": /* these are arbitrary.. but they seem to work ok in FF/IE */
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;
486 function sortWordsIgnoreCase(a, b) {
495 function getSelectedList(sel) {
498 for( var i = 0; i != sel.options.length; i++ ) {
499 if(sel.options[i].selected)
500 vals.push(sel.options[i].value);
506 function setEnterFunc(node, func) {
507 if(!(node && func)) return;
508 node.onkeydown = function(evt) {
509 if( userPressedEnter(evt)) func();
513 function iterate( arr, callback ) {
514 for( var i = 0; arr && i < arr.length; i++ )
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
526 function interval_to_seconds( $interval ) {
528 $interval = $interval.replace( /and/, ',' );
529 $interval = $interval.replace( /,/, ' ' );
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] ;
548 function openWindow( data ) {
550 var data = window.escape(
551 '<html><head><title></title></head><body>' + data + '</body></html>');
554 'data:text/html,' + data,
556 'chrome,resizable,width=700,height=500');
559 win = window.open('','', 'resizable,width=700,height=500,scrollbars=1');
560 win.document.body.innerHTML = data;
565 /* alerts the innerhtml of the node with the given id */
566 function alertId(id) {
568 if(node) alert(node.innerHTML);
571 function alertIdText(id, text) {
575 alert(text + '\n\n' + node.innerHTML);
577 alert(node.innerHTML);
580 function confirmId(id) {
582 if(node) return confirm(node.innerHTML);
586 function goBack() { history.back(); }
587 function goForward() { history.forward(); }
590 function uniquify(arr) {
593 for( var i = 0; i < arr.length; i++ ) {
595 if( ! grep( newarr, function(x) {return (x == item);}))
601 function contains(arr, item) {
602 for( var i = 0; i < arr.length; i++ )
603 if( arr[i] == item ) return true;
608 return (i && !(i+'').match(/f/i) );
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
615 Months are 1-12 (unlike the JS date object)
618 function buildDate( year, month, day, hours, minutes, seconds ) {
621 if(!month) month = 1;
623 if(!hours) hours = 0;
624 if(!minutes) minutes = 0;
625 if(!seconds) seconds = 0;
627 var d = new Date(year, month - 1, day, hours, minutes, seconds);
629 _debug('created date with ' +
630 (d.getYear() + 1900) +'-'+
631 (d.getMonth() + 1) +'-'+
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) ) {
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;
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; }
669 for( var i = 0; i < keys.length; i++ ) {
671 while( key.length < 12 ) key += ' ';
672 var val = obj[keys[i]]();
673 if( typeof val == 'object' ) {
677 _debug(key+' = ' +val);
681 _debug("---------------------");
685 function getTableRows(tbody) {
687 if(!tbody) return rows;
689 var children = tbody.childNodes;
690 if(!children) return rows;
692 for(var i = 0; i < children.length; i++) {
693 var child = children[i];
694 if(child.nodeName.match(/^tr$/i))
700 function getObjectKeys(obj) {
706 /* Export some constants ----------------------------------------------------- */
708 var SHOW_MR_DEFAULT = false; /* true if we show metarecords by default */
710 //var DO_AUTHORITY_LOOKUPS = false;
711 var DO_AUTHORITY_LOOKUPS = true;
713 var STAFF_WEB_BASE_PATH = '/eg'; // root of the web-based staff interfaces
715 /* URL param names */
716 var PARAM_TERM = "t"; /* search term */
717 var PARAM_FACET = "ft"; /* facet term */
718 var PARAM_STYPE = "tp"; /* search type */
719 var PARAM_LOCATION = "l"; /* current location */
720 var PARAM_LASSO = "sg"; /* current location */
721 var PARAM_DEPTH = "d"; /* search depth */
722 var PARAM_FORM = "f"; /* search format */
723 var PARAM_OFFSET = "o"; /* search offset */
724 var PARAM_COUNT = "c"; /* hits per page */
725 var PARAM_HITCOUNT = "hc"; /* hits per page */
726 var PARAM_MRID = "m"; /* metarecord id */
727 var PARAM_RID = "r"; /* record id */
728 var PARAM_RLIST = "rl";
729 var PARAM_ORIGLOC = "ol"; /* the original location */
730 var PARAM_AUTHTIME = "at"; /* inactivity timeout in seconds */
731 var PARAM_ADVTERM = "adv"; /* advanced search term */
732 var PARAM_ADVTYPE = "adt"; /* the advanced search type */
733 var PARAM_RTYPE = "rt";
734 var PARAM_SORT = "s";
735 var PARAM_SORT_DIR = "sd";
736 var PARAM_DEBUG = "dbg";
738 var PARAM_LITFORM = 'lf';
739 var PARAM_ITEMFORM = 'if';
740 var PARAM_ITEMTYPE = 'it';
741 var PARAM_BIBLEVEL = 'bl';
742 var PARAM_AUDIENCE = 'a';
743 var PARAM_SEARCHES = 'ss';
744 var PARAM_LANGUAGE = 'la';
745 var PARAM_TFORM = 'tf'; /* temporary format for title result pages */
746 var PARAM_RDEPTH = 'rd';
747 var PARAM_REDIR = 're'; /* true if we have been redirected by IP (we're at a real lib) */
748 var PARAM_AVAIL = 'av'; /* limit search results to available items */
749 var PARAM_COPYLOCS = 'cl'; // copy (shelving) locations
750 var PARAM_PUBD_BEFORE = 'pdb';
751 var PARAM_PUBD_AFTER = 'pda';
752 var PARAM_PUBD_BETWEEN = 'pdt';
753 var PARAM_PUBD_DURING = 'pdd';
754 var PARAM_NOPERSIST_SEARCH = 'nps';
756 /* URL param values (see comments above) */
802 var COOKIE_SB = "sbe";
803 var COOKIE_SES = "ses";
804 //var COOKIE_IDS = "ids"; /* list of mrecord ids */
805 //var COOKIE_SRIDS = "srids"; /* record ids cached from a search */
806 var COOKIE_FONT = "fnt";
807 var COOKIE_SKIN = "skin";
808 var COOKIE_RIDS = "rids"; /* list of record ids */
809 var COOKIE_SEARCH = 'sr';
812 var MRESULT = "mresult";
813 var RRESULT = "rresult";
814 var RDETAIL = "rdetail";
815 var MYOPAC = "myopac";
816 var ADVANCED = "advanced";
819 var REQITEMS = "reqitems";
820 var CNBROWSE = "cnbrowse";
822 /* search type (STYPE) options */
823 var STYPE_AUTHOR = "author";
824 var STYPE_TITLE = "title";
825 var STYPE_SUBJECT = "subject";
826 var STYPE_SERIES = "series";
827 var STYPE_KEYWORD = "keyword";
829 /* record-level search types */
830 var RTYPE_MRID = "mrid";
831 var RTYPE_COOKIE = "cookie";
832 var RTYPE_AUTHOR = STYPE_AUTHOR;
833 var RTYPE_SUBJECT = STYPE_SUBJECT;
834 var RTYPE_TITLE = STYPE_TITLE;
835 var RTYPE_SERIES = STYPE_SERIES;
836 var RTYPE_KEYWORD = STYPE_KEYWORD;
837 var RTYPE_LIST = "list";
838 var RTYPE_MULTI = 'multi';
839 var RTYPE_MARC = 'marc';
840 var RTYPE_ISBN = 'isbn';
841 var RTYPE_ISSN = 'issn';
842 var RTYPE_TCN = 'tcn';
844 var SORT_TYPE_REL = "rel";
845 var SORT_TYPE_AUTHOR = STYPE_AUTHOR;
846 var SORT_TYPE_TITLE = STYPE_TITLE;
847 var SORT_TYPE_PUBDATE = "pubdate";
848 var SORT_DIR_ASC = "asc";
849 var SORT_DIR_DESC = "desc";
851 /* types of advanced search */
852 var ADVTYPE_MULTI = 'ml';
853 var ADVTYPE_MARC = 'ma';
856 var ADVTYPE_ISBN = 'isbn';
857 var ADVTYPE_ISSN = 'issn';
860 var LOGOUT_WARNING_TIME = 30; /* "head up" for session timeout */
862 /* user preferences */
863 var PREF_HITS_PER = 'opac.hits_per_page';
864 var PREF_DEF_FONT = 'opac.default_font';
865 var PREF_HOLD_NOTIFY = 'opac.hold_notify';
866 var PREF_DEF_LOCATION = 'opac.default_search_location';
867 var PREF_DEF_DEPTH = 'opac.default_search_depth';
870 /** If enabled, added content attribution links will be
871 made visible where appropriate. The added content vendor name
872 and URL are defined in the entities in opac.dtd
874 var ENABLE_ADDED_CONTENT_ATTRIB_LINKS = false;
877 /* container for global variables shared accross pages */
879 G.user = null; /* global user object */
880 G.ui = {} /* cache of UI components */
884 var REGEX_BARCODE = /^\d+/; /* starts with a number */
885 var REGEX_PHONE = /^\d{3}-\d{3}-\d{4}$/; /* 111-222-3333 */
888 /* call me after page init and I will load references
889 to all of the ui object id's defined below
890 They will be stored in G.ui.<page>.<thingy>
892 function loadUIObjects() {
893 for( var p in config.ids ) {
895 for( var o in config.ids[p] )
896 G.ui[p][o] = getId(config.ids[p][o]);
900 /* try our best to free memory */
901 function clearUIObjects() {
902 for( var p in config.ids ) {
903 for( var o in config.ids[p] ) {
905 G.ui[p][o].onclick = null;
906 G.ui[p][o].onkeydown = null;
914 /* ----------------------------------------------------------------------------
915 Set up ID's and CSS classes
916 Any new ids, css, etc. may be added by giving the unique names and putting
917 them into the correct scope
918 /* ---------------------------------------------------------------------------- */
922 /* Set up the page names */
924 config.page[HOME] = "index.xml";
925 config.page[ADVANCED] = "advanced.xml";
926 config.page[MRESULT] = "mresult.xml";
927 config.page[RRESULT] = "rresult.xml";
928 config.page[MYOPAC] = "myopac.xml";
929 config.page[RDETAIL] = "rdetail.xml";
930 config.page[BBAGS] = "bbags.xml";
931 config.page[REQITEMS] = "reqitems.xml";
932 config.page[CNBROWSE] = "cnbrowse.xml";
939 config.images.logo = "main_logo.jpg";
942 /* set up ID's, CSS, and node names */
944 config.ids.result = {};
945 config.ids.mresult = {};
946 config.ids.advanced = {};
947 config.ids.rresult = {};
948 config.ids.myopac = {};
949 config.ids.rdetail = {};
952 config.css.result = {};
953 config.css.mresult = {};
954 config.css.advanced = {};
955 config.css.rresult = {};
956 config.css.myopac = {};
957 config.css.rdetail = {};
960 config.names.result = {};
961 config.names.mresult = {};
962 config.names.advanced = {};
963 config.names.rresult = {};
964 config.names.myopac = {};
965 config.names.rdetail = {};
968 /* id's shared accross skins. These *must* be defined */
969 config.ids.common = {};
970 config.ids.common.loading = "loading_div";
971 config.ids.common.canvas = "canvas";
972 config.ids.common.canvas_main = "canvas_main";
973 config.ids.common.org_tree = "org_tree";
974 config.ids.common.org_container = "org_container";
980 config.css.hide_me = "hide_me";
981 config.css.dim = "dim";
982 config.css.dim2 = "dim2";
985 /* ---------------------------------------------------------------------------- */
986 /* These are pages that may replace the canvas */
987 /* ---------------------------------------------------------------------------- */
988 config.ids.altcanvas = {};
992 /* ---------------------------------------------------------------------------- */
993 /* Methods are defined as service:method
994 An optional 3rd component is when a method is followed by a :1, such methods
995 have a staff counterpart and should have ".staff" appended to the method
996 before the method is called when in XUL mode */
998 var SEARCH_MRS = 'open-ils.search:open-ils.search.metabib.multiclass:1';
999 var SEARCH_RS = 'open-ils.search:open-ils.search.biblio.multiclass:1';
1000 var SEARCH_MRS_QUERY = 'open-ils.search:open-ils.search.metabib.multiclass.query:1';
1001 var SEARCH_RS_QUERY = 'open-ils.search:open-ils.search.biblio.multiclass.query:1';
1002 var FETCH_SEARCH_RIDS = "open-ils.search:open-ils.search.biblio.record.class.search:1";
1003 var CREATE_MFHD_RECORD = "open-ils.cat:open-ils.cat.serial.record.xml.create";
1004 var DELETE_MFHD_RECORD = "open-ils.cat:open-ils.cat.serial.record.delete";
1005 var FETCH_MFHD_SUMMARY = "open-ils.search:open-ils.search.serial.record.bib.retrieve";
1006 var FETCH_MRMODS = "open-ils.search:open-ils.search.biblio.metarecord.mods_slim.retrieve";
1007 var FETCH_MODS_FROM_COPY = "open-ils.search:open-ils.search.biblio.mods_from_copy";
1008 var FETCH_MR_COPY_COUNTS = "open-ils.search:open-ils.search.biblio.metarecord.copy_count:1";
1009 var FETCH_RIDS = "open-ils.search:open-ils.search.biblio.metarecord_to_records:1";
1010 var FETCH_RMODS = "open-ils.search:open-ils.search.biblio.record.mods_slim.retrieve";
1011 var FETCH_R_COPY_COUNTS = "open-ils.search:open-ils.search.biblio.record.copy_count:1";
1012 var FETCH_FLESHED_USER = "open-ils.actor:open-ils.actor.user.fleshed.retrieve";
1013 var FETCH_SESSION = "open-ils.auth:open-ils.auth.session.retrieve";
1014 var LOGIN_INIT = "open-ils.auth:open-ils.auth.authenticate.init";
1015 var LOGIN_COMPLETE = "open-ils.auth:open-ils.auth.authenticate.complete";
1016 var LOGIN_DELETE = "open-ils.auth:open-ils.auth.session.delete";
1017 var FETCH_USER_PREFS = "open-ils.actor:open-ils.actor.patron.settings.retrieve";
1018 var UPDATE_USER_PREFS = "open-ils.actor:open-ils.actor.patron.settings.update";
1019 var FETCH_COPY_STATUSES = "open-ils.search:open-ils.search.config.copy_status.retrieve.all";
1020 var FETCH_COPY_LOCATION_COUNTS_SUMMARY = "open-ils.search:open-ils.search.biblio.copy_location_counts.summary.retrieve";
1021 var FETCH_COPY_COUNTS_SUMMARY = "open-ils.search:open-ils.search.biblio.copy_counts.summary.retrieve";
1022 //var FETCH_COPY_COUNTS_SUMMARY = "open-ils.search:open-ils.search.biblio.copy_counts.location.summary.retrieve";
1023 var FETCH_MARC_HTML = "open-ils.search:open-ils.search.biblio.record.html";
1024 var FETCH_CHECKED_OUT_SUM = "open-ils.actor:open-ils.actor.user.checked_out";
1025 var FETCH_HOLDS = "open-ils.circ:open-ils.circ.holds.retrieve";
1026 var FETCH_FINES_SUMMARY = "open-ils.actor:open-ils.actor.user.fines.summary";
1027 var FETCH_TRANSACTIONS = "open-ils.actor:open-ils.actor.user.transactions.have_charge.fleshed";
1028 var FETCH_MONEY_BILLING = 'open-ils.circ:open-ils.circ.money.billing.retrieve.all';
1029 var FETCH_CROSSREF = "open-ils.search:open-ils.search.authority.crossref";
1030 var FETCH_CROSSREF_BATCH = "open-ils.search:open-ils.search.authority.crossref.batch";
1031 var CREATE_HOLD = "open-ils.circ:open-ils.circ.holds.create";
1032 var CREATE_HOLD_OVERRIDE = "open-ils.circ:open-ils.circ.holds.create.override";
1033 var CANCEL_HOLD = "open-ils.circ:open-ils.circ.hold.cancel";
1034 var UPDATE_USERNAME = "open-ils.actor:open-ils.actor.user.username.update";
1035 var UPDATE_PASSWORD = "open-ils.actor:open-ils.actor.user.password.update";
1036 var UPDATE_EMAIL = "open-ils.actor:open-ils.actor.user.email.update";
1037 var RENEW_CIRC = "open-ils.circ:open-ils.circ.renew";
1038 var CHECK_SPELL = "open-ils.search:open-ils.search.spellcheck";
1039 var FETCH_REVIEWS = "open-ils.search:open-ils.search.added_content.review.retrieve.all";
1040 var FETCH_TOC = "open-ils.search:open-ils.search.added_content.toc.retrieve";
1041 var FETCH_ACONT_SUMMARY = "open-ils.search:open-ils.search.added_content.summary.retrieve";
1042 var FETCH_USER_BYBARCODE = "open-ils.actor:open-ils.actor.user.fleshed.retrieve_by_barcode";
1043 var FETCH_ADV_MARC_MRIDS = "open-ils.search:open-ils.search.biblio.marc:1";
1044 var FETCH_ADV_ISBN_RIDS = "open-ils.search:open-ils.search.biblio.isbn";
1045 var FETCH_ADV_ISSN_RIDS = "open-ils.search:open-ils.search.biblio.issn";
1046 var FETCH_ADV_TCN_RIDS = "open-ils.search:open-ils.search.biblio.tcn";
1047 var FETCH_CNBROWSE = 'open-ils.search:open-ils.search.callnumber.browse';
1048 var FETCH_CONTAINERS = 'open-ils.actor:open-ils.actor.container.retrieve_by_class';
1049 var FETCH_CONTAINERS = 'open-ils.actor:open-ils.actor.container.retrieve_by_class';
1050 var CREATE_CONTAINER = 'open-ils.actor:open-ils.actor.container.create';
1051 var DELETE_CONTAINER = 'open-ils.actor:open-ils.actor.container.full_delete';
1052 var CREATE_CONTAINER_ITEM = 'open-ils.actor:open-ils.actor.container.item.create';
1053 var DELETE_CONTAINER_ITEM = 'open-ils.actor:open-ils.actor.container.item.delete';
1054 var FLESH_CONTAINER = 'open-ils.actor:open-ils.actor.container.flesh';
1055 var FLESH_PUBLIC_CONTAINER = 'open-ils.actor:open-ils.actor.container.public.flesh';
1056 var UPDATE_CONTAINER = 'open-ils.actor:open-ils.actor.container.update';
1057 var FETCH_COPY = 'open-ils.search:open-ils.search.asset.copy.retrieve';
1058 var FETCH_FLESHED_COPY = 'open-ils.search:open-ils.search.asset.copy.fleshed2.retrieve';
1059 var CHECK_HOLD_POSSIBLE = 'open-ils.circ:open-ils.circ.title_hold.is_possible';
1060 var UPDATE_HOLD = 'open-ils.circ:open-ils.circ.hold.update';
1061 var FETCH_COPIES_FROM_VOLUME = 'open-ils.search:open-ils.search.asset.copy.retrieve_by_cn_label:1';
1062 var FETCH_VOLUME_BY_INFO = 'open-ils.search:open-ils.search.call_number.retrieve_by_info'; /* XXX staff method? */
1063 var FETCH_VOLUME = 'open-ils.search:open-ils.search.asset.call_number.retrieve';
1064 var FETCH_ISSUANCE = 'open-ils.serial:open-ils.serial.issuance.pub_fleshed.batch.retrieve';
1065 var FETCH_COPY_LOCATIONS = 'open-ils.circ:open-ils.circ.copy_location.retrieve.all';
1066 var FETCH_COPY_NOTES = 'open-ils.circ:open-ils.circ.copy_note.retrieve.all';
1067 var FETCH_COPY_STAT_CATS = 'open-ils.circ:open-ils.circ.asset.stat_cat_entries.fleshed.retrieve_by_copy';
1068 var FETCH_LIT_FORMS = 'open-ils.search:open-ils.search.biblio.lit_form_map.retrieve.all';
1069 var FETCH_ITEM_FORMS = 'open-ils.search:open-ils.search.biblio.item_form_map.retrieve.all';
1070 var FETCH_ITEM_TYPES = 'open-ils.search:open-ils.search.biblio.item_type_map.retrieve.all';
1071 var FETCH_BIB_LEVELS = 'open-ils.search:open-ils.search.biblio.bib_level_map.retrieve.all';
1072 var FETCH_AUDIENCES = 'open-ils.search:open-ils.search.biblio.audience_map.retrieve.all';
1073 //var FETCH_HOLD_STATUS = 'open-ils.circ:open-ils.circ.hold.status.retrieve';
1074 var FETCH_HOLD_STATUS = 'open-ils.circ:open-ils.circ.hold.queue_stats.retrieve';
1075 var FETCH_NON_CAT_CIRCS = 'open-ils.circ:open-ils.circ.open_non_cataloged_circulation.user';
1076 var FETCH_NON_CAT_CIRC = 'open-ils.circ:open-ils.circ.non_cataloged_circulation.retrieve';
1077 var FETCH_NON_CAT_TYPES = "open-ils.circ:open-ils.circ.non_cat_types.retrieve.all";
1078 var FETCH_BRE = 'open-ils.search:open-ils.search.biblio.record_entry.slim.retrieve';
1079 var CHECK_USERNAME = 'open-ils.actor:open-ils.actor.username.exists';
1080 var FETCH_CIRC_BY_ID = 'open-ils.circ:open-ils.circ.retrieve';
1081 var FETCH_MR_DESCRIPTORS = 'open-ils.search:open-ils.search.metabib.record_to_descriptors';
1082 var FETCH_HIGHEST_PERM_ORG = 'open-ils.actor:open-ils.actor.user.perm.highest_org.batch';
1083 var FETCH_USER_NOTES = 'open-ils.actor:open-ils.actor.note.retrieve.all';
1084 var FETCH_ORG_BY_SHORTNAME = 'open-ils.actor:open-ils.actor.org_unit.retrieve_by_shortname';
1085 var FETCH_BIB_ID_BY_BARCODE = 'open-ils.search:open-ils.search.bib_id.by_barcode';
1086 var FETCH_ORG_SETTING = 'open-ils.actor:open-ils.actor.ou_setting.ancestor_default';
1088 /* ---------------------------------------------------------------------------- */
1091 /* ---------------------------------------------------------------------------- */
1092 /* event callback functions. Other functions may be appended to these vars to
1093 for added functionality. */
1095 G.evt = {}; /* events container */
1097 function runEvt(scope, name, a, b, c, d, e, f, g) {
1098 var evt = G.evt[scope][name];
1099 for( var i in evt ) {
1100 evt[i](a, b, c, d, e, f, g);
1104 /* creates a new event if it doesn't already exist */
1105 function createEvt(scope, name) {
1106 if(!G.evt[scope]) G.evt[scope] = {};
1107 if(G.evt[scope][name] == null)
1108 G.evt[scope][name] = [];
1111 function attachEvt(scope, name, action) {
1112 createEvt(scope, name);
1113 G.evt[scope][name].push(action);
1116 function detachAllEvt(scope, name) {
1117 G.evt[scope][name] = [];
1121 createEvt("common", "init"); /* f() : what happens on page init */
1122 createEvt("common", "pageRendered"); /* f() : what happens when the page is done (up to the skin to call this even)*/
1123 createEvt("common", "unload"); /* f() : what happens on window unload (clean memory, etc.)*/
1124 createEvt("common", "locationChanged"); /* f() : what happens when the location has changed */
1125 createEvt("common", "locationUpdated"); /* f() : what happens when the location has updated by the code */
1127 createEvt("common", "run"); /* f() : make the page do stuff */
1128 createEvt("result", "idsReceived"); /* f(ids) */
1129 createEvt("rresult", "recordDrawn"); /* f(recordid, linkDOMNode) : after record is drawn, allow others (xul) to plugin actions */
1130 createEvt("result", "preCollectRecords"); /* f() we're about to go and grab the recs */
1132 createEvt("result", "hitCountReceived"); /* f() : display hit info, pagination, etc. */
1133 createEvt("result", "recordReceived"); /* f(mvr, pagePosition, isMr) : display the record*/
1134 createEvt("result", "recordDrawn"); /* f(recordid, linkDOMNode) : after record is drawn, allow others (xul) to plugin actions */
1135 createEvt("result", "copyCountsReceived"); /* f(mvr, pagePosition, copyCountInfo) : display copy counts*/
1136 createEvt("result", "allRecordsReceived"); /* f(mvrsArray) : add other page stuff, sidebars, etc.*/
1138 createEvt("rdetail", "recordDrawn"); /* f() : the record has been drawn */
1140 createEvt("common", "loggedIn"); /* f() : user has just logged in */
1141 createEvt('result', 'zeroHits');
1142 createEvt('result', 'lowHits');
1143 createEvt('rdetail', 'recordRetrieved'); /* we are about to draw the rdetail page */
1144 createEvt('common', 'depthChanged');
1145 createEvt('common', 'holdUpdated');
1146 createEvt('common', 'holdUpdateCanceled');
1148 createEvt('rdetail', 'nextPrevDrawn');
1155 /* load up the url parameters */
1157 this._keys = new Array();
1158 this.data = new Object();
1160 var string = location.search.replace(/^\?/,"");
1161 this.server_name = location.href.replace(/^https?:\/\/([^\/]+).+$/,"$1");
1166 var invalue = false;
1168 for( var idx = 0; idx!= string.length; idx++ ) {
1170 var c = string.charAt(idx);
1178 if(c == "&" || c == ";") {
1181 if( ! this.data[key] ) this.data[key] = [];
1182 this.data[key].push(decodeURIComponent(value));
1183 this._keys.push(key);
1184 key = ""; value = "";
1189 else if(invalue) value += c;
1192 if( ! this.data[key] ) this.data[key] = [];
1193 this.data[key].push(decodeURIComponent(value));
1194 this._keys.push(key);
1197 /* returns the value for the given param. If there is only one value for the
1198 given param, it returns that value. Otherwise it returns an array of values
1200 CGI.prototype.param = function(p) {
1201 if(this.data[p] == null) return null;
1202 if(this.data[p].length == 1)
1203 return this.data[p][0];
1204 return this.data[p];
1207 /* returns an array of param names */
1208 CGI.prototype.keys = function() {
1212 /* debuggin method */
1213 CGI.prototype.toString = function() {
1215 var keys = this.keys();
1217 for( var k in keys ) {
1218 string += keys[k] + " : ";
1219 var params = this.param(keys[k]);
1221 for( var p in params ) {
1222 string += params[p] + " ";
1230 // HTTP.Cookies - Burak Gürsoy <burak[at]cpan[dot]org>
1233 I removed all the docs (except author and license info) to reduce download size
1234 -bill erickson <billserickson@gmail.com>
1237 if (!HTTP) var HTTP = {}; // create base class if undefined
1239 HTTP.Cookies = function () { // HTTP.Cookies constructor
1240 this.JAR = ''; // data cache
1243 HTTP.Cookies.VERSION = '1.01';
1245 HTTP.Cookies.Date = function () { // expire time calculation class
1251 'M' : 60 * 60 * 24 * 30,
1252 'y' : 60 * 60 * 24 * 365
1256 HTTP.Cookies.Date.prototype.parse = function (x) {
1257 if(!x || x == 'now') return 0;
1258 var date = x.match(/^(.+?)(\w)$/i);
1260 return (this.is_num(date[1]) && (of = this.is_date(date[1],date[2]))) ? of : 0;
1263 HTTP.Cookies.Date.prototype.is_date = function (num, x) {
1264 if (!x || x.length != 1) return 0;
1266 return (ar = x.match(/^(s|m|h|d|w|M|y)$/) ) ? num * 1000 * this.format[ar[0]] : 0;
1269 HTTP.Cookies.Date.prototype.is_num = function (x) {
1270 if (x.length == 0) return;
1272 for (var i = 0; i < x.length; i++) {
1273 if ("0123456789.-+".indexOf(x.charAt(i)) == -1) {
1281 HTTP.Cookies.prototype.date = new HTTP.Cookies.Date; // date object instance
1283 // Get the value of the named cookie. Usage: password = cookie.read('password');
1284 HTTP.Cookies.prototype.read = function (name) {
1288 var array = document.cookie.split(';');
1289 for (var x = 0; x < array.length; x++) {
1290 var pair = array[x].split('=');
1291 if(pair[0].substring (0,1) == ' ') pair[0] = pair[0].substring(1, pair[0].length);
1292 if(pair[0] == name) {
1295 this.JAR[pair[0]] = pair[1];
1298 for(var cookie in this.JAR) {
1299 if(cookie == name) {
1300 value = this.JAR[cookie];
1304 return value ? unescape(value) : '';
1307 // Create a new cookie or overwrite existing. Usage: cookie.write('password', 'secret', '1m');
1308 HTTP.Cookies.prototype.write = function (name, value, expires, path, domain, secure) {
1310 if (!expires) expires = '';
1311 if (expires == '_epoch') {
1312 expires = new Date(0);
1313 } else if (expires != -1) {
1315 Now.setTime(Now.getTime() + this.date.parse(expires));
1316 expires = Now.toGMTString();
1318 if(expires != -1 && expires) extra += "; expires=" + expires;
1319 if(path ) extra += "; path=" + path;
1320 if(domain ) extra += "; domain=" + domain;
1321 if(secure ) extra += "; secure=" + secure;
1322 document.cookie = name + "=" + escape(value) + extra;
1325 // Delete the named cookie. Usage: cookie.remove('password');
1326 HTTP.Cookies.prototype.remove = function (name, path, domain, secure) {
1327 this.write(name, '', '_epoch', path, domain, secure);
1334 HTTP.Cookies - JavaScript class for reading, writing and deleting cookies
1338 Burak Gürsoy, E<lt>burakE<64>cpan.orgE<gt>
1342 Copyright 2005 Burak Gürsoy. All rights reserved.
1346 This library is free software; you can redistribute it and/or modify
1347 it under the terms of the "Artistic License":
1348 L<http://dev.perl.org/licenses/artistic.html>.
1354 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
1355 * Digest Algorithm, as defined in RFC 1321.
1356 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
1357 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
1358 * Distributed under the BSD License
1359 * See http://pajhome.org.uk/crypt/md5 for more info.
1362 var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
1363 var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
1364 var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
1365 function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
1366 function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
1367 function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
1368 function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
1369 function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
1370 function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
1371 function md5_vm_test()
1373 return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
1375 function core_md5(x, len)
1377 /* append padding */
1378 x[len >> 5] |= 0x80 << ((len) % 32);
1379 x[(((len + 64) >>> 9) << 4) + 14] = len;
1383 var c = -1732584194;
1386 for(var i = 0; i < x.length; i += 16)
1393 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
1394 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
1395 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
1396 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
1397 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
1398 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
1399 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
1400 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
1401 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
1402 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
1403 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
1404 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
1405 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
1406 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
1407 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
1408 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
1410 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
1411 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
1412 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
1413 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
1414 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
1415 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
1416 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
1417 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
1418 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
1419 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
1420 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
1421 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
1422 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
1423 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
1424 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
1425 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
1427 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
1428 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
1429 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
1430 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
1431 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
1432 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
1433 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
1434 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
1435 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
1436 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
1437 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
1438 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
1439 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
1440 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
1441 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
1442 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
1444 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
1445 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
1446 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
1447 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
1448 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
1449 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
1450 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
1451 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
1452 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
1453 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
1454 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
1455 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
1456 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
1457 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
1458 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
1459 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
1461 a = safe_add(a, olda);
1462 b = safe_add(b, oldb);
1463 c = safe_add(c, oldc);
1464 d = safe_add(d, oldd);
1466 return Array(a, b, c, d);
1469 function md5_cmn(q, a, b, x, s, t)
1471 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
1473 function md5_ff(a, b, c, d, x, s, t)
1475 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
1477 function md5_gg(a, b, c, d, x, s, t)
1479 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
1481 function md5_hh(a, b, c, d, x, s, t)
1483 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
1485 function md5_ii(a, b, c, d, x, s, t)
1487 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
1489 function core_hmac_md5(key, data)
1491 var bkey = str2binl(key);
1492 if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
1494 var ipad = Array(16), opad = Array(16);
1495 for(var i = 0; i < 16; i++)
1497 ipad[i] = bkey[i] ^ 0x36363636;
1498 opad[i] = bkey[i] ^ 0x5C5C5C5C;
1501 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
1502 return core_md5(opad.concat(hash), 512 + 128);
1504 function safe_add(x, y)
1506 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
1507 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
1508 return (msw << 16) | (lsw & 0xFFFF);
1510 function bit_rol(num, cnt)
1512 return (num << cnt) | (num >>> (32 - cnt));
1514 function str2binl(str)
1517 var mask = (1 << chrsz) - 1;
1518 for(var i = 0; i < str.length * chrsz; i += chrsz)
1519 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
1522 function binl2str(bin)
1525 var mask = (1 << chrsz) - 1;
1526 for(var i = 0; i < bin.length * 32; i += chrsz)
1527 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
1530 function binl2hex(binarray)
1532 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
1534 for(var i = 0; i < binarray.length * 4; i++)
1536 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
1537 hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
1541 function binl2b64(binarray)
1543 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1545 for(var i = 0; i < binarray.length * 4; i += 3)
1547 var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
1548 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
1549 | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
1550 for(var j = 0; j < 4; j++)
1552 if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
1553 else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
1559 var stpicopen = '../../../../images/slimtree/folder.gif';
1560 var stpicclose = '../../../../images/slimtree/folderopen.gif';
1562 var stpicopen = '../../../../images/slimtree/folder2.gif';
1563 var stpicclose = '../../../../images/slimtree/folderopen2.gif';
1564 var stpicblank = '../../../../images/slimtree/page.gif';
1565 var stpicline = '../../../../images/slimtree/line.gif';
1566 var stpicjoin = '../../../../images/slimtree/join.gif';
1567 var stpicjoinb = '../../../../images/slimtree/joinbottom.gif';
1575 function _apc(root,node) { root.appendChild(node); }
1577 function SlimTree(context, handle, rootimg) {
1580 stimgopen = elem('img',{src:stpicopen,border:0, style:'height:13px;width:31px;'});
1581 stimgclose = elem('img',{src:stpicclose,border:0, style:'height:13px;width:31px;'});
1582 stimgblank = elem('img',{src:stpicblank,border:0, style:'height:18px;width:18px;'});
1583 stimgline = elem('img',{src:stpicline,border:0, style:'height:18px;width:18px;'});
1584 stimgjoin = elem('img',{src:stpicjoin,border:0, style:'display:inline;height:18px;width:18px;'});
1587 this.context = context;
1588 this.handle = handle;
1589 this.cache = new Object();
1591 this.rootimg = elem('img',
1592 {src:rootimg,border:0,style:'padding-right: 4px;'});
1595 SlimTree.prototype.addCachedChildren = function(pid) {
1597 while( child = this.cache[pid].shift() )
1598 this.addNode( child.id, child.pid,
1599 child.name, child.action, child.title );
1600 this.cache[pid] = null;
1603 SlimTree.prototype.addNode = function( id, pid, name, action, title, cls ) {
1605 if( pid != -1 && !$(pid)) {
1606 if(!this.cache[pid]) this.cache[pid] = new Array();
1607 this.cache[pid].push(
1608 {id:id,pid:pid,name:name,action:action,title:title });
1613 action='javascript:'+this.handle+'.toggle("'+id+'");';
1616 if( typeof action == 'string' )
1617 actionref = elem('a',{href:action}, name);
1619 actionref = elem('a',{href:'javascript:void(0);'}, name);
1620 actionref.onclick = action;
1623 var div = elem('div',{id:id});
1624 var topdiv = elem('div',{style:'vertical-align:middle'});
1625 var link = elem('a', {id:'stlink_' + id});
1626 var contdiv = elem('div',{id:'stcont_' + id});
1628 if(cls) addCSSClass(actionref, cls);
1630 //actionref.setAttribute('href',action);
1631 if(title) actionref.setAttribute('title',title);
1632 else actionref.setAttribute('title',name);
1635 _apc(topdiv,actionref);
1642 _apc(this.context,div);
1643 if(this.rootimg) _apc(link,this.rootimg.cloneNode(true));
1644 else _apc(link,stimgblank.cloneNode(true));
1648 if(pid == this.rootid) this.open(pid);
1649 else this.close(pid);
1650 $(pid).setAttribute('haschild','1');
1651 _apc(link,stimgblank.cloneNode(true));
1652 div.style.paddingLeft = '18px';
1653 div.style.backgroundImage = 'url('+stpicjoinb+')';
1654 div.style.backgroundRepeat = 'no-repeat';
1655 _apc($('stcont_' + pid), div);
1656 if (div.previousSibling) stMakePaths(div);
1658 if(this.cache[id]) this.addCachedChildren(id);
1661 function stMakePaths(div) {
1662 _apc(div.previousSibling.firstChild,stimgjoin.cloneNode(true));
1663 _apc(div.previousSibling.firstChild,div.previousSibling.firstChild.firstChild);
1664 _apc(div.previousSibling.firstChild,div.previousSibling.firstChild.firstChild);
1665 div.previousSibling.firstChild.firstChild.style.marginLeft = '-18px';
1666 div.previousSibling.style.backgroundImage = 'url('+stpicline+')';
1667 div.previousSibling.style.backgroundRepeat = 'repeat-y';
1670 SlimTree.prototype.expandAll = function() { this.flex(this.rootid, 'open'); }
1671 SlimTree.prototype.closeAll = function() { this.flex(this.rootid,'close'); }
1672 SlimTree.prototype.flex = function(id, type) {
1673 if(type=='open') this.open(id);
1674 else { if (id != this.rootid) this.close(id); }
1675 var n = $('stcont_' + id);
1676 for( var c = 0; c != n.childNodes.length; c++ ) {
1677 var ch = n.childNodes[c];
1678 if(ch.nodeName.toLowerCase() == 'div') {
1679 if($(ch.id).getAttribute('haschild') == '1')
1680 this.flex(ch.id, type);
1685 SlimTree.prototype.toggle = function(id) {
1686 if($(id).getAttribute('ostate') == '1') this.open(id);
1687 else if($(id).getAttribute('ostate') == '2') this.close(id);
1690 SlimTree.prototype.open = function(id) {
1691 if($(id).getAttribute('ostate') == '2') return;
1692 var link = $('stlink_' + id);
1694 if(id != this.rootid || !this.rootimg) {
1695 removeChildren(link);
1696 _apc(link,stimgclose.cloneNode(true));
1698 link.setAttribute('href','javascript:' + this.handle + '.close("'+id+'");');
1699 unHideMe($('stcont_' + id));
1700 $(id).setAttribute('ostate','2');
1703 SlimTree.prototype.close = function(id) {
1704 var link = $('stlink_' + id);
1706 if(id != this.rootid || !this.rootimg) {
1707 removeChildren(link);
1708 _apc(link,stimgopen.cloneNode(true));
1710 link.setAttribute('href','javascript:' + this.handle + '.open("'+id+'");');
1711 hideMe($('stcont_' + id));
1712 $(id).setAttribute('ostate','1');
1715 /* - Request ------------------------------------------------------------- */
1718 /* define it again here for pages that don't load RemoteRequest */
1719 function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
1722 var cookieManager = new HTTP.Cookies();
1724 var __ilsEvent; /* the last event the occurred */
1727 function Request(type) {
1729 var s = type.split(":");
1730 if(s[2] == "1" && isXUL()) s[1] += ".staff";
1731 this.request = new RemoteRequest(s[0], s[1]);
1735 if(!location.href.match(/^https:/))
1736 this.request.setSecure(false);
1740 if( G.user && G.user.session ) {
1741 /* if the user is logged in, all activity resets the timeout
1742 This is not entirely accurate in the sense that not all
1743 requests will reset the server timeout - this should
1744 get close enough, however.
1746 var at = getAuthtime();
1747 if(at) new AuthTimer(at).run();
1751 for( var x = 1; x!= arguments.length; x++ ) {
1752 p.push(arguments[x]);
1753 this.request.addParam(arguments[x]);
1758 for( var i = 0; i != p.length; i++ ) {
1759 if( i > 0 ) str += ", "
1760 str += js2JSON(p[i]);
1762 _debug('request ' + s[0] + ' ' + s[1] + ' ' + str );
1764 } else if( DEBUGSLIM ) {
1765 _debug('request ' + s[1]);
1769 Request.prototype.callback = function(cal) {this.request.setCompleteCallback(cal);}
1770 Request.prototype.send = function(block){this.request.send(block);}
1771 Request.prototype.result = function(){return this.request.getResultObject();}
1773 function showCanvas() {
1774 for( var x in G.ui.altcanvas ) {
1775 hideMe(G.ui.altcanvas[x]);
1777 hideMe(G.ui.common.loading);
1778 unHideMe(G.ui.common.canvas_main);
1779 try{G.ui.searchbar.text.focus();}catch(e){}
1782 function swapCanvas(newNode) {
1783 for( var x in G.ui.altcanvas )
1784 hideMe(G.ui.altcanvas[x]);
1786 hideMe(G.ui.common.loading);
1787 hideMe(G.ui.common.canvas_main);
1791 /* finds the name of the current page */
1792 var currentPage = null;
1793 function findCurrentPage() {
1794 if(currentPage) return currentPage;
1797 for( var p in config.page ) pages.push(config.page[p]);
1798 pages = pages.sort( function(a,b){ return - (a.length - b.length); } );
1800 var path = location.pathname;
1801 if(!path.match(/.*\.xml$/))
1802 path += "index.xml"; /* in case they go to / */
1805 for( var p = 0; p < pages.length; p++ ) {
1806 if( path.indexOf(pages[p]) != -1)
1810 for( var p in config.page ) {
1811 if(config.page[p] == page) {
1820 /* sets all of the params values ----------------------------- */
1821 function initParams() {
1822 var cgi = new CGI();
1824 /* handle the location var */
1826 var loc = cgi.param(PARAM_LOCATION);
1827 var lasso = cgi.param(PARAM_LASSO);
1830 lasso = findOrgLasso( lasso );
1831 LASSO = lasso ? lasso.id() : null;
1835 org = findOrgUnit(loc);
1836 LOCATION = org ? org.id() : null;
1839 org = findOrgUnit(loc);
1840 LOCATION = org ? org.id() : null;
1845 loc = cgi.param(PARAM_ORIGLOC);
1847 org = findOrgUnit(loc);
1848 if(!org) org = findOrgUnitSN(loc);
1850 ORIGLOC = (org) ? org.id() : null;
1853 DEPTH = parseInt(cgi.param(PARAM_DEPTH));
1854 if(isNaN(DEPTH)) DEPTH = null;
1857 FACET = cgi.param(PARAM_FACET);
1858 TERM = cgi.param(PARAM_TERM);
1859 STYPE = cgi.param(PARAM_STYPE);
1860 FORM = cgi.param(PARAM_FORM);
1861 //DEPTH = parseInt(cgi.param(PARAM_DEPTH));
1862 OFFSET = parseInt(cgi.param(PARAM_OFFSET));
1863 COUNT = parseInt(cgi.param(PARAM_COUNT));
1864 HITCOUNT = parseInt(cgi.param(PARAM_HITCOUNT));
1865 MRID = parseInt(cgi.param(PARAM_MRID));
1866 RID = parseInt(cgi.param(PARAM_RID));
1867 AUTHTIME = parseInt(cgi.param(PARAM_AUTHTIME));
1868 ADVTERM = cgi.param(PARAM_ADVTERM);
1869 ADVTYPE = cgi.param(PARAM_ADVTYPE);
1870 RTYPE = cgi.param(PARAM_RTYPE);
1871 SORT = cgi.param(PARAM_SORT);
1872 SORT_DIR = cgi.param(PARAM_SORT_DIR);
1873 DEBUG = cgi.param(PARAM_DEBUG);
1874 CALLNUM = cgi.param(PARAM_CN);
1875 LITFORM = cgi.param(PARAM_LITFORM);
1876 ITEMFORM = cgi.param(PARAM_ITEMFORM);
1877 ITEMTYPE = cgi.param(PARAM_ITEMTYPE);
1878 BIBLEVEL = cgi.param(PARAM_BIBLEVEL);
1879 AUDIENCE = cgi.param(PARAM_AUDIENCE);
1880 SEARCHES = cgi.param(PARAM_SEARCHES);
1881 LANGUAGE = cgi.param(PARAM_LANGUAGE);
1882 TFORM = cgi.param(PARAM_TFORM);
1883 RDEPTH = cgi.param(PARAM_RDEPTH);
1884 AVAIL = cgi.param(PARAM_AVAIL);
1885 COPYLOCS = cgi.param(PARAM_COPYLOCS);
1886 PUBD_BEFORE = cgi.param(PARAM_PUBD_BEFORE);
1887 PUBD_AFTER = cgi.param(PARAM_PUBD_AFTER);
1888 PUBD_BETWEEN = cgi.param(PARAM_PUBD_BETWEEN);
1889 PUBD_DURING = cgi.param(PARAM_PUBD_DURING);
1892 /* set up some sane defaults */
1893 //if(isNaN(DEPTH)) DEPTH = 0;
1894 if(isNaN(RDEPTH)) RDEPTH = 0;
1895 if(isNaN(OFFSET)) OFFSET = 0;
1896 if(isNaN(COUNT)) COUNT = 10;
1897 if(isNaN(HITCOUNT)) HITCOUNT = 0;
1898 if(isNaN(MRID)) MRID = 0;
1899 if(isNaN(RID)) RID = 0;
1900 if(isNaN(ORIGLOC)) ORIGLOC = 0; /* so we know it hasn't been set */
1901 if(isNaN(AUTHTIME)) AUTHTIME = 0;
1902 if(ADVTERM==null) ADVTERM = "";
1903 if(isNaN(AVAIL)) AVAIL = 0;
1906 function clearSearchParams() {
1933 PUBD_BETWEEN = null;
1938 function initCookies() {
1939 FONTSIZE = "regular";
1940 var font = cookieManager.read(COOKIE_FONT);
1942 if(font) FONTSIZE = font;
1943 SKIN = cookieManager.read(COOKIE_SKIN);
1944 if(findCurrentPage() == HOME)
1945 cookieManager.remove(COOKIE_SEARCH);
1948 /* URL param accessors */
1949 function getTerm(){return TERM;}
1950 function getFacet(){return FACET;}
1951 function getStype(){return STYPE;}
1952 function getLocation(){return LOCATION;}
1953 function getLasso(){return LASSO;}
1954 function getDepth(){return DEPTH;}
1955 function getForm(){return FORM;}
1956 function getTform(){return TFORM;}
1957 function getOffset(){return OFFSET;}
1958 function getDisplayCount(){return COUNT;}
1959 function getHitCount(){return HITCOUNT;}
1960 function getMrid(){return MRID;};
1961 function getRid(){return RID;};
1962 function getOrigLocation(){return ORIGLOC;}
1963 function getAuthtime() { return AUTHTIME; }
1964 function getSearchBarExtras(){return SBEXTRAS;}
1965 function getFontSize(){return FONTSIZE;};
1966 function getSkin(){return SKIN;};
1967 function getAdvTerm(){return ADVTERM;}
1968 function getAdvType(){return ADVTYPE;}
1969 function getRtype(){return RTYPE;}
1970 function getSort(){return SORT;}
1971 function getSortDir(){return SORT_DIR;}
1972 function getDebug(){return DEBUG;}
1973 function getCallnumber() { return CALLNUM; }
1974 function getLitForm() { return LITFORM; }
1975 function getItemForm() { return ITEMFORM; }
1976 function getItemType() { return ITEMTYPE; }
1977 function getBibLevel() { return BIBLEVEL; }
1978 function getAudience() { return AUDIENCE; }
1979 function getSearches() { return SEARCHES; }
1980 function getLanguage() { return LANGUAGE; }
1981 function getRdepth() { return RDEPTH; }
1982 function getAvail() { return AVAIL; }
1983 function getCopyLocs() { return COPYLOCS; }
1984 function getPubdBefore() { return PUBD_BEFORE; }
1985 function getPubdAfter() { return PUBD_AFTER; }
1986 function getPubdBetween() { return PUBD_BETWEEN; }
1987 function getPubdDuring() { return PUBD_DURING; }
1990 function findBasePath() {
1991 var path = location.pathname;
1992 if(!path.match(/.*\.xml$/)) path += "index.xml";
1993 var idx = path.indexOf(config.page[findCurrentPage()]);
1994 return path.substring(0, idx);
1997 function findBaseURL(ssl) {
1998 var path = findBasePath();
1999 var proto = (ssl) ? "https:" : "http:";
2001 /* strip port numbers. This is necessary for browsers that
2002 send an explicit <host>:80, 443 - explicit ports
2003 break links that need to change ports (e.g. http -> https) */
2004 var h = location.host.replace(/:.*/,'');
2006 return proto + "//" + h + path;
2010 function buildISBNSrc(isbn) {
2011 return "http://" + location.host + "/jackets/" + isbn;
2015 function buildImageLink(name, ssl) {
2016 return findBaseURL(ssl) + "../../../../images/" + name;
2019 function buildExtrasLink(name, ssl) {
2020 return findBaseURL(ssl) + "../../../../extras/" + name;
2024 function _debug(str) {
2025 try { dump('dbg: ' + str + '\n'); } catch(e) {}
2027 /* potentially useful, but usually just annoying */
2030 if(!consoleService) {
2032 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
2033 this.consoleService = Components.classes['@mozilla.org/consoleservice;1']
2034 .getService(Components.interfaces.nsIConsoleService);
2039 if(consoleService) {
2040 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
2041 consoleService.logStringMessage(str + '\n');
2048 var forceLoginSSL; // set via Apache env variable
2049 function buildOPACLink(args, slim, ssl) {
2051 if(!args) args = {};
2054 if( ssl == undefined && (
2055 location.protocol == 'https:' ||
2056 (forceLoginSSL && G.user && G.user.session))) {
2061 string = findBaseURL(ssl);
2062 if(args.page) string += config.page[args.page];
2063 else string += config.page[findCurrentPage()];
2066 /* this may seem unnecessary.. safety precaution for now */
2068 if( args[PARAM_DEPTH] == null )
2069 args[PARAM_DEPTH] = getDepth();
2074 for( var x in args ) {
2076 if(x == "page" || v == null || v == undefined || v+'' == 'NaN' ) continue;
2077 if(x == PARAM_OFFSET && v == 0) continue;
2078 if(x == PARAM_COUNT && v == 10) continue;
2079 if(x == PARAM_FORM && v == 'all' ) continue;
2080 if( instanceOf(v, Array) && v.length ) {
2081 for( var i = 0; i < v.length; i++ ) {
2082 string += "&" + x + "=" + encodeURIComponent(v[i]);
2085 string += "&" + x + "=" + encodeURIComponent(v);
2090 string += _appendParam(DEBUG, PARAM_DEBUG, args, getDebug, string);
2091 if(getOrigLocation() != 1)
2092 string += _appendParam(ORIGLOC, PARAM_ORIGLOC, args, getOrigLocation, string);
2094 string += _appendParam(TERM, PARAM_TERM, args, getTerm, string);
2096 string += _appendParam(FACET, PARAM_FACET, args, getFacet, string);
2098 string += _appendParam(STYPE, PARAM_STYPE, args, getStype, string);
2099 if(getLocation() != 1)
2100 string += _appendParam(LOCATION, PARAM_LOCATION, args, getLocation, string);
2101 if(getLasso() != null)
2102 string += _appendParam(LASSO, PARAM_LASSO, args, getLasso, string);
2103 if(getDepth() != null)
2104 string += _appendParam(DEPTH, PARAM_DEPTH, args, getDepth, string);
2105 if(getForm() && (getForm() != 'all') )
2106 string += _appendParam(FORM, PARAM_FORM, args, getForm, string);
2107 if(getTform() && (getTform() != 'all') )
2108 string += _appendParam(TFORM, PARAM_TFORM, args, getTform, string);
2109 if(getOffset() != 0)
2110 string += _appendParam(OFFSET, PARAM_OFFSET, args, getOffset, string);
2111 if(getDisplayCount() != 10)
2112 string += _appendParam(COUNT, PARAM_COUNT, args, getDisplayCount, string);
2114 string += _appendParam(HITCOUNT, PARAM_HITCOUNT, args, getHitCount, string);
2116 string += _appendParam(MRID, PARAM_MRID, args, getMrid, string);
2118 string += _appendParam(RID, PARAM_RID, args, getRid, string);
2120 string += _appendParam(AUTHTIME, PARAM_AUTHTIME, args, getAuthtime, string);
2122 string += _appendParam(ADVTERM, PARAM_ADVTERM, args, getAdvTerm, string);
2124 string += _appendParam(ADVTYPE, PARAM_ADVTYPE, args, getAdvType, string);
2126 string += _appendParam(RTYPE, PARAM_RTYPE, args, getRtype, string);
2128 string += _appendParam(ITEMFORM, PARAM_ITEMFORM, args, getItemForm, string);
2130 string += _appendParam(ITEMTYPE, PARAM_ITEMTYPE, args, getItemType, string);
2132 string += _appendParam(BIBLEVEL, PARAM_BIBLEVEL, args, getBibLevel, string);
2134 string += _appendParam(LITFORM, PARAM_LITFORM, args, getLitForm, string);
2136 string += _appendParam(AUDIENCE, PARAM_AUDIENCE, args, getAudience, string);
2138 string += _appendParam(SEARCHES, PARAM_SEARCHES, args, getSearches, string);
2140 string += _appendParam(LANGUAGE, PARAM_LANGUAGE, args, getLanguage, string);
2141 if(getRdepth() != null)
2142 string += _appendParam(RDEPTH, PARAM_RDEPTH, args, getRdepth, string);
2143 if(getSort() != null)
2144 string += _appendParam(SORT, PARAM_SORT, args, getSort, string);
2145 if(getSortDir() != null)
2146 string += _appendParam(SORT_DIR, PARAM_SORT_DIR, args, getSortDir, string);
2148 string += _appendParam(AVAIL, PARAM_AVAIL, args, getAvail, string);
2150 string += _appendParam(COPYLOCS, PARAM_COPYLOCS, args, getCopyLocs, string);
2152 string += _appendParam(PUBD_BEFORE, PARAM_PUBD_BEFORE, args, getPubdBefore, string);
2154 string += _appendParam(PUBD_AFTER, PARAM_PUBD_AFTER, args, getPubdAfter, string);
2155 if(getPubdBetween())
2156 string += _appendParam(PUBD_BETWEEN, PARAM_PUBD_BETWEEN, args, getPubdBetween, string);
2158 string += _appendParam(PUBD_DURING, PARAM_PUBD_DURING, args, getPubdDuring, string);
2161 return string.replace(/\&$/,'').replace(/\?\&/,"?");
2165 function _appendParam( fieldVar, fieldName, overrideArgs, getFunc, string ) {
2169 if( fieldVar != null &&
2170 (fieldVar +'' != 'NaN') &&
2171 overrideArgs[fieldName] == null &&
2172 getFunc() != null &&
2173 getFunc()+'' != '' ) {
2175 ret = "&" + fieldName + "=" + encodeURIComponent(getFunc());
2181 /* ----------------------------------------------------------------------- */
2182 function cleanISBN(isbn) {
2184 isbn = isbn.toString().replace(/^\s+/,"");
2185 var idx = isbn.indexOf(" ");
2186 if(idx > -1) { isbn = isbn.substring(0, idx); }
2192 /* builds a link that goes to the title listings for a metarecord */
2193 function buildTitleLink(rec, link) {
2195 link.appendChild(text(normalize(truncate(rec.title(), 65))));
2197 args.page = RRESULT;
2198 args[PARAM_OFFSET] = 0;
2199 args[PARAM_MRID] = rec.doc_id();
2200 args[PARAM_RTYPE] = RTYPE_MRID;
2201 var linkText = link.innerHTML; // IE
2202 link.setAttribute("href", buildOPACLink(args));
2203 link.innerHTML = linkText; // IE
2206 function buildTitleDetailLink(rec, link) {
2208 link.appendChild(text(normalize(truncate(rec.title(), 65))));
2210 args.page = RDETAIL;
2211 args[PARAM_RID] = rec.doc_id();
2212 // in IE, if the link text contains a '@', it replaces the innerHTML text
2213 // with the value of the href attribute. Wait, what? Yes. Capture the
2214 // innerHTML and put it back into place after the href is set
2215 var linkText = link.innerHTML; // IE
2216 link.setAttribute("href", buildOPACLink(args));
2217 link.innerHTML = linkText; // IE
2220 /* 'type' is one of STYPE_AUTHOR, STYPE_SUBJECT, ... found in config.js
2221 'trunc' is the number of characters to show in the string, defaults to 65 */
2222 function buildSearchLink(type, string, linknode, trunc) {
2223 if(!trunc) trunc = 65;
2225 if( SHOW_MR_DEFAULT || findCurrentPage() == MRESULT ) {
2226 args.page = MRESULT;
2228 args.page = RRESULT;
2229 args[PARAM_RTYPE] = type;
2231 args[PARAM_OFFSET] = 0;
2232 args[PARAM_TERM] = string;
2233 args[PARAM_STYPE] = type;
2234 linknode.appendChild(text(normalize(truncate(string, trunc))));
2235 linknode.setAttribute("href", buildOPACLink(args));
2238 function setSessionCookie(ses) {
2239 cookieManager.write(COOKIE_SES, ses, -1);
2244 /* ----------------------------------------------------------------------- */
2245 /* user session handling */
2246 /* ----------------------------------------------------------------------- */
2247 /* session is the login session. If no session is provided, we attempt
2248 to find one in the cookies. If 'force' is true we retrieve the
2249 user from the server even if there is already a global user present.
2250 if ses != G.user.session, we also force a grab */
2251 function grabUser(ses, force) {
2253 _debug("grabUser auth token = " + ses);
2254 if(!ses && isXUL()) {
2255 stash = fetchXULStash();
2256 ses = stash.session.key
2257 _debug("stash auth token = " + ses);
2261 ses = cookieManager.read(COOKIE_SES);
2262 /* https cookies don't show up in http servers.. */
2263 _debug("cookie auth token = " + ses);
2266 if(!ses) return false;
2269 if(G.user && G.user.session == ses)
2272 /* first make sure the session is valid */
2273 var request = new Request(FETCH_SESSION, ses, 1 );
2274 request.request.alertEvent = false;
2276 var user = request.result();
2278 if(!user || user.textcode == 'NO_SESSION') {
2281 dojo.require('openils.XUL');
2282 dump('getNewSession in opac_utils.js\n');
2283 openils.XUL.getNewSession(
2284 function(success, authtoken) {
2287 var request = new Request(FETCH_SESSION, ses, 1);
2288 request.request.alertEvent = false;
2290 user = request.result();
2296 if(!user || user.textcode == 'NO_SESSION') {
2298 return false; /* unable to grab the session */
2302 if( !(typeof user == 'object' && user._isfieldmapper) ) {
2308 G.user.fleshed = false;
2309 G.user.session = ses;
2310 setSessionCookie(ses);
2313 if(G.user.prefs['opac.hits_per_page'])
2314 COUNT = parseInt(G.user.prefs['opac.hits_per_page']);
2316 if(G.user.prefs[PREF_DEF_FONT])
2317 setFontSize(G.user.prefs[PREF_DEF_FONT]);
2319 var at = getAuthtime();
2320 //if(isXUL()) at = xulG['authtime'];
2322 if(at && !isXUL()) new AuthTimer(at).run();
2327 /* sets the 'prefs' field of the user object to their preferences
2328 and returns the preferences */
2329 function grabUserPrefs(user, force) {
2330 if(user == null) user = G.user;
2331 if(!force && user.prefs) return user.prefs;
2332 var req = new Request(FETCH_USER_PREFS, G.user.session, user.id());
2334 user.prefs = req.result();
2338 function grabFleshedUser() {
2340 if(!G.user || !G.user.session) {
2342 if(!G.user || !G.user.session) return null;
2345 if(G.user.fleshed) return G.user;
2347 var req = new Request(FETCH_FLESHED_USER, G.user.session);
2350 G.user = req.result();
2352 if(!G.user || G.user.length == 0) {
2353 G.user = null; return false;
2354 cookieManager.write(COOKIE_SES,"");
2357 G.user.session = ses;
2358 G.user.fleshed = true;
2360 setSessionCookie(ses);
2364 function checkUserSkin(new_skin) {
2366 return; /* XXX do some debugging with this... */
2368 var user_skin = getSkin();
2369 var cur_skin = grabSkinFromURL();
2371 if(new_skin) user_skin = new_skin;
2376 if(grabUserPrefs()) {
2377 user_skin = G.user.prefs["opac.skin"];
2378 cookieManager.write( COOKIE_SKIN, user_skin, '+1y' );
2383 if(!user_skin) return;
2385 if( cur_skin != user_skin ) {
2386 var url = buildOPACLink();
2387 goTo(url.replace(cur_skin, user_skin));
2391 function updateUserSetting(setting, value, user) {
2392 if(user == null) user = G.user;
2395 var req = new Request( UPDATE_USER_PREFS, user.session, a );
2397 return req.result();
2400 function commitUserPrefs() {
2401 var req = new Request(
2402 UPDATE_USER_PREFS, G.user.session, null, G.user.prefs );
2404 return req.result();
2407 function grabSkinFromURL() {
2408 var path = findBasePath();
2409 path = path.replace("/xml/", "");
2411 for( var i = path.length - 1; i >= 0; i-- ) {
2412 var ch = path.charAt(i);
2413 if(ch == "/") break;
2418 for( i = skin.length - 1; i >= 0; i--)
2419 skin2 += skin.charAt(i);
2425 /* returns a fleshed G.user on success, false on failure */
2426 function doLogin(suppressEvents) {
2430 var uname = G.ui.login.username.value;
2431 var passwd = G.ui.login.password.value;
2433 var init_request = new Request( LOGIN_INIT, uname );
2434 init_request.send(true);
2435 var seed = init_request.result();
2437 if( ! seed || seed == '0') {
2438 alert( "Error Communicating with Authentication Server" );
2443 password : hex_md5(seed + hex_md5(passwd)),
2445 org : getOrigLocation()
2448 r = fetchOrgSettingDefault(globalOrgTree.id(), 'opac.barcode_regex');
2449 if(r) REGEX_BARCODE = new RegExp(r);
2451 if( uname.match(REGEX_BARCODE) ) args.barcode = uname;
2452 else args.username = uname;
2454 var auth_request = new Request( LOGIN_COMPLETE, args );
2456 auth_request.request.alertEvent = false;
2457 auth_request.send(true);
2458 var auth_result = auth_request.result();
2461 alertId('patron_login_failed');
2465 if( checkILSEvent(auth_result) ) {
2467 if( auth_result.textcode == 'PATRON_INACTIVE' ) {
2468 alertId('patron_inactive_alert');
2472 if( auth_result.textcode == 'PATRON_CARD_INACTIVE' ) {
2473 alertId('patron_card_inactive_alert');
2477 if( auth_result.textcode == 'LOGIN_FAILED' ||
2478 auth_result.textcode == 'PERM_FAILURE' ) {
2479 alertId('patron_login_failed');
2485 AUTHTIME = parseInt(auth_result.payload.authtime);
2486 var u = grabUser(auth_result.payload.authtoken, true);
2487 if(u && ! suppressEvents)
2488 runEvt( "common", "locationChanged", u.ws_ou(), findOrgDepth(u.ws_ou()) );
2495 function doLogout() {
2497 /* cancel everything else */
2500 /* be nice and delete the session from the server */
2501 if(G.user && G.user.session) {
2502 var req = new Request(LOGIN_DELETE, G.user.session);
2504 try { req.result(); } catch(E){}
2509 /* remove any cached data */
2510 dojo.require('dojo.cookie');
2511 dojo.cookie(COOKIE_SES, '', {expires:-1});
2512 dojo.cookie(COOKIE_RIDS, '', {expires:-1});
2513 dojo.cookie(COOKIE_SKIN, '', {expires:-1});
2514 dojo.cookie(COOKIE_SEARCH, '', {expires:-1});
2517 checkUserSkin("default");
2522 args[PARAM_TERM] = "";
2523 args[PARAM_LOCATION] = getOrigLocation();
2524 args[PARAM_DEPTH] = findOrgDepth(getOrigLocation());
2529 try{ if(isFrontPage) nored = true; } catch(e){nored = false;}
2530 if(!nored) goTo(buildOPACLink(args, false, false));
2534 function hideMe(obj) { addCSSClass(obj, config.css.hide_me); }
2535 function unHideMe(obj) { removeCSSClass(obj, config.css.hide_me); }
2538 /* ----------------------------------------------------------------------- */
2539 /* build the org tree */
2540 /* ----------------------------------------------------------------------- */
2541 function drawOrgTree() {
2542 //setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 10 );
2543 setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 1 );
2546 function checkOrgHiding() {
2547 var context_org = getOrigLocation() || globalOrgTree.id();
2548 var depth = fetchOrgSettingDefault( context_org, 'opac.org_unit_hiding.depth');
2550 return false; // disable org hiding for staff client
2552 if ( findOrgDepth( context_org ) < depth ) {
2553 return false; // disable org hiding if Original Location doesn't make sense with setting depth (avoids disjointed org selectors)
2555 return { 'org' : findOrgUnit(context_org), 'depth' : depth };
2558 var orgTreeSelector;
2559 function buildOrgSelector(node) {
2560 var tree = new SlimTree(node,'orgTreeSelector');
2561 orgTreeSelector = tree;
2562 var orgHiding = checkOrgHiding();
2563 for( var i in orgArraySearcher ) {
2564 var node = orgArraySearcher[i];
2565 if( node == null ) continue;
2566 if(!isXUL() && !isTrue(node.opac_visible())) continue;
2568 if ( ! orgIsMine( orgHiding.org, node, orgHiding.depth ) ) {
2572 if(node.parent_ou() == null) {
2573 tree.addNode(node.id(), -1, node.name(),
2574 "javascript:orgSelect(" + node.id() + ");", node.name());
2576 if (orgHiding && orgHiding.depth == findOrgDepth(node)) {
2577 tree.addNode(node.id(), -1, node.name(),
2578 "javascript:orgSelect(" + node.id() + ");", node.name());
2580 tree.addNode(node.id(), node.parent_ou(), node.name(),
2581 "javascript:orgSelect(" + node.id() + ");", node.name());
2585 hideMe($('org_loading_div'));
2586 unHideMe($('org_selector_tip'));
2590 function orgSelect(id) {
2592 runEvt("common", "locationChanged", id, findOrgDepth(id) );
2595 var loc = findOrgLasso(getLasso());
2596 if (!loc) loc = findOrgUnit(id);
2598 removeChildren(G.ui.common.now_searching);
2599 G.ui.common.now_searching.appendChild(text(loc.name()));
2602 function setFontSize(size) {
2604 cookieManager.write(COOKIE_FONT, size, '+1y');
2607 var resourceFormats = [
2610 "sound recording", "software, multimedia",
2615 "three dimensional object" ];
2618 function modsFormatToMARC(format) {
2622 case "moving image":
2624 case "sound recording":
2626 case "sound recording-nonmusical":
2628 case "sound recording-musical":
2630 case "software, multimedia":
2634 case "cartographic":
2636 case "mixed material":
2638 case "notated music":
2640 case "three dimensional object":
2647 function MARCFormatToMods(format) {
2653 return "moving image";
2655 return "sound recording-nonmusical";
2657 return "sound recording-musical";
2659 return "software, multimedia";
2661 return "still image";
2664 return "cartographic";
2667 return "mixed material";
2670 return "notated music";
2672 return "three dimensional object";
2677 function MARCTypeToFriendly(format) {
2678 var words = $('format_words');
2681 case 't' : return $n(words, 'at').innerHTML;
2683 var node = $n(words,format);
2684 if( node ) return node.innerHTML;
2689 function setResourcePic( img, resource ) {
2690 img.setAttribute( "src", "../../../../images/tor/" + resource + ".jpg");
2691 img.title = resource;
2696 function msg( text ) {
2697 try { alert( text ); } catch(e) {}
2700 function findRecord(id,type) {
2702 for( var i = 0; i != recordsCache.length; i++ ) {
2703 var rec = recordsCache[i];
2704 if( rec && rec.doc_id() == id ) return rec;
2707 var meth = FETCH_RMODS
2708 if(type == 'M') meth = FETCH_MRMODS;
2709 var req = new Request(meth, id);
2710 req.request.alertEvent = false;
2712 var res = req.result();
2713 if( checkILSEvent(res) ) return null;
2717 function Timer(name, node){
2722 Timer.prototype.start =
2723 function(){_timerRun(this.name);}
2724 Timer.prototype.stop =
2725 function(){this.done = true;}
2726 function _timerRun(tname) {
2730 if(_t.count > 100) return;
2732 if( (_t.count % 5) == 0 )
2734 _t.node.appendChild(text(str));
2735 setTimeout("_timerRun('"+tname+"');", 200);
2739 function checkILSEvent(obj) {
2740 if( obj && obj.ilsevent != null && obj.ilsevent != 0 )
2741 return parseInt(obj.ilsevent);
2746 function alertILSEvent(evt, msg) {
2749 alert(msg +'\n' + evt.textcode + '\n' + evt.desc );
2751 alert(evt.textcode + '\n' + evt.desc );
2756 function AuthTimer(time) {
2757 this.time = (time - LOGOUT_WARNING_TIME) * 1000;
2759 try {clearTimeout(__authTimer.id)} catch(e){}
2763 AuthTimer.prototype.run = function() {
2764 this.id = setTimeout('_authTimerAlert()', this.time);
2767 function _authTimerAlert() {
2768 alert( $('auth_session_expiring').innerHTML );
2769 if(!grabUser(null, true)) doLogout();
2773 function grabUserByBarcode( authtoken, barcode ) {
2774 var req = new Request( FETCH_USER_BYBARCODE, authtoken, barcode );
2776 return req.result();
2781 goTo(buildOPACLink({page:HOME}));
2785 function buildOrgSel(selector, org, offset, namecol) {
2786 if(!namecol) namecol = 'name';
2787 if(!isXUL() && !isTrue(org.opac_visible())) return;
2788 insertSelectorVal( selector, -1,
2789 org[namecol](), org.id(), null, findOrgDepth(org) - offset );
2790 var kids = org.children();
2792 for( var c = 0; c < kids.length; c++ )
2793 buildOrgSel( selector, kids[c], offset, namecol);
2797 function buildMergedOrgSel(selector, org_list, offset, namecol) {
2798 if(!namecol) namecol = 'name';
2799 for(var i = 0; i < org_list.length; i++) {
2800 var org = findOrgUnit(org_list[i]);
2801 insertSelectorVal( selector, -1,
2802 org[namecol](), org.id(), null, findOrgDepth(org) - offset );
2803 var kids = org.children();
2805 for( var c = 0; c < kids.length; c++ )
2806 buildOrgSel( selector, kids[c], offset, namecol);
2812 function parseForm(form) {
2813 if(!form) return {};
2815 var it = form.replace(/-\w+$/,"");
2820 if(form.match(/-/)) itf = form.replace(/^\w+-/,"");
2824 for( var i = 0; i < it.length; i++ )
2825 item_type.push( it.charAt(i) );
2830 for( var i = 0; i < itf.length; i++ )
2831 item_form.push( itf.charAt(i) );
2834 return {item_type: item_type, item_form:item_form};
2838 function isTrue(x) { return ( x && x != "0" && !(x+'').match(/^f$/i) ); }
2840 function fetchPermOrgs() {
2841 var a = []; /* Q: why does arguments come accross as an object and not an array? A: because arguments is a special object, a collection */
2843 for( var i = 0; i < arguments.length; i++ )
2844 a.push(arguments[i])
2846 var preq = new Request(FETCH_HIGHEST_PERM_ORG,
2847 G.user.session, G.user.id(), a );
2849 return preq.result();
2853 function print_tabs(t) {
2855 for (var j = 0; j < t; j++ ) { r = r + " "; }
2858 function formatJSON(s) {
2859 var r = ''; var t = 0;
2861 if (s[i] == '{' || s[i] == '[' ) {
2862 r = r + s[i] + "\n" + print_tabs(++t);
2863 } else if (s[i] == '}' || s[i] == ']') {
2864 t--; r = r + "\n" + print_tabs(t) + s[i];
2865 } else if (s[i] == ',') {
2866 r = r + s[i] + "\n" + print_tabs(t);
2873 /* ------------------------------------------------------------------------------------------------------ */
2874 /* org tree utilities */
2875 /* ------------------------------------------------------------------------------------------------------ */
2877 try { console.log('org utils'); } catch(E) {}
2879 function fetchOrgSettingDefault(orgId, name) {
2880 var req = new Request(FETCH_ORG_SETTING, orgId, name);
2882 var res = req.result();
2883 return (res) ? res.value : null;
2886 function fetchBatchOrgSetting(orgId, nameList, onload) {
2887 var req = new Request(
2888 'open-ils.actor:open-ils.actor.ou_setting.ancestor_default.batch', orgId, nameList);
2890 req.callback(function(r) { onload(r.getResultObject()); });
2894 return req.result();
2899 /* takes an org unit or id and return the numeric depth */
2900 function findOrgDepth(org_id_or_node) {
2901 var org = findOrgUnit(org_id_or_node);
2903 var type = findOrgType(org.ou_type());
2904 if(type) return type.depth();
2908 function findOrgTypeFromDepth(depth) {
2909 if( depth == null ) return null;
2910 for( var type = 0; type < globalOrgTypes.length; type++ ) {
2911 var t = globalOrgTypes[type];
2912 if( t.depth() == depth ) return t;
2916 /* takes the org type id from orgunit.ou_type() field and returns
2917 the org type object */
2918 function findOrgType(type_id) {
2919 if(typeof type_id == 'object') return type_id;
2920 for(var type = 0; type < globalOrgTypes.length; type++) {
2921 var t =globalOrgTypes[type];
2922 if( t.id() == type_id || t.id() == parseInt(type_id) )
2929 /* returns an org unit by id. if an object is passed in as the id,
2930 then the object is assumed to be an org unit and is returned */
2931 function findOrgUnit(org_id) {
2932 return (typeof org_id == 'object') ? org_id : orgArraySearcher[org_id];
2935 function findOrgLasso(lasso_id) {
2936 if (typeof lasso_id == 'object') return lasso_id;
2937 for (var i = 0; i < _lasso.length; i++) {
2938 if (_lasso[i].id() == lasso_id) return _lasso[i];
2943 var orgArraySearcherSN = {};
2944 function findOrgUnitSN(shortname) {
2945 if (typeof shortname == 'object') return shortname;
2946 if( orgArraySearcherSN[shortname] ) return orgArraySearcherSN[shortname];
2947 _debug("fetching org by shortname "+shortname);
2948 var req = new Request(FETCH_ORG_BY_SHORTNAME, shortname);
2949 req.request.alertEvent = false;
2951 return req.result();
2955 /* builds a trail from the top of the org tree to the node provide.
2956 basically fleshes out 'my orgs'
2957 Returns an array of [org0, org1, ..., myorg] */
2958 function orgNodeTrail(node) {
2959 var na = new Array();
2962 node = findOrgUnit(node.parent_ou());
2964 return na.reverse();
2967 function findSiblingOrgs(node) { return findOrgUnit(node.parent_ou()).children(); }
2969 /* true if 'org' is 'me' or a child of mine, or optionally, a child of an ancestor org within the specified depth */
2970 function orgIsMine(me, org, depth) {
2974 if(me.id() == org.id()) {
2978 while (depth < findOrgDepth(me)) {
2979 me = findOrgUnit( me.parent_ou() );
2981 if(me.id() == org.id()) {
2985 var kids = me.children();
2986 for( var i = 0; kids && i < kids.length; i++ ) {
2987 if(orgIsMine(kids[i], org, false)) {
2995 function orgIsMineFromSet(meList, org) {
2996 org = findOrgUnit(org);
2997 for(var i = 0; i < meList.length; i++) {
2998 if(orgIsMine(findOrgUnit(meList[i]), org))
3004 var orgArraySearcher = {};
3006 for (var i = 0; i < _l.length; i++) {
3009 x.ou_type(_l[i][1]);
3010 x.parent_ou(_l[i][2]);
3012 x.opac_visible(_l[i][4]);
3013 x.shortname(_l[i][5]);
3014 orgArraySearcher[x.id()] = x;
3016 for (var i in orgArraySearcher) {
3017 var x = orgArraySearcher[i];
3018 if (x.parent_ou() == null || x.parent_ou() == '') {
3023 var par = findOrgUnit(x.parent_ou());
3024 if (!par.children()) par.children(new Array());
3025 par.children().push(x);
3028 function _tree_killer () {
3029 for (var i in orgArraySearcher) {
3030 x=orgArraySearcher[i];
3033 orgArraySearcher[i]=null;
3035 globalOrgTree = null;
3036 orgArraySearcher = null;
3037 globalOrgTypes = null;
3040 try { console.log('org utils end'); } catch(E) {}
3043 var XML_HTTP_GATEWAY = "osrf-gateway-v1";
3044 var XML_HTTP_SERVER = "";
3047 /* This object is thrown when network failures occur */
3048 function NetworkFailure(stat, url) {
3049 this._status = stat;
3053 NetworkFailure.prototype.status = function() { return this._status; }
3054 NetworkFailure.prototype.url = function() { return this._url; }
3055 NetworkFailure.prototype.toString = function() {
3056 return "Network Failure: status = " + this.status() +'\n'+this.url();
3061 function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
3062 var _allrequests = {};
3064 // If the legacy JSON gateway is needed by the staff client, uncomment this
3067 XML_HTTP_GATEWAY = 'gateway';
3071 function cleanRemoteRequests() {
3072 for( var i in _allrequests )
3073 destroyRequest(_allrequests[i]);
3076 function abortAllRequests() {
3077 for( var i in _allrequests ) {
3078 var r = _allrequests[i];
3086 function destroyRequest(r) {
3087 if(r == null) return;
3090 r.xmlhttp.onreadystatechange = function(){};
3096 _allrequests[r.id] = null;
3099 /* ----------------------------------------------------------------------- */
3100 /* Request object */
3102 function RemoteRequest( service, method ) {
3104 /* dojo is currently only available in the OPAC */
3106 /* We want OpenSRF.locale for xx-YY format */
3107 this.locale = OpenSRF.locale;
3112 this.service = service;
3113 this.method = method;
3114 this.xmlhttp = false;
3116 this.alertEvent = true; /* only used when isXUL is false */
3118 this.type = "POST"; /* default */
3120 this.cancelled = false;
3122 this.setSecure(false);
3123 if(isXUL()) this.setSecure(true);
3125 _allrequests[this.id] = this;
3130 while(i < arguments.length) {
3131 var object = js2JSON(arguments[i++]);
3132 this.params += "¶m=" + encodeURIComponent(object);
3135 if(!this.params) { this.params = ""; }
3137 this.param_string = "service=" + service + "&method=" + method + this.params;
3138 if (this.locale != null) {
3139 this.param_string = this.param_string + "&locale=" + this.locale;
3141 if( this.buildXMLRequest() == null ) alert("Browser is not supported!");
3146 RemoteRequest.prototype.timeout = function(t) {
3149 req.timeoutFunc = setTimeout(
3151 if( req && req.xmlhttp ) {
3152 req.cancelled = true;
3154 if( req.abtCallback ) {
3155 req.abtCallback(req);
3163 RemoteRequest.prototype.abortCallback = function(func) {
3164 this.abtCallback = func;
3167 RemoteRequest.prototype.event = function(evt) {
3168 if( arguments.length > 0 )
3173 RemoteRequest.prototype.abort = function() {
3174 if( this.xmlhttp ) {
3175 /* this has to come before abort() or IE will puke on you */
3176 this.xmlhttp.onreadystatechange = function(){};
3177 this.xmlhttp.abort();
3181 /* constructs our XMLHTTPRequest object */
3182 RemoteRequest.prototype.buildXMLRequest = function() {
3183 this.xmlhttp = buildXMLRequest();
3188 function buildXMLRequest() {
3190 return new XMLHttpRequest();
3193 return new ActiveXObject("Msxml2.XMLHTTP");
3196 return new ActiveXObject("Microsoft.XMLHTTP");
3198 alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
3206 function _remoteRequestCallback(id) {
3208 var object = _allrequests[id];
3209 if(object.cancelled) return;
3211 if( object.xmlhttp.readyState == 4 ) {
3214 object.duration = new Date().getTime() - object.sendTime;
3215 dump('request ' + object.id + ': duration = ' + object.duration + ' ms\n');
3219 object.callback(object);
3223 destroyRequest(object);
3230 /* define the callback we use when this request has received
3232 RemoteRequest.prototype.setCompleteCallback = function(callback) {
3233 if(this.cancelled) return;
3234 this.callback = callback;
3236 this.xmlhttp.onreadystatechange = function() { _remoteRequestCallback(id); }
3240 /* http by default. This makes it https. *ONLY works when
3241 embedded in a XUL app. */
3242 RemoteRequest.prototype.setSecure = function(bool) {
3246 RemoteRequest.prototype.send = function(blocking) {
3248 if(this.cancelled) return;
3250 /* determine the xmlhttp server dynamically */
3251 var url = location.protocol + "//" + location.host + "/" + XML_HTTP_GATEWAY;
3254 if( XML_HTTP_SERVER )
3255 url = 'http://'+XML_HTTP_SERVER+'/'+XML_HTTP_GATEWAY;
3257 if( url.match(/^http:/) &&
3258 (this.secure || location.href.match(/^https:/)) ) {
3259 netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
3260 url = url.replace(/^http:/, 'https:');
3265 if( this.type == 'GET' ) url += "?" + this.param_string;
3269 //if( isXUL() ) dump('request URL = ' + url + '?' + this.param_string + '\n');
3273 if(blocking) this.xmlhttp.open(this.type, url, false);
3274 else this.xmlhttp.open(this.type, url, true);
3277 alert("Fatal error opening XMLHTTPRequest for URL:\n" + url + '\n' + E);
3281 if( this.type == 'POST' ) {
3282 data = this.param_string;
3283 this.xmlhttp.setRequestHeader('Content-Type',
3284 'application/x-www-form-urlencoded');
3289 try { auth = cookieManager.read(COOKIE_SES) } catch(ee) {}
3290 if( isXUL() ) auth = fetchXULStash().session.key;
3292 this.xmlhttp.setRequestHeader('X-OILS-Authtoken', auth);
3296 if(data && data.match(/param=undefined/)) {
3297 /* we get a bogus param .. replace with NULL */
3298 try{dump('!+! UNDEFINED PARAM IN QUERY: ' + this.service + ' : ' + this.method+'\n');}catch(r){}
3299 data = data.replace(/param=undefined/g,'param=null');
3303 this.sendTime = new Date().getTime();
3304 try{ this.xmlhttp.send( data ); } catch(e){}
3309 /* returns the actual response text from the request */
3310 RemoteRequest.prototype.getText = function() {
3311 return this.xmlhttp.responseText;
3314 RemoteRequest.prototype.isReady = function() {
3315 return this.xmlhttp.readyState == 4;
3319 /* returns the JSON->js result object */
3320 RemoteRequest.prototype.getResultObject = function() {
3322 if(this.cancelled) return null;
3323 if(!this.xmlhttp) return null;
3331 dump(this.url + '?' + this.param_string + '\n' +
3332 'Returned with \n\tstatus = ' + this.xmlhttp.status +
3333 '\n\tpayload= ' + this.xmlhttp.responseText + '\n');
3338 status = this.xmlhttp.status;
3339 if( status != 200 ) failed = true;
3340 } catch(e) { failed = true; }
3343 if(!status) status = '<unknown>';
3344 try{dump('! NETWORK FAILURE. HTTP STATUS = ' +status+'\n'+this.param_string+'\n');}catch(e){}
3346 throw new NetworkFailure(status, this.param_string);
3350 var text = this.xmlhttp.responseText;
3352 //try{if(getDebug()) _debug('response: ' + text + '\n')}catch(e){}
3354 if(text == "" || text == " " || text == null) {
3355 try { dump('dbg: Request returned no text!\n'); } catch(E) {}
3357 throw new NetworkFailure(status, this.param_string);
3361 var obj = JSON2js(text);
3362 if(!obj) return null;
3364 if( obj.status != 200 ) {
3366 var str = 'A server error occurred. Debug information follows: ' +
3367 '\ncode = ' + obj.status +
3368 '\ndebug: ' + obj.debug +
3369 '\npayload: ' + js2JSON(obj.payload);
3381 var payload = obj.payload;
3382 if(!payload || payload.length == 0) return null;
3383 payload = (payload.length == 1) ? payload[0] : payload;
3386 if( checkILSEvent(payload) ) {
3387 this.event(payload);
3388 if( this.alertEvent ) {
3389 alertILSEvent(payload);
3398 /* adds a new parameter to the request */
3399 RemoteRequest.prototype.addParam = function(param) {
3400 var string = encodeURIComponent(js2JSON(param));
3401 this.param_string += "¶m=" + string;
3404 function fetchXULStash() {
3407 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
3408 var __OILS = new Components.Constructor("@mozilla.org/openils_data_cache;1", "nsIOpenILS");
3409 var data_cache = new __OILS( );
3410 return data_cache.wrappedJSObject.OpenILS.prototype.data;
3413 _debug('Error in OpenILS.data._debug_stash(): ' + js2JSON(E) );
3421 /* these events should be used by all */
3423 window.onunload = windowUnload;
3425 attachEvt("common", "init", loadUIObjects);
3426 //attachEvt("common", "init", initParams);
3427 attachEvt("common", "init", initCookies);
3429 attachEvt("common", "unload", _tree_killer);
3430 try{ attachEvt("common", "unload", cleanRemoteRequests);} catch(e){}
3436 if( getLocation() == null && getOrigLocation() != null )
3437 LOCATION = getOrigLocation();
3439 if( getLocation() == null && getOrigLocation() == null )
3440 LOCATION = globalOrgTree.id();
3442 /* if they click on the home page and the origlocation is set
3443 take the opac back to the origlocation */
3444 if( findCurrentPage() == HOME && getOrigLocation() != null )
3445 LOCATION = getOrigLocation();
3447 if(getDepth() == null) DEPTH = findOrgDepth(getLocation());
3450 runEvt('common','init');
3452 var cgi = new CGI();
3454 if( cgi.param(PARAM_LOCATION) == null ) {
3455 var org = G.user.prefs[PREF_DEF_LOCATION];
3456 var depth = G.user.prefs[PREF_DEF_DEPTH];
3458 if(org == null) org = G.user.ws_ou();
3459 if(depth == null) depth = findOrgDepth(org);
3466 runEvt("common", "run");
3469 var loc = findOrgLasso(getLasso());
3470 if (!loc) loc = findOrgUnit(getLocation());
3472 if (getLasso()) G.ui.common.now_searching.appendChild(text('Search group: '));
3473 G.ui.common.now_searching.appendChild(text(loc.name()));
3476 function windowUnload() { runEvt("common", "unload"); }
3478 * This function should return a URL which points to the book cover image based on ISBN.
3482 function buildISBNSrc(isbn, size) {
3483 size = (size) ? size : 'small';
3484 var protocol = (OILS_OPAC_STATIC_PROTOCOL) ? OILS_OPAC_STATIC_PROTOCOL + ':' : location.protocol;
3485 if(OILS_OPAC_IMAGES_HOST)
3486 return protocol + '//' + OILS_OPAC_IMAGES_HOST + size + '/' + isbn;
3487 return '../../../../extras/ac/jacket/'+size+'/'+isbn;
3491 function acMakeURL(type, key) {
3492 return '../../../../extras/ac/' + type + '/html/' + key;
3496 function acCollectData( key, callback ) {
3497 var context = { key : key, callback: callback, data : {} };
3498 acCollectItem(context, 'summary');
3499 acCollectItem(context, 'reviews');
3500 acCollectItem(context, 'toc');
3501 acCollectItem(context, 'excerpt');
3502 acCollectItem(context, 'anotes');
3505 function acCheckDone(context) {
3506 if( context.data.reviews && context.data.reviews.done &&
3507 context.data.toc && context.data.toc.done &&
3508 context.data.excerpt && context.data.excerpt.done &&
3509 context.data.anotes && context.data.anotes.done ) {
3511 if(context.callback) context.callback(context.data);
3515 function acCollectItem(context, type) {
3516 var req = buildXMLRequest();
3517 req.open('GET', acMakeURL(type, context.key), true);
3518 req.onreadystatechange = function() {
3519 if( req.readyState == 4 ) {
3520 context.data[type] = { done : true }
3524 /* Someone please explain why IE treats status 404 as status 200??
3525 On second thought, don't bother.
3527 if( ! req.responseText.match(
3528 /The requested URL.*was not found on this server/) )
3529 context.data[type].html = req.responseText;
3532 if( req.status != 404 )
3533 context.data[type].html = req.responseText;
3535 acCheckDone(context);