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