Initial dev repository
[kcls-web.git] / opac / common / js / combined.js
diff --git a/opac/common/js/combined.js b/opac/common/js/combined.js
new file mode 100644 (file)
index 0000000..b691526
--- /dev/null
@@ -0,0 +1,3541 @@
+function $(id) { return getId(id); }
+function getId(id) {
+       return document.getElementById(id);
+}
+
+function swapCSSClass(obj, old, newc ) {
+       removeCSSClass(obj, old );
+       addCSSClass(obj, newc );
+}
+
+
+function addCSSClass(e,c) {
+       if(!e || !c) return;
+
+       var css_class_string = e.className;
+       var css_class_array;
+
+       if(css_class_string)
+               css_class_array = css_class_string.split(/\s+/);
+
+       var string_ip = ""; /*strip out nulls*/
+       for (var css_class in css_class_array) {
+               if (css_class_array[css_class] == c) { return; }
+               if(css_class_array[css_class] !=null)
+                       string_ip += css_class_array[css_class] + " ";
+       }
+       string_ip += c;
+       e.className = string_ip;
+}
+
+function removeCSSClass(e, c) {
+       if(!e || !c) return;
+
+       var css_class_string = '';
+
+       var css_class_array = e.className;
+       if( css_class_array )
+               css_class_array = css_class_array.split(/\s+/);
+
+       var first = 1;
+       for (var css_class in css_class_array) {
+               if (css_class_array[css_class] != c) {
+                       if (first == 1) {
+                               css_class_string = css_class_array[css_class];
+                               first = 0;
+                       } else {
+                               css_class_string = css_class_string + ' ' +
+                                       css_class_array[css_class];
+                       }
+               }
+       }
+       e.className = css_class_string;
+}
+
+
+/*returns the character code pressed that caused the event */
+function grabCharCode(evt) {
+   evt = (evt) ? evt : ((window.event) ? event : null); 
+   if( evt ) {
+      return (evt.charCode ? evt.charCode : 
+         ((evt.which) ? evt.which : evt.keyCode ));
+   } else { return -1; }
+}       
+
+
+/* returns true if the user pressed enter */
+function userPressedEnter(evt) {
+   var code = grabCharCode(evt);
+   if(code==13||code==3) return true;
+   return false;
+}   
+
+
+function goTo(url) {
+       /* setTimeout because ie sux */
+       setTimeout( function(){ location.href = url; }, 0 );
+}
+
+
+function removeChildren(dom) {
+       if(!dom) return;
+       while(dom.childNodes[0])
+               dom.removeChild(dom.childNodes[0]);
+}
+
+function appendClear(node, child) {
+       if(typeof child =='string') child = text(child);
+       removeChildren(node);
+       node.appendChild(child);
+}
+
+
+function instanceOf(object, constructorFunction) {
+
+   if(!IE) {
+      while (object != null) {
+         if (object == constructorFunction.prototype)
+            return true;
+         object = object.__proto__;
+      }
+   } else {
+      while(object != null) {
+         if( object instanceof constructorFunction )
+            return true;
+         object = object.__proto__;
+      }
+   }
+   return false;
+}         
+
+
+/* ------------------------------------------------------------------------------------------- */
+/* detect my browser */
+var isMac, NS, NS4, NS6, IE, IE4, IEmac, IE4plus, IE5, IE5plus, IE6, IEMajor, ver4, Safari;
+function detect_browser() {       
+
+   isMac = (navigator.appVersion.indexOf("Mac")!=-1) ? true : false;
+   NS = (navigator.appName == "Netscape") ? true : false;
+   NS4 = (document.layers) ? true : false;
+   IE = (navigator.appName == "Microsoft Internet Explorer") ? true : false;
+   IEmac = ((document.all)&&(isMac)) ? true : false;
+   IE4plus = (document.all) ? true : false;
+   IE4 = ((document.all)&&(navigator.appVersion.indexOf("MSIE 4.")!=-1)) ? true : false;
+   IE5 = ((document.all)&&(navigator.appVersion.indexOf("MSIE 5.")!=-1)) ? true : false;
+   IE6 = ((document.all)&&(navigator.appVersion.indexOf("MSIE 6.")!=-1)) ? true : false;
+   ver4 = (NS4 || IE4plus) ? true : false;
+   NS6 = (!document.layers) && (navigator.userAgent.indexOf('Netscape')!=-1)?true:false;
+   Safari = navigator.userAgent.match(/Safari/);
+
+   IE5plus = IE5 || IE6;
+   IEMajor = 0;
+
+   if (IE4plus) {
+      var start = navigator.appVersion.indexOf("MSIE");
+      var end = navigator.appVersion.indexOf(".",start);
+      IEMajor = parseInt(navigator.appVersion.substring(start+5,end));
+      IE5plus = (IEMajor>=5) ? true : false;
+   }
+}  
+detect_browser();
+/* ------------------------------------------------------------------------------------------- */
+
+
+function text(t) {
+       if(t == null) t = "";
+       return document.createTextNode(t);
+}
+
+function elem(name, attrs, txt) {
+    var e = document.createElement(name);
+    if (attrs) {
+        for (key in attrs) {
+                         if( key == 'id') e.id = attrs[key];
+                         else e.setAttribute(key, attrs[key]);
+        }
+    }
+    if (txt) e.appendChild(text(txt));
+    return e;
+}                   
+
+
+/* sel is the selector object, sets selected on the 
+       option with the given value. case does not matter...*/
+function setSelector( sel, value ) {
+       if(sel && value != null) {
+               for( var i = 0; i!= sel.options.length; i++ ) { 
+                       if( sel.options[i] ) {
+                               var val = sel.options[i].value;
+                               if( val == null || val == "" ) /* for IE */
+                                       val = sel.options[i].innerHTML;
+                               value += ""; /* in case of number */ 
+                               if( val && val.toLowerCase() == value.toLowerCase() ) {
+                                       sel.selectedIndex = i;
+                                       sel.options[i].selected = true;
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
+function setSelectorRegex( sel, regex ) {
+       if(sel && regex != null) {
+               for( var i = 0; i!= sel.options.length; i++ ) { 
+                       if( sel.options[i] ) {
+                               var val = sel.options[i].value;
+                               if( val == null || val == "" ) /* for IE */
+                                       val = sel.options[i].innerHTML;
+                               value += ""; /* in case of number */ 
+                               if( val && val.match(regex) ) {
+                                       sel.selectedIndex = i;
+                                       sel.options[i].selected = true;
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
+function getSelectorVal( sel ) {
+       if(!sel) return null;
+       var idx = sel.selectedIndex;
+       if( idx < 0 ) return null;
+       var o = sel.options[idx];
+       var v = o.value; 
+       if(v == null) v = o.innerHTML;
+       return v;
+}
+
+function getSelectorName( sel ) {
+       var o = sel.options[sel.selectedIndex];
+       var v = o.name;
+       if(v == null || v == undefined || v == "") v = o.innerHTML;
+       return v;
+}
+
+function setSelectorByName( sel, name ) {
+       for( var o in sel.options ) {
+               var opt = sel.options[o];
+               if( opt.name == name || opt.innerHTML == name ) {
+                       sel.selectedIndex = o;
+                       opt.selected = true;
+               }
+       }
+}
+
+function findSelectorOptByValue( sel, val ) {
+       for( var i = 0; i < sel.options.length; i++ ) {
+               var opt = sel.options[i];
+               if( opt.value == val ) return opt;
+       }
+       return null;
+}
+
+function debugSelector(sel) {
+       var s = 'Selector\n';
+       for( var i = 0; i != sel.options.length; i++ ) {
+               var o = sel.options[i];
+               s += "\t" + o.innerHTML + "\n";
+       }
+       return s;
+}
+
+function findParentByNodeName(node, name) {
+       while( ( node = node.parentNode) ) 
+               if (node.nodeName == name) return node;
+       return null;
+}
+
+/* returns only elements in nodes childNodes list, not sub-children */
+function getElementsByTagNameFlat( node, name ) {
+       var elements = [];
+       for( var e in node.childNodes ) {
+               var n = node.childNodes[e];
+               if( n && n.nodeName == name ) elements.push(n);
+       }
+       return elements;
+}
+
+/* expects a tree with a id() method on each node and a 
+children() method to get to each node */
+function findTreeItemById( tree, id ) {
+       if( tree.id() == id ) return tree;
+       for( var c in tree.children() ) {
+               var found = findTreeItemById( tree.children()[c], id );
+               if(found) return found;
+       }
+       return null;
+}
+
+/* returns null if none of the tests are true.  returns sub-array of 
+matching array items otherwise */
+function grep( arr, func ) {
+       var results = [];
+       if(!arr) return null;
+       if( arr.constructor == Array ) {
+               for( var i = 0; i < arr.length; i++ ) {
+                       if( func(arr[i]) ) 
+                               results.push(arr[i]);
+               }
+       } else {
+               for( var i in arr ) {
+                       if( func(arr[i]) ) 
+                               results.push(arr[i]);
+               }
+       }
+       if(results.length > 0) return results;
+       return null;
+}
+
+function ogrep( obj, func ) {
+       var results = {};
+       var found = false;
+       for( var i in obj ) {
+               if( func(obj[i]) ) {
+                       results[i] = obj[i];
+                       found = true;
+               }
+       }
+       if(found) return results;
+       return null;
+}
+
+function doSelectorActions(sel) {
+       if((IE || Safari) && sel) { 
+               sel.onchange = function() {
+                       var o = sel.options[sel.selectedIndex];
+                       if(o && o.onclick) o.onclick()
+               }
+       }
+}
+
+/* if index < 0, the item is pushed onto the end */
+function insertSelectorVal( selector, index, name, value, action, indent ) {
+       if( index < 0 ) index = selector.options.length;
+       var a = [];
+       for( var i = selector.options.length; i != index; i-- ) 
+               a[i] = selector.options[i-1];
+
+       var opt = setSelectorVal( selector, index, name, value, action, indent );
+
+       for( var i = index + 1; i < a.length; i++ ) 
+               selector.options[i] = a[i];
+
+       return opt;
+}
+
+/* changes the value of the option at the specified index */
+function setSelectorVal( selector, index, name, value, action, indent ) {
+       if(!indent || indent < 0) indent = 0;
+       indent = parseInt(indent);
+
+       var option;
+
+       if(IE) {
+               var pre = elem("pre");
+               for( var i = 0; i != indent; i++ )
+                       pre.appendChild(text("   "));
+
+               pre.appendChild(text(name));
+               option = new Option("", value);
+               selector.options[index] = option;
+               option.appendChild(pre);
+       
+       } else {
+               indent = indent * 14;
+               option= new Option(name, value);
+               option.setAttribute("style", "padding-left: "+indent+'px;');
+               selector.options[index] = option;
+               if(action) option.onclick = action;
+       }
+
+       if(action) option.onclick = action;
+       return option;
+}
+
+
+/* split on spaces.  capitalize the first /\w/ character in
+   each substring */
+function normalize(val) {
+       return val; /* disable me for now */
+
+   if(!val) return ""; 
+
+   var newVal = '';
+   try {val = val.split(' ');} catch(E) {return val;}
+   var reg = /\w/;
+
+   for( var c = 0; c < val.length; c++) {
+
+      var string = val[c];
+      var cap = false; 
+      for(var x = 0; x != string.length; x++) {
+
+         if(!cap) {
+            var ch = string.charAt(x);
+            if(reg.exec(ch + "")) {
+               newVal += string.charAt(x).toUpperCase();
+               cap = true;
+               continue;
+            }
+         }
+
+         newVal += string.charAt(x).toLowerCase();
+      }
+      if(c < (val.length-1)) newVal += " ";
+   }
+
+   newVal = newVal.replace(/\s*\.\s*$/,'');
+   newVal = newVal.replace(/\s*\/\s*\/\s*$/,' / ');
+   newVal = newVal.replace(/\s*\/\s*$/,'');
+
+   return newVal;
+}
+
+
+/* returns true if n is null or stringifies to 'undefined' */
+function isNull(n) {
+       if( n == null || n == undefined || n.toString().toLowerCase() == "undefined" 
+               || n.toString().toLowerCase() == "null" )
+               return true;
+       return false;
+}
+
+
+/* find nodes with an attribute of 'name' that equals nodeName */
+
+function $n( root, nodeName ) { return findNodeByName(root,nodeName); }
+
+function findNodeByName(root, nodeName) {
+       if( !root || !nodeName) return null;
+
+       if(root.nodeType != 1) return null;
+
+       if(root.getAttribute("name") == nodeName || root.name == nodeName ) 
+               return root;
+
+       var children = root.childNodes;
+
+       for( var i = 0; i != children.length; i++ ) {
+               var n = findNodeByName(children[i], nodeName);
+               if(n) return n;
+       }
+
+       return null;
+}
+
+
+/* truncates the string at 'size' characters and appends a '...' to the end */
+function truncate(string, size) {
+       if(string && size != null && 
+                       size > -1 && string.length > size) 
+               return string.substr(0, size) + "... "; 
+       return string;
+}
+
+
+/* style sheets must have a 'name' attribute for these functions to work */
+function setActivateStyleSheet(name) {
+       var i, a, main;
+       for (i = 0; (a = document.getElementsByTagName ("link")[i]); i++) {
+               if (a.getAttribute ("rel").indexOf ("style") != -1 && a.getAttribute ("name")) {
+                       a.disabled = true;
+                       if (a.getAttribute ("name").indexOf(name) != -1)
+                               a.disabled = false;
+               }
+       }
+}
+
+
+/* ----------------------------------------------------- */
+var currentFontSize;
+function scaleFonts(type) {
+
+       var size                = "";
+       var ssize       = "";
+       var size2       = "";
+       var a;
+       
+       if(!currentFontSize) currentFontSize = 'regular';
+       if(currentFontSize == 'regular' && type == 'regular' ) return;
+       if( currentFontSize == type ) return;
+       currentFontSize = type;
+
+       switch(type) {
+               case "large":  /* these are arbitrary.. but they seem to work ok in FF/IE */
+                       size = "142%"; 
+                       size2 = "107%"; 
+                       ssize = "94%";
+                       break;
+       }
+
+       document.getElementsByTagName('body')[0].style.fontSize = size;
+       for (i = 0; (a = document.getElementsByTagName ("td")[i]); i++) a.style.fontSize = size;;
+       for (i = 0; (a = document.getElementsByTagName ("div")[i]); i++) a.style.fontSize = ssize;
+       for (i = 0; (a = document.getElementsByTagName ("option")[i]); i++) a.style.fontSize = ssize;
+       for (i = 0; (a = document.getElementsByTagName ("li")[i]); i++) a.style.fontSize = ssize;
+       for (i = 0; (a = document.getElementsByTagName ("span")[i]); i++) a.style.fontSize = ssize;
+       for (i = 0; (a = document.getElementsByTagName ("select")[i]); i++) a.style.fontSize = ssize;
+       for (i = 0; (a = document.getElementsByTagName ("a")[i]); i++) a.style.fontSize = size2;
+}
+
+
+function sortWordsIgnoreCase(a, b) {
+       a = a.toLowerCase();
+       b = b.toLowerCase();
+       if(a>b) return 1;
+       if(a<b) return -1;
+       return 0;
+}
+
+
+function getSelectedList(sel) {
+       if(!sel) return [];
+       var vals = [];
+       for( var i = 0; i != sel.options.length; i++ ) {
+               if(sel.options[i].selected)
+                       vals.push(sel.options[i].value);
+       }
+       return vals;
+}
+
+
+function setEnterFunc(node, func) {
+       if(!(node && func)) return;
+       node.onkeydown = function(evt) {
+               if( userPressedEnter(evt)) func();
+       }
+}
+
+function iterate( arr, callback ) {
+       for( var i = 0; arr && i < arr.length; i++ ) 
+               callback(arr[i]);
+}
+
+
+
+
+/* taken directly from the JSAN util.date library */
+/* but changed from the util.date.interval_to_seconds invocation, 
+because JSAN will assume the whole library is already loaded if 
+it sees that, and the staff client uses both this file and the
+JSAN library*/
+function interval_to_seconds( $interval ) {
+
+       $interval = $interval.replace( /and/, ',' );
+       $interval = $interval.replace( /,/, ' ' );
+       
+       var $amount = 0;
+       var results = $interval.match( /\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/g);  
+       for( var i = 0; i < results.length; i++ ) {
+               if(!results[i]) continue;
+               var result = results[i].match( /\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/ );
+               if (result[2] == 's') $amount += result[1] ;
+               if (result[2] == 'm') $amount += 60 * result[1] ;
+               if (result[2] == 'h') $amount += 60 * 60 * result[1] ;
+               if (result[2] == 'd') $amount += 60 * 60 * 24 * result[1] ;
+               if (result[2] == 'w') $amount += 60 * 60 * 24 * 7 * result[1] ;
+               if (result[2] == 'M') $amount += ((60 * 60 * 24 * 365)/12) * result[1] ;
+               if (result[2] == 'y') $amount += 60 * 60 * 24 * 365 * result[1] ;
+       }
+       return $amount;
+}
+
+
+function openWindow( data ) {
+       if( isXUL() ) {
+               var data = window.escape(
+                       '<html><head><title></title></head><body>' + data + '</body></html>');
+
+               xulG.window_open(
+                       'data:text/html,' + data,
+                       '', 
+                       'chrome,resizable,width=700,height=500'); 
+
+       } else {
+               win = window.open('','', 'resizable,width=700,height=500,scrollbars=1'); 
+               win.document.body.innerHTML = data;
+       }
+}
+
+
+/* alerts the innerhtml of the node with the given id */
+function alertId(id) {
+       var node = $(id);
+       if(node) alert(node.innerHTML);
+}
+
+function alertIdText(id, text) {
+       var node = $(id);
+   if(!node) return;
+   if(text)
+      alert(text + '\n\n' + node.innerHTML);
+   else 
+          alert(node.innerHTML);
+}
+
+function confirmId(id) {
+       var node = $(id);
+       if(node) return confirm(node.innerHTML);
+}
+
+
+function goBack() { history.back(); }
+function goForward() { history.forward(); }
+
+
+function uniquify(arr) {
+       if(!arr) return [];
+       var newarr = [];
+       for( var i = 0; i < arr.length; i++ ) {
+               var item = arr[i];
+               if( ! grep( newarr, function(x) {return (x == item);}))
+                       newarr.push(item);
+       }
+       return newarr;
+}
+
+function contains(arr, item) {
+       for( var i = 0; i < arr.length; i++ ) 
+               if( arr[i] == item ) return true;
+       return false;
+}
+
+function isTrue(i) {
+       return (i && !(i+'').match(/f/i) );
+}
+
+
+/* builds a JS date object with the given info.  The given data
+       has to be valid (e.g. months == 30 is not valid).  Returns NULL on 
+       invalid date 
+       Months are 1-12 (unlike the JS date object)
+       */
+
+function buildDate( year, month, day, hours, minutes, seconds ) {
+
+       if(!year) year = 0;
+       if(!month) month = 1;
+       if(!day) day = 1;
+       if(!hours) hours = 0;
+       if(!minutes) minutes = 0;
+       if(!seconds) seconds = 0;
+
+       var d = new Date(year, month - 1, day, hours, minutes, seconds);
+       
+       _debug('created date with ' +
+               (d.getYear() + 1900) +'-'+
+               (d.getMonth() + 1) +'-'+
+               d.getDate()+' '+
+               d.getHours()+':'+
+               d.getMinutes()+':'+
+               d.getSeconds());
+
+
+       if( 
+               (d.getYear() + 1900) == year &&
+               d.getMonth()    == (month - 1) &&
+               d.getDate()             == new Number(day) &&
+               d.getHours()    == new Number(hours) &&
+               d.getMinutes() == new Number(minutes) &&
+               d.getSeconds() == new Number(seconds) ) {
+               return d;
+       }
+
+       return null;
+}
+
+function mkYearMonDay(date) {
+       if(!date) date = new Date();
+       var y = date.getYear() + 1900;
+       var m = (date.getMonth() + 1)+'';
+       var d = date.getDate()+'';
+       if(m.length == 1) m = '0'+m;
+       if(d.length == 1) d = '0'+d;
+       return y+'-'+m+'-'+d;
+}
+
+
+function debugFMObject(obj) {
+       if(typeof obj != 'object' ) return obj;
+       _debug("---------------------");
+       var keys = fmclasses[obj.classname];
+       if(!keys) { _debug(formatJSON(js2JSON(obj))); return; }
+
+       keys.sort();
+       for( var i = 0; i < keys.length; i++ ) {
+               var key = keys[i];
+               while( key.length < 12 ) key += ' ';
+               var val = obj[keys[i]]();
+               if( typeof val == 'object' ) {
+                       _debug(key+' :=\n');
+                       _debugFMObject(val);
+               } else {
+                       _debug(key+' = ' +val);
+               }
+
+       }
+       _debug("---------------------");
+}
+
+
+function getTableRows(tbody) {
+    var rows = [];
+    if(!tbody) return rows;
+
+    var children = tbody.childNodes;
+    if(!children) return rows;
+
+    for(var i = 0; i < children.length; i++) {
+        var child = children[i];
+        if(child.nodeName.match(/^tr$/i)) 
+            rows.push(child);
+    }
+    return rows;
+}
+
+function getObjectKeys(obj) {
+    keys = []
+    for(var k in obj)
+        keys.push(k)
+    return keys;
+}
+/* Export some constants  ----------------------------------------------------- */
+
+var SHOW_MR_DEFAULT = false; /* true if we show metarecords by default */
+
+//var DO_AUTHORITY_LOOKUPS = false;
+var DO_AUTHORITY_LOOKUPS = true;
+
+var STAFF_WEB_BASE_PATH = '/eg'; // root of the web-based staff interfaces
+
+/* URL param names */
+var PARAM_TERM                 = "t";                  /* search term */
+var PARAM_FACET                        = "ft";                 /* facet term */
+var PARAM_STYPE                = "tp";                 /* search type */
+var PARAM_LOCATION     = "l";                  /* current location */
+var PARAM_LASSO        = "sg";                 /* current location */
+var PARAM_DEPTH                = "d";                  /* search depth */
+var PARAM_FORM                 = "f";                  /* search format */
+var PARAM_OFFSET               = "o";                  /* search offset */
+var PARAM_COUNT                = "c";                  /* hits per page */
+var PARAM_HITCOUNT     = "hc";                 /* hits per page */
+var PARAM_MRID                 = "m";                  /* metarecord id */
+var PARAM_RID                  = "r";                  /* record id */
+var PARAM_RLIST                = "rl";
+var PARAM_ORIGLOC              = "ol";                 /* the original location */
+var PARAM_AUTHTIME     = "at";                 /* inactivity timeout in seconds */
+var PARAM_ADVTERM              = "adv";                        /* advanced search term */
+var PARAM_ADVTYPE              = "adt";                        /* the advanced search type */
+var PARAM_RTYPE                = "rt";
+var PARAM_SORT                 = "s";
+var PARAM_SORT_DIR     = "sd";
+var PARAM_DEBUG                = "dbg";
+var PARAM_CN                   = "cn";
+var PARAM_LITFORM              = 'lf';
+var PARAM_ITEMFORM     = 'if';
+var PARAM_ITEMTYPE     = 'it';
+var PARAM_BIBLEVEL     = 'bl';
+var PARAM_AUDIENCE     = 'a';
+var PARAM_SEARCHES     = 'ss';
+var PARAM_LANGUAGE     = 'la';
+var PARAM_TFORM                = 'tf'; /* temporary format for title result pages */
+var PARAM_RDEPTH               = 'rd';
+var PARAM_REDIR                = 're'; /* true if we have been redirected by IP (we're at a real lib) */
+var PARAM_AVAIL     = 'av'; /* limit search results to available items */
+var PARAM_COPYLOCS  = 'cl'; // copy (shelving) locations
+var PARAM_PUBD_BEFORE = 'pdb';
+var PARAM_PUBD_AFTER = 'pda';
+var PARAM_PUBD_BETWEEN = 'pdt';
+var PARAM_PUBD_DURING = 'pdd';
+var PARAM_NOPERSIST_SEARCH = 'nps';
+
+/* URL param values (see comments above) */
+var TERM;  
+var FACET;  
+var STYPE;  
+var LOCATION;  
+var LASSO;  
+var DEPTH;  
+var FORM; 
+var OFFSET;
+var COUNT;  
+var HITCOUNT;  
+var RANKS; 
+var FONTSIZE;
+var ORIGLOC;
+var AUTHTIME;
+var ADVTERM;
+var ADVTYPE;
+var MRID;
+var RID;
+var RTYPE;
+var SORT;
+var SORT_DIR;
+var RLIST;
+var DEBUG;
+var CALLNUM;
+var LITFORM;
+var ITEMFORM;
+var ITEMTYPE;
+var BIBLEVEL;
+var AUDIENCE;
+var SEARCHES;
+var LANGUAGE;
+var TFORM;
+var RDEPTH;
+var AVAIL;
+var COPYLOCS;
+var PUBD_BEFORE;
+var PUBD_AFTER;
+var PUBD_BETWEEN;
+var PUBD_DURING;
+
+/* cookie values */
+var SBEXTRAS; 
+var SKIN;
+
+/* cookies */
+var COOKIE_SB          = "sbe";
+var COOKIE_SES         = "ses";
+//var COOKIE_IDS               = "ids"; /* list of mrecord ids */
+//var COOKIE_SRIDS     = "srids"; /* record ids cached from a search */
+var COOKIE_FONT        = "fnt";
+var COOKIE_SKIN        = "skin";
+var COOKIE_RIDS        = "rids"; /* list of record ids */
+var COOKIE_SEARCH = 'sr';
+
+/* pages */
+var MRESULT            = "mresult";
+var RRESULT            = "rresult";
+var RDETAIL            = "rdetail";
+var MYOPAC             = "myopac";
+var ADVANCED   = "advanced";
+var HOME                       = "home";
+var BBAGS              = "bbags";
+var REQITEMS   = "reqitems";
+var CNBROWSE   = "cnbrowse";
+
+/* search type (STYPE) options */
+var STYPE_AUTHOR       = "author";
+var STYPE_TITLE        = "title";
+var STYPE_SUBJECT      = "subject";
+var STYPE_SERIES       = "series";
+var STYPE_KEYWORD      = "keyword";
+
+/* record-level search types */
+var RTYPE_MRID         = "mrid";
+var RTYPE_COOKIE       = "cookie";
+var RTYPE_AUTHOR       = STYPE_AUTHOR;
+var RTYPE_SUBJECT      = STYPE_SUBJECT;
+var RTYPE_TITLE        = STYPE_TITLE;
+var RTYPE_SERIES       = STYPE_SERIES;
+var RTYPE_KEYWORD      = STYPE_KEYWORD;
+var RTYPE_LIST         = "list";
+var RTYPE_MULTI        = 'multi';
+var RTYPE_MARC         = 'marc';
+var RTYPE_ISBN         = 'isbn';
+var RTYPE_ISSN         = 'issn';
+var RTYPE_TCN          = 'tcn';
+
+var SORT_TYPE_REL                      = "rel";
+var SORT_TYPE_AUTHOR           = STYPE_AUTHOR; 
+var SORT_TYPE_TITLE            = STYPE_TITLE;
+var SORT_TYPE_PUBDATE  = "pubdate";
+var SORT_DIR_ASC                       = "asc";
+var SORT_DIR_DESC                      = "desc";
+
+/* types of advanced search */
+var ADVTYPE_MULTI = 'ml';
+var ADVTYPE_MARC       = 'ma';
+
+/*
+var ADVTYPE_ISBN       = 'isbn';
+var ADVTYPE_ISSN       = 'issn';
+*/
+
+var LOGOUT_WARNING_TIME = 30; /* "head up" for session timeout */
+
+/* user preferences */
+var PREF_HITS_PER              = 'opac.hits_per_page';
+var PREF_DEF_FONT              = 'opac.default_font';
+var PREF_HOLD_NOTIFY = 'opac.hold_notify';
+var PREF_DEF_LOCATION = 'opac.default_search_location';
+var PREF_DEF_DEPTH     = 'opac.default_search_depth';
+
+
+/** If enabled, added content attribution links will be 
+    made visible where appropriate.  The added content vendor name 
+    and URL are defined in the entities in opac.dtd
+    */
+var ENABLE_ADDED_CONTENT_ATTRIB_LINKS = false;
+
+
+/* container for global variables shared accross pages */
+var G          = {};
+G.user = null; /* global user object */
+G.ui           = {} /* cache of UI components */
+
+
+/* regexes */
+var REGEX_BARCODE = /^\d+/; /* starts with a number */
+var REGEX_PHONE = /^\d{3}-\d{3}-\d{4}$/; /* 111-222-3333 */
+
+
+/* call me after page init and I will load references 
+       to all of the ui object id's defined below 
+       They will be stored in G.ui.<page>.<thingy>
+ */
+function loadUIObjects() {
+       for( var p in config.ids ) {
+               G.ui[p] = {};
+               for( var o in config.ids[p] ) 
+                       G.ui[p][o] = getId(config.ids[p][o]);
+       }
+}
+
+/* try our best to free memory */
+function clearUIObjects() {
+       for( var p in config.ids ) {
+               for( var o in config.ids[p] ) {
+                       if(G.ui[p][o]) {
+                               G.ui[p][o].onclick = null;
+                               G.ui[p][o].onkeydown = null;
+                               G.ui[p][o] = null;
+                       }
+               }
+               G.ui[p] = null;
+       }
+}
+
+/* ---------------------------------------------------------------------------- 
+       Set up ID's and CSS classes 
+       Any new ids, css, etc. may be added by giving the unique names and putting 
+       them into the correct scope 
+/* ---------------------------------------------------------------------------- */
+
+var config = {};
+
+/* Set up the page names */
+config.page = {};
+config.page[HOME]                      = "index.xml";
+config.page[ADVANCED]  = "advanced.xml";
+config.page[MRESULT]           = "mresult.xml";
+config.page[RRESULT]           = "rresult.xml";
+config.page[MYOPAC]            = "myopac.xml";
+config.page[RDETAIL]           = "rdetail.xml";
+config.page[BBAGS]             = "bbags.xml";
+config.page[REQITEMS]  = "reqitems.xml";
+config.page[CNBROWSE]  = "cnbrowse.xml";
+
+/* themes */
+config.themes = {};
+
+/* set up images  */
+config.images = {};
+config.images.logo = "main_logo.jpg";
+
+
+/* set up ID's, CSS, and node names */
+config.ids                             = {};
+config.ids.result              = {};
+config.ids.mresult     = {};
+config.ids.advanced    = {};
+config.ids.rresult     = {};
+config.ids.myopac              = {};
+config.ids.rdetail     = {};
+
+config.css                             = {};
+config.css.result              = {};
+config.css.mresult     = {};
+config.css.advanced    = {};
+config.css.rresult     = {};
+config.css.myopac              = {};
+config.css.rdetail     = {};
+
+config.names                   = {};
+config.names.result    = {};
+config.names.mresult = {};
+config.names.advanced = {};
+config.names.rresult = {};
+config.names.myopac    = {};
+config.names.rdetail = {};
+
+
+/* id's shared accross skins. These *must* be defined */
+config.ids.common = {};
+config.ids.common.loading                      = "loading_div";                
+config.ids.common.canvas                       = "canvas";                             
+config.ids.common.canvas_main          = "canvas_main";                
+config.ids.common.org_tree                     = "org_tree";                   
+config.ids.common.org_container        = "org_container";
+
+config.ids.xul = {};
+
+
+/* shared CSS */
+config.css.hide_me = "hide_me";
+config.css.dim = "dim";
+config.css.dim2 = "dim2";
+
+
+/* ---------------------------------------------------------------------------- */
+/* These are pages that may replace the canvas */
+/* ---------------------------------------------------------------------------- */
+config.ids.altcanvas = {};
+
+
+
+/* ---------------------------------------------------------------------------- */
+/* Methods are defined as service:method 
+       An optional 3rd component is when a method is followed by a :1, such methods
+       have a staff counterpart and should have ".staff" appended to the method 
+       before the method is called when in XUL mode */
+
+var SEARCH_MRS                                         = 'open-ils.search:open-ils.search.metabib.multiclass:1';
+var SEARCH_RS                                          = 'open-ils.search:open-ils.search.biblio.multiclass:1';
+var SEARCH_MRS_QUERY                   = 'open-ils.search:open-ils.search.metabib.multiclass.query:1';
+var SEARCH_RS_QUERY             = 'open-ils.search:open-ils.search.biblio.multiclass.query:1';
+var FETCH_SEARCH_RIDS                  = "open-ils.search:open-ils.search.biblio.record.class.search:1";
+var CREATE_MFHD_RECORD                 = "open-ils.cat:open-ils.cat.serial.record.xml.create";
+var DELETE_MFHD_RECORD                 = "open-ils.cat:open-ils.cat.serial.record.delete";
+var FETCH_MFHD_SUMMARY                 = "open-ils.search:open-ils.search.serial.record.bib.retrieve";
+var FETCH_MRMODS                                       = "open-ils.search:open-ils.search.biblio.metarecord.mods_slim.retrieve";
+var FETCH_MODS_FROM_COPY               = "open-ils.search:open-ils.search.biblio.mods_from_copy";
+var FETCH_MR_COPY_COUNTS               = "open-ils.search:open-ils.search.biblio.metarecord.copy_count:1";
+var FETCH_RIDS                                         = "open-ils.search:open-ils.search.biblio.metarecord_to_records:1";
+var FETCH_RMODS                                        = "open-ils.search:open-ils.search.biblio.record.mods_slim.retrieve";
+var FETCH_R_COPY_COUNTS                        = "open-ils.search:open-ils.search.biblio.record.copy_count:1";
+var FETCH_FLESHED_USER                 = "open-ils.actor:open-ils.actor.user.fleshed.retrieve";
+var FETCH_SESSION                                      = "open-ils.auth:open-ils.auth.session.retrieve";
+var LOGIN_INIT                                         = "open-ils.auth:open-ils.auth.authenticate.init";
+var LOGIN_COMPLETE                             = "open-ils.auth:open-ils.auth.authenticate.complete";
+var LOGIN_DELETE                                       = "open-ils.auth:open-ils.auth.session.delete";
+var FETCH_USER_PREFS                           = "open-ils.actor:open-ils.actor.patron.settings.retrieve"; 
+var UPDATE_USER_PREFS                  = "open-ils.actor:open-ils.actor.patron.settings.update"; 
+var FETCH_COPY_STATUSES                        = "open-ils.search:open-ils.search.config.copy_status.retrieve.all";
+var FETCH_COPY_LOCATION_COUNTS_SUMMARY = "open-ils.search:open-ils.search.biblio.copy_location_counts.summary.retrieve";
+var FETCH_COPY_COUNTS_SUMMARY  = "open-ils.search:open-ils.search.biblio.copy_counts.summary.retrieve";
+//var FETCH_COPY_COUNTS_SUMMARY        = "open-ils.search:open-ils.search.biblio.copy_counts.location.summary.retrieve";
+var FETCH_MARC_HTML                            = "open-ils.search:open-ils.search.biblio.record.html";
+var FETCH_CHECKED_OUT_SUM              = "open-ils.actor:open-ils.actor.user.checked_out";
+var FETCH_HOLDS                                        = "open-ils.circ:open-ils.circ.holds.retrieve";
+var FETCH_FINES_SUMMARY                        = "open-ils.actor:open-ils.actor.user.fines.summary";
+var FETCH_TRANSACTIONS                 = "open-ils.actor:open-ils.actor.user.transactions.have_charge.fleshed";
+var FETCH_MONEY_BILLING                        = 'open-ils.circ:open-ils.circ.money.billing.retrieve.all';
+var FETCH_CROSSREF                             = "open-ils.search:open-ils.search.authority.crossref";
+var FETCH_CROSSREF_BATCH               = "open-ils.search:open-ils.search.authority.crossref.batch";
+var CREATE_HOLD                                        = "open-ils.circ:open-ils.circ.holds.create";
+var CREATE_HOLD_OVERRIDE               = "open-ils.circ:open-ils.circ.holds.create.override";
+var CANCEL_HOLD                                        = "open-ils.circ:open-ils.circ.hold.cancel";
+var UPDATE_USERNAME                            = "open-ils.actor:open-ils.actor.user.username.update";
+var UPDATE_PASSWORD                            = "open-ils.actor:open-ils.actor.user.password.update";
+var UPDATE_EMAIL                                       = "open-ils.actor:open-ils.actor.user.email.update";
+var RENEW_CIRC                                         = "open-ils.circ:open-ils.circ.renew";
+var CHECK_SPELL                                        = "open-ils.search:open-ils.search.spellcheck";
+var FETCH_REVIEWS                                      = "open-ils.search:open-ils.search.added_content.review.retrieve.all";
+var FETCH_TOC                                          = "open-ils.search:open-ils.search.added_content.toc.retrieve";
+var FETCH_ACONT_SUMMARY                        = "open-ils.search:open-ils.search.added_content.summary.retrieve";
+var FETCH_USER_BYBARCODE               = "open-ils.actor:open-ils.actor.user.fleshed.retrieve_by_barcode";
+var FETCH_ADV_MARC_MRIDS               = "open-ils.search:open-ils.search.biblio.marc:1";
+var FETCH_ADV_ISBN_RIDS                        = "open-ils.search:open-ils.search.biblio.isbn";
+var FETCH_ADV_ISSN_RIDS                        = "open-ils.search:open-ils.search.biblio.issn";
+var FETCH_ADV_TCN_RIDS                 = "open-ils.search:open-ils.search.biblio.tcn";
+var FETCH_CNBROWSE                             = 'open-ils.search:open-ils.search.callnumber.browse';
+var FETCH_CONTAINERS                           = 'open-ils.actor:open-ils.actor.container.retrieve_by_class';
+var FETCH_CONTAINERS                           = 'open-ils.actor:open-ils.actor.container.retrieve_by_class';
+var CREATE_CONTAINER                           = 'open-ils.actor:open-ils.actor.container.create';
+var DELETE_CONTAINER                           = 'open-ils.actor:open-ils.actor.container.full_delete';
+var CREATE_CONTAINER_ITEM              = 'open-ils.actor:open-ils.actor.container.item.create';
+var DELETE_CONTAINER_ITEM              = 'open-ils.actor:open-ils.actor.container.item.delete';
+var FLESH_CONTAINER                            = 'open-ils.actor:open-ils.actor.container.flesh';
+var FLESH_PUBLIC_CONTAINER             = 'open-ils.actor:open-ils.actor.container.public.flesh';
+var UPDATE_CONTAINER                           = 'open-ils.actor:open-ils.actor.container.update';
+var FETCH_COPY                                         = 'open-ils.search:open-ils.search.asset.copy.retrieve';
+var FETCH_FLESHED_COPY                 = 'open-ils.search:open-ils.search.asset.copy.fleshed2.retrieve';
+var CHECK_HOLD_POSSIBLE                        = 'open-ils.circ:open-ils.circ.title_hold.is_possible';
+var UPDATE_HOLD                                        = 'open-ils.circ:open-ils.circ.hold.update';
+var FETCH_COPIES_FROM_VOLUME   = 'open-ils.search:open-ils.search.asset.copy.retrieve_by_cn_label:1';
+var FETCH_VOLUME_BY_INFO               = 'open-ils.search:open-ils.search.call_number.retrieve_by_info'; /* XXX staff method? */
+var FETCH_VOLUME                                       = 'open-ils.search:open-ils.search.asset.call_number.retrieve';
+var FETCH_ISSUANCE                                     = 'open-ils.serial:open-ils.serial.issuance.pub_fleshed.batch.retrieve';
+var FETCH_COPY_LOCATIONS               = 'open-ils.circ:open-ils.circ.copy_location.retrieve.all';
+var FETCH_COPY_NOTES                           = 'open-ils.circ:open-ils.circ.copy_note.retrieve.all';
+var FETCH_COPY_STAT_CATS               = 'open-ils.circ:open-ils.circ.asset.stat_cat_entries.fleshed.retrieve_by_copy';
+var FETCH_LIT_FORMS                            = 'open-ils.search:open-ils.search.biblio.lit_form_map.retrieve.all';
+var FETCH_ITEM_FORMS                           = 'open-ils.search:open-ils.search.biblio.item_form_map.retrieve.all';
+var FETCH_ITEM_TYPES                           = 'open-ils.search:open-ils.search.biblio.item_type_map.retrieve.all';
+var FETCH_BIB_LEVELS                           = 'open-ils.search:open-ils.search.biblio.bib_level_map.retrieve.all';
+var FETCH_AUDIENCES                            = 'open-ils.search:open-ils.search.biblio.audience_map.retrieve.all';
+//var FETCH_HOLD_STATUS                        = 'open-ils.circ:open-ils.circ.hold.status.retrieve';
+var FETCH_HOLD_STATUS                  = 'open-ils.circ:open-ils.circ.hold.queue_stats.retrieve';
+var FETCH_NON_CAT_CIRCS                        = 'open-ils.circ:open-ils.circ.open_non_cataloged_circulation.user';
+var FETCH_NON_CAT_CIRC                 = 'open-ils.circ:open-ils.circ.non_cataloged_circulation.retrieve';
+var FETCH_NON_CAT_TYPES                        = "open-ils.circ:open-ils.circ.non_cat_types.retrieve.all";
+var FETCH_BRE                                          = 'open-ils.search:open-ils.search.biblio.record_entry.slim.retrieve';
+var CHECK_USERNAME                             = 'open-ils.actor:open-ils.actor.username.exists';
+var FETCH_CIRC_BY_ID                           = 'open-ils.circ:open-ils.circ.retrieve';
+var FETCH_MR_DESCRIPTORS               = 'open-ils.search:open-ils.search.metabib.record_to_descriptors';
+var FETCH_HIGHEST_PERM_ORG             = 'open-ils.actor:open-ils.actor.user.perm.highest_org.batch';
+var FETCH_USER_NOTES                           = 'open-ils.actor:open-ils.actor.note.retrieve.all';
+var FETCH_ORG_BY_SHORTNAME             = 'open-ils.actor:open-ils.actor.org_unit.retrieve_by_shortname';
+var FETCH_BIB_ID_BY_BARCODE = 'open-ils.search:open-ils.search.bib_id.by_barcode';
+var FETCH_ORG_SETTING = 'open-ils.actor:open-ils.actor.ou_setting.ancestor_default';
+
+/* ---------------------------------------------------------------------------- */
+
+
+/* ---------------------------------------------------------------------------- */
+/* event callback functions. Other functions may be appended to these vars to
+       for added functionality.  */
+
+G.evt                          = {}; /* events container */
+
+function runEvt(scope, name, a, b, c, d, e, f, g) {
+       var evt = G.evt[scope][name];
+       for( var i in evt ) {
+               evt[i](a, b, c, d, e, f, g);    
+       }
+}
+
+/* creates a new event if it doesn't already exist */
+function createEvt(scope, name) {
+       if(!G.evt[scope]) G.evt[scope] = {};
+       if(G.evt[scope][name] == null)
+               G.evt[scope][name] = []; 
+}
+
+function attachEvt(scope, name, action) {
+       createEvt(scope, name);
+       G.evt[scope][name].push(action);
+}
+
+function detachAllEvt(scope, name) {
+       G.evt[scope][name] = [];
+}
+
+
+createEvt("common", "init");                                           /* f() : what happens on page init */
+createEvt("common", "pageRendered");                   /* f() : what happens when the page is done (up to the skin to call this even)*/
+createEvt("common", "unload");                                 /* f() : what happens on window unload (clean memory, etc.)*/
+createEvt("common", "locationChanged");                /* f() : what happens when the location has changed */
+createEvt("common", "locationUpdated");                /* f() : what happens when the location has updated by the code */
+
+createEvt("common", "run");                                            /* f() : make the page do stuff */
+createEvt("result", "idsReceived");                            /* f(ids) */
+createEvt("rresult", "recordDrawn");                   /* f(recordid, linkDOMNode) : after record is drawn, allow others (xul) to plugin actions */
+createEvt("result", "preCollectRecords");              /* f() we're about to go and grab the recs */
+
+createEvt("result", "hitCountReceived");               /* f() : display hit info, pagination, etc. */
+createEvt("result", "recordReceived");                 /* f(mvr, pagePosition, isMr) : display the record*/
+createEvt("result", "recordDrawn");                            /* f(recordid, linkDOMNode) : after record is drawn, allow others (xul) to plugin actions */
+createEvt("result", "copyCountsReceived");     /* f(mvr, pagePosition, copyCountInfo) : display copy counts*/
+createEvt("result", "allRecordsReceived");     /* f(mvrsArray) : add other page stuff, sidebars, etc.*/
+
+createEvt("rdetail", "recordDrawn");                   /* f() : the record has been drawn */
+
+createEvt("common", "loggedIn");                                       /* f() : user has just logged in */
+createEvt('result', 'zeroHits');
+createEvt('result', 'lowHits');
+createEvt('rdetail', 'recordRetrieved');                       /* we are about to draw the rdetail page */
+createEvt('common', 'depthChanged');
+createEvt('common', 'holdUpdated'); 
+createEvt('common', 'holdUpdateCanceled'); 
+
+createEvt('rdetail', 'nextPrevDrawn');
+
+
+
+
+
+function CGI() {
+       /* load up the url parameters */
+
+       this._keys = new Array();
+       this.data = new Object();
+
+       var string = location.search.replace(/^\?/,"");
+       this.server_name = location.href.replace(/^https?:\/\/([^\/]+).+$/,"$1");
+
+       var key = ""; 
+       var value = "";
+       var inkey = true;
+       var invalue = false;
+
+       for( var idx = 0; idx!= string.length; idx++ ) {
+
+               var c = string.charAt(idx);
+
+               if( c == "=" )  {
+                       invalue = true;
+                       inkey = false;
+                       continue;
+               } 
+
+               if(c == "&" || c == ";") {
+                       inkey = 1;
+                       invalue = 0;
+                       if( ! this.data[key] ) this.data[key] = [];
+                       this.data[key].push(decodeURIComponent(value));
+                       this._keys.push(key);
+                       key = ""; value = "";
+                       continue;
+               }
+
+               if(inkey) key += c;
+               else if(invalue) value += c;
+       }
+
+       if( ! this.data[key] ) this.data[key] = [];
+       this.data[key].push(decodeURIComponent(value));
+       this._keys.push(key);
+}
+
+/* returns the value for the given param.  If there is only one value for the
+   given param, it returns that value.  Otherwise it returns an array of values
+ */
+CGI.prototype.param = function(p) {
+       if(this.data[p] == null) return null;
+       if(this.data[p].length == 1)
+               return this.data[p][0];
+       return this.data[p];
+}
+
+/* returns an array of param names */
+CGI.prototype.keys = function() {
+       return this._keys;
+}
+
+/* debuggin method */
+CGI.prototype.toString = function() {
+       var string = "";
+       var keys = this.keys();
+
+       for( var k in keys ) {
+               string += keys[k] + " : ";
+               var params = this.param(keys[k]);
+
+               for( var p in params ) {
+                       string +=  params[p] + " ";
+               }
+               string += "\n";
+       }
+       return string;
+}
+
+
+// HTTP.Cookies - Burak Gürsoy <burak[at]cpan[dot]org>
+
+/*
+I removed all the docs (except author and license info) to reduce download size
+-bill erickson <billserickson@gmail.com>
+*/
+
+if (!HTTP) var HTTP = {}; // create base class if undefined
+
+HTTP.Cookies = function () { // HTTP.Cookies constructor
+   this.JAR = ''; // data cache
+}
+
+HTTP.Cookies.VERSION = '1.01';
+
+HTTP.Cookies.Date = function () { // expire time calculation class
+   this.format = {
+   's' : 1,
+   'm' : 60,
+   'h' : 60 * 60,
+   'd' : 60 * 60 * 24,
+   'M' : 60 * 60 * 24 * 30,
+   'y' : 60 * 60 * 24 * 365
+   };
+}
+
+HTTP.Cookies.Date.prototype.parse = function (x) {
+   if(!x || x == 'now') return 0;
+   var date = x.match(/^(.+?)(\w)$/i);
+   var of = 0;
+   return (this.is_num(date[1]) && (of = this.is_date(date[1],date[2]))) ? of : 0;
+}
+
+HTTP.Cookies.Date.prototype.is_date = function (num, x) {
+   if (!x || x.length != 1) return 0;
+   var ar = [];
+   return (ar = x.match(/^(s|m|h|d|w|M|y)$/) ) ? num * 1000 * this.format[ar[0]] : 0;
+}
+
+HTTP.Cookies.Date.prototype.is_num = function (x) {
+   if (x.length == 0) return;
+   var ok = 1;
+   for (var i = 0; i < x.length; i++) {
+      if ("0123456789.-+".indexOf(x.charAt(i)) == -1) {
+         ok--;
+         break;
+      }
+   }
+   return ok;
+}
+
+HTTP.Cookies.prototype.date = new HTTP.Cookies.Date; // date object instance
+
+// Get the value of the named cookie. Usage: password = cookie.read('password');
+HTTP.Cookies.prototype.read = function (name) {
+   var value  = '';
+   if(!this.JAR) {
+               this.JAR = {};
+      var array  = document.cookie.split(';');
+      for (var x = 0; x < array.length; x++) {
+         var pair = array[x].split('=');
+         if(pair[0].substring (0,1) == ' ') pair[0] = pair[0].substring(1, pair[0].length);
+         if(pair[0] == name) {
+            value = pair[1];
+         }
+         this.JAR[pair[0]] = pair[1];
+      }
+   } else {
+      for(var cookie in this.JAR) {
+         if(cookie == name) {
+            value = this.JAR[cookie];
+         }
+          }
+   }
+   return value ? unescape(value) : '';
+}
+
+// Create a new cookie or overwrite existing. Usage: cookie.write('password', 'secret', '1m');
+HTTP.Cookies.prototype.write = function (name, value, expires, path, domain, secure) {
+   var extra = '';
+   if (!expires) expires = '';
+   if (expires == '_epoch') {
+      expires = new Date(0);
+   } else if (expires != -1) {
+      var Now  = new Date;
+      Now.setTime(Now.getTime() + this.date.parse(expires));
+      expires = Now.toGMTString();
+   }
+   if(expires != -1 && expires) extra += "; expires=" + expires;
+   if(path   ) extra += "; path="    + path;
+   if(domain ) extra += "; domain="  + domain;
+   if(secure ) extra += "; secure="  + secure;
+   document.cookie = name + "=" + escape(value) + extra;
+}
+
+// Delete the named cookie. Usage: cookie.remove('password');
+HTTP.Cookies.prototype.remove = function (name, path, domain, secure) {
+   this.write(name, '', '_epoch', path, domain, secure);
+}
+
+/*
+
+=head1 NAME
+
+HTTP.Cookies - JavaScript class for reading, writing and deleting cookies
+
+=head1 AUTHOR
+
+Burak Gürsoy, E<lt>burakE<64>cpan.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright 2005 Burak Gürsoy. All rights reserved.
+
+=head1 LICENSE
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the "Artistic License":
+L<http://dev.perl.org/licenses/artistic.html>.
+
+=cut
+
+*/
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}
+/*
+var stpicopen  = '../../../../images/slimtree/folder.gif';
+var stpicclose = '../../../../images/slimtree/folderopen.gif';
+*/
+var stpicopen  = '../../../../images/slimtree/folder2.gif';
+var stpicclose = '../../../../images/slimtree/folderopen2.gif';
+var stpicblank = '../../../../images/slimtree/page.gif';
+var stpicline  = '../../../../images/slimtree/line.gif';
+var stpicjoin  = '../../../../images/slimtree/join.gif';
+var stpicjoinb = '../../../../images/slimtree/joinbottom.gif';
+
+var stimgopen;
+var stimgclose;
+var stimgblank;
+var stimgline;
+var stimgjoin;
+
+function _apc(root,node) { root.appendChild(node); }
+
+function SlimTree(context, handle, rootimg) { 
+       
+       if(!stimgopen) {
+               stimgopen       = elem('img',{src:stpicopen,border:0, style:'height:13px;width:31px;'});
+               stimgclose      = elem('img',{src:stpicclose,border:0, style:'height:13px;width:31px;'});
+               stimgblank      = elem('img',{src:stpicblank,border:0, style:'height:18px;width:18px;'});
+               stimgline       = elem('img',{src:stpicline,border:0, style:'height:18px;width:18px;'});
+               stimgjoin       = elem('img',{src:stpicjoin,border:0, style:'display:inline;height:18px;width:18px;'});
+       }
+
+       this.context    = context; 
+       this.handle             = handle;
+       this.cache              = new Object();
+       if(rootimg) 
+               this.rootimg = elem('img', 
+                       {src:rootimg,border:0,style:'padding-right: 4px;'});
+}
+
+SlimTree.prototype.addCachedChildren = function(pid) {
+       var child;
+       while( child = this.cache[pid].shift() ) 
+               this.addNode( child.id, child.pid, 
+                       child.name, child.action, child.title );
+       this.cache[pid] = null;
+}
+
+SlimTree.prototype.addNode = function( id, pid, name, action, title, cls ) {
+
+       if( pid != -1 && !$(pid)) {
+               if(!this.cache[pid]) this.cache[pid] = new Array();
+               this.cache[pid].push(
+                       {id:id,pid:pid,name:name,action:action,title:title });
+               return;
+       }
+
+       if(!action)
+               action='javascript:'+this.handle+'.toggle("'+id+'");';
+
+       var actionref;
+       if( typeof action == 'string' )
+               actionref = elem('a',{href:action}, name);
+       else {
+               actionref = elem('a',{href:'javascript:void(0);'}, name);
+               actionref.onclick = action;
+       }
+
+       var div                 = elem('div',{id:id});
+       var topdiv              = elem('div',{style:'vertical-align:middle'});
+       var link                        = elem('a', {id:'stlink_' + id}); 
+       var contdiv             = elem('div',{id:'stcont_' + id});
+
+       if(cls) addCSSClass(actionref, cls);
+
+       //actionref.setAttribute('href',action);
+       if(title) actionref.setAttribute('title',title);
+       else actionref.setAttribute('title',name);
+
+       _apc(topdiv,link);
+       _apc(topdiv,actionref);
+       _apc(div,topdiv);
+       _apc(div,contdiv);
+
+       if( pid == -1 ) { 
+
+               this.rootid = id;
+               _apc(this.context,div);
+               if(this.rootimg) _apc(link,this.rootimg.cloneNode(true));
+               else _apc(link,stimgblank.cloneNode(true));
+
+       } else {
+
+               if(pid == this.rootid) this.open(pid);
+               else this.close(pid);
+               $(pid).setAttribute('haschild','1');
+               _apc(link,stimgblank.cloneNode(true));
+               div.style.paddingLeft = '18px';
+               div.style.backgroundImage = 'url('+stpicjoinb+')';
+               div.style.backgroundRepeat = 'no-repeat';
+               _apc($('stcont_' + pid), div);
+               if (div.previousSibling) stMakePaths(div);
+       }
+       if(this.cache[id]) this.addCachedChildren(id);
+}
+
+function stMakePaths(div) {
+       _apc(div.previousSibling.firstChild,stimgjoin.cloneNode(true));
+       _apc(div.previousSibling.firstChild,div.previousSibling.firstChild.firstChild);
+       _apc(div.previousSibling.firstChild,div.previousSibling.firstChild.firstChild);
+       div.previousSibling.firstChild.firstChild.style.marginLeft = '-18px';
+       div.previousSibling.style.backgroundImage = 'url('+stpicline+')';
+       div.previousSibling.style.backgroundRepeat = 'repeat-y';
+}
+
+SlimTree.prototype.expandAll = function() { this.flex(this.rootid, 'open'); }
+SlimTree.prototype.closeAll = function() { this.flex(this.rootid,'close'); }
+SlimTree.prototype.flex = function(id, type) {
+       if(type=='open') this.open(id);
+       else { if (id != this.rootid) this.close(id); }
+       var n = $('stcont_' + id);
+       for( var c = 0; c != n.childNodes.length; c++ ) {
+               var ch = n.childNodes[c];
+               if(ch.nodeName.toLowerCase() == 'div') {
+                       if($(ch.id).getAttribute('haschild') == '1') 
+                               this.flex(ch.id, type);
+               }
+       }
+}
+
+SlimTree.prototype.toggle = function(id) {
+       if($(id).getAttribute('ostate') == '1') this.open(id);
+       else if($(id).getAttribute('ostate') == '2') this.close(id);
+}
+
+SlimTree.prototype.open = function(id) {
+       if($(id).getAttribute('ostate') == '2') return;
+       var link = $('stlink_' + id);
+       if(!link) return;
+       if(id != this.rootid || !this.rootimg) {
+               removeChildren(link);
+               _apc(link,stimgclose.cloneNode(true));
+       }
+       link.setAttribute('href','javascript:' + this.handle + '.close("'+id+'");');
+       unHideMe($('stcont_' + id));
+       $(id).setAttribute('ostate','2');
+}
+
+SlimTree.prototype.close = function(id) {
+       var link = $('stlink_' + id);
+       if(!link) return;
+       if(id != this.rootid || !this.rootimg) {
+               removeChildren(link);
+               _apc(link,stimgopen.cloneNode(true));
+       }
+       link.setAttribute('href','javascript:' + this.handle + '.open("'+id+'");');
+       hideMe($('stcont_' + id));
+       $(id).setAttribute('ostate','1');
+}
+
+/* - Request ------------------------------------------------------------- */
+
+
+/* define it again here for pages that don't load RemoteRequest */
+function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
+
+
+var cookieManager = new HTTP.Cookies();
+
+var __ilsEvent; /* the last event the occurred */
+
+var DEBUGSLIM;
+function Request(type) {
+
+       var s = type.split(":");
+       if(s[2] == "1" && isXUL()) s[1] += ".staff";
+       this.request = new RemoteRequest(s[0], s[1]);
+       var p = [];
+
+       if(isXUL()) {
+               if(!location.href.match(/^https:/))
+                       this.request.setSecure(false);
+
+       } else {
+
+               if( G.user && G.user.session ) {
+                       /* if the user is logged in, all activity resets the timeout 
+                               This is not entirely accurate in the sense that not all 
+                               requests will reset the server timeout - this should
+                               get close enough, however.
+                       */
+                       var at = getAuthtime();
+                       if(at) new AuthTimer(at).run(); 
+               }
+       }
+
+       for( var x = 1; x!= arguments.length; x++ ) {
+               p.push(arguments[x]);
+               this.request.addParam(arguments[x]);
+       }
+
+       if( getDebug() ) {
+               var str = "";
+               for( var i = 0; i != p.length; i++ ) {
+                       if( i > 0 ) str += ", "
+                       str += js2JSON(p[i]);
+               }
+               _debug('request ' + s[0] + ' ' + s[1] + ' ' + str );
+
+       } else if( DEBUGSLIM ) {
+               _debug('request ' + s[1]);
+       }
+}
+
+Request.prototype.callback = function(cal) {this.request.setCompleteCallback(cal);}
+Request.prototype.send         = function(block){this.request.send(block);}
+Request.prototype.result       = function(){return this.request.getResultObject();}
+
+function showCanvas() {
+       for( var x in G.ui.altcanvas ) {
+               hideMe(G.ui.altcanvas[x]);
+       }
+       hideMe(G.ui.common.loading);
+       unHideMe(G.ui.common.canvas_main);
+       try{G.ui.searchbar.text.focus();}catch(e){}
+}
+
+function swapCanvas(newNode) {
+       for( var x in G.ui.altcanvas ) 
+               hideMe(G.ui.altcanvas[x]);
+
+       hideMe(G.ui.common.loading);
+       hideMe(G.ui.common.canvas_main);
+       unHideMe(newNode);
+}
+
+/* finds the name of the current page */
+var currentPage = null;
+function findCurrentPage() {
+       if(currentPage) return currentPage;
+
+       var pages = [];
+       for( var p in config.page ) pages.push(config.page[p]);
+       pages = pages.sort( function(a,b){ return - (a.length - b.length); } );
+
+       var path = location.pathname;
+       if(!path.match(/.*\.xml$/))
+               path += "index.xml"; /* in case they go to  / */
+
+       var page = null;
+       for( var p = 0; p < pages.length; p++ ) {
+               if( path.indexOf(pages[p]) != -1)
+                       page = pages[p];
+       }
+
+       for( var p in config.page ) {
+               if(config.page[p] == page) {
+                       currentPage = p;
+                       return p;
+               }
+       }
+       return null;
+}
+
+
+/* sets all of the params values  ----------------------------- */
+function initParams() {
+       var cgi = new CGI();    
+
+       /* handle the location var */
+       var org;
+       var loc = cgi.param(PARAM_LOCATION);
+       var lasso = cgi.param(PARAM_LASSO);
+
+    if ( lasso ) {
+               lasso = findOrgLasso( lasso );
+               LASSO = lasso ? lasso.id() : null;
+       }
+
+    if (loc) {
+               org = findOrgUnit(loc);
+               LOCATION = org ? org.id() : null;
+
+               if ( !LOCATION ){
+                       org = findOrgUnit(loc);
+                       LOCATION = org ? org.id() : null;
+               }
+    }
+
+       org = null;
+       loc = cgi.param(PARAM_ORIGLOC);
+       if( loc ) {
+               org = findOrgUnit(loc);
+               if(!org) org = findOrgUnitSN(loc);
+       }
+       ORIGLOC = (org) ? org.id() : null;
+
+
+       DEPTH = parseInt(cgi.param(PARAM_DEPTH));
+       if(isNaN(DEPTH)) DEPTH = null;
+
+
+       FACET           = cgi.param(PARAM_FACET);
+       TERM            = cgi.param(PARAM_TERM);
+       STYPE           = cgi.param(PARAM_STYPE);
+       FORM            = cgi.param(PARAM_FORM);
+       //DEPTH         = parseInt(cgi.param(PARAM_DEPTH));
+       OFFSET  = parseInt(cgi.param(PARAM_OFFSET));
+       COUNT           = parseInt(cgi.param(PARAM_COUNT));
+       HITCOUNT        = parseInt(cgi.param(PARAM_HITCOUNT));
+       MRID            = parseInt(cgi.param(PARAM_MRID));
+       RID             = parseInt(cgi.param(PARAM_RID));
+       AUTHTIME        = parseInt(cgi.param(PARAM_AUTHTIME));
+       ADVTERM = cgi.param(PARAM_ADVTERM);
+       ADVTYPE = cgi.param(PARAM_ADVTYPE);
+       RTYPE           = cgi.param(PARAM_RTYPE);
+       SORT            = cgi.param(PARAM_SORT);
+       SORT_DIR        = cgi.param(PARAM_SORT_DIR);
+       DEBUG           = cgi.param(PARAM_DEBUG);
+       CALLNUM = cgi.param(PARAM_CN);
+       LITFORM = cgi.param(PARAM_LITFORM);
+       ITEMFORM        = cgi.param(PARAM_ITEMFORM);
+       ITEMTYPE        = cgi.param(PARAM_ITEMTYPE);
+       BIBLEVEL        = cgi.param(PARAM_BIBLEVEL);
+       AUDIENCE        = cgi.param(PARAM_AUDIENCE);
+       SEARCHES = cgi.param(PARAM_SEARCHES);
+       LANGUAGE        = cgi.param(PARAM_LANGUAGE);
+       TFORM           = cgi.param(PARAM_TFORM);
+       RDEPTH  = cgi.param(PARAM_RDEPTH);
+    AVAIL   = cgi.param(PARAM_AVAIL);
+    COPYLOCS   = cgi.param(PARAM_COPYLOCS);
+    PUBD_BEFORE = cgi.param(PARAM_PUBD_BEFORE);
+    PUBD_AFTER = cgi.param(PARAM_PUBD_AFTER);
+    PUBD_BETWEEN = cgi.param(PARAM_PUBD_BETWEEN);
+    PUBD_DURING = cgi.param(PARAM_PUBD_DURING);
+
+    
+       /* set up some sane defaults */
+       //if(isNaN(DEPTH))      DEPTH           = 0;
+       if(isNaN(RDEPTH))       RDEPTH  = 0;
+       if(isNaN(OFFSET))       OFFSET  = 0;
+       if(isNaN(COUNT))        COUNT           = 10;
+       if(isNaN(HITCOUNT))     HITCOUNT        = 0;
+       if(isNaN(MRID))         MRID            = 0;
+       if(isNaN(RID))          RID             = 0;
+       if(isNaN(ORIGLOC))      ORIGLOC = 0; /* so we know it hasn't been set */
+       if(isNaN(AUTHTIME))     AUTHTIME        = 0;
+       if(ADVTERM==null)       ADVTERM = "";
+    if(isNaN(AVAIL))    AVAIL = 0;
+}
+
+function clearSearchParams() {
+       TERM        = null;
+       STYPE       = null;
+       FORM        = null;
+       OFFSET      = 0;
+       HITCOUNT    = 0;  
+       ADVTERM     = null;
+       ADVTYPE     = null;
+       MRID        = null;
+       RID         = null;
+       RTYPE       = null;
+       SORT        = null;
+       SORT_DIR    = null;
+       RLIST       = null;
+       CALLNUM     = null;
+       LITFORM     = null;
+       ITEMFORM    = null;
+       ITEMTYPE    = null;
+       BIBLEVEL    = null;
+       AUDIENCE    = null;
+       SEARCHES    = null;
+       LANGUAGE    = null;
+       RDEPTH      = null;
+    AVAIL       = null;
+    COPYLOCS    = null;
+    PUBD_BEFORE = null;
+    PUBD_AFTER  = null;
+    PUBD_BETWEEN = null;
+    PUBD_DURING = null;
+}
+
+
+function initCookies() {
+       FONTSIZE = "regular";
+       var font = cookieManager.read(COOKIE_FONT);
+       scaleFonts(font);
+       if(font) FONTSIZE = font;
+       SKIN = cookieManager.read(COOKIE_SKIN);
+    if(findCurrentPage() == HOME)
+        cookieManager.remove(COOKIE_SEARCH);
+}
+
+/* URL param accessors */
+function getTerm(){return TERM;}
+function getFacet(){return FACET;}
+function getStype(){return STYPE;}
+function getLocation(){return LOCATION;}
+function getLasso(){return LASSO;}
+function getDepth(){return DEPTH;}
+function getForm(){return FORM;}
+function getTform(){return TFORM;}
+function getOffset(){return OFFSET;}
+function getDisplayCount(){return COUNT;}
+function getHitCount(){return HITCOUNT;}
+function getMrid(){return MRID;};
+function getRid(){return RID;};
+function getOrigLocation(){return ORIGLOC;}
+function getAuthtime() { return AUTHTIME; }
+function getSearchBarExtras(){return SBEXTRAS;}
+function getFontSize(){return FONTSIZE;};
+function getSkin(){return SKIN;};
+function getAdvTerm(){return ADVTERM;}
+function getAdvType(){return ADVTYPE;}
+function getRtype(){return RTYPE;}
+function getSort(){return SORT;}
+function getSortDir(){return SORT_DIR;}
+function getDebug(){return DEBUG;}
+function getCallnumber() { return CALLNUM; }
+function getLitForm() { return LITFORM; }
+function getItemForm() { return ITEMFORM; }
+function getItemType() { return ITEMTYPE; }
+function getBibLevel() { return BIBLEVEL; }
+function getAudience() { return AUDIENCE; }
+function getSearches() { return SEARCHES; }
+function getLanguage() { return LANGUAGE; }
+function getRdepth() { return RDEPTH; }
+function getAvail() { return AVAIL; }
+function getCopyLocs() { return COPYLOCS; }
+function getPubdBefore() { return PUBD_BEFORE; }
+function getPubdAfter() { return PUBD_AFTER; }
+function getPubdBetween() { return PUBD_BETWEEN; }
+function getPubdDuring() { return PUBD_DURING; }
+
+
+function findBasePath() {
+       var path = location.pathname;
+       if(!path.match(/.*\.xml$/)) path += "index.xml"; 
+       var idx = path.indexOf(config.page[findCurrentPage()]);
+       return path.substring(0, idx);
+}
+
+function findBaseURL(ssl) {
+       var path = findBasePath();
+       var proto = (ssl) ? "https:" : "http:";
+
+       /* strip port numbers.  This is necessary for browsers that
+       send an explicit  <host>:80, 443 - explicit ports
+       break links that need to change ports (e.g. http -> https) */
+       var h = location.host.replace(/:.*/,''); 
+
+       return proto + "//" + h + path;
+}
+
+/*
+function buildISBNSrc(isbn) {
+       return "http://" + location.host + "/jackets/" + isbn;
+}
+*/
+
+function buildImageLink(name, ssl) {
+       return findBaseURL(ssl) + "../../../../images/" + name;
+}
+
+function buildExtrasLink(name, ssl) {
+       return findBaseURL(ssl) + "../../../../extras/" + name;
+}
+
+var consoleService;
+function _debug(str) { 
+       try { dump('dbg: ' + str + '\n'); } catch(e) {} 
+
+       /* potentially useful, but usually just annoying */
+       /*
+       if(!IE) {
+               if(!consoleService) {
+                       try {
+                               netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                               this.consoleService = Components.classes['@mozilla.org/consoleservice;1']
+                                       .getService(Components.interfaces.nsIConsoleService);
+                       } catch(e) {}
+               }
+       
+               try {
+                       if(consoleService) {
+                               netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                               consoleService.logStringMessage(str + '\n');
+                       }
+               } catch(e){}
+       }
+       */
+}
+
+var forceLoginSSL; // set via Apache env variable
+function  buildOPACLink(args, slim, ssl) {
+
+       if(!args) args = {};
+       var string = "";
+
+    if( ssl == undefined && (
+            location.protocol == 'https:' ||
+            (forceLoginSSL && G.user && G.user.session))) {
+        ssl = true;
+    }
+
+       if(!slim) {
+               string = findBaseURL(ssl);
+               if(args.page) string += config.page[args.page];
+               else string += config.page[findCurrentPage()];
+       }
+
+       /* this may seem unnecessary.. safety precaution for now */
+       /*
+       if( args[PARAM_DEPTH] == null )
+               args[PARAM_DEPTH] = getDepth();
+               */
+
+       string += "?";
+
+       for( var x in args ) {
+               var v = args[x];
+               if(x == "page" || v == null || v == undefined || v+'' == 'NaN' ) continue;
+               if(x == PARAM_OFFSET && v == 0) continue;
+               if(x == PARAM_COUNT && v == 10) continue;
+               if(x == PARAM_FORM && v == 'all' ) continue;
+               if( instanceOf(v, Array) && v.length ) {
+                       for( var i = 0; i < v.length; i++ ) {
+                               string += "&" + x + "=" + encodeURIComponent(v[i]);
+                       }
+               } else {
+                       string += "&" + x + "=" + encodeURIComponent(v);
+               }
+       }
+
+       if(getDebug())
+               string += _appendParam(DEBUG,           PARAM_DEBUG, args, getDebug, string);
+       if(getOrigLocation() != 1) 
+               string += _appendParam(ORIGLOC, PARAM_ORIGLOC, args, getOrigLocation, string);
+       if(getTerm()) 
+               string += _appendParam(TERM,            PARAM_TERM, args, getTerm, string);
+       if(getFacet()) 
+               string += _appendParam(FACET,           PARAM_FACET, args, getFacet, string);
+       if(getStype()) 
+               string += _appendParam(STYPE,           PARAM_STYPE, args, getStype, string);
+       if(getLocation() != 1) 
+               string += _appendParam(LOCATION, PARAM_LOCATION, args, getLocation, string);
+       if(getLasso() != null) 
+               string += _appendParam(LASSO, PARAM_LASSO, args, getLasso, string);
+       if(getDepth() != null) 
+               string += _appendParam(DEPTH,           PARAM_DEPTH, args, getDepth, string);
+       if(getForm() && (getForm() != 'all') ) 
+               string += _appendParam(FORM,            PARAM_FORM, args, getForm, string);
+       if(getTform() && (getTform() != 'all') ) 
+               string += _appendParam(TFORM,           PARAM_TFORM, args, getTform, string);
+       if(getOffset() != 0) 
+               string += _appendParam(OFFSET,  PARAM_OFFSET, args, getOffset, string);
+       if(getDisplayCount() != 10) 
+               string += _appendParam(COUNT,           PARAM_COUNT, args, getDisplayCount, string);
+       if(getHitCount()) 
+               string += _appendParam(HITCOUNT, PARAM_HITCOUNT, args, getHitCount, string);
+       if(getMrid())
+               string += _appendParam(MRID,            PARAM_MRID, args, getMrid, string);
+       if(getRid())
+               string += _appendParam(RID,             PARAM_RID, args, getRid, string);
+       if(getAuthtime())
+               string += _appendParam(AUTHTIME,        PARAM_AUTHTIME, args, getAuthtime, string);
+       if(getAdvTerm())
+               string += _appendParam(ADVTERM, PARAM_ADVTERM, args, getAdvTerm, string);
+       if(getAdvType())
+               string += _appendParam(ADVTYPE, PARAM_ADVTYPE, args, getAdvType, string);
+       if(getRtype())
+               string += _appendParam(RTYPE,           PARAM_RTYPE, args, getRtype, string);
+       if(getItemForm())
+               string += _appendParam(ITEMFORM,        PARAM_ITEMFORM, args, getItemForm, string);
+       if(getItemType())
+               string += _appendParam(ITEMTYPE,        PARAM_ITEMTYPE, args, getItemType, string);
+       if(getBibLevel())
+               string += _appendParam(BIBLEVEL,        PARAM_BIBLEVEL, args, getBibLevel, string);
+       if(getLitForm())
+               string += _appendParam(LITFORM, PARAM_LITFORM, args, getLitForm, string);
+       if(getAudience())
+               string += _appendParam(AUDIENCE,        PARAM_AUDIENCE, args, getAudience, string);
+       if(getSearches())
+               string += _appendParam(SEARCHES,        PARAM_SEARCHES, args, getSearches, string);
+       if(getLanguage())
+               string += _appendParam(LANGUAGE,        PARAM_LANGUAGE, args, getLanguage, string);
+       if(getRdepth() != null)
+               string += _appendParam(RDEPTH,  PARAM_RDEPTH, args, getRdepth, string);
+       if(getSort() != null)
+               string += _appendParam(SORT,    PARAM_SORT, args, getSort, string);
+       if(getSortDir() != null)
+               string += _appendParam(SORT_DIR,        PARAM_SORT_DIR, args, getSortDir, string);
+       if(getAvail())
+               string += _appendParam(AVAIL, PARAM_AVAIL, args, getAvail, string);
+       if(getCopyLocs())
+               string += _appendParam(COPYLOCS, PARAM_COPYLOCS, args, getCopyLocs, string);
+    if(getPubdBefore())
+               string += _appendParam(PUBD_BEFORE, PARAM_PUBD_BEFORE, args, getPubdBefore, string);
+    if(getPubdAfter())
+               string += _appendParam(PUBD_AFTER, PARAM_PUBD_AFTER, args, getPubdAfter, string);
+    if(getPubdBetween())
+               string += _appendParam(PUBD_BETWEEN, PARAM_PUBD_BETWEEN, args, getPubdBetween, string);
+    if(getPubdDuring())
+               string += _appendParam(PUBD_DURING, PARAM_PUBD_DURING, args, getPubdDuring, string);
+
+
+       return string.replace(/\&$/,'').replace(/\?\&/,"?");    
+}
+
+var xx = 1;
+function _appendParam( fieldVar, fieldName, overrideArgs, getFunc, string ) {
+
+       var ret = "";
+
+       if(     fieldVar != null && 
+                       (fieldVar +'' != 'NaN') && 
+                       overrideArgs[fieldName] == null &&
+                       getFunc() != null &&
+                       getFunc()+'' != '' ) {
+
+               ret = "&" + fieldName + "=" + encodeURIComponent(getFunc());
+       }
+
+       return ret;
+}
+
+/* ----------------------------------------------------------------------- */
+function cleanISBN(isbn) {
+   if(isbn) {
+      isbn = isbn.toString().replace(/^\s+/,"");
+      var idx = isbn.indexOf(" ");
+      if(idx > -1) { isbn = isbn.substring(0, idx); }
+   } else isbn = "";
+   return isbn;
+}       
+
+
+/* builds a link that goes to the title listings for a metarecord */
+function buildTitleLink(rec, link) {
+       if(!rec) return;
+       link.appendChild(text(normalize(truncate(rec.title(), 65))));
+       var args = {};
+       args.page = RRESULT;
+       args[PARAM_OFFSET] = 0;
+       args[PARAM_MRID] = rec.doc_id();
+       args[PARAM_RTYPE] = RTYPE_MRID;
+    var linkText = link.innerHTML; // IE
+       link.setAttribute("href", buildOPACLink(args));
+    link.innerHTML = linkText; // IE
+}
+
+function buildTitleDetailLink(rec, link) {
+       if(!rec) return;
+       link.appendChild(text(normalize(truncate(rec.title(), 65))));
+       var args = {};
+       args.page = RDETAIL;
+       args[PARAM_RID] = rec.doc_id();
+    // in IE, if the link text contains a '@', it replaces the innerHTML text 
+    // with the value of the href attribute.  Wait, what?  Yes.  Capture the
+    // innerHTML and put it back into place after the href is set
+    var linkText = link.innerHTML; // IE
+       link.setAttribute("href", buildOPACLink(args));
+    link.innerHTML = linkText; // IE
+}
+
+/* 'type' is one of STYPE_AUTHOR, STYPE_SUBJECT, ... found in config.js 
+       'trunc' is the number of characters to show in the string, defaults to 65 */
+function buildSearchLink(type, string, linknode, trunc) {
+       if(!trunc) trunc = 65;
+       var args = {};
+       if( SHOW_MR_DEFAULT || findCurrentPage() == MRESULT ) {
+               args.page = MRESULT;
+       } else {
+               args.page = RRESULT;
+               args[PARAM_RTYPE] = type;
+       }
+       args[PARAM_OFFSET] = 0;
+       args[PARAM_TERM] = string;
+       args[PARAM_STYPE] = type;
+       linknode.appendChild(text(normalize(truncate(string, trunc))));
+       linknode.setAttribute("href", buildOPACLink(args));
+}
+
+function setSessionCookie(ses) {
+       cookieManager.write(COOKIE_SES, ses, -1);
+}
+
+
+
+/* ----------------------------------------------------------------------- */
+/* user session handling */
+/* ----------------------------------------------------------------------- */
+/* session is the login session.  If no session is provided, we attempt
+       to find one in the cookies.  If 'force' is true we retrieve the 
+       user from the server even if there is already a global user present.
+       if ses != G.user.session, we also force a grab */
+function grabUser(ses, force) {
+
+    _debug("grabUser auth token = " + ses);
+       if(!ses && isXUL()) {
+               stash = fetchXULStash();
+               ses = stash.session.key
+               _debug("stash auth token = " + ses);
+       }
+
+       if(!ses) {
+               ses = cookieManager.read(COOKIE_SES);
+               /* https cookies don't show up in http servers.. */
+               _debug("cookie auth token = " + ses);
+       }
+
+       if(!ses) return false;
+
+       if(!force) 
+               if(G.user && G.user.session == ses)
+                       return G.user;
+
+       /* first make sure the session is valid */
+       var request = new Request(FETCH_SESSION, ses, 1 );
+       request.request.alertEvent = false;
+       request.send(true);
+       var user = request.result();
+
+       if(!user || user.textcode == 'NO_SESSION') {
+
+        if(isXUL()) {
+            dojo.require('openils.XUL');
+            dump('getNewSession in opac_utils.js\n');
+            openils.XUL.getNewSession( 
+                function(success, authtoken) { 
+                    if(success) {
+                        ses = authtoken;
+                        var request = new Request(FETCH_SESSION, ses, 1);
+                        request.request.alertEvent = false;
+                        request.send(true);
+                        user = request.result();
+                    }
+                }
+            );
+        }
+
+           if(!user || user.textcode == 'NO_SESSION') {
+                   doLogout();
+                   return false; /* unable to grab the session */
+        }
+       }
+
+       if( !(typeof user == 'object' && user._isfieldmapper) ) {
+               doLogout();
+               return false;
+       }
+
+       G.user = user;
+       G.user.fleshed = false;
+       G.user.session = ses;
+       setSessionCookie(ses);
+
+       grabUserPrefs();
+       if(G.user.prefs['opac.hits_per_page'])
+               COUNT = parseInt(G.user.prefs['opac.hits_per_page']);
+
+       if(G.user.prefs[PREF_DEF_FONT]) 
+               setFontSize(G.user.prefs[PREF_DEF_FONT]);
+
+       var at = getAuthtime();
+       //if(isXUL()) at = xulG['authtime'];
+
+       if(at && !isXUL()) new AuthTimer(at).run(); 
+       return G.user;
+}
+
+
+/* sets the 'prefs' field of the user object to their preferences 
+       and returns the preferences */
+function grabUserPrefs(user, force) {
+       if(user == null) user = G.user;
+       if(!force && user.prefs) return user.prefs;     
+       var req = new Request(FETCH_USER_PREFS, G.user.session, user.id());
+       req.send(true);
+       user.prefs = req.result();
+       return user.prefs;
+}
+
+function grabFleshedUser() {
+
+       if(!G.user || !G.user.session) {
+               grabUser();     
+               if(!G.user || !G.user.session) return null;
+       }
+
+       if(G.user.fleshed) return G.user;
+
+   var req = new Request(FETCH_FLESHED_USER, G.user.session);
+       req.send(true);
+
+       G.user = req.result();
+
+       if(!G.user || G.user.length == 0) { 
+               G.user = null; return false; 
+               cookieManager.write(COOKIE_SES,"");
+       }
+
+       G.user.session = ses;
+       G.user.fleshed = true;
+
+       setSessionCookie(ses);
+       return G.user;
+}
+
+function checkUserSkin(new_skin) {
+
+       return; /* XXX do some debugging with this... */
+
+       var user_skin = getSkin();
+       var cur_skin = grabSkinFromURL();
+
+       if(new_skin) user_skin = new_skin;
+
+       if(!user_skin) {
+
+               if(grabUser()) {
+                       if(grabUserPrefs()) {
+                               user_skin = G.user.prefs["opac.skin"];
+                               cookieManager.write( COOKIE_SKIN, user_skin, '+1y' );
+                       }
+               }
+       }
+
+       if(!user_skin) return;
+
+       if( cur_skin != user_skin ) {
+               var url = buildOPACLink();
+               goTo(url.replace(cur_skin, user_skin));
+       }
+}
+
+function updateUserSetting(setting, value, user) {
+       if(user == null) user = G.user;
+       var a = {};
+       a[setting] = value;
+       var req = new Request( UPDATE_USER_PREFS, user.session, a );
+       req.send(true);
+       return req.result();
+}
+
+function commitUserPrefs() {
+       var req = new Request( 
+               UPDATE_USER_PREFS, G.user.session, null, G.user.prefs );
+       req.send(true);
+       return req.result();
+}
+
+function grabSkinFromURL() {
+       var path = findBasePath();
+       path = path.replace("/xml/", "");
+       var skin = "";
+       for( var i = path.length - 1; i >= 0; i-- ) {
+               var ch = path.charAt(i);
+               if(ch == "/") break;
+               skin += ch;
+       }
+
+       var skin2 = "";
+       for( i = skin.length - 1; i >= 0; i--)
+               skin2 += skin.charAt(i);
+
+       return skin2;
+}
+
+
+/* returns a fleshed G.user on success, false on failure */
+function doLogin(suppressEvents) {
+
+       abortAllRequests();
+
+       var uname = G.ui.login.username.value;
+       var passwd = G.ui.login.password.value; 
+
+       var init_request = new Request( LOGIN_INIT, uname );
+   init_request.send(true);
+   var seed = init_request.result();
+
+   if( ! seed || seed == '0') {
+      alert( "Error Communicating with Authentication Server" );
+      return null;
+   }
+
+       var args = {
+               password : hex_md5(seed + hex_md5(passwd)), 
+               type            : "opac", 
+               org             : getOrigLocation()
+       };
+
+    r = fetchOrgSettingDefault(globalOrgTree.id(), 'opac.barcode_regex');
+    if(r) REGEX_BARCODE = new RegExp(r);
+    
+    if( uname.match(REGEX_BARCODE) ) args.barcode = uname;
+       else args.username = uname;
+
+   var auth_request = new Request( LOGIN_COMPLETE, args );
+
+       auth_request.request.alertEvent = false;
+   auth_request.send(true);
+   var auth_result = auth_request.result();
+
+       if(!auth_result) {
+               alertId('patron_login_failed');
+               return null;
+       }
+
+       if( checkILSEvent(auth_result) ) {
+
+               if( auth_result.textcode == 'PATRON_INACTIVE' ) {
+                       alertId('patron_inactive_alert');
+                       return;
+               }
+
+               if( auth_result.textcode == 'PATRON_CARD_INACTIVE' ) {
+                       alertId('patron_card_inactive_alert');
+                       return;
+               }
+
+               if( auth_result.textcode == 'LOGIN_FAILED' || 
+                               auth_result.textcode == 'PERM_FAILURE' ) {
+                       alertId('patron_login_failed');
+                       return;
+               }
+       }
+
+
+       AUTHTIME = parseInt(auth_result.payload.authtime);
+       var u = grabUser(auth_result.payload.authtoken, true);
+       if(u && ! suppressEvents) 
+               runEvt( "common", "locationChanged", u.ws_ou(), findOrgDepth(u.ws_ou()) );
+
+       checkUserSkin();
+
+       return u;
+}
+
+function doLogout() {
+
+       /* cancel everything else */
+       abortAllRequests();
+
+       /* be nice and delete the session from the server */
+       if(G.user && G.user.session) { 
+               var req = new Request(LOGIN_DELETE, G.user.session);
+      req.send(true);
+               try { req.result(); } catch(E){}
+    }
+
+       G.user = null;
+
+       /* remove any cached data */
+    dojo.require('dojo.cookie');
+    dojo.cookie(COOKIE_SES, '', {expires:-1});
+    dojo.cookie(COOKIE_RIDS, '', {expires:-1});
+    dojo.cookie(COOKIE_SKIN, '', {expires:-1});
+    dojo.cookie(COOKIE_SEARCH, '', {expires:-1});
+
+
+       checkUserSkin("default");
+       COUNT = 10;
+
+
+       var args = {};
+       args[PARAM_TERM] = "";
+       args[PARAM_LOCATION] = getOrigLocation();
+       args[PARAM_DEPTH] = findOrgDepth(getOrigLocation());
+       args.page = "home";
+
+       
+       var nored = false;
+       try{ if(isFrontPage) nored = true; } catch(e){nored = false;}
+       if(!nored) goTo(buildOPACLink(args, false, false));
+}
+
+
+function hideMe(obj) { addCSSClass(obj, config.css.hide_me); } 
+function unHideMe(obj) { removeCSSClass(obj, config.css.hide_me); }
+
+
+/* ----------------------------------------------------------------------- */
+/* build the org tree */
+/* ----------------------------------------------------------------------- */
+function drawOrgTree() {
+       //setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 10 );
+       setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 1 );
+}
+       
+function checkOrgHiding() {
+       var context_org = getOrigLocation() || globalOrgTree.id();
+       var depth = fetchOrgSettingDefault( context_org, 'opac.org_unit_hiding.depth');
+       if (isXUL()) {
+               return false; // disable org hiding for staff client
+       }
+       if ( findOrgDepth( context_org ) < depth ) {
+               return false; // disable org hiding if Original Location doesn't make sense with setting depth (avoids disjointed org selectors)
+       }
+       return { 'org' : findOrgUnit(context_org), 'depth' : depth };
+}
+
+var orgTreeSelector;
+function buildOrgSelector(node) {
+       var tree = new SlimTree(node,'orgTreeSelector');
+       orgTreeSelector = tree;
+       var orgHiding = checkOrgHiding();
+       for( var i in orgArraySearcher ) { 
+               var node = orgArraySearcher[i];
+               if( node == null ) continue;
+               if(!isXUL() && !isTrue(node.opac_visible())) continue; 
+               if (orgHiding) {
+                       if ( ! orgIsMine( orgHiding.org, node, orgHiding.depth ) ) {
+                               continue;
+                       }
+               }
+               if(node.parent_ou() == null) {
+                       tree.addNode(node.id(), -1, node.name(), 
+                               "javascript:orgSelect(" + node.id() + ");", node.name());
+               } else {
+                       if (orgHiding && orgHiding.depth == findOrgDepth(node)) {
+                               tree.addNode(node.id(), -1, node.name(), 
+                                       "javascript:orgSelect(" + node.id() + ");", node.name());
+                       } else {
+                               tree.addNode(node.id(), node.parent_ou(), node.name(), 
+                                       "javascript:orgSelect(" + node.id() + ");", node.name());
+                       }
+               }
+       }
+       hideMe($('org_loading_div'));
+       unHideMe($('org_selector_tip'));
+       return tree;
+}
+
+function orgSelect(id) {
+       showCanvas();
+       runEvt("common", "locationChanged", id, findOrgDepth(id) );
+
+
+       var loc = findOrgLasso(getLasso());
+       if (!loc) loc = findOrgUnit(id);
+
+       removeChildren(G.ui.common.now_searching);
+       G.ui.common.now_searching.appendChild(text(loc.name()));
+}
+
+function setFontSize(size) {
+       scaleFonts(size);
+       cookieManager.write(COOKIE_FONT, size, '+1y');
+}
+
+var resourceFormats = [
+   "text",
+   "moving image",
+   "sound recording", "software, multimedia",
+   "still image",
+   "cartographic",
+   "mixed material",
+   "notated music",
+   "three dimensional object" ];
+
+
+function modsFormatToMARC(format) {
+   switch(format) {
+      case "text":
+         return "at";
+      case "moving image":
+         return "g";
+      case "sound recording":
+         return "ij";
+      case "sound recording-nonmusical":
+         return "i";
+      case "sound recording-musical":
+         return "j";
+      case "software, multimedia":
+         return "m";
+      case "still image":
+         return "k";
+      case "cartographic":
+         return "ef";
+      case "mixed material":
+         return "op";
+      case "notated music":
+         return "cd";
+      case "three dimensional object":
+         return "r";
+   }
+   return "at";
+}
+
+
+function MARCFormatToMods(format) {
+   switch(format) {
+      case "a":
+      case "t":
+         return "text";
+      case "g":
+         return "moving image";
+      case "i":
+         return "sound recording-nonmusical";
+      case "j":
+         return "sound recording-musical";
+      case "m":
+         return "software, multimedia";
+      case "k":
+         return "still image";
+      case "e":
+      case "f":
+         return "cartographic";
+      case "o":
+      case "p":
+         return "mixed material";
+      case "c":
+      case "d":
+         return "notated music";
+      case "r":
+         return "three dimensional object";
+   }
+   return "text";
+}
+
+function MARCTypeToFriendly(format) {
+       var words = $('format_words');
+       switch(format) {
+               case 'a' :
+               case 't' : return $n(words, 'at').innerHTML;
+               default:
+                       var node = $n(words,format);
+                       if( node ) return node.innerHTML;
+       }
+       return "";
+}
+
+function setResourcePic( img, resource ) {
+       img.setAttribute( "src", "../../../../images/tor/" + resource + ".jpg");
+       img.title = resource;
+}
+
+
+
+function msg( text ) {
+       try { alert( text ); } catch(e) {}
+}
+
+function findRecord(id,type) {
+       try {
+               for( var i = 0; i != recordsCache.length; i++ ) {
+                       var rec = recordsCache[i];
+                       if( rec && rec.doc_id() == id ) return rec;
+               }
+       } catch(E){}
+       var meth = FETCH_RMODS
+       if(type == 'M') meth = FETCH_MRMODS;
+       var req = new Request(meth, id);
+       req.request.alertEvent = false;
+       req.send(true);
+       var res = req.result();
+       if( checkILSEvent(res) ) return null; 
+       return res;
+}
+
+function Timer(name, node){
+       this.name = name;
+       this.count = 1;
+       this.node = node;
+}
+Timer.prototype.start = 
+       function(){_timerRun(this.name);}
+Timer.prototype.stop = 
+       function(){this.done = true;}
+function _timerRun(tname) {
+       var _t;
+       eval('_t='+tname);
+       if(_t.done) return;
+       if(_t.count > 100) return;
+       var str = ' . ';
+       if( (_t.count % 5) == 0 ) 
+               str = _t.count / 5;
+       _t.node.appendChild(text(str));
+       setTimeout("_timerRun('"+tname+"');", 200);
+       _t.count++;
+}
+
+function checkILSEvent(obj) {
+       if( obj && obj.ilsevent != null && obj.ilsevent != 0 )
+               return parseInt(obj.ilsevent);
+       return null;
+}
+
+
+function alertILSEvent(evt, msg) {
+   if(!msg) msg = "";
+       if(msg)
+               alert(msg +'\n' + evt.textcode + '\n' + evt.desc );
+       else 
+               alert(evt.textcode + '\n' + evt.desc );
+}
+
+
+var __authTimer;
+function AuthTimer(time) { 
+       this.time = (time - LOGOUT_WARNING_TIME) * 1000; 
+       if(__authTimer) 
+               try {clearTimeout(__authTimer.id)} catch(e){}
+       __authTimer = this;
+}
+
+AuthTimer.prototype.run = function() {
+       this.id = setTimeout('_authTimerAlert()', this.time);
+}
+
+function _authTimerAlert() {
+       alert( $('auth_session_expiring').innerHTML );
+       if(!grabUser(null, true)) doLogout();
+}
+
+
+function grabUserByBarcode( authtoken, barcode ) {
+       var req = new Request( FETCH_USER_BYBARCODE, authtoken, barcode );
+       req.send(true);
+       return req.result();
+}
+
+
+function goHome() {
+       goTo(buildOPACLink({page:HOME}));
+}
+
+
+function buildOrgSel(selector, org, offset, namecol) {
+    if(!namecol) namecol = 'name';
+    if(!isXUL() && !isTrue(org.opac_visible())) return;
+       insertSelectorVal( selector, -1, 
+               org[namecol](), org.id(), null, findOrgDepth(org) - offset );
+    var kids = org.children();
+    if (kids) {
+           for( var c = 0; c < kids.length; c++ )
+                   buildOrgSel( selector, kids[c], offset, namecol);
+    }
+}
+
+function buildMergedOrgSel(selector, org_list, offset, namecol) {
+    if(!namecol) namecol = 'name';
+    for(var i = 0; i < org_list.length; i++) {
+        var org = findOrgUnit(org_list[i]);
+       insertSelectorVal( selector, -1, 
+                   org[namecol](), org.id(), null, findOrgDepth(org) - offset );
+        var kids = org.children();
+        if (kids) {
+               for( var c = 0; c < kids.length; c++ )
+                       buildOrgSel( selector, kids[c], offset, namecol);
+        }
+    }
+}
+
+
+function parseForm(form) {
+       if(!form) return {};
+
+       var it = form.replace(/-\w+$/,"");
+       var itf = null;
+       var item_form;
+       var item_type;
+
+       if(form.match(/-/)) itf = form.replace(/^\w+-/,"");
+
+       if(it) {
+               item_type = [];
+               for( var i = 0; i < it.length; i++ ) 
+                       item_type.push( it.charAt(i) );
+       }
+
+       if(itf) {
+               item_form = [];
+               for( var i = 0; i < itf.length; i++ ) 
+                       item_form.push( itf.charAt(i) );
+       }
+
+       return {item_type: item_type, item_form:item_form};
+}
+
+
+function isTrue(x) { return ( x && x != "0" && !(x+'').match(/^f$/i) ); }
+
+function fetchPermOrgs() {
+       var a = []; /* Q: why does arguments come accross as an object and not an array? A: because arguments is a special object, a collection */
+
+       for( var i = 0; i < arguments.length; i++ ) 
+               a.push(arguments[i])
+
+       var preq = new Request(FETCH_HIGHEST_PERM_ORG, 
+               G.user.session, G.user.id(), a );
+       preq.send(true);
+       return preq.result();
+}
+
+
+function print_tabs(t) {
+       var r = '';
+       for (var j = 0; j < t; j++ ) { r = r + "  "; }
+       return r;
+}
+function formatJSON(s) {
+       var r = ''; var t = 0;
+       for (var i in s) {
+               if (s[i] == '{' || s[i] == '[' ) {
+                       r = r + s[i] + "\n" + print_tabs(++t);
+               } else if (s[i] == '}' || s[i] == ']') {
+                       t--; r = r + "\n" + print_tabs(t) + s[i];
+               } else if (s[i] == ',') {
+                       r = r + s[i] + "\n" + print_tabs(t);
+               } else {
+                       r = r + s[i];
+               }
+       }
+       return r;
+}
+/* ------------------------------------------------------------------------------------------------------ */
+/* org tree utilities */
+/* ------------------------------------------------------------------------------------------------------ */
+
+try { console.log('org utils'); } catch(E) {}
+
+function fetchOrgSettingDefault(orgId, name) {
+    var req = new Request(FETCH_ORG_SETTING, orgId, name);
+    req.send(true);
+    var res = req.result();
+    return (res) ? res.value : null;
+}
+
+function fetchBatchOrgSetting(orgId, nameList, onload) {
+    var req = new Request(
+        'open-ils.actor:open-ils.actor.ou_setting.ancestor_default.batch', orgId, nameList);
+    if(onload) {
+        req.callback(function(r) { onload(r.getResultObject()); });
+        req.send();
+    } else {
+        req.send(true);
+        return req.result();
+    }
+}
+
+
+/* takes an org unit or id and return the numeric depth */
+function findOrgDepth(org_id_or_node) {
+       var org = findOrgUnit(org_id_or_node);
+       if(!org) return -1;
+       var type = findOrgType(org.ou_type());
+       if(type) return type.depth();
+       return -1;
+}
+
+function findOrgTypeFromDepth(depth) {
+       if( depth == null ) return null;
+       for( var type = 0; type < globalOrgTypes.length; type++ ) {
+               var t = globalOrgTypes[type];
+               if( t.depth() == depth ) return t;
+       }
+}
+
+/* takes the org type id from orgunit.ou_type() field and returns
+       the org type object */
+function findOrgType(type_id) {
+       if(typeof type_id == 'object') return type_id;
+       for(var type = 0; type < globalOrgTypes.length; type++) {
+               var t =globalOrgTypes[type]; 
+               if( t.id() == type_id || t.id() == parseInt(type_id) ) 
+                       return t;
+       }
+       return null;
+}
+
+
+/* returns an org unit by id.  if an object is passed in as the id,
+       then the object is assumed to be an org unit and is returned */
+function findOrgUnit(org_id) {
+       return (typeof org_id == 'object') ? org_id : orgArraySearcher[org_id];
+}
+
+function findOrgLasso(lasso_id) {
+       if (typeof lasso_id == 'object') return lasso_id;
+    for (var i = 0; i < _lasso.length; i++) {
+        if (_lasso[i].id() == lasso_id) return _lasso[i];
+    }
+    return null;
+}
+
+var orgArraySearcherSN = {};
+function findOrgUnitSN(shortname) {
+       if (typeof shortname == 'object') return shortname;
+       if( orgArraySearcherSN[shortname] ) return orgArraySearcherSN[shortname];
+       _debug("fetching org by shortname "+shortname);
+       var req = new Request(FETCH_ORG_BY_SHORTNAME, shortname);
+       req.request.alertEvent = false;
+       req.send(true);
+       return req.result();
+}
+
+
+/* builds a trail from the top of the org tree to the node provide.
+       basically fleshes out 'my orgs' 
+       Returns an array of [org0, org1, ..., myorg] */
+function orgNodeTrail(node) {
+       var na = new Array();
+       while( node ) {
+               na.push(node);
+               node = findOrgUnit(node.parent_ou());
+       }
+       return na.reverse();
+}
+
+function findSiblingOrgs(node) { return findOrgUnit(node.parent_ou()).children(); }
+
+/* true if 'org' is 'me' or a child of mine, or optionally, a child of an ancestor org within the specified depth */
+function orgIsMine(me, org, depth) {
+       if(!me || !org) {
+               return false;
+       }
+       if(me.id() == org.id()) {
+               return true;
+       }
+       if (depth) {
+               while (depth < findOrgDepth(me)) {
+                       me = findOrgUnit( me.parent_ou() );
+               }
+               if(me.id() == org.id()) {
+                       return true;
+               }
+       }
+       var kids = me.children();
+       for( var i = 0; kids && i < kids.length; i++ ) {
+               if(orgIsMine(kids[i], org, false)) {
+                       return true;
+               }
+
+       }
+       return false;
+}
+
+function orgIsMineFromSet(meList, org) {
+    org = findOrgUnit(org);
+    for(var i = 0; i < meList.length; i++) {
+        if(orgIsMine(findOrgUnit(meList[i]), org))
+            return true;
+    }
+    return false;
+}
+
+var orgArraySearcher = {};
+var globalOrgTree;
+for (var i = 0; i < _l.length; i++) {
+       var x = new aou();
+       x.id(_l[i][0]);
+       x.ou_type(_l[i][1]);
+       x.parent_ou(_l[i][2]);
+       x.name(_l[i][3]);
+    x.opac_visible(_l[i][4]);
+    x.shortname(_l[i][5]);
+       orgArraySearcher[x.id()] = x;
+}
+for (var i in orgArraySearcher) {
+       var x = orgArraySearcher[i];
+       if (x.parent_ou() == null || x.parent_ou() == '') {
+               globalOrgTree = x;
+               continue;
+       } 
+
+       var par = findOrgUnit(x.parent_ou());
+       if (!par.children()) par.children(new Array());
+       par.children().push(x);
+}
+
+function _tree_killer () {
+       for (var i in orgArraySearcher) {
+               x=orgArraySearcher[i];
+               x.children(null);
+               x.parent_ou(null);
+               orgArraySearcher[i]=null;
+       }
+       globalOrgTree = null;
+       orgArraySearcher = null;
+       globalOrgTypes = null;
+}
+
+try { console.log('org utils end'); } catch(E) {}
+
+
+var XML_HTTP_GATEWAY = "osrf-gateway-v1";
+var XML_HTTP_SERVER = "";
+
+
+/* This object is thrown when network failures occur */
+function NetworkFailure(stat, url) { 
+       this._status = stat; 
+       this._url = url;
+}
+
+NetworkFailure.prototype.status = function() { return this._status; }
+NetworkFailure.prototype.url = function() { return this._url; }
+NetworkFailure.prototype.toString = function() { 
+       return "Network Failure: status = " + this.status() +'\n'+this.url(); 
+}
+
+
+
+function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
+var _allrequests = {};
+
+// If the legacy JSON gateway is needed by the staff client, uncomment this
+/* 
+if(isXUL()) {
+    XML_HTTP_GATEWAY = 'gateway';
+}
+*/
+
+function cleanRemoteRequests() {
+       for( var i in _allrequests ) 
+               destroyRequest(_allrequests[i]);
+}
+
+function abortAllRequests() {
+       for( var i in _allrequests ) {
+               var r = _allrequests[i];
+               if(r) { 
+                       r.abort();
+                       destroyRequest(r);
+               }
+       }
+}
+
+function destroyRequest(r) {
+       if(r == null) return;
+
+       if( r.xmlhttp ) {
+               r.xmlhttp.onreadystatechange = function(){};
+               r.xmlhttp = null;
+       }
+
+       r.callback                              = null;
+       r.userdata                              = null;
+       _allrequests[r.id]      = null;
+}
+
+/* ----------------------------------------------------------------------- */
+/* Request object */
+var rrId = 0;
+function RemoteRequest( service, method ) {
+
+       /* dojo is currently only available in the OPAC */
+       try {
+               /* We want OpenSRF.locale for xx-YY format */
+               this.locale     = OpenSRF.locale;
+       }
+       catch (e) {
+               this.locale = null;
+       }
+       this.service    = service;
+       this.method             = method;
+       this.xmlhttp    = false;
+       this.name               = null;
+       this.alertEvent = true; /* only used when isXUL is false */
+
+       this.type               = "POST"; /* default */
+       this.id                 = rrId++;
+       this.cancelled = false;
+
+       this.setSecure(false);
+       if(isXUL()) this.setSecure(true);
+
+       _allrequests[this.id] = this;
+
+       var i = 2;
+       this.params = ""; 
+
+       while(i < arguments.length) {
+               var object = js2JSON(arguments[i++]);
+               this.params += "&param=" + encodeURIComponent(object);
+       }
+
+       if(!this.params) { this.params = ""; }
+
+       this.param_string = "service=" + service + "&method=" + method + this.params;
+       if (this.locale != null) {
+               this.param_string = this.param_string + "&locale=" + this.locale;
+       }
+       if( this.buildXMLRequest() == null ) alert("Browser is not supported!");
+
+}
+
+
+RemoteRequest.prototype.timeout = function(t) {
+       t *= 1000
+       var req = this;
+       req.timeoutFunc = setTimeout(
+               function() {
+                       if( req && req.xmlhttp ) {
+                               req.cancelled = true;
+                               req.abort();
+                               if( req.abtCallback ) {
+                                       req.abtCallback(req);
+                               }
+                       }
+               },
+               t
+       );
+}
+
+RemoteRequest.prototype.abortCallback = function(func) {
+       this.abtCallback = func;
+}
+
+RemoteRequest.prototype.event = function(evt) {
+       if( arguments.length > 0 )
+               this.evt = evt;
+       return this.evt;
+}
+
+RemoteRequest.prototype.abort = function() {
+       if( this.xmlhttp ) {
+               /* this has to come before abort() or IE will puke on you */
+               this.xmlhttp.onreadystatechange = function(){};
+               this.xmlhttp.abort();
+       }
+}
+
+/* constructs our XMLHTTPRequest object */
+RemoteRequest.prototype.buildXMLRequest = function() {
+       this.xmlhttp = buildXMLRequest();
+       return true;
+}
+
+
+function buildXMLRequest() {
+    try {
+           return new XMLHttpRequest();
+    } catch(e) {
+           try { 
+                   return new ActiveXObject("Msxml2.XMLHTTP"); 
+           } catch (e2) {
+                   try { 
+                           return new ActiveXObject("Microsoft.XMLHTTP"); 
+                   } catch (e3) {
+                       alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
+                return null;
+                   }
+           }
+    }
+}
+
+
+function _remoteRequestCallback(id) {
+
+       var object = _allrequests[id];
+       if(object.cancelled) return;
+
+       if( object.xmlhttp.readyState == 4 ) {
+
+        try {
+            object.duration = new Date().getTime() - object.sendTime;
+            dump('request ' + object.id + ': duration = ' + object.duration + ' ms\n');
+        } catch(ee){}
+
+               try {
+                       object.callback(object);
+               } catch(E) {
+            throw E
+               } finally { 
+                       destroyRequest(object); 
+                       object = null; 
+               }  
+       }
+}
+
+
+/* define the callback we use when this request has received
+       all of its data */
+RemoteRequest.prototype.setCompleteCallback = function(callback) {
+       if(this.cancelled) return;
+       this.callback = callback;
+       var id = this.id;
+       this.xmlhttp.onreadystatechange = function() { _remoteRequestCallback(id); }
+}
+
+
+/* http by default.  This makes it https. *ONLY works when
+       embedded in a XUL app. */
+RemoteRequest.prototype.setSecure = function(bool) {
+       this.secure = bool; 
+}
+
+RemoteRequest.prototype.send = function(blocking) {
+
+       if(this.cancelled) return;
+
+       /* determine the xmlhttp server dynamically */
+       var url = location.protocol + "//" + location.host + "/" + XML_HTTP_GATEWAY;
+
+       if(isXUL()) {
+               if( XML_HTTP_SERVER ) 
+                       url = 'http://'+XML_HTTP_SERVER+'/'+XML_HTTP_GATEWAY;
+
+               if( url.match(/^http:/) && 
+                               (this.secure || location.href.match(/^https:/)) ) {
+                       netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
+                       url = url.replace(/^http:/, 'https:');
+               }
+       }
+
+       var data = null;
+       if( this.type == 'GET' ) url +=  "?" + this.param_string; 
+
+       this.url = url;
+
+   //if( isXUL() ) dump('request URL = ' + url + '?' + this.param_string + '\n');
+
+       try {
+
+               if(blocking) this.xmlhttp.open(this.type, url, false);
+               else this.xmlhttp.open(this.type, url, true);
+               
+       } catch(E) {
+               alert("Fatal error opening XMLHTTPRequest for URL:\n" + url + '\n' + E);
+               return;
+       }
+
+       if( this.type == 'POST' ) {
+               data = this.param_string;
+               this.xmlhttp.setRequestHeader('Content-Type',
+                               'application/x-www-form-urlencoded');
+       }
+
+       try {
+               var auth;
+               try { auth = cookieManager.read(COOKIE_SES) } catch(ee) {}
+               if( isXUL() ) auth = fetchXULStash().session.key;
+               if( auth ) 
+                       this.xmlhttp.setRequestHeader('X-OILS-Authtoken', auth);
+
+       } catch(e) {}
+
+       if(data && data.match(/param=undefined/)) {
+               /* we get a bogus param .. replace with NULL */
+               try{dump('!+! UNDEFINED PARAM IN QUERY: ' + this.service + ' : ' + this.method+'\n');}catch(r){}
+               data = data.replace(/param=undefined/g,'param=null');
+       }
+
+
+    this.sendTime = new Date().getTime();
+       try{ this.xmlhttp.send( data ); } catch(e){}
+
+       return this;
+}
+
+/* returns the actual response text from the request */
+RemoteRequest.prototype.getText = function() {
+       return this.xmlhttp.responseText;
+}
+
+RemoteRequest.prototype.isReady = function() {
+       return this.xmlhttp.readyState == 4;
+}
+
+
+/* returns the JSON->js result object  */
+RemoteRequest.prototype.getResultObject = function() {
+
+       if(this.cancelled) return null;
+       if(!this.xmlhttp) return null;
+
+       var failed = false;
+       var status = null;
+       this.event(null);
+
+       /*
+       try {
+               dump(this.url + '?' + this.param_string + '\n' +
+                       'Returned with \n\tstatus = ' + this.xmlhttp.status + 
+                       '\n\tpayload= ' + this.xmlhttp.responseText + '\n');
+       } catch(e) {}
+       */
+
+       try {
+               status = this.xmlhttp.status;
+               if( status != 200 ) failed = true;
+       } catch(e) { failed = true; }
+
+       if( failed ) {
+               if(!status) status = '<unknown>';
+               try{dump('! NETWORK FAILURE.  HTTP STATUS = ' +status+'\n'+this.param_string+'\n');}catch(e){}
+               if(isXUL()) 
+                       throw new NetworkFailure(status, this.param_string);
+               else return null;
+       }
+
+       var text = this.xmlhttp.responseText;
+
+       //try{if(getDebug()) _debug('response: ' + text + '\n')}catch(e){}
+
+       if(text == "" || text == " " || text == null) {
+               try { dump('dbg: Request returned no text!\n'); } catch(E) {}
+               if(isXUL()) 
+                       throw new NetworkFailure(status, this.param_string);
+               return null;
+       }
+
+       var obj = JSON2js(text);
+       if(!obj) return null;
+
+       if( obj.status != 200 ) {
+
+               var str = 'A server error occurred. Debug information follows: ' +
+                                       '\ncode = '             + obj.status + 
+                                       '\ndebug: '             + obj.debug + 
+                                       '\npayload: '   + js2JSON(obj.payload); 
+
+               if(isXUL()) {
+                       dump(str);
+                       throw obj;
+
+               } else {
+                       _debug(str);
+                       throw str;
+               }
+       }
+
+       var payload = obj.payload;
+       if(!payload || payload.length == 0) return null;
+       payload = (payload.length == 1) ? payload[0] : payload;
+
+       if(!isXUL()) {
+               if( checkILSEvent(payload) ) {
+                       this.event(payload);
+                       if( this.alertEvent ) {
+                               alertILSEvent(payload);
+                               return null;
+                       }
+               } 
+       }
+
+       return payload;
+}
+
+/* adds a new parameter to the request */
+RemoteRequest.prototype.addParam = function(param) {
+       var string = encodeURIComponent(js2JSON(param));
+       this.param_string += "&param=" + string;
+}
+
+function fetchXULStash() {
+       if( isXUL() ) {
+               try {
+                       netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                       var __OILS = new Components.Constructor("@mozilla.org/openils_data_cache;1", "nsIOpenILS");
+                       var data_cache = new __OILS( );
+                       return data_cache.wrappedJSObject.OpenILS.prototype.data;
+       
+               } catch(E) {
+                       _debug('Error in OpenILS.data._debug_stash(): ' + js2JSON(E) );
+               }
+       }
+       return {};
+}
+
+
+
+/* these events should be used by all */
+
+window.onunload = windowUnload;
+
+attachEvt("common", "init", loadUIObjects);
+//attachEvt("common", "init", initParams);
+attachEvt("common", "init", initCookies);
+
+attachEvt("common", "unload", _tree_killer);
+try{ attachEvt("common", "unload", cleanRemoteRequests);} catch(e){}
+
+function init() {
+
+       initParams();
+
+       if( getLocation() == null && getOrigLocation() != null )
+               LOCATION = getOrigLocation();
+
+       if( getLocation() == null && getOrigLocation() == null )
+               LOCATION = globalOrgTree.id();
+
+       /* if they click on the home page and the origlocation is set
+               take the opac back to the origlocation */
+       if( findCurrentPage() == HOME && getOrigLocation() != null )
+               LOCATION = getOrigLocation();
+
+       if(getDepth() == null) DEPTH = findOrgDepth(getLocation());
+
+
+       runEvt('common','init');
+
+       var cgi = new CGI();
+       if( grabUser() ) {
+               if( cgi.param(PARAM_LOCATION) == null ) {
+                       var org = G.user.prefs[PREF_DEF_LOCATION];
+                       var depth = G.user.prefs[PREF_DEF_DEPTH];
+
+                       if(org == null) org = G.user.ws_ou();
+                       if(depth == null) depth = findOrgDepth(org);
+
+                       LOCATION = org;
+                       DEPTH = depth;
+               }
+       }
+
+       runEvt("common", "run");
+       //checkUserSkin();
+
+       var loc = findOrgLasso(getLasso());
+       if (!loc) loc = findOrgUnit(getLocation());
+
+       if (getLasso()) G.ui.common.now_searching.appendChild(text('Search group: '));
+       G.ui.common.now_searching.appendChild(text(loc.name()));
+}
+
+function windowUnload() { runEvt("common", "unload"); }
+/**
+* This function should return a URL which points to the book cover image based on ISBN.
+*/
+
+
+function buildISBNSrc(isbn, size) {
+       size = (size) ? size : 'small';
+       var protocol = (OILS_OPAC_STATIC_PROTOCOL) ? OILS_OPAC_STATIC_PROTOCOL + ':' : location.protocol;
+    if(OILS_OPAC_IMAGES_HOST)
+        return protocol + '//' + OILS_OPAC_IMAGES_HOST + size + '/' + isbn;
+       return '../../../../extras/ac/jacket/'+size+'/'+isbn;
+}      
+
+
+function acMakeURL(type, key) {
+       return '../../../../extras/ac/' + type + '/html/' + key;
+}
+
+
+function acCollectData( key, callback ) {
+       var context = { key : key, callback: callback, data : {} };
+       acCollectItem(context, 'summary');
+       acCollectItem(context, 'reviews');
+       acCollectItem(context, 'toc');
+       acCollectItem(context, 'excerpt');
+       acCollectItem(context, 'anotes');
+}
+
+function acCheckDone(context) {
+       if(     context.data.reviews && context.data.reviews.done &&
+                       context.data.toc                && context.data.toc.done &&
+                       context.data.excerpt && context.data.excerpt.done &&
+                       context.data.anotes     && context.data.anotes.done ) {
+
+               if(context.callback) context.callback(context.data);
+       }
+}
+
+function acCollectItem(context, type) {
+       var req = buildXMLRequest();
+       req.open('GET', acMakeURL(type, context.key), true);
+       req.onreadystatechange = function() {
+               if( req.readyState == 4 ) {
+                       context.data[type] = { done : true }
+
+                       if(IE) {
+
+                               /* Someone please explain why IE treats status 404 as status 200?? 
+                                       On second thought, don't bother.
+                               */
+                               if( ! req.responseText.match(
+                                       /The requested URL.*was not found on this server/) )
+                                       context.data[type].html = req.responseText;
+
+                       } else {
+                               if( req.status != 404 ) 
+                                       context.data[type].html = req.responseText;
+                       }
+                       acCheckDone(context);
+               }
+       }
+       req.send(null);
+}
+
+