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