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