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