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