87d53ca087c28350ce45dca64ff7077a38323b9c
[working/Evergreen.git] / Open-ILS / web / opac / common / js / opac_utils.js
1
2
3 /* - Request ------------------------------------------------------------- */
4 function Request(type) {
5         var s = type.split(":");
6         if(s[2] == "1" && isXUL()) s[1] += ".staff";
7         this.request = new RemoteRequest(s[0], s[1]);
8         for( var x = 1; x!= arguments.length; x++ ) 
9                 this.request.addParam(arguments[x]);
10 }
11
12 Request.prototype.callback = function(cal) { this.request.setCompleteCallback(cal); }
13 Request.prototype.send          = function(block){this.request.send(block);}
14 Request.prototype.result        = function(){return this.request.getResultObject();}
15 /* ----------------------------------------------------------------------- */
16
17 function showCanvas() { setTimeout(_showCanvas, 200); }
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 var newCanvasNode;
28 function swapCanvas(newNode) { newCanvasNode = newNode; setTimeout(_swapCanvas, 200); }
29 function _swapCanvas() {
30         for( var x in G.ui.altcanvas ) 
31                 hideMe(G.ui.altcanvas[x]);
32
33         hideMe(G.ui.common.loading);
34         hideMe(G.ui.common.canvas_main);
35         unHideMe(newCanvasNode);
36 }
37
38 /* finds the name of the current page */
39 var currentPage = null;
40 function findCurrentPage() {
41         if(currentPage) return currentPage;
42
43         var pages = [];
44         for( var p in config.page ) pages.push(config.page[p]);
45         pages = pages.sort( function(a,b){ return - (a.length - b.length); } );
46
47         var path = location.pathname;
48         if(!path.match(/.*\.xml$/))
49                 path += "index.xml"; /* in case they go to  / */
50
51         var page = null;
52         for( var p in pages ) {
53                 if( path.indexOf(pages[p]) != -1)
54                         page = pages[p];
55         }
56
57         for( var p in config.page ) {
58                 if(config.page[p] == page) {
59                         currentPage = p;
60                         return p;
61                 }
62         }
63
64         return null;
65 }
66
67
68 /* sets all of the params values  ----------------------------- */
69 var TERM,  STYPE,  LOCATION,  DEPTH,  FORM, OFFSET,  COUNT,  
70          HITCOUNT,  RANKS, SEARCHBAR_EXTRAS;
71
72 function initParams() {
73         var cgi = new CGI();    
74
75         TERM    = cgi.param(PARAM_TERM);
76         STYPE   = cgi.param(PARAM_STYPE);
77         FORM    = cgi.param(PARAM_FORM);
78
79         LOCATION        = parseInt(cgi.param(PARAM_LOCATION));
80         DEPTH           = parseInt(cgi.param(PARAM_DEPTH));
81         OFFSET  = parseInt(cgi.param(PARAM_OFFSET));
82         COUNT           = parseInt(cgi.param(PARAM_COUNT));
83         HITCOUNT        = parseInt(cgi.param(PARAM_HITCOUNT));
84         MRID            = parseInt(cgi.param(PARAM_MRID));
85         RID             = parseInt(cgi.param(PARAM_RID));
86
87         /* set up some sane defaults */
88         if(isNaN(LOCATION))     LOCATION        = 1;
89         if(isNaN(DEPTH))                DEPTH           = 0;
90         if(isNaN(OFFSET))               OFFSET  = 0;
91         if(isNaN(COUNT))                COUNT           = 10;
92         if(isNaN(HITCOUNT))     HITCOUNT        = 0;
93         if(isNaN(SEARCHBAR_EXTRAS))     SEARCHBAR_EXTRAS        = 0;
94         if(isNaN(MRID))         MRID            = 0;
95         if(isNaN(RID))                  RID             = 0;
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 getSearchBarExtras(){return SEARCHBAR_EXTRAS;}
108 function getMrid(){return MRID;};
109 function getRid(){return RID;};
110
111
112
113 /* builds an opac URL.  If no page is defined, the current page is used
114         if slim, then only everything after the ? is returned (no host portion) */
115 function findBasePath() {
116         var path = location.pathname;
117         if(!path.match(/.*\.xml$/)) path += "index.xml"; 
118         var idx = path.indexOf(config.page[findCurrentPage()]);
119         return path.substring(0, idx);
120 }
121
122 function findBaseURL(ssl) {
123         var path = findBasePath();
124         var proto = location.protocol;
125         if(ssl) proto = "https";
126         return location.protocol + "//" + location.host + path;
127 }
128
129 function buildImageLink(name, ssl) {
130         return findBaseURL(ssl) + "../../../images/" + name;
131 }
132
133 function  buildOPACLink(args, slim, ssl) {
134
135         if(!args) args = {};
136         var string = "";
137
138         if(!slim) {
139                 string = findBaseURL(ssl);
140                 if(args.page) string += config.page[args.page];
141                 else string += config.page[findCurrentPage()];
142         }
143
144         string += "?";
145
146         for( var x in args ) {
147                 if(x == "page" || args[x] == null) continue;
148                 string += "&" + x + "=" + encodeURIComponent(args[x]);
149         }
150
151         string += _appendParam(TERM,            PARAM_TERM, args, getTerm, string);
152         string += _appendParam(STYPE,           PARAM_STYPE, args, getStype, string);
153         string += _appendParam(LOCATION, PARAM_LOCATION, args, getLocation, string);
154         string += _appendParam(DEPTH,           PARAM_DEPTH, args, getDepth, string);
155         string += _appendParam(FORM,            PARAM_FORM, args, getForm, string);
156         string += _appendParam(OFFSET,  PARAM_OFFSET, args, getOffset, string);
157         string += _appendParam(COUNT,           PARAM_COUNT, args, getDisplayCount, string);
158         string += _appendParam(HITCOUNT, PARAM_HITCOUNT, args, getHitCount, string);
159         string += _appendParam(MRID,            PARAM_MRID, args, getMrid, string);
160         string += _appendParam(RID,             PARAM_RID, args, getRid, string);
161         return string.replace(/\&$/,'').replace(/\?\&/,"?");    
162 }
163
164 function _appendParam( fieldVar, fieldName, overrideArgs, getFunc, string ) {
165         var ret = "";
166         if( fieldVar != null && overrideArgs[fieldName] == null ) 
167                 ret = "&" + fieldName + "=" + encodeURIComponent(getFunc());
168         return ret;
169 }
170
171
172 /*
173 function EX(message) { this.init(message); }
174 EX.prototype.init = function(message) { this.message = message; }
175 EX.prototype.toString = function() { return "\n *** Exception Occured \n" + this.message; }  
176 EXCommunication.prototype              = new EX();
177 EXCommunication.prototype.constructor  = EXCommunication;
178 EXCommunication.baseClass              = EX.prototype.constructor;
179 function EXCommunication(message) { this.init("EXCommunication: " + message); }                          
180 */
181
182 /* ----------------------------------------------------------------------- */
183 function cleanISBN(isbn) {
184    if(isbn) {
185       isbn = isbn.toString().replace(/^\s+/,"");
186       var idx = isbn.indexOf(" ");
187       if(idx > -1) { isbn = isbn.substring(0, idx); }
188    } else isbn = "";
189    return isbn;
190 }       
191
192
193
194
195 /* builds a link that goes to the title listings for a metarecord */
196 function buildTitleLink(rec, link) {
197         if(!rec) return;
198         link.appendChild(text(normalize(truncate(rec.title(), 65))));
199         var args = {};
200         args.page = RRESULT;
201         args[PARAM_OFFSET] = 0;
202         args[PARAM_MRID] = rec.doc_id();
203         link.setAttribute("href", buildOPACLink(args));
204 }
205
206 function buildTitleDetailLink(rec, link) {
207         if(!rec) return;
208         link.appendChild(text(normalize(truncate(rec.title(), 65))));
209         var args = {};
210         args.page = RDETAIL;
211         args[PARAM_OFFSET] = 0;
212         args[PARAM_RID] = rec.doc_id();
213         link.setAttribute("href", buildOPACLink(args));
214 }
215
216 /* 'type' is one of STYPE_AUTHOR, STYPE_SUBJECT, ... found in config.js 
217         'trunc' is the number of characters to show in the string, defaults to 65 */
218 function buildSearchLink(type, string, linknode, trunc) {
219         if(!trunc) trunc = 65;
220         var args = {};
221         args.page = MRESULT;
222         args[PARAM_OFFSET] = 0;
223         args[PARAM_TERM] = string;
224         args[PARAM_STYPE] = type;
225         linknode.appendChild(text(normalize(truncate(string, trunc))));
226         linknode.setAttribute("href", buildOPACLink(args));
227 }
228
229
230 /* ----------------------------------------------------------------------- */
231 /* user session handling */
232 /* ----------------------------------------------------------------------- */
233
234 /* session is the login session.  If no session is provided, we attempt
235         to find one in the cookies.  If 'force' is true we retrieve the 
236         user from the server even if there is already a global user present.
237         if ses != G.user.session, we also force a grab */
238 var cookie = new cookieObject("ses", 1, "/", COOKIE_SES);
239 function grabUser(ses, force) {
240
241         if(!ses) ses = cookie.get(COOKIE_SES);
242         if(!ses) return false;
243
244         if(!force) 
245                 if(G.user && G.user.session == ses)
246                         return G.user;
247
248         /* first make sure the session is valid */
249         var request = new Request(FETCH_SESSION, ses );
250         request.send(true);
251         var user = request.result();
252         if( !(typeof user == 'object' && user._isfieldmapper) ) {
253                 return false;
254         }
255
256         G.user = user;
257         G.user.fleshed = false;
258         G.user.session = ses;
259         cookie.put(COOKIE_SES, ses);
260         cookie.write();
261
262         return G.user;
263
264 }
265
266 function grabFleshedUser() {
267
268         if(!G.user || !G.user.session) {
269                 grabUser();     
270                 if(!G.user || !G.user.session) return null;
271         }
272
273         if(G.user.fleshed) return G.user;
274
275    var req = new Request(FETCH_FLESHED_USER, G.user.session);
276         req.send(true);
277
278         G.user = req.result();
279
280         if(!G.user || G.user.length == 0) { 
281                 G.user = null; return false; 
282                 cookie.remove(COOKIE_SES);
283         }
284
285         G.user.session = ses;
286         G.user.fleshed = true;
287
288         cookie.put(COOKIE_SES, ses); /*  update the cookie */
289         cookie.write();
290
291         return G.user;
292 }
293
294
295 /* returns a fleshed G.user on success, false on failure */
296 function doLogin() {
297
298         var uname = G.ui.login.username.value;
299         var passwd = G.ui.login.password.value; 
300
301         var init_request = new Request( LOGIN_INIT, uname );
302    init_request.send(true);
303    var seed = init_request.result();
304
305    if( ! seed || seed == '0') {
306       alert( "Error Communicating with Authentication Server" );
307       return null;
308    }
309
310    var auth_request = new Request( LOGIN_COMPLETE, 
311                 uname, hex_md5(seed + hex_md5(passwd)), "opac");
312
313    auth_request.send(true);
314    var auth_result = auth_request.result();
315
316    if(auth_result == '0' || auth_result == null || auth_result.length == 0) { return false; }
317
318         var u = grabUser(auth_result, true);
319         if(u) updateLoc(u.home_ou(), findOrgDepth(u.home_ou()));
320
321         return u;
322 }
323
324 function doLogout() {
325
326         /* be nice and delete the session from the server */
327         if(G.user && G.user.session) { 
328                 var req = new Request(LOGIN_DELETE, G.user.session);
329       req.send(true);
330                 try { req.result(); } catch(E){}
331     }
332
333         G.user = null;
334         cookie.remove(COOKIE_SES);
335
336         hideMe(G.ui.sidebar.logoutbox);
337         unHideMe(G.ui.sidebar.loginbox);
338         hideMe(G.ui.sidebar.logged_in_as);
339
340 }
341
342
343 function hideMe(obj) { addCSSClass(obj, config.css.hide_me); } 
344 function unHideMe(obj) { removeCSSClass(obj, config.css.hide_me); }
345
346
347 /* ----------------------------------------------------------------------- */
348 /* build the org tree */
349 /* ----------------------------------------------------------------------- */
350
351
352 function drawOrgTree() {
353         G.ui.common.org_tree.innerHTML = buildOrgSelector().toString();
354 }
355         
356 var orgTreeSelector;
357 function buildOrgSelector() {
358         var tree = new dTree("orgTreeSelector"); 
359         for( var i in orgArraySearcher ) { 
360                 var node = orgArraySearcher[i];
361                 if( node == null ) continue;
362                 if(node.parent_ou() == null)
363                         tree.add(node.id(), -1, node.name(), 
364                                 "javascript:orgSelect(" + node.id() + ");", node.name());
365                 else {
366                         tree.add(node.id(), findOrgUnit(node.parent_ou()).id(), node.name(), 
367                                 "javascript:orgSelect(" + node.id() + ");", node.name());
368                 }
369         }
370         orgTreeSelector = tree;
371         return tree;
372 }
373
374 function orgSelect(id) {
375         showCanvas();
376         updateLoc(id, findOrgDepth(id));
377 }
378
379
380 /* ------------------------------------------------------------------------------------------------------ */
381 /* org tree utilities */
382 /* ------------------------------------------------------------------------------------------------------ */
383
384 /* takes an org unit or id and return the numeric depth */
385 function findOrgDepth(org_id_or_node) {
386         return findOrgType(findOrgUnit(org_id_or_node).ou_type()).depth();
387 }
388
389 /* takes the org type id from orgunit.ou_type() field and returns
390         the org type object */
391 function findOrgType(type_id) {
392         if(typeof type_id == 'object') return type_id;
393         for(var type in globalOrgTypes) {
394                 var t =globalOrgTypes[type]; 
395                 if( t.id() == type_id || t.id() == parseInt(type_id) ) 
396                         return t;
397         }
398         return null;
399 }
400
401
402 /* returns an org unit by id.  if an object is passed in as the id,
403         then the object is assumed to be an org unit and is returned */
404 function findOrgUnit(org_id) {
405         return (typeof org_id == 'object') ? org_id : orgArraySearcher[org_id];
406 }
407
408
409 /* builds a trail from the top of the org tree to the node provide.
410         basically fleshes out 'my orgs' 
411         Returns an array of [org0, org1, ..., myorg] */
412 function orgNodeTrail(node) {
413         var na = new Array();
414         while( node ) {
415                 na.push(node);
416                 node = findOrgUnit(node.parent_ou());
417         }
418         return na.reverse();
419 }
420
421
422 /* returns an array of sibling org units */
423 function findSiblingOrgs(node) { return findOrgUnit(node.parent_ou()).children(); }
424 /* ------------------------------------------------------------------------------------------------------ */
425
426
427
428
429
430
431