added a new pile of icons; updated icon img src code to use new icons
[evergreen-equinox.git] / Open-ILS / web / opac / skin / kcls / js / misc.js
1 var anonListCache;
2 var webCacheKey;
3 var userVitalStats;
4
5 function opac_init() {
6         var advLink = getId("home_adv_search_link");
7         if(advLink) advLink.setAttribute("href", buildOPACLink({page:ADVANCED})); 
8         getId("home_myopac_link").setAttribute("href", buildOPACLink({page:MYOPAC}, false, true));
9         getId("myopac_link").setAttribute("href", buildOPACLink({page:MYOPAC}, false, true));
10         getOrgs();
11         
12   var u = grabUser();
13   if(u) {
14         unHideMe($('dash_wrapper'));
15           //alert(fetchOrgSettingDefault(G.user.home_ou(), 'auth.persistent_login_interval'));
16         try {
17           var stats = fieldmapper.standardRequest(['open-ils.actor', 'open-ils.actor.user.opac.vital_stats'], {async:false, params:[u.session]});
18         } catch(e){}
19         userVitalStats = stats;
20         if(!stats) return;
21         
22         var dashfines = $('dash_fines');
23         if(stats.fines.balance_owed > 0) {
24                 dashfines.style.color = "#f41d36";
25                 dashfines.innerHTML = "$"+parseFloat(stats.fines.balance_owed).toFixed(2)
26         } else {
27                 dashfines.style.fontWeight="normal";
28                 dashfines.innerHTML = "No";
29         }
30         $('dash_user').innerHTML = u.first_given_name()+' '+u.family_name();
31         $('dash_checked').innerHTML = stats.checkouts.out+stats.checkouts.overdue;
32         $('dash_holds').innerHTML = stats.holds.total;
33         $('dash_pickup').innerHTML = stats.holds.ready;
34   } else unHideMe($('your-acct-login'));
35 }
36
37 function mySuperInitFunction() {
38         G.ui.common.now_searching = elem('div');
39         webCacheKey = cookieManager.read('sessionID');
40         var list = getCacheValue('anonListCache');
41         anonListCache = isTrue(list)?list:[];
42         if(anonListCache.length) try { unHideMe($('cacheListLink')); } catch(e){}
43         
44     /* overkill
45         if(G.user && G.user.prefs[PREF_DEF_LOCATION]!="1") {
46           G.user.prefs[PREF_DEF_LOCATION]="1";
47           LOCATION = "1";
48           commitUserPrefs();
49           setSelector($('depth_selector'),      getLocation());
50           _newlocation = getLocation();
51         }
52     */
53 }
54
55 function setCacheValue(field, value, timeout) {
56         if(!timeout) timeout = '30m';
57         var key = fieldmapper.standardRequest(['open-ils.actor','open-ils.actor.anon_cache.set_value'],{async:false, params:[webCacheKey, field, value]});
58         if(!isTrue(webCacheKey)) {
59                 webCacheKey = key;
60                 cookieManager.write('sessionID', webCacheKey, timeout);
61         }
62         return key;
63 }
64
65 function getCacheValue(field) {
66         if(!isTrue(webCacheKey)) return null;
67         var val = fieldmapper.standardRequest(['open-ils.actor','open-ils.actor.anon_cache.get_value'], {async:false, params:[webCacheKey, field]});
68         return val;
69 }
70
71 function isInAnonList(id) {
72         for(var i in anonListCache) {
73                 if(anonListCache[i] == id) return true;
74         }       
75         return false;
76 }
77
78 var isCacheListDrawn = false;
79 var anonListParent;
80 var anonListTemp;
81 function showCachedList() {
82         if(grabUser()) goTo(buildOPACLink({page:MYOPAC, 'acctpage':6}, false, true));
83         if(!anonListCache.length) {try { hideResultsPage(); } catch(e) {} hideMe($('anonListTable')); hideMe($('cacheListLink')); return;}
84         try { hideResultsPage(true); } catch(e) {}
85         unHideMe($('anonListTable'));
86         if(!isCacheListDrawn) fieldmapper.standardRequest(["open-ils.search","open-ils.search.biblio.record.mods_slim.retrieve"],{async:true, params:[anonListCache], oncomplete:drawCacheList});       
87 }
88
89 function drawCacheList(r) {
90         isCacheListDrawn = true;
91         var bibs = r.recv().content();
92         if(!anonListParent) anonListParent = $('anonListParent');
93         if(!anonListTemp) anonListTemp = anonListParent.removeChild($('anonListTemp'));
94         removeChildren(anonListParent);
95         $('anon_selector').checked = false;
96         
97         if(grabUser()) {
98                 unHideMe($('holdsCacheSel'));
99                 setSelector($('holdsCacheSel'), grabUser().home_ou());
100         }
101         
102         for(var i in bibs) {
103                 var row = anonListTemp.cloneNode(true);
104                 $n(row, 'anon_selector').doc_id = bibs[i].doc_id();
105                 $n(row, 'curr_row').innerHTML = parseInt(i)+1;
106                 $n(row, 'title').innerHTML = bibs[i].title();
107                 anonListParent.appendChild(row);
108         }
109 }
110
111 function createBibHoldObject(org) {
112         if(!G.user) return null;
113         if(!org) org = G.user.home_ou();
114         
115         var node = findOrgUnit(org);
116         var ntype = findOrgType(node.ou_type());
117         if(!ntype.can_have_users()) return null;
118         
119         var hold = new ahr();
120         var interval = fetchOrgSettingDefault(G.user.home_ou(), 'circ.hold_expire_interval');
121
122         if(interval) {
123             var secs = interval_to_seconds(interval);
124             var expire = new Date();
125             expire.setTime(expire.getTime() + Number(secs + '000'));
126             var expireDate = holdsVerifyThawDate(dojo.date.stamp.toISOString(expire)); 
127             if(expireDate) hold.expire_time(expireDate);
128     }
129
130         hold.phone_notify("");
131         hold.email_notify(0);
132         hold.pickup_lib(org);
133         hold.usr(G.user.id());
134         hold.hold_type("T");
135         hold.frozen('f');
136         hold.thaw_date(null);
137         
138         return hold;
139 }
140
141 function batchHoldMyList(org, parent) {
142         if(!grabUser()) return;
143         if(!org) G.user.home_ou();
144         if(!parent) parent = $('myopac_bookbag_div');
145
146         var items = dojo.query('input[name=list_action_chbx]', parent);
147         if(!items.length) items = dojo.query('.list_action_chbx', parent);
148     if(!items.length) return;
149         var nodes = items.filter(function(node, index){ return node.checked; });
150         
151         var arr = [];
152         nodes.forEach(function(node, index){ arr.push(node.getAttribute("recordid")); });
153         var error = {err:""};
154         var resp = placeBatchHold(arr, org, error);
155         if(resp == -1) alert("Unable to place holds"); else alert(resp+" hold"+(resp==1?"":"s")+" placed successfully\n\n"+error.err);
156
157 }
158
159 function placeBatchHold(ids, org, error) { // array of bib IDs, pickup lib (optional), error msgs from holds (optional)
160         if(!grabUser() || !ids.length) return -1;
161         if(!org) org = G.user.home_ou();
162
163         var str = "";
164     var success = -1;
165     var errCount = 0;
166
167     dojo.forEach(ids,
168         function(target) {
169             // first see if the hold is permitted
170                     var hold = createBibHoldObject(org);
171                     hold.target(target);
172             var test = {titleid: hold.target(), hold_type: "T", patronid: G.user.id(), depth: 0, pickup_lib: org}
173
174                 var resp = fieldmapper.standardRequest(
175                 ['open-ils.circ','open-ils.circ.title_hold.is_possible'], 
176                 {   async:false, 
177                     params:[G.user.session, test]
178                 }
179             );
180
181             if(!resp.success) {
182                             str += target + ": " + (resp.last_event.desc ? resp.last_event.desc : resp.last_event.textcode) + "\n";
183                 errCount++;
184                 return;
185             }
186
187             var resp2 = fieldmapper.standardRequest(
188                 ['open-ils.circ','open-ils.circ.holds.create'], 
189                 {   async:false, 
190                     params:[grabUser().session, hold]
191                 }
192             );
193
194             if(typeof(resp2) == 'object') {
195                 if(dojo.isArray(resp2)) resp2 = resp2[0];
196                 str += target + ": " + (resp2.desc || '') +"\n";
197                 errCount++;
198             } else {
199                 success++;
200             }
201         }
202     );
203
204         if(str != "") error.err+=errCount+" hold"+(errCount==1?"":"s")+" not placed successfully\n"+str;
205     return ++success;
206
207     /*
208     // Previous batch implementation, which doesn't work because the patron could exceed 
209     // max holds during batch creation, after the initial permit test...
210
211         var holds = [];
212         var chkArr = [];
213         for(var i=0; i<ids.length; i++) {
214                 holds[i] = createBibHoldObject(org);
215                 holds[i].target(ids[i]);
216                 chkArr.push({titleid: ids[i], volume_id: undefined, copy_id: undefined, hold_type: "T", patronid: G.user.id(), depth: 0, pickup_lib: org});
217         }
218
219         
220         var resp = fieldmapper.standardRequest(['open-ils.circ','open-ils.circ.title_hold.is_possible.batch.atomic'], {async:false, params:[grabUser().session, chkArr]});
221         
222         var str = "";
223         var errCount = 0;
224         var flag = false;
225         for(var n in resp) {
226                 if(!resp[n].success) {
227                         flag = true;
228                         str+=ids[n]+": "+(resp[n].last_event.desc==""?resp[n].last_event.textcode:resp[n].last_event.desc)+"\n";
229                         errCount++;
230                 }
231         }
232         
233         if(str != "") error.err+=errCount+" hold"+(errCount==1?"":"s")+" not placed successfully\n"+str;
234         if(flag) return 0;
235         
236         var resp2 = fieldmapper.standardRequest(['open-ils.circ','open-ils.circ.holds.create.batch.atomic'], {async:false, params:[grabUser().session, holds]});
237         var count = -1;
238         for(var t in resp2) {
239                 if(typeof(resp2[t]) != "object") count++; else {
240                         str+=ids[t]+": "+resp2[t][0].desc+"\n";
241                         errCount++;
242                 }
243         }
244         if(str != "") error.err+=errCount+" holds not placed successfully\n"+str;
245         return ++count;
246     */
247 }
248
249 function placeHoldOnCache() {
250         //holdsDrawWindow(true);
251         var holdsArr = [];
252         dojo.query('input[name=anon_selector]',$('anonListParent')).filter(function(node, index){
253                 if(node.checked) holdsArr.push(node.doc_id+'');
254         });
255         
256         if(!holdsArr.length) return;
257         setCacheValue('saveAnonCache', holdsArr);
258         goTo(buildOPACLink({page:MYOPAC}, false, true));
259 }
260
261 function delSelCache(parent, name) {
262         if(!parent) parent = $('anonListParent');
263         if(!name) name = 'anon_selector';
264         anonListCache = [];
265         var found = false;
266         var nodes = dojo.query('input[name='+name+']',parent);
267         if(!nodes.length) nodes = dojo.query('.'+name,parent);
268         nodes.forEach(function(node, index){
269                 if(!node.checked) anonListCache.push(node.doc_id); else {
270                         found = true;
271                         var holdsLink = $n($('result_table_template_'+node.doc_id), 'result_my_list_link');
272                         if(holdsLink) {
273                                 removeChildren(holdsLink);
274                                 holdsLink.innerHTML = '';
275                                 holdsLink.appendChild(elem('img', {src:'/opac/skin/kcls/graphics/add_mylist.gif'}, null));
276                                 holdsLink.title = "Add to my list";
277                         }
278                 }
279         });
280         
281         if(found) {
282                 isCacheListDrawn = false;
283                 setCacheValue('anonListCache', anonListCache);
284                 if(name=='anon_selector') showCachedList();
285         }
286 }
287
288 String.prototype.trim = function() {
289         return this.replace(/^\s+|\s+$/g,"");
290 }
291 String.prototype.ltrim = function() {
292         return this.replace(/^\s+/,"");
293 }
294 String.prototype.rtrim = function() {
295         return this.replace(/\s+$/,"");
296 }
297
298
299 //////////////////////
300 //Stephen Chapman
301 document.getElementsByClassName = function(cl) {
302 var retnode = [];
303 var myclass = new RegExp('\\b'+cl+'\\b');
304 var elems = document.getElementsByTagName('*');
305 for (var i = 0; i < elems.length; i++) {
306 var classes = elems[i].className;
307 if (myclass.test(classes)) retnode.push(elems[i]);
308 }
309 return retnode;
310 };
311
312 $c = document.getElementsByClassName;
313 ////////////////////////////////////////////////////////////////////////
314
315 function getOrgs() {
316   var tree = $('depth_selector');
317   buildOrgSel(tree, globalOrgTree, 0);
318   setSelector(tree, getLocation());
319   //setSelector(tree, "1");
320 }
321
322 function swapTabs(el) {
323   if(!el) return;
324   var tabs = dojo.query("a",el.parentNode.id);
325   for(var n=0; n< tabs.length;n++) {
326         var i = tabs[n];
327         if(i==el) {
328           unHideMe($(i.rel));
329           i.style.background="url('/opac/skin/kcls/graphics/"+i.id+"_on.gif') no-repeat bottom";
330         } else {
331           hideMe($(i.rel));
332           i.style.background="url('/opac/skin/kcls/graphics/"+i.id+"_off.gif') no-repeat bottom";
333         }
334   }
335 }
336
337 // walk the marc record dom - returns a concatenated string of the requested marc subfields
338 // depth-first recursive function
339 function walkXML(xml,field,subfield) {
340         if(!xml || !field || !subfield) return "";
341         var nodes = (xml.childNodes)?xml.childNodes:null;
342         if(!nodes) return "";
343         var str = "";
344         
345         for(var i=0; i<nodes.length; i++) {
346                 var obj = nodes[i];
347                 if(obj.hasChildNodes()) {
348                         var tag = (obj.nodeName=="datafield")?obj.getAttribute("tag"):"";
349                         if(tag==field) {
350                           for(var n=0; n<obj.childNodes.length; n++){
351                             var child = obj.childNodes[n];
352                             var code = (child.nodeName=="subfield")?child.getAttribute("code"):"";
353                             if(code==subfield) str += (child.textContent)?child.textContent:child.text; // IE check
354                           }
355                         }
356                         str += walkXML(obj,field,subfield);
357                 }
358         }
359         return str;
360 }
361
362 // returns the requested marc data or passes it to callback if present
363 // callback arg is optional
364 function getMarcData(docid, field, subfield, callback) {
365         if(!docid || !field || !subfield) return "";
366         var cgi = new CGI();
367         var xhr = buildXMLRequest();
368         var proto = (location.href.match(/^[Hh][Tt][Tt][Pp][Ss]:/))?"https://":"http://";
369         
370         if(typeof(callback)=="function") {
371                 xhr.onreadystatechange = function() {
372                                 if(xhr.readyState==4 && xhr.status == 200) callback(walkXML(xhr.responseXML.documentElement,field.toLowerCase(),subfield.toLowerCase()), docid);
373                 }
374         }
375         
376         xhr.open("GET",proto+cgi.server_name+"/opac/extras/supercat/retrieve/marcxml/record/"+docid,((callback)?true:false));
377         xhr.send(null);
378         
379         if(typeof(callback)!="function" && xhr.status == 200) {
380                 return walkXML(xhr.responseXML.documentElement,field.toLowerCase(),subfield.toLowerCase());
381         } else return "";
382 }
383
384 function setFormatIcon(imgEl, type) {
385         if(!imgEl) return false;
386         if(!type) { hideMe(imgEl); return false; }
387         var img = "";
388         
389         switch(type.toLowerCase()) {
390           case "a": img="media_book.png"; break;
391           case "b": img="media_magazines.png"; break;
392           case "c": img="media_printedmusic.png"; break;
393           case "d": img="media_microform.png"; break;
394           case "e": img="media_equipment.png"; break;
395           case "f": img="media_films.png"; break;
396           case "g": img="media_films.png"; break;
397           case "h": img="media_dvd.png"; break;
398           case "i": img="media_bookoncassette.png"; break;
399           case "j": img="media_musiccd.png"; break;
400           case "k": img="media_musiccassette.png"; break;
401           case "l": img="media_musicrecord.png"; break;
402           case "m": img="media_software.png"; break;
403           case "n": img="media_bookoncd.png"; break;
404           case "o": img="media_kit.png"; break;
405           case "p": img="media_newspaper.png"; break;
406           case "q": img="media_largeprint.png"; break;
407           case "r": img="media_3dobject.png"; break;
408           case "s": img="media_slide.png"; break;
409           case "t": img="media_online.png"; break;
410           case "u": img="media_eaudio.png"; break;
411           case "v": img="media_ebooktext.png"; break;
412           case "w": img="media_eaudio.png"; break;
413           case "x": img="media_downloadmusic.png"; break;
414           case "y": img="media_downloadvideo.png"; break;
415           case "z": img="media_map.png"; break;
416           case "2": img="media_cassettewithbook.png"; break;
417           case "5": img="media_cdwithbook.png"; break;
418         }
419         
420         if(img) {
421                 imgEl.title = get998dValue(type);
422                 dojo.attr(imgEl, "src","/opac/skin/kcls/graphics/"+img);
423                 dojo.attr(imgEl, "alt", get998dValue(type));
424         } else { hideMe(imgEl); return false; }
425         
426         unHideMe(imgEl);
427         return true;
428 }
429
430 function get998dValue(code) {
431         if(!code) code = "";
432         code = code.toLowerCase();
433         var Label = "";
434         
435         switch(code) {
436                 case "a": Label = "Book"; break;
437                 case "i": Label = "Book on cassette"; break;
438                 case "n": Label = "Book on CD"; break;
439                 case "x": Label = "Download music"; break;
440                 case "y": Label = "Download video"; break;
441                 case "h": Label = "DVD"; break;
442                 case "w": Label = "eBook - Audio"; break;
443                 case "v": Label = "eBook - Text"; break;
444                 case "e": Label = "Equipment"; break;
445                 case "f": Label = "Films"; break;
446                 case "o": Label = "Kit"; break;
447                 case "q": Label = "Large print"; break;
448                 case "b": Label = "Magazine"; break;
449                 case "d": Label = "Microform"; break;
450                 case "k": Label = "Music cassette"; break;
451                 case "j": Label = "Music CD"; break;
452                 case "l": Label = "Music LP"; break;
453                 case "p": Label = "Newspaper"; break;
454                 case "t": Label = "Online"; break;
455                 case "u": Label = "Player"; break;
456                 case "c": Label = "Printed music"; break;
457                 case "2": Label = "Read along with cassette"; break;
458                 case "5": Label = "Read along with CD"; break;
459                 case "c": Label = "Scores"; break;
460                 case "m": Label = "Software"; break;
461                 case "g": Label = "Video"; break;
462                 case "r": Label = "3-D Object"; break;
463                 case "z": Label = "Map"; break;
464                 case "s": Label = "Slide set"; break;
465         }
466         return Label;
467 }
468
469 function mapLibUrl(lib) {
470         var url = "";
471         switch(lib) {
472                 case "1489": url = "http://www.kcls.org/algonapacific/"; break;
473                 case "1490": url = "http://www.kcls.org/auburn/"; break;
474                 case "1492": url = "http://www.kcls.org/bellevue/"; break;
475                 case "1491": url = "http://www.kcls.org/blackdiamond/"; break;
476                 case "1493": url = "http://www.kcls.org/bothell/"; break;
477                 case "1494": url = "http://www.kcls.org/boulevardpark/"; break;
478                 case "1495": url = "http://www.kcls.org/burien/"; break;
479                 case "1496": url = "http://www.kcls.org/carnation/"; break;
480                 case "1497": url = "http://www.kcls.org/covington/"; break;
481                 case "1502": url = "http://www.kcls.org/desmoines/"; break;
482                 case "1503": url = "http://www.kcls.org/duvall/"; break;
483                 case "1508": url = "http://www.kcls.org/fairwood/"; break;
484                 case "1506": url = "http://www.kcls.org/fallcity/"; break;
485                 case "1509": url = "http://www.kcls.org/federalway/"; break;
486                 case "1505": url = "http://www.kcls.org/320th/"; break;
487                 case "1507": url = "http://www.kcls.org/foster/"; break;
488                 case "1513": url = "http://www.kcls.org/issaquah/"; break;
489                 case "1519": url = "http://www.kcls.org/kenmore/"; break;
490                 case "1520": url = "http://www.kcls.org/kent/"; break;
491                 case "1517": url = "http://www.kcls.org/kingsgate/"; break;
492                 case "1518": url = "http://www.kcls.org/kirkland/"; break;
493                 case "1521": url = "http://www.kcls.org/lakeforestpark/"; break;
494                 case "1522": url = "http://www.kcls.org/lakehills/"; break;
495                 case "1499": url = "http://www.kcls.org/crossroads/"; break;
496                 case "1538": url = "http://www.kcls.org/southcenter/"; break;
497                 case "1527": url = "http://www.kcls.org/maplevalley/"; break;
498                 case "1525": url = "http://www.kcls.org/mercerisland/"; break;
499                 case "1526": url = "http://www.kcls.org/muckleshoot/"; break;
500                 case "1529": url = "http://www.kcls.org/newportway/"; break;
501                 case "1528": url = "http://www.kcls.org/northbend/"; break;
502                 case "1533": url = "http://www.kcls.org/redmond/"; break;
503                 case "1532": url = "http://www.kcls.org/richmondbeach/"; break;
504                 case "1534": url = "http://www.kcls.org/sammamish/"; break;
505                 case "1536": url = "http://www.kcls.org/skykomish/"; break;
506                 case "1541": url = "http://www.kcls.org/skyway/"; break;
507                 case "1537": url = "http://www.kcls.org/snoqualmie/"; break;
508                 case "1546": url = "http://www.kcls.org/valleyview/"; break;
509                 case "1545": url = "http://www.kcls.org/vashon/"; break;
510                 case "1547": url = "http://www.kcls.org/whitecenter/"; break;
511                 case "1548": url = "http://www.kcls.org/woodinville/"; break;
512                 case "1549": url = "http://www.kcls.org/woodmont/"; break;
513                 case "1535": url = "http://www.kcls.org/shoreline/"; break;
514                 case "1540": url = "http://www.kcls.org/servicecenter/"; break;
515                 case "1510": url = "http://www.kcls.org/greenbridge/"; break;
516                 //case "": url = "http://www.kcls.org/federalway/#closure"; break;
517                 case "1559": url = "http://www.kcls.org/libraryexpress/"; break;
518                 case "1556": url = "http://www.kcls.org/renton/"; break;
519                 case "1557": url = "http://www.kcls.org/rentonhighlands/"; break;
520                 default: url = "";
521         }
522         return url;
523 }
524
525 function checkAll(parent, id, name) {//Object, string
526         var obj = typeof(id)=="object"?id:$(id);
527         if(!parent || !obj) return;
528         if(!name) name = id.toString();
529         var nodes = dojo.query('input[name='+name+']', parent);
530         if(!nodes.length) nodes = dojo.query('.'+name, parent);
531         nodes.forEach(function(node, index){
532                 node.checked = obj.checked;
533         });
534 }
535
536 var blinkMeArr = [];
537 function blinkMe(str,bool) {
538         var obj = $(str);
539         if(!obj) return;
540         
541         if(bool) {
542                 clearInterval(blinkMeArr[str]);
543                 hideMe(obj);
544         } else blinkMeArr[str] = setInterval(function(){
545                 obj.blinker?hideMe(obj):unHideMe(obj);
546                 obj.blinker=!obj.blinker;}, 500);
547 }
548
549 // null out all children of parent obj
550 errCounter=0;
551 errCounter2=0;
552 function destroyObj(obj) {
553         errCounter++;
554         if(!obj) return;
555         errCounter2++;
556         for(var i in obj) {
557                 if(typeof(obj[i])=="function" && i=="destroyObj") continue;
558                 if(typeof(obj[i])=="object" && obj[i]!=null && typeof(obj[i].tagName)=="undefined") destroyObj(obj[i]);
559                 try { obj[i]=null; } catch(e){}
560         }
561         obj=null;
562 }
563
564 attachEvt("common","init",mySuperInitFunction);