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