]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/holds.js
fixed logic error created by log line (no brackets), removed alert line
[working/Evergreen.git] / Open-ILS / web / opac / skin / default / js / holds.js
1 var holdsOrgSelectorBuilt = false;
2 var holdArgs;
3
4 /* 
5 note: metarecord holds have a holdable_formats field that contains
6 item_type(s)-item_forms(s)-language
7 item_form and language are optional - if language exist and no 
8 item_form is specified, use item_type(s)--language
9 */
10
11 function holdsHandleStaff() {
12         swapCanvas($('xulholds_box'));
13         $('xul_recipient_barcode').focus();
14         $('xul_recipient_barcode').onkeypress = function(evt) 
15                 {if(userPressedEnter(evt)) { _holdsHandleStaff(); } };
16         $('xul_recipient_barcode_submit').onclick = _holdsHandleStaff;
17         $('xul_recipient_me').onclick = _holdsHandleStaffMe;
18 }
19
20 function _holdsHandleStaffMe() {
21         holdArgs.recipient = G.user;
22         holdsDrawEditor();
23 }
24
25 function _holdsHandleStaff() {
26         var barcode = $('xul_recipient_barcode').value;
27         var user = grabUserByBarcode( G.user.session, barcode );
28         if(!user) {
29                 alert('fixme: invalid user barcode: ['+barcode+']');
30                 return
31         }
32         holdArgs.recipient = user;
33         holdsDrawEditor();
34 }
35
36
37
38 /** args:
39   * record, volume, copy (ids)
40   * request, recipient, editHold (objects)
41   */
42
43 function holdsDrawEditor(args) {
44
45         holdArgs = (args) ? args : holdArgs;
46
47         if(isXUL() && holdArgs.recipient == null 
48                         && holdArgs.editHold == null) {
49                 holdsHandleStaff();
50                 return;
51         }
52
53         if(!holdArgs.recipient) holdArgs.recipient = G.user;
54         if(!holdArgs.requestor) holdArgs.requestor = G.user;
55
56         if(!(holdArgs.requestor && holdArgs.requestor.session)) {
57                 detachAllEvt('common','locationChanged');
58                 attachEvt('common','loggedIn', holdsDrawEditor)
59                 initLogin();
60                 return;
61         }
62
63         if(holdArgs.editHold) // flesh the args with the existing hold 
64                 holdArgsFromHold(holdArgs.editHold, holdArgs);
65
66         holdsDrawWindow();
67 }
68
69
70 // updates the edit window with the existing hold's data 
71 function _holdsUpdateEditHold() {
72
73         var hold = holdArgs.editHold;
74         var status = holdArgs.status;
75
76         var orgsel = $('holds_org_selector');
77         setSelector(orgsel, hold.pickup_lib());
78
79         if( hold.capture_time() || status > 2 )
80                 orgsel.disabled = true;
81         else    
82                 orgsel.disabled = false;
83
84
85         $('holds_submit').onclick = holdsEditHold;
86         $('holds_update').onclick = holdsEditHold;
87
88         if(hold.phone_notify()) {
89                 $('holds_enable_phone').checked = true;
90                 $('holds_phone').value = hold.phone_notify();
91
92         } else {
93                 $('holds_phone').disabled = true;
94                 $('holds_enable_phone').checked = false;
95         }
96
97         if(isTrue(hold.email_notify())) {
98                 $('holds_enable_email').checked = true;
99
100         } else {
101                 $('holds_enable_email').checked = false;
102         }
103 }
104
105 function holdsEditHold() {
106         var hold = holdsBuildHoldFromWindow();
107         if(!hold) return;
108         holdsUpdate(hold);
109         showCanvas();
110         if(holdArgs.onComplete)
111                 holdArgs.onComplete(hold);
112 }
113
114 function holdArgsFromHold(hold, oargs) {
115         var args = (oargs) ? oargs : {};
116         args.type = hold.hold_type();
117         var target = hold.target();
118
119         switch(args.type) {
120                 case 'M':
121                         args.metarecord = target;
122                         break;
123                 case 'T':
124                         args.record = target;
125                         break;
126                 case 'V':
127                         args.volume = target;
128                         break;
129                 case 'C':
130                         args.copy = target;
131                         break;
132         }
133         return args;
134 }
135
136 function holdFetchObjects(hold, doneCallback) {
137
138         var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
139
140         var type = args.type;
141
142         if( type == 'C' ) {
143
144                 if( args.copyObject ) {
145
146                         args.copy = args.copyObject.id();
147                         args.volume = args.copyObject.call_number();
148                         _h_set_vol(args, doneCallback);
149
150                 } else {
151                         var creq = new Request(FETCH_COPY, args.copy);
152
153                         creq.callback(
154                                 function(r) {
155                                         var cp = r.getResultObject();
156                                         args.copyObject = cp;
157                                         args.volume = args.copyObject.call_number();
158                                         _h_set_vol(args, doneCallback);
159                                 }
160                         );
161                         creq.send();
162                 }
163         } else {
164                 if( type == 'V' ) {
165                         _h_set_vol(args, doneCallback);
166
167                 } else {
168                         if( type == 'T' ) {
169                                 _h_set_rec(args, doneCallback);
170                         } else {
171                                 _h_set_rec_descriptors(args, doneCallback);
172                         }
173                 }
174         }
175
176         return args;
177 }
178
179 function _h_set_vol(args, doneCallback) {
180
181         if( args.volumeObject ) {
182                 args.volume = args.volumeObject.id();
183                 args.record = args.volumeObject.record();
184                 _h_set_rec(args, doneCallback);
185
186         } else {
187
188                 var vreq = new Request(FETCH_VOLUME, args.volume);
189                 vreq.callback(
190                         function(r) {
191                                 var vol = r.getResultObject();
192                                 args.volumeObject = vol;
193                                 args.record = vol.record();
194                                 _h_set_rec(args, doneCallback);
195                         }
196                 );
197                 vreq.send();
198         }
199 }
200
201 function _h_set_rec(args, doneCallback) {
202
203         if(args.recordObject) 
204                 args.record = args.recordObject.doc_id();
205         else 
206                 args.recordObject = findRecord( args.record, 'T' );
207         
208         if( args.type == 'T' || args.type == 'M' ) 
209                 _h_set_rec_descriptors(args, doneCallback);
210         else 
211                 if(doneCallback) doneCallback(args);
212 }
213
214
215 function _h_set_rec_descriptors(args, doneCallback) {
216
217         // grab the list of record desciptors attached to this records metarecord 
218         if( ! args.recordDescriptors )  {
219                 var params = { record: args.record };
220
221                 if( ! args.record ) {
222                         if( args.metarecord )
223                                 params = { metarecord : args.metarecord };
224                         else 
225                                 params = { metarecord : args.metarecordObject.doc_id() };
226                 }
227
228                 var req = new Request(FETCH_MR_DESCRIPTORS, params );
229                 req.callback(
230                         function(r) {
231                                 var data = r.getResultObject();
232                                 args.recordDescriptors = data.descriptors;
233                                 args.metarecord = data.metarecord;
234                                 if( args.type == 'M' && ! args.metarecordObject) 
235                                         args.metarecordObject = findRecord(args.metarecord, 'M');       
236                                  
237                                 if(doneCallback) doneCallback(args);
238                         }
239                 );
240                 req.send();
241
242         } else {
243                 if(doneCallback) doneCallback(args);
244         }
245
246         return args;
247 }
248
249
250
251 function holdsDrawWindow() {
252         swapCanvas($('holds_box'));
253         $('holds_cancel').onclick = function(){ runEvt('common', 'holdUpdateCanceled'), showCanvas() };
254         $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
255         $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
256         holdFetchObjects(null, 
257                 function(){
258                         __holdsDrawWindow();
259
260                         if(holdArgs.editHold) {
261                                 hideMe($('holds_submit'));
262                                 unHideMe($('holds_update'));
263                                 var req = new Request(FETCH_HOLD_STATUS, 
264                                         G.user.session, holdArgs.editHold.id());
265                                 req.send(true);
266                                 holdArgs.status = req.result();
267                                 _holdsUpdateEditHold();
268                         }  
269                 }
270         );
271 }
272
273 function __holdsDrawWindow() {
274
275         var rec = holdArgs.recordObject;
276         var vol = holdArgs.volumeObject;
277         var copy = holdArgs.copyObject;
278         var mr = holdArgs.metarecordObject;
279
280         rec = (rec) ? rec : mr;
281
282         if(!holdsOrgSelectorBuilt) {
283                 holdsBuildOrgSelector(null,0);
284                 holdsOrgSelectorBuilt = true;
285                 var selector = $('holds_org_selector');
286
287                 /*
288                 var o_loc = findOrgUnit(getOrigLocation());
289                 var t = findOrgType(o_loc.ou_type());
290                 if( t.can_have_users() ) 
291                         setSelector(selector, o_loc.id());
292                 else 
293                 */
294
295                 setSelector(selector, holdArgs.recipient.home_ou());
296         
297         }
298
299         /*
300         if(isXUL()) {
301                 var dsel = $('holds_depth_selector');
302                 unHideMe($('holds_depth_selector_row'));
303                 if(dsel.getElementsByTagName('option').length == 0) {
304                         var types = globalOrgTypes;
305                         var depth = findOrgDepth(G.user.ws_ou());
306                         iterate(types, 
307                                 function(t) {
308                                         if(t.depth() > depth) return;
309                                         insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
310                                 }
311                         );
312                 }
313         }
314         */
315
316         appendClear($('holds_recipient'), text(
317                 holdArgs.recipient.family_name() + ', ' +  
318                         holdArgs.recipient.first_given_name()));
319         appendClear($('holds_title'), text(rec.title()));
320         appendClear($('holds_author'), text(rec.author()));
321
322         if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
323
324                 unHideMe($('holds_type_row'));
325                 unHideMe($('holds_cn_row'));
326                 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
327
328                 if( holdArgs.type == 'V'  ) {
329                         unHideMe($('holds_is_cn'));
330                         hideMe($('holds_is_copy'));
331
332                 } else {
333                         hideMe($('holds_is_cn'));
334                         unHideMe($('holds_is_copy'));
335                         unHideMe($('holds_copy_row'));
336                         appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
337                 }
338
339         } else {
340                 hideMe($('holds_type_row'));
341                 hideMe($('holds_copy_row'));
342                 hideMe($('holds_cn_row'));
343         }
344
345         removeChildren($('holds_format'));
346
347         var mods_formats = rec.types_of_resource();
348         var formats;
349
350         if(holdArgs.recordDescriptors)
351                 formats = holdArgs.recordDescriptors[0].item_type();
352
353         if( holdArgs.type == 'T' ) {
354                 var desc = grep( holdArgs.recordDescriptors,
355                         function(i) {
356                                 return (i.record() == holdArgs.record); 
357                         }
358                 );
359                 formats = desc[0].item_type();
360         }
361
362         if( holdArgs.type == 'M' ) {
363                 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());
364                 mods_formats = data.mods_formats;
365                 formats = data.formats;
366         }
367
368
369         for( var i in mods_formats ) {
370                 var res = mods_formats[i];
371                 var img = elem("img");
372                 setResourcePic(img, res);
373                 $('holds_format').appendChild(img);
374                 if(formats)
375                         $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
376                 else
377                         $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
378                 $('holds_format').appendChild(elem('br'));
379         }
380
381
382         $('holds_phone').value = holdArgs.recipient.day_phone();
383         appendClear( $('holds_email'), text(holdArgs.recipient.email()));
384
385         var pref = G.user.prefs[PREF_HOLD_NOTIFY];
386
387         if(pref) {
388                 if( ! pref.match(/email/i) ) 
389                         $('holds_enable_email').checked = false;
390
391                 if( ! pref.match(/phone/i) ) {
392                         $('holds_phone').disabled = true;
393                         $('holds_enable_phone').checked = false;
394                 }
395         }
396
397         if(!$('holds_phone').value) 
398                 $('holds_enable_phone').checked = false;        
399
400         appendClear($('holds_physical_desc'), text(rec.physical_description()));
401
402         if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
403
404         holdsSetFormatSelector();
405 }
406
407 function holdsParseMRFormats(str) {
408         var data = str.split(/-/);      
409
410         var formats = [];
411         var mods_formats = [];
412
413         for( var i = 0; i < data[0].length; i++ ) {
414                 formats.push( data[0].charAt(i) );
415                 mods_formats.push( MARCFormatToMods( formats[i] ) );
416         }
417         
418         formats = uniquify(formats);
419         mods_formats = uniquify(mods_formats);
420
421         return {
422                 formats                 : formats,
423                 mods_formats    : mods_formats,
424                 lang                            : data[2],
425                 largeprint              : data[1]
426         };
427 }
428
429
430 function holdsSetFormatSelector() {
431         var type = holdArgs.type;
432         if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
433
434         var data                                = holdsGetFormats();
435         var avail_formats       = data.avail_formats;
436         var sel_formats = data.sel_formats;
437         holdArgs.language = data.lang;
438
439         unHideMe($('holds_alt_formats_row_extras'));
440         var selector = $('hold_alt_form_selector');
441
442         for( var i = 0; i < avail_formats.length; i++ ) {
443                 var form = avail_formats[i];
444                 unHideMe(findSelectorOptByValue(selector, form));
445         }
446 }
447
448
449 function holdsGetFormats() {
450
451         var lang;
452         var formats = [];
453         var sformats = []; // selected formats 
454
455         var type = holdArgs.type;
456         var desc = holdArgs.recordDescriptors;
457         var rec = holdArgs.record;
458         var mrec = holdArgs.metarecord;
459
460         if( type == 'T' ) {
461
462                 for( var i = 0; i < desc.length; i++ ) {
463                         var d = desc[i];
464                         if( d.record() == holdArgs.record ) {
465                                 lang = d.item_lang();
466                                 holdArgs.myFormat =  _t_f_2_format(d.item_type(), d.item_form());
467                                 sformats.push(holdArgs.myFormat);
468                                 break;
469                         }
470                 }
471         }
472
473         for( var i = 0; i < desc.length; i++ ) {
474                 var d = desc[i];
475                 if( d.item_lang() != lang ) continue;
476                 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
477         }
478
479         formats = uniquify(formats);
480
481         return {
482                 lang : lang,
483                 avail_formats : formats, 
484                 sel_formats : sformats
485         };
486 }
487
488
489
490 function _t_f_2_format(type, form) {
491         if( form == 'd' ) return 'at-d';
492         return (type == 'a' || type == 't') ? 'at' : 
493                 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
494 }
495
496 function holdsSetSelectedFormats() {
497
498         var cn = $('holds_alt_formats_row').className;
499         if( cn && cn.match(/hide_me/) ) return;
500
501         var selector = $('hold_alt_form_selector');
502         var vals = getSelectedList(selector);
503
504         if(vals.length == 0) return;
505
506         var fstring = "";
507
508         if( contains(vals, 'at-d') ) {
509                 if( contains(vals, 'at') )
510                         fstring = 'at';
511                 else 
512                         fstring = 'at-d';
513         } else {
514                 if( contains(vals, 'at') )
515                         fstring = 'at';
516         }
517
518         for( var i = 0; i < vals.length; i++ ) {
519                 var val = vals[i];
520                 if( !val.match(/at/) ) fstring = val + fstring;
521         }
522
523         if( holdArgs.language ) {
524                 if( fstring.match(/-/) )
525                         fstring = fstring + '-' + holdArgs.language;
526                 else
527                         fstring = fstring + '--' + holdArgs.language;
528         }
529
530
531         return fstring;
532 }
533
534
535 function holdsCheckPossibility(pickuplib, hold, recurse) {
536         var rec = holdArgs.record;
537         var type = holdArgs.type;
538         var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, 
539                         { titleid : rec, patronid : G.user.id(), depth : 0, pickup_lib : pickuplib } );
540         req.request.alertEvent = false;
541         req.request._hold = hold;
542         req.request._recurse = recurse;
543         req.callback(holdHandleCreateResponse);
544         req.send();
545 }
546
547
548 function holdsBuildOrgSelector(node) {
549
550         if(!node) node = globalOrgTree;
551
552         var selector = $('holds_org_selector');
553         var index = selector.options.length;
554
555         var type = findOrgType(node.ou_type());
556         var indent = type.depth() - 1;
557         var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
558         if(!type.can_have_users()) {
559                 opt.disabled = true;
560                 addCSSClass(opt, 'disabled_option');
561         }
562         
563         for( var i in node.children() ) {
564                 var child = node.children()[i];
565                 if(child) holdsBuildOrgSelector(child);
566         }
567 }
568
569 function holdsBuildHoldFromWindow() {
570
571         var org = getSelectorVal($('holds_org_selector'));
572         var node = findOrgUnit(org);
573         var ntype = findOrgType(node.ou_type());
574         if(!ntype.can_have_users()) {
575                 alertId('holds_pick_good_org');
576                 return;
577         }
578
579         var hold = new ahr();
580         if(holdArgs.editHold) {
581                 hold = holdArgs.editHold;
582                 holdArgs.editHold = null;
583         }
584
585         if( $('holds_enable_phone').checked ) {
586                 var phone = $('holds_phone').value;
587                 if( !phone || !phone.match(REGEX_PHONE) ) {
588                         alert($('holds_bad_phone').innerHTML);
589                         return null;
590                 }
591                 hold.phone_notify(phone);
592
593         } else {
594                 hold.phone_notify("");
595         }
596
597         if( $('holds_enable_email').checked ) 
598                 hold.email_notify(1);
599         else
600                 hold.email_notify(0);
601
602         var target;
603
604         switch(holdArgs.type) {
605                 case 'M':
606                         target = holdArgs.metarecord; break;
607                 case 'T':
608                         target = holdArgs.record; break;
609                 case 'V':
610                         target = holdArgs.volume; break;
611                 case 'C':
612                         target = holdArgs.copy; break;
613         }
614
615
616
617         hold.pickup_lib(org); 
618         hold.request_lib(org); 
619         hold.requestor(holdArgs.requestor.id());
620         hold.usr(holdArgs.recipient.id());
621         hold.target(target);
622         hold.hold_type(holdArgs.type);
623
624         //check for alternate hold formats 
625         var fstring = holdsSetSelectedFormats();
626         if(fstring) { 
627                 hold.hold_type('M'); 
628                 hold.holdable_formats(fstring);
629                 hold.target(holdArgs.metarecord);
630         }
631
632         //alert(fstring); return;
633
634         /*
635         if(isXUL())             
636                 hold.selection_depth(getSelectorVal($('holds_depth_selector')));
637                 */
638
639         return hold;
640 }
641         
642 function holdsPlaceHold(hold, recurse) {
643
644         if(!hold) return;
645
646         swapCanvas($('check_holds_box'));
647
648         if( holdArgs.type == 'M' || holdArgs.type == 'T' ) {
649                 var res = holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
650
651                 /*
652                 if(!res || checkILSEvent(res) ) {
653                         if(!res) {
654                                 alert($('hold_not_allowed').innerHTML);
655                         } else {
656                                 if( res.textcode == 'PATRON_BARRED' ) {
657                                         alertId('hold_failed_patron_barred');
658                                 } else {
659                                         alert($('hold_not_allowed').innerHTML);
660                                 }
661                         }
662                         swapCanvas($('holds_box'));
663                         return;
664                 }
665                 */
666
667         } else {
668                 holdCreateHold(recurse, hold);
669         }
670 }
671
672
673 function holdHandleCreateResponse(r) {
674         var res = r.getResultObject();
675         if(!res || checkILSEvent(res) ) {
676                 if(!res) {
677                         alert($('hold_not_allowed').innerHTML);
678                 } else {
679                         if( res.textcode == 'PATRON_BARRED' ) {
680                                 alertId('hold_failed_patron_barred');
681                         } else {
682                                 alert($('hold_not_allowed').innerHTML);
683                         }
684                 }
685                 swapCanvas($('holds_box'));
686                 return;
687         }
688         
689         holdCreateHold(r._recurse, r._hold);
690 }
691
692
693 function holdCreateHold( recurse, hold ) {
694         var method = CREATE_HOLD;
695         if(recurse) method = CREATE_HOLD_OVERRIDE;
696         var req = new Request( method, holdArgs.requestor.session, hold );
697         req.request.alertEvent = false;
698         req.send(true);
699         var res = req.result();
700         holdProcessResult(hold, res, recurse);
701         
702         showCanvas();
703
704         holdArgs = null;
705         runEvt('common', 'holdUpdated');
706 }
707
708
709 function holdProcessResult( hold, res, recurse ) {
710
711         if( res == '1' ) {
712                 alert($('holds_success').innerHTML);
713
714         } else {
715
716                 if( recurse ) {
717                         alert($('holds_failure').innerHTML);
718                         return;
719                 }
720
721                 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
722                         if( fetchPermOrgs('HOLD_EXISTS')[0] ) {
723                                 if( confirm($('hold_dup_exists_override').innerHTML) ) {
724                                         return holdsPlaceHold(hold, true);
725                                 }
726
727                         } else {
728                                 return alert($('hold_dup_exists').innerHTML);
729                         }
730                 }
731
732                 alert($('holds_failure').innerHTML);
733         }
734 }
735
736
737 function holdsCancel(holdid, user) {
738         if(!user) user = G.user;
739         var req = new Request(CANCEL_HOLD, user.session, holdid);
740         req.send(true);
741         return req.result();
742         runEvt('common', 'holdUpdated');
743 }
744
745 function holdsUpdate(hold, user) {
746         if(!user) user = G.user;
747         var req = new Request(UPDATE_HOLD, user.session, hold);
748         req.send(true);
749         var x = req.result(); // cause an exception if there is one 
750         runEvt('common', 'holdUpdated');
751 }
752
753