adding basic preference grabbing and updating example for myopac,
[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         if(!ses) return false;
233
234         if(!force) 
235                 if(G.user && G.user.session == ses)
236                         return G.user;
237
238         /* first make sure the session is valid */
239         var request = new Request(FETCH_SESSION, ses );
240         request.send(true);
241         var user = request.result();
242         if( !(typeof user == 'object' && user._isfieldmapper) ) {
243                 return false;
244         }
245
246         G.user = user;
247         G.user.fleshed = false;
248         G.user.session = ses;
249         cookie.put(COOKIE_SES, ses);
250         cookie.write();
251
252         return G.user;
253
254 }
255
256
257 /* sets the 'prefs' field of the user object to their preferences 
258         and returns the preferences */
259 function grabUserPrefs(user, force) {
260         if(user == null) user = G.user;
261         if(!force && user.prefs) return user.prefs;     
262         var req = new Request(FETCH_USER_PREFS, user.session, user.id());
263         req.send(true);
264         user.prefs = req.result();
265         return user.prefs;
266 }
267
268 function grabFleshedUser() {
269
270         if(!G.user || !G.user.session) {
271                 grabUser();     
272                 if(!G.user || !G.user.session) return null;
273         }
274
275         if(G.user.fleshed) return G.user;
276
277    var req = new Request(FETCH_FLESHED_USER, G.user.session);
278         req.send(true);
279
280         G.user = req.result();
281
282         if(!G.user || G.user.length == 0) { 
283                 G.user = null; return false; 
284                 cookie.remove(COOKIE_SES);
285         }
286
287         G.user.session = ses;
288         G.user.fleshed = true;
289
290         cookie.put(COOKIE_SES, ses); /*  update the cookie */
291         cookie.write();
292
293         return G.user;
294 }
295
296 var skinCookie = new cookieObject("skin", 1, "/", COOKIE_SKIN);
297 function checkUserSkin(new_skin) {
298
299         return; /* XXX do some debugging with this... */
300
301         var user_skin = getSkin();
302         var cur_skin = grabSkinFromURL();
303
304         if(new_skin) user_skin = new_skin;
305
306         if(!user_skin) {
307
308                 if(grabUser()) {
309                         if(grabUserPrefs()) {
310                                 user_skin = G.user.prefs["opac.skin"];
311                                 skinCookie.put( COOKIE_SKIN, user_skin );
312                                 skinCookie.write();
313                         }
314                 }
315         }
316
317         if(!user_skin) return;
318
319         if( cur_skin != user_skin ) {
320                 var url = buildOPACLink();
321                 goTo(url.replace(cur_skin, user_skin));
322         }
323 }
324
325 function updateUserSetting(setting, value, user) {
326         if(user == null) user = G.user;
327         var a = {};
328         a[setting] = value;
329         var req = new Request( UPDATE_USER_PREFS, user.session, a );
330         req.send(true);
331         return req.result();
332 }
333
334 function commitUserPrefs() {
335         var req = new Request( 
336                 UPDATE_USER_PREFS, G.user.session, G.user.prefs );
337         req.send(true);
338         return req.result();
339 }
340
341 function grabSkinFromURL() {
342         var path = findBasePath();
343         path = path.replace("/xml/", "");
344         var skin = "";
345         for( var i = path.length - 1; i >= 0; i-- ) {
346                 var ch = path.charAt(i);
347                 if(ch == "/") break;
348                 skin += ch;
349         }
350
351         var skin2 = "";
352         for( i = skin.length - 1; i >= 0; i--)
353                 skin2 += skin.charAt(i);
354
355         return skin2;
356 }
357
358
359 /* returns a fleshed G.user on success, false on failure */
360 function doLogin() {
361
362         var uname = G.ui.login.username.value;
363         var passwd = G.ui.login.password.value; 
364
365         var init_request = new Request( LOGIN_INIT, uname );
366    init_request.send(true);
367    var seed = init_request.result();
368
369    if( ! seed || seed == '0') {
370       alert( "Error Communicating with Authentication Server" );
371       return null;
372    }
373
374    var auth_request = new Request( LOGIN_COMPLETE, 
375                 uname, hex_md5(seed + hex_md5(passwd)), "opac");
376
377
378    auth_request.send(true);
379    var auth_result = auth_request.result();
380
381    if(auth_result == '0' || auth_result == null || auth_result.length == 0) { 
382                 alert("Login failed");
383                 return false; 
384         }
385
386         var u = grabUser(auth_result, true);
387         if(u) runEvt( "common", "locationChanged", u.home_ou(), findOrgDepth(u.home_ou()) );
388
389         checkUserSkin();
390
391         return u;
392 }
393
394 function doLogout() {
395
396         /* be nice and delete the session from the server */
397         if(G.user && G.user.session) { 
398                 var req = new Request(LOGIN_DELETE, G.user.session);
399       req.send(true);
400                 try { req.result(); } catch(E){}
401     }
402
403         G.user = null;
404         cookie.remove(COOKIE_SES);
405         skinCookie.remove(COOKIE_SKIN);
406         checkUserSkin("default");
407
408         var args = {};
409         args[PARAM_TERM] = "";
410         args[PARAM_LOCATION] = globalOrgTree.id();
411         args[PARAM_DEPTH] = findOrgDepth(globalOrgTree);
412         args.page = "home";
413
414         goTo(buildOPACLink(args));
415 }
416
417
418 function hideMe(obj) { addCSSClass(obj, config.css.hide_me); } 
419 function unHideMe(obj) { removeCSSClass(obj, config.css.hide_me); }
420
421
422 /* ----------------------------------------------------------------------- */
423 /* build the org tree */
424 /* ----------------------------------------------------------------------- */
425 function drawOrgTree() {
426         //G.ui.common.org_tree.innerHTML = buildOrgSelector().toString();
427         //buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);
428         setTimeout( 'buildOrgSelector(G.ui.common.org_tree, orgTreeSelector);', 10 );
429 }
430         
431 var orgTreeSelector;
432 function buildOrgSelector(node) {
433         //var tree = new dTree("orgTreeSelector"); 
434         var tree = new SlimTree(node,'orgTreeSelector');
435         orgTreeSelector = tree;
436         for( var i in orgArraySearcher ) { 
437                 var node = orgArraySearcher[i];
438                 if( node == null ) continue;
439                 if(node.parent_ou() == null)
440                         tree.addNode(node.id(), -1, node.name(), 
441                                 "javascript:orgSelect(" + node.id() + ");", node.name());
442                 else {
443                         tree.addNode(node.id(), findOrgUnit(node.parent_ou()).id(), node.name(), 
444                                 "javascript:orgSelect(" + node.id() + ");", node.name());
445                 }
446         }
447         hideMe($('org_loading_div'));
448         unHideMe($('org_selector_tip'));
449         return tree;
450 }
451
452 function orgSelect(id) {
453         showCanvas();
454         runEvt("common", "locationChanged", id, findOrgDepth(id) );
455
456         removeChildren(G.ui.common.now_searching);
457         G.ui.common.now_searching.appendChild(text(findOrgUnit(id).name()));
458 }
459
460 var fontCookie = new cookieObject("fonts", 1, "/", COOKIE_FONT);
461 function setFontSize(size) {
462         scaleFonts(size);
463         fontCookie.put(COOKIE_FONT, size);
464         fontCookie.write();
465 }
466
467
468 var resourceFormats = [
469    "text",
470    "moving image",
471    "sound recording", "software, multimedia",
472    "still images",
473    "cartographic",
474    "mixed material",
475    "notated music",
476    "three dimensional object" ];
477
478
479 function modsFormatToMARC(format) {
480    switch(format) {
481       case "text":
482          return "at";
483       case "moving image":
484          return "g";
485       case "sound recording":
486          return "ij";
487       case "sound recording-nonmusical":
488          return "i";
489       case "sound recording-musical":
490          return "j";
491       case "software, multimedia":
492          return "m";
493       case "still images":
494          return "k";
495       case "cartographic":
496          return "ef";
497       case "mixed material":
498          return "op";
499       case "notated music":
500          return "cd";
501       case "three dimensional object":
502          return "r";
503    }
504    return "at";
505 }
506
507
508 function MARCFormatToMods(format) {
509    switch(format) {
510       case "a":
511       case "t":
512          return "text";
513       case "g":
514          return "moving image";
515       case "i":
516          return "sound recording-nonmusical";
517       case "j":
518          return "sound recording-musical";
519       case "m":
520          return "software, multimedia";
521       case "k":
522          return "still images";
523       case "e":
524       case "f":
525          return "cartographic";
526       case "o":
527       case "p":
528          return "mixed material";
529       case "c":
530       case "d":
531          return "notated music";
532       case "r":
533          return "three dimensional object";
534    }
535    return "text";
536 }
537
538 function setResourcePic( img, resource ) {
539         img.setAttribute( "src", "../../../images/tor/" + resource + ".jpg");
540         img.title = resource;
541 }
542
543
544
545 function msg( text ) {
546         try {
547                 alert( text );
548         } catch(e) {}
549 }
550
551 function findRecord(id,type) {
552         try {
553                 for( var i = 0; i != recordsCache.length; i++ ) {
554                         var rec = recordsCache[i];
555                         if( rec && rec.doc_id() == id ) return rec;
556                 }
557         } catch(E){}
558         var meth = FETCH_RMODS
559         if(type == 'M') meth = FETCH_MRMODS;
560         var req = new Request(meth, id);
561         req.send(true);
562         return req.result();
563 }
564
565
566
567