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