]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/common/js/opac_utils.js
adding bib_level filter to the advanced search
[Evergreen.git] / Open-ILS / web / opac / common / js / opac_utils.js
1 /* - Request ------------------------------------------------------------- */
2
3 /* define it again here for pages that don't load RemoteRequest */
4 function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
5
6
7 var cookieManager = new HTTP.Cookies();
8
9 var __ilsEvent; /* the last event the occurred */
10
11 var DEBUGSLIM;
12 function Request(type) {
13
14         var s = type.split(":");
15         if(s[2] == "1" && isXUL()) s[1] += ".staff";
16         this.request = new RemoteRequest(s[0], s[1]);
17         var p = [];
18
19         if(isXUL()) {
20                 if(!location.href.match(/^https:/))
21                         this.request.setSecure(false);
22
23         } else {
24
25                 if( G.user && G.user.session ) {
26                         /* if the user is logged in, all activity resets the timeout 
27                                 This is not entirely accurate in the sense that not all 
28                                 requests will reset the server timeout - this should
29                                 get close enough, however.
30                         */
31                         var at = getAuthtime();
32                         if(at) new AuthTimer(at).run(); 
33                 }
34         }
35
36         for( var x = 1; x!= arguments.length; x++ ) {
37                 p.push(arguments[x]);
38                 this.request.addParam(arguments[x]);
39         }
40
41         if( getDebug() ) {
42                 var str = "";
43                 for( var i = 0; i != p.length; i++ ) {
44                         if( i > 0 ) str += ", "
45                         str += js2JSON(p[i]);
46                 }
47                 _debug('request ' + s[0] + ' ' + s[1] + ' ' + str );
48
49         } else if( DEBUGSLIM ) {
50                 _debug('request ' + s[1]);
51         }
52 }
53
54 Request.prototype.callback = function(cal) {this.request.setCompleteCallback(cal);}
55 Request.prototype.send          = function(block){this.request.send(block);}
56 Request.prototype.result        = function(){return this.request.getResultObject();}
57
58 function showCanvas() {
59         for( var x in G.ui.altcanvas ) {
60                 hideMe(G.ui.altcanvas[x]);
61         }
62         hideMe(G.ui.common.loading);
63         unHideMe(G.ui.common.canvas_main);
64         try{G.ui.searchbar.text.focus();}catch(e){}
65 }
66
67 function swapCanvas(newNode) {
68         for( var x in G.ui.altcanvas ) 
69                 hideMe(G.ui.altcanvas[x]);
70
71         hideMe(G.ui.common.loading);
72         hideMe(G.ui.common.canvas_main);
73         unHideMe(newNode);
74 }
75
76 /* finds the name of the current page */
77 var currentPage = null;
78 function findCurrentPage() {
79         if(currentPage) return currentPage;
80
81         var pages = [];
82         for( var p in config.page ) pages.push(config.page[p]);
83         pages = pages.sort( function(a,b){ return - (a.length - b.length); } );
84
85         var path = location.pathname;
86         if(!path.match(/.*\.xml$/))
87                 path += "index.xml"; /* in case they go to  / */
88
89         var page = null;
90         for( var p in pages ) {
91                 if( path.indexOf(pages[p]) != -1)
92                         page = pages[p];
93         }
94
95         for( var p in config.page ) {
96                 if(config.page[p] == page) {
97                         currentPage = p;
98                         return p;
99                 }
100         }
101         return null;
102 }
103
104
105 /* sets all of the params values  ----------------------------- */
106 function initParams() {
107         var cgi = new CGI();    
108
109         /* handle the location var */
110         var org;
111         var loc = cgi.param(PARAM_LOCATION);
112         if( loc ) {
113                 org = findOrgUnit(loc);
114                 if(!org) org = findOrgUnitSN(loc);
115         } 
116         LOCATION        = (org) ? org.id() : null;
117
118         org = null;
119         loc = cgi.param(PARAM_ORIGLOC);
120         if( loc ) {
121                 org = findOrgUnit(loc);
122                 if(!org) org = findOrgUnitSN(loc);
123         }
124         ORIGLOC = (org) ? org.id() : null;
125
126
127         DEPTH = parseInt(cgi.param(PARAM_DEPTH));
128         if(isNaN(DEPTH)) DEPTH = null;
129
130
131         TERM            = cgi.param(PARAM_TERM);
132         STYPE           = cgi.param(PARAM_STYPE);
133         FORM            = cgi.param(PARAM_FORM);
134         //DEPTH         = parseInt(cgi.param(PARAM_DEPTH));
135         OFFSET  = parseInt(cgi.param(PARAM_OFFSET));
136         COUNT           = parseInt(cgi.param(PARAM_COUNT));
137         HITCOUNT        = parseInt(cgi.param(PARAM_HITCOUNT));
138         MRID            = parseInt(cgi.param(PARAM_MRID));
139         RID             = parseInt(cgi.param(PARAM_RID));
140         AUTHTIME        = parseInt(cgi.param(PARAM_AUTHTIME));
141         ADVTERM = cgi.param(PARAM_ADVTERM);
142         ADVTYPE = cgi.param(PARAM_ADVTYPE);
143         RTYPE           = cgi.param(PARAM_RTYPE);
144         SORT            = cgi.param(PARAM_SORT);
145         SORT_DIR        = cgi.param(PARAM_SORT_DIR);
146         DEBUG           = cgi.param(PARAM_DEBUG);
147         CALLNUM = cgi.param(PARAM_CN);
148         LITFORM = cgi.param(PARAM_LITFORM);
149         ITEMFORM        = cgi.param(PARAM_ITEMFORM);
150         ITEMTYPE        = cgi.param(PARAM_ITEMTYPE);
151         BIBLEVEL        = cgi.param(PARAM_BIBLEVEL);
152         AUDIENCE        = cgi.param(PARAM_AUDIENCE);
153         SEARCHES = cgi.param(PARAM_SEARCHES);
154         LANGUAGE        = cgi.param(PARAM_LANGUAGE);
155         TFORM           = cgi.param(PARAM_TFORM);
156         RDEPTH  = cgi.param(PARAM_RDEPTH);
157     AVAIL   = cgi.param(PARAM_AVAIL);
158
159         /* set up some sane defaults */
160         //if(isNaN(DEPTH))      DEPTH           = 0;
161         if(isNaN(RDEPTH))       RDEPTH  = 0;
162         if(isNaN(OFFSET))       OFFSET  = 0;
163         if(isNaN(COUNT))        COUNT           = 10;
164         if(isNaN(HITCOUNT))     HITCOUNT        = 0;
165         if(isNaN(MRID))         MRID            = 0;
166         if(isNaN(RID))          RID             = 0;
167         if(isNaN(ORIGLOC))      ORIGLOC = 0; /* so we know it hasn't been set */
168         if(isNaN(AUTHTIME))     AUTHTIME        = 0;
169         if(ADVTERM==null)       ADVTERM = "";
170     if(isNaN(AVAIL))    AVAIL = 0;
171 }
172
173 function clearSearchParams() {
174         TERM        = null;
175         STYPE       = null;
176         FORM        = null;
177         OFFSET      = 0;
178         HITCOUNT    = 0;  
179         ADVTERM     = null;
180         ADVTYPE     = null;
181         MRID        = null;
182         RID         = null;
183         RTYPE       = null;
184         SORT        = null;
185         SORT_DIR    = null;
186         RLIST       = null;
187         CALLNUM     = null;
188         LITFORM     = null;
189         ITEMFORM    = null;
190         ITEMTYPE    = null;
191         BIBLEVEL    = null;
192         AUDIENCE    = null;
193         SEARCHES    = null;
194         LANGUAGE    = null;
195         RDEPTH      = null;
196     AVAIL       = null;
197 }
198
199
200 function initCookies() {
201         FONTSIZE = "regular";
202         var font = cookieManager.read(COOKIE_FONT);
203         scaleFonts(font);
204         if(font) FONTSIZE = font;
205         SKIN = cookieManager.read(COOKIE_SKIN);
206     if(findCurrentPage() == HOME)
207         cookieManager.remove(COOKIE_SEARCH);
208         
209
210 }
211
212 /* URL param accessors */
213 function getTerm(){return TERM;}
214 function getStype(){return STYPE;}
215 function getLocation(){return LOCATION;}
216 function getDepth(){return DEPTH;}
217 function getForm(){return FORM;}
218 function getTform(){return TFORM;}
219 function getOffset(){return OFFSET;}
220 function getDisplayCount(){return COUNT;}
221 function getHitCount(){return HITCOUNT;}
222 function getMrid(){return MRID;};
223 function getRid(){return RID;};
224 function getOrigLocation(){return ORIGLOC;}
225 function getAuthtime() { return AUTHTIME; }
226 function getSearchBarExtras(){return SBEXTRAS;}
227 function getFontSize(){return FONTSIZE;};
228 function getSkin(){return SKIN;};
229 function getAdvTerm(){return ADVTERM;}
230 function getAdvType(){return ADVTYPE;}
231 function getRtype(){return RTYPE;}
232 function getSort(){return SORT;}
233 function getSortDir(){return SORT_DIR;}
234 function getDebug(){return DEBUG;}
235 function getCallnumber() { return CALLNUM; }
236 function getLitForm() { return LITFORM; }
237 function getItemForm() { return ITEMFORM; }
238 function getItemType() { return ITEMTYPE; }
239 function getBibLevel() { return BIBLEVEL; }
240 function getAudience() { return AUDIENCE; }
241 function getSearches() { return SEARCHES; }
242 function getLanguage() { return LANGUAGE; }
243 function getRdepth() { return RDEPTH; }
244 function getAvail() { return AVAIL; }
245
246
247 function findBasePath() {
248         var path = location.pathname;
249         if(!path.match(/.*\.xml$/)) path += "index.xml"; 
250         var idx = path.indexOf(config.page[findCurrentPage()]);
251         return path.substring(0, idx);
252 }
253
254 function findBaseURL(ssl) {
255         var path = findBasePath();
256         var proto = (ssl) ? "https:" : "http:";
257
258         /* strip port numbers.  This is necessary for browsers that
259         send an explicit  <host>:80, 443 - explicit ports
260         break links that need to change ports (e.g. http -> https) */
261         var h = location.host.replace(/:.*/,''); 
262
263         return proto + "//" + h + path;
264 }
265
266 /*
267 function buildISBNSrc(isbn) {
268         return "http://" + location.host + "/jackets/" + isbn;
269 }
270 */
271
272 function buildImageLink(name, ssl) {
273         return findBaseURL(ssl) + "../../../../images/" + name;
274 }
275
276 function buildExtrasLink(name, ssl) {
277         return findBaseURL(ssl) + "../../../../extras/" + name;
278 }
279
280 var consoleService;
281 function _debug(str) { 
282         try { dump('dbg: ' + str + '\n'); } catch(e) {} 
283
284         /* potentially useful, but usually just annoying */
285         /*
286         if(!IE) {
287                 if(!consoleService) {
288                         try {
289                                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
290                                 this.consoleService = Components.classes['@mozilla.org/consoleservice;1']
291                                         .getService(Components.interfaces.nsIConsoleService);
292                         } catch(e) {}
293                 }
294         
295                 try {
296                         if(consoleService) {
297                                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
298                                 consoleService.logStringMessage(str + '\n');
299                         }
300                 } catch(e){}
301         }
302         */
303 }
304
305 function  buildOPACLink(args, slim, ssl) {
306
307         if(!args) args = {};
308         var string = "";
309
310         if(!slim) {
311                 string = findBaseURL(ssl);
312                 if(args.page) string += config.page[args.page];
313                 else string += config.page[findCurrentPage()];
314         }
315
316         /* this may seem unnecessary.. safety precaution for now */
317         /*
318         if( args[PARAM_DEPTH] == null )
319                 args[PARAM_DEPTH] = getDepth();
320                 */
321
322         string += "?";
323
324         for( var x in args ) {
325                 var v = args[x];
326                 if(x == "page" || v == null || v == undefined || v+'' == 'NaN' ) continue;
327                 if(x == PARAM_OFFSET && v == 0) continue;
328                 if(x == PARAM_COUNT && v == 10) continue;
329                 if(x == PARAM_FORM && v == 'all' ) continue;
330                 if( instanceOf(v, Array) && v.length ) {
331                         for( var i = 0; i < v.length; i++ ) {
332                                 string += "&" + x + "=" + encodeURIComponent(v[i]);
333                         }
334                 } else {
335                         string += "&" + x + "=" + encodeURIComponent(v);
336                 }
337         }
338
339         if(getDebug())
340                 string += _appendParam(DEBUG,           PARAM_DEBUG, args, getDebug, string);
341         if(getOrigLocation() != 1) 
342                 string += _appendParam(ORIGLOC, PARAM_ORIGLOC, args, getOrigLocation, string);
343         if(getTerm()) 
344                 string += _appendParam(TERM,            PARAM_TERM, args, getTerm, string);
345         if(getStype()) 
346                 string += _appendParam(STYPE,           PARAM_STYPE, args, getStype, string);
347         if(getLocation() != 1) 
348                 string += _appendParam(LOCATION, PARAM_LOCATION, args, getLocation, string);
349         if(getDepth() != null) 
350                 string += _appendParam(DEPTH,           PARAM_DEPTH, args, getDepth, string);
351         if(getForm() && (getForm() != 'all') ) 
352                 string += _appendParam(FORM,            PARAM_FORM, args, getForm, string);
353         if(getTform() && (getTform() != 'all') ) 
354                 string += _appendParam(TFORM,           PARAM_TFORM, args, getTform, string);
355         if(getOffset() != 0) 
356                 string += _appendParam(OFFSET,  PARAM_OFFSET, args, getOffset, string);
357         if(getDisplayCount() != 10) 
358                 string += _appendParam(COUNT,           PARAM_COUNT, args, getDisplayCount, string);
359         if(getHitCount()) 
360                 string += _appendParam(HITCOUNT, PARAM_HITCOUNT, args, getHitCount, string);
361         if(getMrid())
362                 string += _appendParam(MRID,            PARAM_MRID, args, getMrid, string);
363         if(getRid())
364                 string += _appendParam(RID,             PARAM_RID, args, getRid, string);
365         if(getAuthtime())
366                 string += _appendParam(AUTHTIME,        PARAM_AUTHTIME, args, getAuthtime, string);
367         if(getAdvTerm())
368                 string += _appendParam(ADVTERM, PARAM_ADVTERM, args, getAdvTerm, string);
369         if(getAdvType())
370                 string += _appendParam(ADVTYPE, PARAM_ADVTYPE, args, getAdvType, string);
371         if(getRtype())
372                 string += _appendParam(RTYPE,           PARAM_RTYPE, args, getRtype, string);
373         if(getItemForm())
374                 string += _appendParam(ITEMFORM,        PARAM_ITEMFORM, args, getItemForm, string);
375         if(getItemType())
376                 string += _appendParam(ITEMTYPE,        PARAM_ITEMTYPE, args, getItemType, string);
377         if(getBibLevel())
378                 string += _appendParam(BIBLEVEL,        PARAM_BIBLEVEL, args, getBibLevel, string);
379         if(getLitForm())
380                 string += _appendParam(LITFORM, PARAM_LITFORM, args, getLitForm, string);
381         if(getAudience())
382                 string += _appendParam(AUDIENCE,        PARAM_AUDIENCE, args, getAudience, string);
383         if(getSearches())
384                 string += _appendParam(SEARCHES,        PARAM_SEARCHES, args, getSearches, string);
385         if(getLanguage())
386                 string += _appendParam(LANGUAGE,        PARAM_LANGUAGE, args, getLanguage, string);
387         if(getRdepth() != null)
388                 string += _appendParam(RDEPTH,  PARAM_RDEPTH, args, getRdepth, string);
389         if(getSort() != null)
390                 string += _appendParam(SORT,    PARAM_SORT, args, getSort, string);
391         if(getSortDir() != null)
392                 string += _appendParam(SORT_DIR,        PARAM_SORT_DIR, args, getSortDir, string);
393         if(getAvail())
394                 string += _appendParam(AVAIL, PARAM_AVAIL, args, getAvail, string);
395
396         return string.replace(/\&$/,'').replace(/\?\&/,"?");    
397 }
398
399 var xx = 1;
400 function _appendParam( fieldVar, fieldName, overrideArgs, getFunc, string ) {
401
402         var ret = "";
403
404         if(     fieldVar != null && 
405                         (fieldVar +'' != 'NaN') && 
406                         overrideArgs[fieldName] == null &&
407                         getFunc() != null &&
408                         getFunc()+'' != '' ) {
409
410                 ret = "&" + fieldName + "=" + encodeURIComponent(getFunc());
411         }
412
413         return ret;
414 }
415
416 /* ----------------------------------------------------------------------- */
417 function cleanISBN(isbn) {
418    if(isbn) {
419       isbn = isbn.toString().replace(/^\s+/,"");
420       var idx = isbn.indexOf(" ");
421       if(idx > -1) { isbn = isbn.substring(0, idx); }
422    } else isbn = "";
423    return isbn;
424 }       
425
426
427 /* builds a link that goes to the title listings for a metarecord */
428 function buildTitleLink(rec, link) {
429         if(!rec) return;
430         link.appendChild(text(normalize(truncate(rec.title(), 65))));
431         var args = {};
432         args.page = RRESULT;
433         args[PARAM_OFFSET] = 0;
434         args[PARAM_MRID] = rec.doc_id();
435         args[PARAM_RTYPE] = RTYPE_MRID;
436         link.setAttribute("href", buildOPACLink(args));
437 }
438
439 function buildTitleDetailLink(rec, link) {
440         if(!rec) return;
441         link.appendChild(text(normalize(truncate(rec.title(), 65))));
442         var args = {};
443         args.page = RDETAIL;
444         //args[PARAM_OFFSET] = 0;
445         args[PARAM_RID] = rec.doc_id();
446         link.setAttribute("href", buildOPACLink(args));
447 }
448
449 /* 'type' is one of STYPE_AUTHOR, STYPE_SUBJECT, ... found in config.js 
450         'trunc' is the number of characters to show in the string, defaults to 65 */
451 function buildSearchLink(type, string, linknode, trunc) {
452         if(!trunc) trunc = 65;
453         var args = {};
454         if( SHOW_MR_DEFAULT) {
455                 args.page = MRESULT;
456         } else {
457                 args.page = RRESULT;
458                 args[PARAM_RTYPE] = type;
459         }
460         args[PARAM_OFFSET] = 0;
461         args[PARAM_TERM] = string;
462         args[PARAM_STYPE] = type;
463         linknode.appendChild(text(normalize(truncate(string, trunc))));
464         linknode.setAttribute("href", buildOPACLink(args));
465 }
466
467 function setSessionCookie(ses) {
468         cookieManager.write(COOKIE_SES, ses, -1);
469 }
470
471
472
473 /* ----------------------------------------------------------------------- */
474 /* user session handling */
475 /* ----------------------------------------------------------------------- */
476 /* session is the login session.  If no session is provided, we attempt
477         to find one in the cookies.  If 'force' is true we retrieve the 
478         user from the server even if there is already a global user present.
479         if ses != G.user.session, we also force a grab */
480 function grabUser(ses, force) {
481
482         if(!ses && isXUL()) {
483                 stash = fetchXULStash();
484                 ses = stash.session.key
485                 _debug("stash auth token = " + ses);
486         }
487
488         if(!ses) {
489                 ses = cookieManager.read(COOKIE_SES);
490                 /* https cookies don't show up in http servers.. */
491         }
492
493         if(!ses) return false;
494
495         if(!force) 
496                 if(G.user && G.user.session == ses)
497                         return G.user;
498
499         /* first make sure the session is valid */
500         var request = new Request(FETCH_SESSION, ses, 1 );
501         request.request.alertEvent = false;
502         request.send(true);
503         var user = request.result();
504
505         if(!user) {
506                 doLogout();
507                 return false; /* unable to grab the session */
508         }
509
510         if( !(typeof user == 'object' && user._isfieldmapper) ) {
511                 doLogout();
512                 return false;
513         }
514
515         G.user = user;
516         G.user.fleshed = false;
517         G.user.session = ses;
518         setSessionCookie(ses);
519
520         grabUserPrefs();
521         if(G.user.prefs['opac.hits_per_page'])
522                 COUNT = parseInt(G.user.prefs['opac.hits_per_page']);
523
524         if(G.user.prefs[PREF_DEF_FONT]) 
525                 setFontSize(G.user.prefs[PREF_DEF_FONT]);
526
527         var at = getAuthtime();
528         //if(isXUL()) at = xulG['authtime'];
529
530         if(at && !isXUL()) new AuthTimer(at).run(); 
531         return G.user;
532 }
533
534
535 /* sets the 'prefs' field of the user object to their preferences 
536         and returns the preferences */
537 function grabUserPrefs(user, force) {
538         if(user == null) user = G.user;
539         if(!force && user.prefs) return user.prefs;     
540         var req = new Request(FETCH_USER_PREFS, user.session, user.id());
541         req.send(true);
542         user.prefs = req.result();
543         return user.prefs;
544 }
545
546 function grabFleshedUser() {
547
548         if(!G.user || !G.user.session) {
549                 grabUser();     
550                 if(!G.user || !G.user.session) return null;
551         }
552
553         if(G.user.fleshed) return G.user;
554
555    var req = new Request(FETCH_FLESHED_USER, G.user.session);
556         req.send(true);
557
558         G.user = req.result();
559
560         if(!G.user || G.user.length == 0) { 
561                 G.user = null; return false; 
562                 cookieManager.write(COOKIE_SES,"");
563         }
564
565         G.user.session = ses;
566         G.user.fleshed = true;
567
568         setSessionCookie(ses);
569         return G.user;
570 }
571
572 function checkUserSkin(new_skin) {
573
574         return; /* XXX do some debugging with this... */
575
576         var user_skin = getSkin();
577         var cur_skin = grabSkinFromURL();
578
579         if(new_skin) user_skin = new_skin;
580
581         if(!user_skin) {
582
583                 if(grabUser()) {
584                         if(grabUserPrefs()) {
585                                 user_skin = G.user.prefs["opac.skin"];
586                                 cookieManager.write( COOKIE_SKIN, user_skin, '+1y' );
587                         }
588                 }
589         }
590
591         if(!user_skin) return;
592
593         if( cur_skin != user_skin ) {
594                 var url = buildOPACLink();
595                 goTo(url.replace(cur_skin, user_skin));
596         }
597 }
598
599 function updateUserSetting(setting, value, user) {
600         if(user == null) user = G.user;
601         var a = {};
602         a[setting] = value;
603         var req = new Request( UPDATE_USER_PREFS, user.session, a );
604         req.send(true);
605         return req.result();
606 }
607
608 function commitUserPrefs() {
609         var req = new Request( 
610                 UPDATE_USER_PREFS, G.user.session, null, G.user.prefs );
611         req.send(true);
612         return req.result();
613 }
614
615 function grabSkinFromURL() {
616         var path = findBasePath();
617         path = path.replace("/xml/", "");
618         var skin = "";
619         for( var i = path.length - 1; i >= 0; i-- ) {
620                 var ch = path.charAt(i);
621                 if(ch == "/") break;
622                 skin += ch;
623         }
624
625         var skin2 = "";
626         for( i = skin.length - 1; i >= 0; i--)
627                 skin2 += skin.charAt(i);
628
629         return skin2;
630 }
631
632
633 /* returns a fleshed G.user on success, false on failure */
634 function doLogin(suppressEvents) {
635
636         abortAllRequests();
637
638         var uname = G.ui.login.username.value;
639         var passwd = G.ui.login.password.value; 
640
641         var init_request = new Request( LOGIN_INIT, uname );
642    init_request.send(true);
643    var seed = init_request.result();
644
645    if( ! seed || seed == '0') {
646       alert( "Error Communicating with Authentication Server" );
647       return null;
648    }
649
650         var args = {
651                 password : hex_md5(seed + hex_md5(passwd)), 
652                 type            : "opac", 
653                 org             : getOrigLocation()
654         };
655
656     r = fetchOrgSettingDefault(globalOrgTree.id(), 'opac.barcode_regex');
657     if(r) REGEX_BARCODE = new RegExp(r);
658     
659     if( uname.match(REGEX_BARCODE) ) args.barcode = uname;
660         else args.username = uname;
661
662    var auth_request = new Request( LOGIN_COMPLETE, args );
663
664         auth_request.request.alertEvent = false;
665    auth_request.send(true);
666    var auth_result = auth_request.result();
667
668         if(!auth_result) {
669                 alertId('patron_login_failed');
670                 return null;
671         }
672
673         if( checkILSEvent(auth_result) ) {
674
675                 if( auth_result.textcode == 'PATRON_INACTIVE' ) {
676                         alertId('patron_inactive_alert');
677                         return;
678                 }
679
680                 if( auth_result.textcode == 'PATRON_CARD_INACTIVE' ) {
681                         alertId('patron_card_inactive_alert');
682                         return;
683                 }
684
685                 if( auth_result.textcode == 'LOGIN_FAILED' || 
686                                 auth_result.textcode == 'PERM_FAILURE' ) {
687                         alertId('patron_login_failed');
688                         return;
689                 }
690         }
691
692
693         AUTHTIME = parseInt(auth_result.payload.authtime);
694         var u = grabUser(auth_result.payload.authtoken, true);
695         if(u && ! suppressEvents) 
696                 runEvt( "common", "locationChanged", u.ws_ou(), findOrgDepth(u.ws_ou()) );
697
698         checkUserSkin();
699
700         return u;
701 }
702
703 function doLogout(noredirect) {
704
705         /* cancel everything else */
706         abortAllRequests();
707
708         /* be nice and delete the session from the server */
709         if(G.user && G.user.session) { 
710                 var req = new Request(LOGIN_DELETE, G.user.session);
711       req.send(true);
712                 try { req.result(); } catch(E){}
713     }
714
715         G.user = null;
716
717         /* remove any cached data */
718         //cookieManager.remove(COOKIE_IDS);
719         //cookieManager.remove(COOKIE_SRIDS);
720         cookieManager.remove(COOKIE_RIDS);
721         cookieManager.remove(COOKIE_SES);
722         cookieManager.remove(COOKIE_SKIN);
723         cookieManager.remove(COOKIE_SEARCH);
724
725         checkUserSkin("default");
726         COUNT = 10;
727
728
729         var args = {};
730         args[PARAM_TERM] = "";
731         args[PARAM_LOCATION] = getOrigLocation();
732         args[PARAM_DEPTH] = findOrgDepth(getOrigLocation());
733         args.page = "home";
734
735         
736         var nored = false;
737         try{ if(isFrontPage) nored = true; } catch(e){nored = false;}
738         if(!nored) goTo(buildOPACLink(args));
739 }
740
741
742 function hideMe(obj) { addCSSClass(obj, config.css.hide_me); } 
743 function unHideMe(obj) { removeCSSClass(obj, config.css.hide_me); }
744
745
746 /* ----------------------------------------------------------------------- */
747 /* build the org tree */
748 /* ----------------------------------------------------------------------- */
749 function drawOrgTree() {
750         //setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 10 );
751         setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 1 );
752 }
753         
754 var orgTreeSelector;
755 function buildOrgSelector(node) {
756         var tree = new SlimTree(node,'orgTreeSelector');
757         orgTreeSelector = tree;
758         for( var i in orgArraySearcher ) { 
759                 var node = orgArraySearcher[i];
760                 if( node == null ) continue;
761         if(!isXUL() && !isTrue(node.opac_visible())) continue; 
762                 if(node.parent_ou() == null)
763                         tree.addNode(node.id(), -1, node.name(), 
764                                 "javascript:orgSelect(" + node.id() + ");", node.name());
765                 else {
766                         tree.addNode(node.id(), node.parent_ou(), node.name(), 
767                                 "javascript:orgSelect(" + node.id() + ");", node.name());
768                 }
769         }
770         hideMe($('org_loading_div'));
771         unHideMe($('org_selector_tip'));
772         return tree;
773 }
774
775 function orgSelect(id) {
776         showCanvas();
777         runEvt("common", "locationChanged", id, findOrgDepth(id) );
778
779         removeChildren(G.ui.common.now_searching);
780         G.ui.common.now_searching.appendChild(text(findOrgUnit(id).name()));
781 }
782
783 function setFontSize(size) {
784         scaleFonts(size);
785         cookieManager.write(COOKIE_FONT, size, '+1y');
786 }
787
788 var resourceFormats = [
789    "text",
790    "moving image",
791    "sound recording", "software, multimedia",
792    "still image",
793    "cartographic",
794    "mixed material",
795    "notated music",
796    "three dimensional object" ];
797
798
799 function modsFormatToMARC(format) {
800    switch(format) {
801       case "text":
802          return "at";
803       case "moving image":
804          return "g";
805       case "sound recording":
806          return "ij";
807       case "sound recording-nonmusical":
808          return "i";
809       case "sound recording-musical":
810          return "j";
811       case "software, multimedia":
812          return "m";
813       case "still image":
814          return "k";
815       case "cartographic":
816          return "ef";
817       case "mixed material":
818          return "op";
819       case "notated music":
820          return "cd";
821       case "three dimensional object":
822          return "r";
823    }
824    return "at";
825 }
826
827
828 function MARCFormatToMods(format) {
829    switch(format) {
830       case "a":
831       case "t":
832          return "text";
833       case "g":
834          return "moving image";
835       case "i":
836          return "sound recording-nonmusical";
837       case "j":
838          return "sound recording-musical";
839       case "m":
840          return "software, multimedia";
841       case "k":
842          return "still image";
843       case "e":
844       case "f":
845          return "cartographic";
846       case "o":
847       case "p":
848          return "mixed material";
849       case "c":
850       case "d":
851          return "notated music";
852       case "r":
853          return "three dimensional object";
854    }
855    return "text";
856 }
857
858 function MARCTypeToFriendly(format) {
859         var words = $('format_words');
860         switch(format) {
861                 case 'a' :
862                 case 't' : return $n(words, 'at').innerHTML;
863                 default:
864                         var node = $n(words,format);
865                         if( node ) return node.innerHTML;
866         }
867         return "";
868 }
869
870 function setResourcePic( img, resource ) {
871         img.setAttribute( "src", "../../../../images/tor/" + resource + ".jpg");
872         img.title = resource;
873 }
874
875
876
877 function msg( text ) {
878         try { alert( text ); } catch(e) {}
879 }
880
881 function findRecord(id,type) {
882         try {
883                 for( var i = 0; i != recordsCache.length; i++ ) {
884                         var rec = recordsCache[i];
885                         if( rec && rec.doc_id() == id ) return rec;
886                 }
887         } catch(E){}
888         var meth = FETCH_RMODS
889         if(type == 'M') meth = FETCH_MRMODS;
890         var req = new Request(meth, id);
891         req.request.alertEvent = false;
892         req.send(true);
893         var res = req.result();
894         if( checkILSEvent(res) ) return null; 
895         return res;
896 }
897
898 function Timer(name, node){
899         this.name = name;
900         this.count = 1;
901         this.node = node;
902 }
903 Timer.prototype.start = 
904         function(){_timerRun(this.name);}
905 Timer.prototype.stop = 
906         function(){this.done = true;}
907 function _timerRun(tname) {
908         var _t;
909         eval('_t='+tname);
910         if(_t.done) return;
911         if(_t.count > 100) return;
912         var str = ' . ';
913         if( (_t.count % 5) == 0 ) 
914                 str = _t.count / 5;
915         _t.node.appendChild(text(str));
916         setTimeout("_timerRun('"+tname+"');", 200);
917         _t.count++;
918 }
919
920 function checkILSEvent(obj) {
921         if( obj && obj.ilsevent != null && obj.ilsevent != 0 )
922                 return parseInt(obj.ilsevent);
923         return null;
924 }
925
926
927 function alertILSEvent(evt, msg) {
928    if(!msg) msg = "";
929         if(msg)
930                 alert(msg +'\n' + evt.textcode + '\n' + evt.desc );
931         else 
932                 alert(evt.textcode + '\n' + evt.desc );
933 }
934
935
936 var __authTimer;
937 function AuthTimer(time) { 
938         this.time = (time - LOGOUT_WARNING_TIME) * 1000; 
939         if(__authTimer) 
940                 try {clearTimeout(__authTimer.id)} catch(e){}
941         __authTimer = this;
942 }
943
944 AuthTimer.prototype.run = function() {
945         this.id = setTimeout('_authTimerAlert()', this.time);
946 }
947
948 function _authTimerAlert() {
949         alert( $('auth_session_expiring').innerHTML );
950         if(!grabUser(null, true)) doLogout();
951 }
952
953
954 function grabUserByBarcode( authtoken, barcode ) {
955         var req = new Request( FETCH_USER_BYBARCODE, authtoken, barcode );
956         req.send(true);
957         return req.result();
958 }
959
960
961 function goHome() {
962         goTo(buildOPACLink({page:HOME}));
963 }
964
965
966 function buildOrgSel(selector, org, offset) {
967         insertSelectorVal( selector, -1, 
968                 org.name(), org.id(), null, findOrgDepth(org) - offset );
969         for( var c in org.children() )
970                 buildOrgSel( selector, org.children()[c], offset);
971 }
972
973
974 function parseForm(form) {
975         if(!form) return {};
976
977         var it = form.replace(/-\w+$/,"");
978         var itf = null;
979         var item_form;
980         var item_type;
981
982         if(form.match(/-/)) itf = form.replace(/^\w+-/,"");
983
984         if(it) {
985                 item_type = [];
986                 for( var i = 0; i < it.length; i++ ) 
987                         item_type.push( it.charAt(i) );
988         }
989
990         if(itf) {
991                 item_form = [];
992                 for( var i = 0; i < itf.length; i++ ) 
993                         item_form.push( itf.charAt(i) );
994         }
995
996         return {item_type: item_type, item_form:item_form};
997 }
998
999
1000 function isTrue(x) { return ( x && x != "0" && !(x+'').match(/^f$/i) ); }
1001
1002 function fetchPermOrgs() {
1003         var a = []; /* why does arguments come accross as an object and not an array? */
1004         for( var i = 0; i < arguments.length; i++ ) 
1005                 a.push(arguments[i])
1006
1007         var preq = new Request(FETCH_HIGHEST_PERM_ORG, 
1008                 G.user.session, G.user.id(), a );
1009         preq.send(true);
1010         return preq.result();
1011 }
1012
1013
1014 function print_tabs(t) {
1015         var r = '';
1016         for (var j = 0; j < t; j++ ) { r = r + "  "; }
1017         return r;
1018 }
1019 function formatJSON(s) {
1020         var r = ''; var t = 0;
1021         for (var i in s) {
1022                 if (s[i] == '{' || s[i] == '[' ) {
1023                         r = r + s[i] + "\n" + print_tabs(++t);
1024                 } else if (s[i] == '}' || s[i] == ']') {
1025                         t--; r = r + "\n" + print_tabs(t) + s[i];
1026                 } else if (s[i] == ',') {
1027                         r = r + s[i] + "\n" + print_tabs(t);
1028                 } else {
1029                         r = r + s[i];
1030                 }
1031         }
1032         return r;
1033 }