getting authtime from xul
[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 function Request(type) {
7         var s = type.split(":");
8         if(s[2] == "1" && isXUL()) s[1] += ".staff";
9         this.request = new RemoteRequest(s[0], s[1]);
10         for( var x = 1; x!= arguments.length; x++ ) 
11                 this.request.addParam(arguments[x]);
12 }
13
14 Request.prototype.callback = function(cal) { this.request.setCompleteCallback(cal); }
15 Request.prototype.send          = function(block){this.request.send(block);}
16 Request.prototype.result        = function(){return this.request.getResultObject();}
17
18 function showCanvas() {
19         for( var x in G.ui.altcanvas ) {
20                 hideMe(G.ui.altcanvas[x]);
21         }
22         hideMe(G.ui.common.loading);
23         unHideMe(G.ui.common.canvas_main);
24         G.ui.searchbar.text.focus(); 
25 }
26
27 function swapCanvas(newNode) {
28         for( var x in G.ui.altcanvas ) 
29                 hideMe(G.ui.altcanvas[x]);
30
31         hideMe(G.ui.common.loading);
32         hideMe(G.ui.common.canvas_main);
33         unHideMe(newNode);
34 }
35
36 /* finds the name of the current page */
37 var currentPage = null;
38 function findCurrentPage() {
39         if(currentPage) return currentPage;
40
41         var pages = [];
42         for( var p in config.page ) pages.push(config.page[p]);
43         pages = pages.sort( function(a,b){ return - (a.length - b.length); } );
44
45         var path = location.pathname;
46         if(!path.match(/.*\.xml$/))
47                 path += "index.xml"; /* in case they go to  / */
48
49         var page = null;
50         for( var p in pages ) {
51                 if( path.indexOf(pages[p]) != -1)
52                         page = pages[p];
53         }
54
55         for( var p in config.page ) {
56                 if(config.page[p] == page) {
57                         currentPage = p;
58                         return p;
59                 }
60         }
61         return null;
62 }
63
64
65 /* sets all of the params values  ----------------------------- */
66 function initParams() {
67         var cgi = new CGI();    
68
69         TERM    = cgi.param(PARAM_TERM);
70         STYPE   = cgi.param(PARAM_STYPE);
71         FORM    = cgi.param(PARAM_FORM);
72
73         LOCATION        = parseInt(cgi.param(PARAM_LOCATION));
74         ORIGLOC = parseInt(cgi.param(PARAM_ORIGLOC));
75         DEPTH           = parseInt(cgi.param(PARAM_DEPTH));
76         OFFSET  = parseInt(cgi.param(PARAM_OFFSET));
77         COUNT           = parseInt(cgi.param(PARAM_COUNT));
78         HITCOUNT        = parseInt(cgi.param(PARAM_HITCOUNT));
79         MRID            = parseInt(cgi.param(PARAM_MRID));
80         RID             = parseInt(cgi.param(PARAM_RID));
81         TOPRANK  = parseFloat(cgi.param(PARAM_TOPRANK));
82         AUTHTIME        = parseInt(cgi.param(PARAM_AUTHTIME));
83
84         /* set up some sane defaults */
85         if(isNaN(LOCATION))     LOCATION        = 1;
86         if(isNaN(DEPTH))                DEPTH           = 0;
87         if(isNaN(OFFSET))               OFFSET  = 0;
88         if(isNaN(COUNT))                COUNT           = 10;
89         if(isNaN(HITCOUNT))     HITCOUNT        = 0;
90         if(isNaN(MRID))         MRID            = 0;
91         if(isNaN(RID))                  RID             = 0;
92         if(isNaN(ORIGLOC))      ORIGLOC = 0;
93         if(isNaN(TOPRANK))      TOPRANK = 1;
94         if(isNaN(AUTHTIME))     AUTHTIME        = 1;
95 }
96
97 function initCookies() {
98         FONTSIZE = "medium";
99         var font = fontCookie.get(COOKIE_FONT);
100         if(font) FONTSIZE = font;
101         SKIN = skinCookie.get(COOKIE_SKIN);
102 }
103
104 /* URL param accessors */
105 function getTerm(){return TERM;}
106 function getStype(){return STYPE;}
107 function getLocation(){return LOCATION;}
108 function getDepth(){return DEPTH;}
109 function getForm(){return FORM;}
110 function getOffset(){return OFFSET;}
111 function getDisplayCount(){return COUNT;}
112 function getHitCount(){return HITCOUNT;}
113 function getMrid(){return MRID;};
114 function getRid(){return RID;};
115 function getOrigLocation(){return ORIGLOC;}
116 function getTopRank(){return TOPRANK;}
117 function getAuthtime() { return AUTHTIME; }
118
119 function getSearchBarExtras(){return SBEXTRAS;}
120 function getFontSize(){return FONTSIZE;};
121 function getSkin(){return SKIN;};
122
123
124 function findBasePath() {
125         var path = location.pathname;
126         if(!path.match(/.*\.xml$/)) path += "index.xml"; 
127         var idx = path.indexOf(config.page[findCurrentPage()]);
128         return path.substring(0, idx);
129 }
130
131 function findBaseURL(ssl) {
132         var path = findBasePath();
133         var proto = (ssl) ? "https:" : "http:";
134         return proto + "//" + location.host + path;
135         dump( 'ssl: ' + ssl + 'proto ' + proto );
136 }
137
138 /*
139 function buildISBNSrc(isbn) {
140         return "http://" + location.host + "/jackets/" + isbn;
141 }
142 */
143
144 function buildImageLink(name, ssl) {
145         return findBaseURL(ssl) + "../../../images/" + name;
146 }
147
148 function  buildOPACLink(args, slim, ssl) {
149
150         if(!args) args = {};
151         var string = "";
152
153         if(!slim) {
154                 string = findBaseURL(ssl);
155                 if(args.page) string += config.page[args.page];
156                 else string += config.page[findCurrentPage()];
157         }
158
159         string += "?";
160
161         for( var x in args ) {
162                 if(x == "page" || args[x] == null) continue;
163                 string += "&" + x + "=" + encodeURIComponent(args[x]);
164         }
165
166         string += _appendParam(ORIGLOC, PARAM_ORIGLOC, args, getOrigLocation, string);
167         string += _appendParam(TERM,            PARAM_TERM, args, getTerm, string);
168         string += _appendParam(STYPE,           PARAM_STYPE, args, getStype, string);
169         string += _appendParam(LOCATION, PARAM_LOCATION, args, getLocation, string);
170         string += _appendParam(DEPTH,           PARAM_DEPTH, args, getDepth, string);
171         string += _appendParam(FORM,            PARAM_FORM, args, getForm, string);
172         string += _appendParam(OFFSET,  PARAM_OFFSET, args, getOffset, string);
173         string += _appendParam(COUNT,           PARAM_COUNT, args, getDisplayCount, string);
174         string += _appendParam(HITCOUNT, PARAM_HITCOUNT, args, getHitCount, string);
175         string += _appendParam(MRID,            PARAM_MRID, args, getMrid, string);
176         string += _appendParam(RID,             PARAM_RID, args, getRid, string);
177         string += _appendParam(TOPRANK, PARAM_TOPRANK, args, getTopRank, string);
178         string += _appendParam(AUTHTIME,        PARAM_AUTHTIME, args, getAuthtime, string);
179
180         return string.replace(/\&$/,'').replace(/\?\&/,"?");    
181 }
182
183 function _appendParam( fieldVar, fieldName, overrideArgs, getFunc, string ) {
184         var ret = "";
185         if( fieldVar != null && overrideArgs[fieldName] == null ) 
186                 ret = "&" + fieldName + "=" + encodeURIComponent(getFunc());
187         return ret;
188 }
189
190 /* ----------------------------------------------------------------------- */
191 function cleanISBN(isbn) {
192    if(isbn) {
193       isbn = isbn.toString().replace(/^\s+/,"");
194       var idx = isbn.indexOf(" ");
195       if(idx > -1) { isbn = isbn.substring(0, idx); }
196    } else isbn = "";
197    return isbn;
198 }       
199
200
201 /* builds a link that goes to the title listings for a metarecord */
202 function buildTitleLink(rec, link) {
203         if(!rec) return;
204         link.appendChild(text(normalize(truncate(rec.title(), 65))));
205         var args = {};
206         args.page = RRESULT;
207         args[PARAM_OFFSET] = 0;
208         args[PARAM_MRID] = rec.doc_id();
209         link.setAttribute("href", buildOPACLink(args));
210 }
211
212 function buildTitleDetailLink(rec, link) {
213         if(!rec) return;
214         link.appendChild(text(normalize(truncate(rec.title(), 65))));
215         var args = {};
216         args.page = RDETAIL;
217         args[PARAM_OFFSET] = 0;
218         args[PARAM_RID] = rec.doc_id();
219         link.setAttribute("href", buildOPACLink(args));
220 }
221
222 /* 'type' is one of STYPE_AUTHOR, STYPE_SUBJECT, ... found in config.js 
223         'trunc' is the number of characters to show in the string, defaults to 65 */
224 function buildSearchLink(type, string, linknode, trunc) {
225         if(!trunc) trunc = 65;
226         var args = {};
227         args.page = MRESULT;
228         args[PARAM_OFFSET] = 0;
229         args[PARAM_TERM] = string;
230         args[PARAM_STYPE] = type;
231         linknode.appendChild(text(normalize(truncate(string, trunc))));
232         linknode.setAttribute("href", buildOPACLink(args));
233 }
234
235
236 /* ----------------------------------------------------------------------- */
237 /* user session handling */
238 /* ----------------------------------------------------------------------- */
239 /* session is the login session.  If no session is provided, we attempt
240         to find one in the cookies.  If 'force' is true we retrieve the 
241         user from the server even if there is already a global user present.
242         if ses != G.user.session, we also force a grab */
243 var cookie = new cookieObject("ses", 1, "/", COOKIE_SES);
244 function grabUser(ses, force) {
245
246         if(!ses && isXUL()) ses = xulG['authtoken'];
247         if(!ses) ses = cookie.get(COOKIE_SES);
248         if(!ses) return false;
249
250         if(!force) 
251                 if(G.user && G.user.session == ses)
252                         return G.user;
253
254         /* first make sure the session is valid */
255         var request = new Request(FETCH_SESSION, ses, 1 );
256         request.send(true);
257         var user = request.result();
258
259         if(checkILSEvent(user)) {
260                 doLogout();
261                 return false; /* unable to grab the session */
262         }
263
264         if( !(typeof user == 'object' && user._isfieldmapper) ) {
265                 doLogout();
266                 return false;
267         }
268
269         G.user = user;
270         G.user.fleshed = false;
271         G.user.session = ses;
272         cookie.put(COOKIE_SES, ses);
273         cookie.write();
274
275         grabUserPrefs();
276         if(G.user.prefs['opac.hits_per_page'])
277                 COUNT = parseInt(G.user.prefs['opac.hits_per_page']);
278
279         var at = getAuthtime();
280         if(isXUL()) at = xulG['authtime'];
281         new AuthTimer(at).run();
282
283         return G.user;
284 }
285
286
287 /* sets the 'prefs' field of the user object to their preferences 
288         and returns the preferences */
289 function grabUserPrefs(user, force) {
290         if(user == null) user = G.user;
291         if(!force && user.prefs) return user.prefs;     
292         var req = new Request(FETCH_USER_PREFS, user.session, user.id());
293         req.send(true);
294         user.prefs = req.result();
295         return user.prefs;
296 }
297
298 function grabFleshedUser() {
299
300         if(!G.user || !G.user.session) {
301                 grabUser();     
302                 if(!G.user || !G.user.session) return null;
303         }
304
305         if(G.user.fleshed) return G.user;
306
307    var req = new Request(FETCH_FLESHED_USER, G.user.session);
308         req.send(true);
309
310         G.user = req.result();
311
312         if(!G.user || G.user.length == 0) { 
313                 G.user = null; return false; 
314                 cookie.remove(COOKIE_SES);
315         }
316
317         G.user.session = ses;
318         G.user.fleshed = true;
319
320         cookie.put(COOKIE_SES, ses); /*  update the cookie */
321         cookie.write();
322
323         return G.user;
324 }
325
326 var skinCookie = new cookieObject("skin", 1, "/", COOKIE_SKIN);
327 function checkUserSkin(new_skin) {
328
329         return; /* XXX do some debugging with this... */
330
331         var user_skin = getSkin();
332         var cur_skin = grabSkinFromURL();
333
334         if(new_skin) user_skin = new_skin;
335
336         if(!user_skin) {
337
338                 if(grabUser()) {
339                         if(grabUserPrefs()) {
340                                 user_skin = G.user.prefs["opac.skin"];
341                                 skinCookie.put( COOKIE_SKIN, user_skin );
342                                 skinCookie.write();
343                         }
344                 }
345         }
346
347         if(!user_skin) return;
348
349         if( cur_skin != user_skin ) {
350                 var url = buildOPACLink();
351                 goTo(url.replace(cur_skin, user_skin));
352         }
353 }
354
355 function updateUserSetting(setting, value, user) {
356         if(user == null) user = G.user;
357         var a = {};
358         a[setting] = value;
359         var req = new Request( UPDATE_USER_PREFS, user.session, a );
360         req.send(true);
361         return req.result();
362 }
363
364 function commitUserPrefs() {
365         var req = new Request( 
366                 UPDATE_USER_PREFS, G.user.session, G.user.prefs );
367         req.send(true);
368         return req.result();
369 }
370
371 function grabSkinFromURL() {
372         var path = findBasePath();
373         path = path.replace("/xml/", "");
374         var skin = "";
375         for( var i = path.length - 1; i >= 0; i-- ) {
376                 var ch = path.charAt(i);
377                 if(ch == "/") break;
378                 skin += ch;
379         }
380
381         var skin2 = "";
382         for( i = skin.length - 1; i >= 0; i--)
383                 skin2 += skin.charAt(i);
384
385         return skin2;
386 }
387
388
389 /* returns a fleshed G.user on success, false on failure */
390 function doLogin() {
391
392         var uname = G.ui.login.username.value;
393         var passwd = G.ui.login.password.value; 
394
395         var init_request = new Request( LOGIN_INIT, uname );
396    init_request.send(true);
397    var seed = init_request.result();
398
399    if( ! seed || seed == '0') {
400       alert( "Error Communicating with Authentication Server" );
401       return null;
402    }
403
404    var auth_request = new Request( LOGIN_COMPLETE, 
405                 uname, hex_md5(seed + hex_md5(passwd)), "opac", getOrigLocation());
406
407
408    auth_request.send(true);
409    var auth_result = auth_request.result();
410
411         var code = checkILSEvent(auth_result);
412         if(code) { alertILSEvent(code); return null; }
413
414         var u = grabUser(auth_result.payload.authtoken, true);
415         AUTHTIME = parseInt(auth_result.payload.authtime);
416         if(u) runEvt( "common", "locationChanged", u.home_ou(), findOrgDepth(u.home_ou()) );
417
418         checkUserSkin();
419
420         return u;
421 }
422
423 function doLogout() {
424
425         /* be nice and delete the session from the server */
426         if(G.user && G.user.session) { 
427                 var req = new Request(LOGIN_DELETE, G.user.session);
428       req.send(true);
429                 try { req.result(); } catch(E){}
430     }
431
432         G.user = null;
433         cookie.remove(COOKIE_SES);
434         skinCookie.remove(COOKIE_SKIN);
435         checkUserSkin("default");
436         COUNT = 10;
437
438         var args = {};
439         args[PARAM_TERM] = "";
440         args[PARAM_LOCATION] = globalOrgTree.id();
441         args[PARAM_DEPTH] = findOrgDepth(globalOrgTree);
442         args.page = "home";
443
444         goTo(buildOPACLink(args));
445 }
446
447
448 function hideMe(obj) { addCSSClass(obj, config.css.hide_me); } 
449 function unHideMe(obj) { removeCSSClass(obj, config.css.hide_me); }
450
451
452 /* ----------------------------------------------------------------------- */
453 /* build the org tree */
454 /* ----------------------------------------------------------------------- */
455 function drawOrgTree() {
456         //G.ui.common.org_tree.innerHTML = buildOrgSelector().toString();
457         //buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);
458         setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 10 );
459 }
460         
461 var orgTreeSelector;
462 function buildOrgSelector(node) {
463         //var tree = new dTree("orgTreeSelector"); 
464         var tree = new SlimTree(node,'orgTreeSelector');
465         orgTreeSelector = tree;
466         for( var i in orgArraySearcher ) { 
467                 var node = orgArraySearcher[i];
468                 if( node == null ) continue;
469                 if(node.parent_ou() == null)
470                         tree.addNode(node.id(), -1, node.name(), 
471                                 "javascript:orgSelect(" + node.id() + ");", node.name());
472                 else {
473                         tree.addNode(node.id(), findOrgUnit(node.parent_ou()).id(), node.name(), 
474                                 "javascript:orgSelect(" + node.id() + ");", node.name());
475                 }
476         }
477         hideMe($('org_loading_div'));
478         unHideMe($('org_selector_tip'));
479         return tree;
480 }
481
482 function orgSelect(id) {
483         showCanvas();
484         runEvt("common", "locationChanged", id, findOrgDepth(id) );
485
486         removeChildren(G.ui.common.now_searching);
487         G.ui.common.now_searching.appendChild(text(findOrgUnit(id).name()));
488 }
489
490 var fontCookie = new cookieObject("fonts", 1, "/", COOKIE_FONT);
491 function setFontSize(size) {
492         scaleFonts(size);
493         fontCookie.put(COOKIE_FONT, size);
494         fontCookie.write();
495 }
496
497
498 var resourceFormats = [
499    "text",
500    "moving image",
501    "sound recording", "software, multimedia",
502    "still images",
503    "cartographic",
504    "mixed material",
505    "notated music",
506    "three dimensional object" ];
507
508
509 function modsFormatToMARC(format) {
510    switch(format) {
511       case "text":
512          return "at";
513       case "moving image":
514          return "g";
515       case "sound recording":
516          return "ij";
517       case "sound recording-nonmusical":
518          return "i";
519       case "sound recording-musical":
520          return "j";
521       case "software, multimedia":
522          return "m";
523       case "still images":
524          return "k";
525       case "cartographic":
526          return "ef";
527       case "mixed material":
528          return "op";
529       case "notated music":
530          return "cd";
531       case "three dimensional object":
532          return "r";
533    }
534    return "at";
535 }
536
537
538 function MARCFormatToMods(format) {
539    switch(format) {
540       case "a":
541       case "t":
542          return "text";
543       case "g":
544          return "moving image";
545       case "i":
546          return "sound recording-nonmusical";
547       case "j":
548          return "sound recording-musical";
549       case "m":
550          return "software, multimedia";
551       case "k":
552          return "still images";
553       case "e":
554       case "f":
555          return "cartographic";
556       case "o":
557       case "p":
558          return "mixed material";
559       case "c":
560       case "d":
561          return "notated music";
562       case "r":
563          return "three dimensional object";
564    }
565    return "text";
566 }
567
568 function setResourcePic( img, resource ) {
569         img.setAttribute( "src", "../../../images/tor/" + resource + ".jpg");
570         img.title = resource;
571 }
572
573
574
575 function msg( text ) {
576         try { alert( text ); } catch(e) {}
577 }
578
579 function findRecord(id,type) {
580         try {
581                 for( var i = 0; i != recordsCache.length; i++ ) {
582                         var rec = recordsCache[i];
583                         if( rec && rec.doc_id() == id ) return rec;
584                 }
585         } catch(E){}
586         var meth = FETCH_RMODS
587         if(type == 'M') meth = FETCH_MRMODS;
588         var req = new Request(meth, id);
589         req.send(true);
590         return req.result();
591 }
592
593 function Timer(name, node){
594         this.name = name;
595         this.count = 1;
596         this.node = node;
597 }
598 Timer.prototype.start = 
599         function(){_timerRun(this.name);}
600 Timer.prototype.stop = 
601         function(){this.done = true;}
602 function _timerRun(tname) {
603         var _t;
604         eval('_t='+tname);
605         if(_t.done) return;
606         var str = ' . ';
607         if( (_t.count % 5) == 0 ) 
608                 str = _t.count / 5;
609         _t.node.appendChild(text(str));
610         setTimeout("_timerRun('"+tname+"');", 200);
611         _t.count++;
612 }
613
614 function checkILSEvent(obj) {
615         if( obj.ilsevent != null && obj.ilsevent != 0 )
616                 return parseInt(obj.ilsevent);
617         return null;
618 }
619 function alertILSEvent(code, msg) {
620         alert( msg + '\n' + $('ilsevent.' + code).innerHTML );
621 }
622
623
624 var __authTimer;
625 function AuthTimer(time) { 
626         this.time = (time - LOGOUT_WARNING_TIME) * 1000; 
627         __authTimer = this;
628 }
629
630 AuthTimer.prototype.run = function() {
631         setTimeout('_authTimerAlert()', this.time);
632 }
633
634 function _authTimerAlert() {
635         if( confirm( $('auth_session_expiring').innerHTML ) ) 
636                 doLogout();
637         else {
638                 if(!grabUser(null, true)) {
639                         alert($('auth_session_expired').innerHTML);
640                 }
641         }
642 }
643
644
645 function grabUserByBarcode( authtoken, barcode ) {
646         var req = new Request( FETCH_USER_BYBARCODE, authtoken, barcode );
647         req.send(true);
648         return req.result();
649 }
650