]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/holds.js
c4486c34073d1f928506e566328bdaa52bfc6202
[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) {
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.send(true);
542         return req.result();
543 }
544
545
546 function holdsBuildOrgSelector(node) {
547
548         if(!node) node = globalOrgTree;
549
550         var selector = $('holds_org_selector');
551         var index = selector.options.length;
552
553         var type = findOrgType(node.ou_type());
554         var indent = type.depth() - 1;
555         var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
556         if(!type.can_have_users()) {
557                 opt.disabled = true;
558                 addCSSClass(opt, 'disabled_option');
559         }
560         
561         for( var i in node.children() ) {
562                 var child = node.children()[i];
563                 if(child) holdsBuildOrgSelector(child);
564         }
565 }
566
567 function holdsBuildHoldFromWindow() {
568
569         var org = getSelectorVal($('holds_org_selector'));
570         var node = findOrgUnit(org);
571         var ntype = findOrgType(node.ou_type());
572         if(!ntype.can_have_users()) {
573                 alertId('holds_pick_good_org');
574                 return;
575         }
576
577         var hold = new ahr();
578         if(holdArgs.editHold) {
579                 hold = holdArgs.editHold;
580                 holdArgs.editHold = null;
581         }
582
583         if( $('holds_enable_phone').checked ) {
584                 var phone = $('holds_phone').value;
585                 if( !phone || !phone.match(REGEX_PHONE) ) {
586                         alert($('holds_bad_phone').innerHTML);
587                         return null;
588                 }
589                 hold.phone_notify(phone);
590
591         } else {
592                 hold.phone_notify("");
593         }
594
595         if( $('holds_enable_email').checked ) 
596                 hold.email_notify(1);
597         else
598                 hold.email_notify(0);
599
600         var target;
601
602         switch(holdArgs.type) {
603                 case 'M':
604                         target = holdArgs.metarecord; break;
605                 case 'T':
606                         target = holdArgs.record; break;
607                 case 'V':
608                         target = holdArgs.volume; break;
609                 case 'C':
610                         target = holdArgs.copy; break;
611         }
612
613
614
615         hold.pickup_lib(org); 
616         hold.request_lib(org); 
617         hold.requestor(holdArgs.requestor.id());
618         hold.usr(holdArgs.recipient.id());
619         hold.target(target);
620         hold.hold_type(holdArgs.type);
621
622         //check for alternate hold formats 
623         var fstring = holdsSetSelectedFormats();
624         if(fstring) { 
625                 hold.hold_type('M'); 
626                 hold.holdable_formats(fstring);
627                 hold.target(holdArgs.metarecord);
628         }
629
630         //alert(fstring); return;
631
632         /*
633         if(isXUL())             
634                 hold.selection_depth(getSelectorVal($('holds_depth_selector')));
635                 */
636
637         return hold;
638 }
639         
640 function holdsPlaceHold(hold, recurse) {
641
642         if(!hold) return;
643
644         swapCanvas($('check_holds_box'));
645
646         if( holdArgs.type == 'M' || holdArgs.type == 'T' ) {
647                 var res = holdsCheckPossibility(hold.pickup_lib());
648                 if(!res || checkILSEvent(res) ) {
649                         if(!res) {
650                                 alert($('hold_not_allowed').innerHTML);
651                         } else {
652                                 if( res.textcode == 'PATRON_BARRED' ) {
653                                         alertId('hold_failed_patron_barred');
654                                 } else {
655                                         alert($('hold_not_allowed').innerHTML);
656                                 }
657                         }
658                         swapCanvas($('holds_box'));
659                         return;
660                 }
661         }
662
663         var method = CREATE_HOLD;
664         if(recurse) method = CREATE_HOLD_OVERRIDE;
665
666         var req = new Request( method, holdArgs.requestor.session, hold );
667         req.request.alertEvent = false;
668         req.send(true);
669         var res = req.result();
670         holdProcessResult(hold, res, recurse);
671         
672         showCanvas();
673
674         holdArgs = null;
675         runEvt('common', 'holdUpdated');
676 }
677
678 function holdProcessResult( hold, res, recurse ) {
679
680         if( res == '1' ) {
681                 alert($('holds_success').innerHTML);
682
683         } else {
684
685                 if( recurse ) {
686                         alert($('holds_failure').innerHTML);
687                         return;
688                 }
689
690                 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
691                         if( fetchPermOrgs('HOLD_EXISTS')[0] ) {
692                                 if( confirm($('hold_dup_exists_override').innerHTML) ) {
693                                         return holdsPlaceHold(hold, true);
694                                 }
695
696                         } else {
697                                 return alert($('hold_dup_exists').innerHTML);
698                         }
699                 }
700
701                 alert($('holds_failure').innerHTML);
702         }
703 }
704
705
706 function holdsCancel(holdid, user) {
707         if(!user) user = G.user;
708         var req = new Request(CANCEL_HOLD, user.session, holdid);
709         req.send(true);
710         return req.result();
711         runEvt('common', 'holdUpdated');
712 }
713
714 function holdsUpdate(hold, user) {
715         if(!user) user = G.user;
716         var req = new Request(UPDATE_HOLD, user.session, hold);
717         req.send(true);
718         var x = req.result(); // cause an exception if there is one 
719         runEvt('common', 'holdUpdated');
720 }
721
722