]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/holds.js
put temporary warning in hold user fetcher
[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(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
286                 var selector = $('holds_org_selector');
287                 var o_loc = findOrgUnit(getOrigLocation());
288                 var t = findOrgType(o_loc.ou_type());
289
290                 if( t.can_have_users() ) 
291                         setSelector(selector, o_loc.id());
292                 else 
293                         setSelector(selector, holdArgs.recipient.home_ou());
294         
295         }
296
297         /*
298         if(isXUL()) {
299                 var dsel = $('holds_depth_selector');
300                 unHideMe($('holds_depth_selector_row'));
301                 if(dsel.getElementsByTagName('option').length == 0) {
302                         var types = globalOrgTypes;
303                         var depth = findOrgDepth(G.user.ws_ou());
304                         iterate(types, 
305                                 function(t) {
306                                         if(t.depth() > depth) return;
307                                         insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
308                                 }
309                         );
310                 }
311         }
312         */
313
314         appendClear($('holds_recipient'), text(
315                 holdArgs.recipient.family_name() + ', ' +  
316                         holdArgs.recipient.first_given_name()));
317         appendClear($('holds_title'), text(rec.title()));
318         appendClear($('holds_author'), text(rec.author()));
319
320         if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
321
322                 unHideMe($('holds_type_row'));
323                 unHideMe($('holds_cn_row'));
324                 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
325
326                 if( holdArgs.type == 'V'  ) {
327                         unHideMe($('holds_is_cn'));
328                         hideMe($('holds_is_copy'));
329
330                 } else {
331                         hideMe($('holds_is_cn'));
332                         unHideMe($('holds_is_copy'));
333                         unHideMe($('holds_copy_row'));
334                         appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
335                 }
336
337         } else {
338                 hideMe($('holds_type_row'));
339                 hideMe($('holds_copy_row'));
340                 hideMe($('holds_cn_row'));
341         }
342
343         removeChildren($('holds_format'));
344
345         var mods_formats = rec.types_of_resource();
346         var formats;
347
348         if(holdArgs.recordDescriptors)
349                 formats = holdArgs.recordDescriptors[0].item_type();
350
351         if( holdArgs.type == 'T' ) {
352                 var desc = grep( holdArgs.recordDescriptors,
353                         function(i) {
354                                 return (i.record() == holdArgs.record); 
355                         }
356                 );
357                 formats = desc[0].item_type();
358         }
359
360         if( holdArgs.type == 'M' ) {
361                 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());
362                 mods_formats = data.mods_formats;
363                 formats = data.formats;
364         }
365
366
367         for( var i in mods_formats ) {
368                 var res = mods_formats[i];
369                 var img = elem("img");
370                 setResourcePic(img, res);
371                 $('holds_format').appendChild(img);
372                 if(formats)
373                         $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
374                 else
375                         $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
376                 $('holds_format').appendChild(elem('br'));
377         }
378
379
380         $('holds_phone').value = holdArgs.recipient.day_phone();
381         appendClear( $('holds_email'), text(holdArgs.recipient.email()));
382
383         var pref = G.user.prefs[PREF_HOLD_NOTIFY];
384
385         if(pref) {
386                 if( ! pref.match(/email/i) ) 
387                         $('holds_enable_email').checked = false;
388
389                 if( ! pref.match(/phone/i) ) {
390                         $('holds_phone').disabled = true;
391                         $('holds_enable_phone').checked = false;
392                 }
393         }
394
395         appendClear($('holds_physical_desc'), text(rec.physical_description()));
396
397         if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
398
399         holdsSetFormatSelector();
400 }
401
402 function holdsParseMRFormats(str) {
403         var data = str.split(/-/);      
404
405         var formats = [];
406         var mods_formats = [];
407
408         for( var i = 0; i < data[0].length; i++ ) {
409                 formats.push( data[0].charAt(i) );
410                 mods_formats.push( MARCFormatToMods( formats[i] ) );
411         }
412         
413         formats = uniquify(formats);
414         mods_formats = uniquify(mods_formats);
415
416         return {
417                 formats                 : formats,
418                 mods_formats    : mods_formats,
419                 lang                            : data[2],
420                 largeprint              : data[1]
421         };
422 }
423
424
425 function holdsSetFormatSelector() {
426         var type = holdArgs.type;
427         if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
428
429         var data                                = holdsGetFormats();
430         var avail_formats       = data.avail_formats;
431         var sel_formats = data.sel_formats;
432         holdArgs.language = data.lang;
433
434         unHideMe($('holds_alt_formats_row_extras'));
435         var selector = $('hold_alt_form_selector');
436
437         for( var i = 0; i < avail_formats.length; i++ ) {
438                 var form = avail_formats[i];
439                 unHideMe(findSelectorOptByValue(selector, form));
440         }
441 }
442
443
444 function holdsGetFormats() {
445
446         var lang;
447         var formats = [];
448         var sformats = []; // selected formats 
449
450         var type = holdArgs.type;
451         var desc = holdArgs.recordDescriptors;
452         var rec = holdArgs.record;
453         var mrec = holdArgs.metarecord;
454
455         if( type == 'T' ) {
456
457                 for( var i = 0; i < desc.length; i++ ) {
458                         var d = desc[i];
459                         if( d.record() == holdArgs.record ) {
460                                 lang = d.item_lang();
461                                 holdArgs.myFormat =  _t_f_2_format(d.item_type(), d.item_form());
462                                 sformats.push(holdArgs.myFormat);
463                                 break;
464                         }
465                 }
466         }
467
468         for( var i = 0; i < desc.length; i++ ) {
469                 var d = desc[i];
470                 if( d.item_lang() != lang ) continue;
471                 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
472         }
473
474         formats = uniquify(formats);
475
476         return {
477                 lang : lang,
478                 avail_formats : formats, 
479                 sel_formats : sformats
480         };
481 }
482
483
484
485 function _t_f_2_format(type, form) {
486         if( form == 'd' ) return 'at-d';
487         return (type == 'a' || type == 't') ? 'at' : 
488                 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
489 }
490
491 function holdsSetSelectedFormats() {
492
493         var cn = $('holds_alt_formats_row').className;
494         if( cn && cn.match(/hide_me/) ) return;
495
496         var selector = $('hold_alt_form_selector');
497         var vals = getSelectedList(selector);
498
499         if(vals.length == 0) return;
500
501         var fstring = "";
502
503         if( contains(vals, 'at-d') ) {
504                 if( contains(vals, 'at') )
505                         fstring = 'at';
506                 else 
507                         fstring = 'at-d';
508         } else {
509                 if( contains(vals, 'at') )
510                         fstring = 'at';
511         }
512
513         for( var i = 0; i < vals.length; i++ ) {
514                 var val = vals[i];
515                 if( !val.match(/at/) ) fstring = val + fstring;
516         }
517
518         if( holdArgs.language ) {
519                 if( fstring.match(/-/) )
520                         fstring = fstring + '-' + holdArgs.language;
521                 else
522                         fstring = fstring + '--' + holdArgs.language;
523         }
524
525
526         return fstring;
527 }
528
529
530 function holdsCheckPossibility(pickuplib) {
531         var rec = holdArgs.record;
532         var type = holdArgs.type;
533         var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, 
534                         { titleid : rec, patronid : G.user.id(), depth : 0, pickup_lib : pickuplib } );
535         req.send(true);
536         return req.result();
537 }
538
539
540 function holdsBuildOrgSelector(node) {
541
542         if(!node) node = globalOrgTree;
543
544         var selector = $('holds_org_selector');
545         var index = selector.options.length;
546
547         var type = findOrgType(node.ou_type());
548         var indent = type.depth() - 1;
549         var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
550         if(!type.can_have_users()) {
551                 opt.disabled = true;
552                 addCSSClass(opt, 'disabled_option');
553         }
554         
555         for( var i in node.children() ) {
556                 var child = node.children()[i];
557                 if(child) holdsBuildOrgSelector(child);
558         }
559 }
560
561 function holdsBuildHoldFromWindow() {
562
563         var org = getSelectorVal($('holds_org_selector'));
564         var node = findOrgUnit(org);
565         var ntype = findOrgType(node.ou_type());
566         if(!ntype.can_have_users()) {
567                 alertId('holds_pick_good_org');
568                 return;
569         }
570
571         var hold = new ahr();
572         if(holdArgs.editHold) {
573                 hold = holdArgs.editHold;
574                 holdArgs.editHold = null;
575         }
576
577         if( $('holds_enable_phone').checked ) {
578                 var phone = $('holds_phone').value;
579                 if( !phone || !phone.match(REGEX_PHONE) ) {
580                         alert($('holds_bad_phone').innerHTML);
581                         return null;
582                 }
583                 hold.phone_notify(phone);
584
585         } else {
586                 hold.phone_notify("");
587         }
588
589         if( $('holds_enable_email').checked ) 
590                 hold.email_notify(1);
591         else
592                 hold.email_notify(0);
593
594         var target;
595
596         switch(holdArgs.type) {
597                 case 'M':
598                         target = holdArgs.metarecord; break;
599                 case 'T':
600                         target = holdArgs.record; break;
601                 case 'V':
602                         target = holdArgs.volume; break;
603                 case 'C':
604                         target = holdArgs.copy; break;
605         }
606
607
608
609         hold.pickup_lib(org); 
610         hold.request_lib(org); 
611         hold.requestor(holdArgs.requestor.id());
612         hold.usr(holdArgs.recipient.id());
613         hold.target(target);
614         hold.hold_type(holdArgs.type);
615
616         //check for alternate hold formats 
617         var fstring = holdsSetSelectedFormats();
618         if(fstring) { 
619                 hold.hold_type('M'); 
620                 hold.holdable_formats(fstring);
621                 hold.target(holdArgs.metarecord);
622         }
623
624         //alert(fstring); return;
625
626         /*
627         if(isXUL())             
628                 hold.selection_depth(getSelectorVal($('holds_depth_selector')));
629                 */
630
631         return hold;
632 }
633         
634 function holdsPlaceHold(hold) {
635
636         if(!hold) return;
637
638         swapCanvas($('check_holds_box'));
639
640         if( holdArgs.type == 'M' || holdArgs.type == 'T' ) {
641                 if( ! holdsCheckPossibility(hold.pickup_lib() ) ) {
642                         alert($('hold_not_allowed').innerHTML);
643                         swapCanvas($('holds_box'));
644                         return;
645                 }
646         }
647
648         var req = new Request( CREATE_HOLD, holdArgs.requestor.session, hold );
649         req.send(true);
650         var res = req.result();
651
652         if( res == '1' ) alert($('holds_success').innerHTML);
653         else alert($('holds_failure').innerHTML);
654         
655         showCanvas();
656
657         holdArgs = null;
658         runEvt('common', 'holdUpdated');
659 }
660
661 function holdsCancel(holdid, user) {
662         if(!user) user = G.user;
663         var req = new Request(CANCEL_HOLD, user.session, holdid);
664         req.send(true);
665         return req.result();
666         runEvt('common', 'holdUpdated');
667 }
668
669 function holdsUpdate(hold, user) {
670         if(!user) user = G.user;
671         var req = new Request(UPDATE_HOLD, user.session, hold);
672         req.send(true);
673         var x = req.result(); // cause an exception if there is one 
674         runEvt('common', 'holdUpdated');
675 }
676
677