]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/holds.js
Don't hardcode our password forms to en-US
[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 var noEmailMessage;
12 var noEmailMessageXUL;
13
14 function holdsHandleStaff() {
15
16     // if we know the recipient's barcode, use it
17     if(xulG.patron_barcode) return _holdsHandleStaff();
18
19         swapCanvas($('xulholds_box'));
20         $('xul_recipient_barcode').focus();
21         $('xul_recipient_barcode').onkeypress = function(evt) 
22                 {if(userPressedEnter(evt)) { _holdsHandleStaff(); } };
23         $('xul_recipient_barcode_submit').onclick = _holdsHandleStaff;
24         $('xul_recipient_me').onclick = _holdsHandleStaffMe;
25
26         $('xul_recipient_barcode').onkeyup = function(evt) {
27         if($('xul_recipient_barcode').value == '') 
28             $('xul_recipient_me').disabled = false;
29         else
30             $('xul_recipient_me').disabled = true;
31     };
32 }
33
34 $('holds_frozen_thaw_input').onchange = 
35         function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}
36 $('holds_frozen_thaw_input').onkeyup = 
37         function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}
38
39 function _holdsHandleStaffMe() {
40         holdArgs.recipient = G.user;
41         holdsDrawEditor();
42 }
43
44 function _holdsHandleStaff() {
45         var barcode = xulG.patron_barcode || $('xul_recipient_barcode').value;
46         var user = grabUserByBarcode( G.user.session, barcode );
47
48         var evt;
49         if(evt = checkILSEvent(user)) {
50                 alertILSEvent(user);
51                 return;
52         }
53
54         if(!barcode || !user) {
55                 alertId('holds_invalid_recipient', barcode);
56                 return
57         }
58
59         grabUserPrefs(user);
60
61         holdArgs.recipient = user;
62         holdsDrawEditor();
63 }
64
65
66
67 /** args:
68   * record, volume, copy (ids)
69   * request, recipient, editHold (objects)
70   */
71
72 function holdsDrawEditor(args) {
73
74         holdArgs = (args) ? args : holdArgs;
75
76     if(!noEmailMessage)
77         noEmailMessage = $('holds_email').removeChild($('holds.no_email'));
78
79     if(!noEmailMessageXUL)
80         noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));
81
82         if(isXUL() && holdArgs.recipient == null 
83                         && holdArgs.editHold == null) {
84                 holdsHandleStaff();
85                 return;
86         }
87
88         if(!holdArgs.recipient) holdArgs.recipient = G.user;
89         if(!holdArgs.requestor) holdArgs.requestor = G.user;
90
91         if(!(holdArgs.requestor && holdArgs.requestor.session)) {
92                 detachAllEvt('common','locationChanged');
93                 attachEvt('common','loggedIn', holdsDrawEditor)
94                 initLogin();
95                 return;
96         }
97
98         if(holdArgs.editHold) // flesh the args with the existing hold 
99                 holdArgsFromHold(holdArgs.editHold, holdArgs);
100
101         holdsDrawWindow();
102 }
103
104
105 // updates the edit window with the existing hold's data 
106 function _holdsUpdateEditHold() {
107
108         var hold = holdArgs.editHold;
109         var qstats = holdArgs.status;
110
111         var orgsel = $('holds_org_selector');
112     var frozenbox = $('holds_frozen_chkbox');
113
114         setSelector(orgsel, hold.pickup_lib());
115
116         if( hold.capture_time() || qstats.status > 2 ) {
117         frozenbox.disabled = true;
118         $('holds_frozen_thaw_input').disabled = true;
119         if(qstats.status == 3) {
120             // no pickup lib changes while in-transit
121                     orgsel.disabled = true;
122         } else {
123             var orgs = fetchPermOrgs('UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF');
124             if(orgs[0] == -1)
125                         orgsel.disabled = true;
126         }
127     } else {
128                 orgsel.disabled = false;
129         frozenbox.disabled = false;
130     }
131
132
133         $('holds_submit').onclick = holdsEditHold;
134         $('holds_update').onclick = holdsEditHold;
135
136         if(hold.phone_notify()) {
137                 $('holds_enable_phone').checked = true;
138                 $('holds_phone').value = hold.phone_notify();
139
140         } else {
141                 $('holds_phone').disabled = true;
142                 $('holds_enable_phone').checked = false;
143         }
144
145         if(isTrue(hold.email_notify())) {
146                 $('holds_enable_email').checked = true;
147
148         } else {
149                 $('holds_enable_email').checked = false;
150         }
151
152     dijit.byId('holds_expire_time').setValue(dojo.date.stamp.fromISOString(hold.expire_time()));
153
154     /* populate the hold freezing info */
155     if(!frozenbox.disabled && isTrue(hold.frozen())) {
156         frozenbox.checked = true;
157         unHideMe($('hold_frozen_thaw_row'));
158         if(hold.thaw_date()) {
159             dijit.byId('holds_frozen_thaw_input').setValue(dojo.date.stamp.fromISOString(hold.thaw_date()));
160         } else {
161             dijit.byId('holds_frozen_thaw_input').setValue('');
162         }
163     } else {
164         frozenbox.checked = false;
165         dijit.byId('holds_frozen_thaw_input').setValue('');
166         hideMe($('hold_frozen_thaw_row'));
167     }
168 }
169
170 function holdsEditHold() {
171         var hold = holdsBuildHoldFromWindow();
172         if(!hold) return;
173         holdsUpdate(hold);
174         showCanvas();
175         if(holdArgs.onComplete)
176                 holdArgs.onComplete(hold);
177 }
178
179 function holdArgsFromHold(hold, oargs) {
180         var args = (oargs) ? oargs : {};
181         args.type = hold.hold_type();
182         var target = hold.target();
183
184         switch(args.type) {
185                 case 'M':
186                         args.metarecord = target;
187                         break;
188                 case 'T':
189                         args.record = target;
190                         break;
191                 case 'V':
192                         args.volume = target;
193                         break;
194                 case 'C':
195                         args.copy = target;
196                         break;
197         }
198         return args;
199 }
200
201 function holdFetchObjects(hold, doneCallback) {
202
203         var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
204
205         var type = args.type;
206
207         if( type == 'C' ) {
208
209                 if( args.copyObject ) {
210
211                         args.copy = args.copyObject.id();
212                         args.volume = args.copyObject.call_number();
213                         _h_set_vol(args, doneCallback);
214
215                 } else {
216                         var creq = new Request(FETCH_COPY, args.copy);
217
218                         creq.callback(
219                                 function(r) {
220                                         var cp = r.getResultObject();
221                                         args.copyObject = cp;
222                                         args.volume = args.copyObject.call_number();
223                                         _h_set_vol(args, doneCallback);
224                                 }
225                         );
226                         creq.send();
227                 }
228         } else {
229                 if( type == 'V' ) {
230                         _h_set_vol(args, doneCallback);
231
232                 } else {
233                         if( type == 'T' ) {
234                                 _h_set_rec(args, doneCallback);
235                         } else {
236                                 _h_set_rec_descriptors(args, doneCallback);
237                         }
238                 }
239         }
240
241         return args;
242 }
243
244 function _h_set_vol(args, doneCallback) {
245
246         if( args.volumeObject ) {
247                 args.volume = args.volumeObject.id();
248                 args.record = args.volumeObject.record();
249                 _h_set_rec(args, doneCallback);
250
251         } else {
252
253                 var vreq = new Request(FETCH_VOLUME, args.volume);
254                 vreq.callback(
255                         function(r) {
256                                 var vol = r.getResultObject();
257                                 args.volumeObject = vol;
258                                 args.record = vol.record();
259                                 _h_set_rec(args, doneCallback);
260                         }
261                 );
262                 vreq.send();
263         }
264 }
265
266 function _h_set_rec(args, doneCallback) {
267
268         if(args.recordObject) 
269                 args.record = args.recordObject.doc_id();
270         else 
271                 args.recordObject = findRecord( args.record, 'T' );
272         
273         if( args.type == 'T' || args.type == 'M' ) 
274                 _h_set_rec_descriptors(args, doneCallback);
275         else 
276                 if(doneCallback) doneCallback(args);
277 }
278
279
280 function _h_set_rec_descriptors(args, doneCallback) {
281
282         // grab the list of record desciptors attached to this records metarecord 
283         if( ! args.recordDescriptors )  {
284                 var params = {};
285
286         if (args.type == 'M') {
287                 if( !args.metarecord && args.record) {
288                 params.metarecord = args.metarecord = args.record;
289                 delete(args.record);
290                 } else {
291                                 params = { metarecord : args.metarecordObject.doc_id() };
292                 }
293         } else {
294                 params = { record: args.record };
295         }
296
297                 if( ! args.record ) {
298                         if( args.metarecord )
299                                 params = { metarecord : args.metarecord };
300                         else 
301                                 params = { metarecord : args.metarecordObject.doc_id() };
302                 }
303
304                 var req = new Request(FETCH_MR_DESCRIPTORS, params );
305                 req.callback(
306                         function(r) {
307                                 var data = r.getResultObject();
308                                 holdArgs.recordDescriptors = args.recordDescriptors = data.descriptors;
309                                 holdArgs.metarecord = args.metarecord = data.metarecord;
310                                 if( args.type == 'M' && ! args.metarecordObject) 
311                                         holdArgs.metarecordObject = args.metarecordObject = findRecord(args.metarecord, 'M');   
312
313                                 if(doneCallback) doneCallback(args);
314                         }
315                 );
316                 req.send();
317
318         } else {
319                 if(doneCallback) doneCallback(args);
320         }
321
322         return args;
323 }
324
325
326
327 function holdsDrawWindow() {
328         swapCanvas($('holds_box'));
329         $('holds_cancel').onclick = function(){ runEvt('common', 'holdUpdateCanceled'), showCanvas() };
330         $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
331         $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
332         holdFetchObjects(null, 
333                 function(){
334                         __holdsDrawWindow();
335
336                         if(holdArgs.editHold) {
337                                 hideMe($('holds_submit'));
338                                 unHideMe($('holds_update'));
339                                 var req = new Request(FETCH_HOLD_STATUS, 
340                                         G.user.session, holdArgs.editHold.id());
341                                 req.send(true);
342                                 holdArgs.status = req.result();
343                                 _holdsUpdateEditHold();
344                         }  
345                 }
346         );
347 }
348
349 function __holdsDrawWindow() {
350
351         var rec = holdArgs.recordObject;
352         var vol = holdArgs.volumeObject;
353         var copy = holdArgs.copyObject;
354         var mr = holdArgs.metarecordObject;
355
356         rec = (rec) ? rec : mr;
357
358         if(!holdsOrgSelectorBuilt) {
359                 holdsBuildOrgSelector(null,0);
360                 holdsOrgSelectorBuilt = true;
361                 var selector = $('holds_org_selector');
362
363                 /*
364                 var o_loc = findOrgUnit(getOrigLocation());
365                 var t = findOrgType(o_loc.ou_type());
366                 if( t.can_have_users() ) 
367                         setSelector(selector, o_loc.id());
368                 else 
369                 */
370
371                 setSelector(selector, holdArgs.recipient.home_ou());
372         
373         }
374
375         /*
376         if(isXUL()) {
377                 var dsel = $('holds_depth_selector');
378                 unHideMe($('holds_depth_selector_row'));
379                 if(dsel.getElementsByTagName('option').length == 0) {
380                         var types = globalOrgTypes;
381                         var depth = findOrgDepth(G.user.ws_ou());
382                         iterate(types, 
383                                 function(t) {
384                                         if(t.depth() > depth) return;
385                                         insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
386                                 }
387                         );
388                 }
389         }
390         */
391
392         appendClear($('holds_recipient'), text(
393                 holdArgs.recipient.family_name() + ', ' +  
394                         holdArgs.recipient.first_given_name()));
395         appendClear($('holds_title'), text(rec.title()));
396         appendClear($('holds_author'), text(rec.author()));
397
398         if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
399
400                 unHideMe($('holds_type_row'));
401                 unHideMe($('holds_cn_row'));
402                 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
403
404                 if( holdArgs.type == 'V'  ) {
405                         unHideMe($('holds_is_cn'));
406                         hideMe($('holds_is_copy'));
407
408                 } else {
409                         hideMe($('holds_is_cn'));
410                         unHideMe($('holds_is_copy'));
411                         unHideMe($('holds_copy_row'));
412                         appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
413                 }
414
415         } else {
416                 hideMe($('holds_type_row'));
417                 hideMe($('holds_copy_row'));
418                 hideMe($('holds_cn_row'));
419         }
420
421         removeChildren($('holds_format'));
422
423         var mods_formats = rec.types_of_resource();
424         var formats;
425
426         if(holdArgs.recordDescriptors)
427                 formats = holdArgs.recordDescriptors[0].item_type();
428
429         if( holdArgs.type == 'T' ) {
430                 var desc = grep( holdArgs.recordDescriptors,
431                         function(i) {
432                                 return (i.record() == holdArgs.record); 
433                         }
434                 );
435                 formats = desc[0].item_type();
436         }
437
438         if( holdArgs.type == 'M' ) {
439                 var mr_formats;
440                 if(holdArgs.editHold){
441                         mr_formats = holdArgs.editHold.holdable_formats();
442                 }else{
443                         mr_formats = ''; // collect the item_type()s from all holdArgs.recordDescriptors
444                         for(var desc in holdArgs.recordDescriptors){
445                 if (!holdArgs.recordDescriptors[desc].item_type()) continue;
446                                 mr_formats += holdArgs.recordDescriptors[desc].item_type();
447                         }
448
449             var first_form = 1;
450                         for(var desc in holdArgs.recordDescriptors){
451                 if (!holdArgs.recordDescriptors[desc].item_form()) continue;
452                 if (first_form) {
453                     mr_formats += '-';
454                     first_form = 0;
455                 }
456                                 mr_formats += holdArgs.recordDescriptors[desc].item_form();
457                         }
458
459
460                 }
461                 
462                 var data = holdsParseMRFormats(mr_formats);
463                 mods_formats = data.mods_formats;
464                 formats = data.formats;
465         }
466
467
468         for( var i in mods_formats ) {
469                 var res = mods_formats[i];
470                 var img = elem("img");
471                 setResourcePic(img, res);
472                 $('holds_format').appendChild(img);
473                 if(formats)
474                         $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
475                 else
476                         $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
477                 $('holds_format').appendChild(elem('br'));
478         }
479
480
481         $('holds_phone').value = holdArgs.recipient.day_phone();
482         appendClear( $('holds_email'), text(holdArgs.recipient.email()));
483
484         var pref = holdArgs.recipient.prefs[PREF_HOLD_NOTIFY];
485
486         if(pref) {
487                 if( ! pref.match(/email/i) ) {
488                         $('holds_enable_email').checked = false;
489                 } else {
490                         $('holds_enable_email').checked = true;
491                 }
492
493                 if( ! pref.match(/phone/i) ) {
494                         $('holds_phone').disabled = true;
495                         $('holds_enable_phone').checked = false;
496                 } else {
497                         $('holds_phone').disabled = false;
498                         $('holds_enable_phone').checked = true;
499                 }
500         }
501
502     if(!holdArgs.recipient.email()) {
503                 $('holds_enable_email').checked = false;        
504                 $('holds_enable_email').disabled = true;
505         var message;
506         if(isXUL()) {
507             message = noEmailMessageXUL.cloneNode(true);
508                 appendClear($('holds_email'), message);
509         } else {
510             message = noEmailMessage.cloneNode(true);
511                 appendClear($('holds_email'), message);
512             $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));
513         }
514         unHideMe(message);
515     }
516
517         if(!$('holds_phone').value) 
518                 $('holds_enable_phone').checked = false;        
519
520         appendClear($('holds_physical_desc'), text(rec.physical_description()));
521
522         if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
523
524         holdsSetFormatSelector();
525
526     $('holds_frozen_chkbox').checked = false;
527     hideMe($('hold_frozen_thaw_row'));
528
529     var interval = fetchOrgSettingDefault(holdArgs.recipient.home_ou(), 'circ.hold_expire_interval');
530     var secs = 0;
531     if(interval) {
532         secs = interval_to_seconds(interval);
533         var expire = new Date();
534         expire.setTime(expire.getTime() + Number(secs + '000'));
535         dijit.byId('holds_expire_time').setValue(expire);
536     }
537 }
538
539 function holdsParseMRFormats(str) {
540         var data = str.split(/-/);      
541
542         var formats = [];
543         var mods_formats = [];
544
545         for( var i = 0; i < data[0].length; i++ ) {
546                 formats.push( data[0].charAt(i) );
547                 mods_formats.push( MARCFormatToMods( formats[i] ) );
548         }
549         
550         formats = uniquify(formats);
551         mods_formats = uniquify(mods_formats);
552
553         return {
554                 formats                 : formats,
555                 mods_formats    : mods_formats,
556                 lang                            : data[2],
557                 largeprint              : data[1]
558         };
559 }
560
561
562 function holdsSetFormatSelector() {
563         var type = holdArgs.type;
564         if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
565
566         var data                                = holdsGetFormats();
567         var avail_formats       = data.avail_formats;
568         var sel_formats = data.sel_formats;
569         holdArgs.language = data.lang;
570         if( type=='M'){         
571                 hideMe($('holds_alt_formats_row_extras'));
572                 unHideMe($('holds_alt_formats_row'));   
573         }else{
574                 unHideMe($('holds_alt_formats_row_extras'));
575         }
576
577         var selector = $('hold_alt_form_selector');
578
579     for( var i = 0; i < selector.options.length; i++ ) {
580         if (selector.options[i].className.indexOf('hide_me') == -1)
581             hideMe(selector.options[i]);
582     }
583
584         for( var i = 0; i < avail_formats.length; i++ ) {
585                 var form = avail_formats[i];
586                 var opt = findFormatSelectorOptByParts(selector,form);
587         if (!opt) continue;
588                 if(type=='M') opt.selected=true;
589                 unHideMe(opt);
590         }
591 }
592
593 function findFormatSelectorOptByParts( sel, val ) {
594     var parts = val.split('-');
595     for( var i = 0; i < sel.options.length; i++ ) {
596         var opt = sel.options[i];
597         var oval = opt.value;
598         var oparts = oval.split('-');
599         if( oparts[0].indexOf(parts[0]) > -1 && (!parts[1] || oparts[1].indexOf(parts[1]) > -1) ) return opt;
600     }
601     return null;
602 }
603
604 function holdsGetFormats() {
605
606         var lang;
607         var formats = [];
608         var sformats = []; // selected formats 
609
610         var type = holdArgs.type;
611         var desc = holdArgs.recordDescriptors;
612         var rec = holdArgs.record;
613         var mrec = holdArgs.metarecord;
614
615         for( var i = 0; i < desc.length; i++ ) {
616                 var d = desc[i];
617                 if( type == 'T' && d.item_lang() != lang ) continue;
618                 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
619         }
620
621         formats = uniquify(formats);
622
623         if( type == 'T') {
624
625                 for( var i = 0; i < desc.length; i++ ) {
626                         var d = desc[i];
627                         if( d.record() == holdArgs.record ) {
628                                 lang = d.item_lang();
629                                 holdArgs.myFormat =  _t_f_2_format(d.item_type(), d.item_form());
630                                 sformats.push(holdArgs.myFormat);
631                                 break;
632                         }
633                 }
634         } else if( type =='M') {
635
636         // All available formats are selected by default in MR holds
637                 for( var i = 0; i < formats.length; i++ ) {
638                         sformats.push(formats[i]);
639                 }
640         }
641
642         return {
643                 lang : lang,
644                 avail_formats : formats, 
645                 sel_formats : sformats
646         };
647 }
648
649
650
651 function _t_f_2_format(type, form) {
652         if( (type == 'a' || type == 't') && form == 's' ) return 'at-s';
653         if( form == 'd' ) return 'at-d';
654         return (type == 'a' || type == 't') ? 'at' : type;
655 }
656
657 function holdsSetSelectedFormats() {
658
659         var cn = $('holds_alt_formats_row').className;
660         if( cn && cn.match(/hide_me/) ) return;
661
662         var selector = $('hold_alt_form_selector');
663         var vals = getSelectedList(selector);
664
665         if(vals.length == 0) return;
666
667         var fstring = "";
668
669         if( contains(vals, 'at-d') || contains(vals, 'at-s')) {
670                 if( contains(vals, 'at') ) {
671                         fstring = 'at';
672                 } else if (contains(vals, 'at-s') && contains(vals, 'at-d')) {
673                         fstring = 'at-sd';
674                 } else if (!contains(vals, 'at-s')) {
675                         fstring = 'at-d';
676         } else {
677                         fstring = 'at-s';
678                 }
679         }
680
681         for( var i = 0; i < vals.length; i++ ) {
682                 var val = vals[i];
683                 if( !val.match(/at/) ) fstring = val + fstring;
684         }
685
686         if( holdArgs.language ) {
687                 if( fstring.match(/-/) )
688                         fstring = fstring + '-' + holdArgs.language;
689                 else
690                         fstring = fstring + '--' + holdArgs.language;
691         }
692
693
694         return fstring;
695 }
696
697
698 function holdsCheckPossibility(pickuplib, hold, recurse) {
699
700         var args = { 
701                 titleid : holdArgs.record,
702                 mrid : holdArgs.metarecord,
703                 volume_id : holdArgs.volume,
704                 copy_id : holdArgs.copy,
705                 hold_type : holdArgs.type,
706                 patronid : holdArgs.recipient.id(),
707                 depth : 0, 
708                 pickup_lib : pickuplib 
709         };
710
711         if(recurse) {
712                 /* if we're calling create again (recursing), 
713                         we know that the hold possibility check already succeeded */
714                 holdHandleCreateResponse({_recurse:true, _hold:hold}, true );
715
716         } else {
717                 _debug("hold possible args = "+js2JSON(args));
718         
719                 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );
720         
721                 req.request.alertEvent = false;
722                 req.request._hold = hold;
723                 req.request._recurse = recurse;
724                 req.callback(holdHandleCreateResponse);
725                 req.send();
726         }
727 }
728
729
730 function holdsBuildOrgSelector(node) {
731
732         if(!node) node = globalOrgTree;
733     if(!isTrue(node.opac_visible())) return;
734
735         var selector = $('holds_org_selector');
736         var index = selector.options.length;
737
738         var type = findOrgType(node.ou_type());
739         var indent = type.depth() - 1;
740         var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
741         if(!type.can_have_users()) {
742                 opt.disabled = true;
743                 addCSSClass(opt, 'disabled_option');
744         }
745         
746         for( var i in node.children() ) {
747                 var child = node.children()[i];
748                 if(child) holdsBuildOrgSelector(child);
749         }
750 }
751
752 function holdsBuildHoldFromWindow() {
753
754         var org = getSelectorVal($('holds_org_selector'));
755         var node = findOrgUnit(org);
756         var ntype = findOrgType(node.ou_type());
757         if(!ntype.can_have_users()) {
758                 alertId('holds_pick_good_org');
759                 return;
760         }
761
762         var hold = new ahr();
763         if(holdArgs.editHold) {
764                 hold = holdArgs.editHold;
765                 holdArgs.editHold = null;
766         }
767
768         if( $('holds_enable_phone').checked ) {
769                 var phone = $('holds_phone').value;
770                 if( !phone || !phone.match(REGEX_PHONE) ) {
771                         alert($('holds_bad_phone').innerHTML);
772                         return null;
773                 }
774                 hold.phone_notify(phone);
775
776         } else {
777                 hold.phone_notify("");
778         }
779
780         if( $('holds_enable_email').checked ) 
781                 hold.email_notify(1);
782         else
783                 hold.email_notify(0);
784
785         var target;
786
787         switch(holdArgs.type) {
788                 case 'M':
789                         target = holdArgs.metarecord; break;
790                 case 'T':
791                         target = holdArgs.record; break;
792                 case 'V':
793                         target = holdArgs.volume; break;
794                 case 'C':
795                         target = holdArgs.copy; break;
796         }
797
798
799
800         hold.pickup_lib(org); 
801         //hold.request_lib(org); 
802         hold.requestor(holdArgs.requestor.id());
803         hold.usr(holdArgs.recipient.id());
804         hold.target(target);
805         hold.hold_type(holdArgs.type);
806
807     var expDate = dijit.byId('holds_expire_time').getValue();
808     if(expDate) {
809         var expireDate = dojo.date.stamp.toISOString(expDate);
810         expireDate = holdsVerifyThawDate(expireDate); 
811         if(expireDate)
812             hold.expire_time(expireDate);
813         else 
814             return;
815     }
816
817     // see if this hold should be frozen and for how long
818     if($('holds_frozen_chkbox').checked) {
819         hold.frozen('t');
820         unHideMe($('hold_frozen_thaw_row'));
821         var thawDate = dijit.byId('holds_frozen_thaw_input').attr('value');
822         if(thawDate) {
823             thawDate = dojo.date.stamp.toISOString(thawDate);
824             thawDate = holdsVerifyThawDate(thawDate); 
825             if(thawDate) 
826                 hold.thaw_date(thawDate);
827             else
828                 return;
829         } else {
830             hold.thaw_date(null);
831         }
832     } else {
833         hold.frozen('f');
834         hold.thaw_date(null);
835     }
836
837         //check for alternate hold formats 
838         var fstring = holdsSetSelectedFormats();
839         if(fstring) { 
840                 hold.hold_type('M'); 
841                 hold.holdable_formats(fstring);
842                 hold.target(holdArgs.metarecord);
843         }
844         return hold;
845 }
846         
847 function holdsPlaceHold(hold, recurse) {
848         if(!hold) return;
849         swapCanvas($('check_holds_box'));
850         holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
851 }
852
853
854 function holdHandleCreateResponse(r, recurse) {
855
856         if(!recurse) {
857                 var res = r.getResultObject();
858                 if(checkILSEvent(res) || res.success != 1) {
859                         if(res.success != 1) {
860                                 alert($('hold_not_allowed').innerHTML);
861                         } else {
862                                 if( res.textcode == 'PATRON_BARRED' ) {
863                                         alertId('hold_failed_patron_barred');
864                         } else {
865                                         alert($('hold_not_allowed').innerHTML);
866                                 }
867                         }
868                         swapCanvas($('holds_box'));
869                         return;
870                 }
871         r._hold.selection_depth(res.depth);
872         }       
873
874         holdCreateHold(r._recurse, r._hold);
875 }
876
877
878 function holdCreateHold( recurse, hold ) {
879         var method = CREATE_HOLD;
880         if(recurse) method = CREATE_HOLD_OVERRIDE;
881         var req = new Request( method, holdArgs.requestor.session, hold );
882         req.request.alertEvent = false;
883         req.send(true);
884         var res = req.result();
885         holdProcessResult(hold, res, recurse);
886         
887         showCanvas();
888
889         runEvt('common', 'holdUpdated');
890 }
891
892
893 function holdProcessResult( hold, res, recurse ) {
894
895         if( res && res > -1 ) {
896                 alert($('holds_success').innerHTML);
897                 holdArgs = null;
898         if(isXUL() && typeof xulG.opac_hold_placed == 'function')
899             xulG.opac_hold_placed(res);
900
901         } else {
902
903                 if( recurse ) {
904                         alert($('holds_failure').innerHTML);
905                         return;
906                 }
907
908                 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
909                         if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {
910                                 if( confirm($('hold_dup_exists_override').innerHTML) ) {
911                                         return holdsPlaceHold(hold, true);
912                                 }
913                 return;
914
915                         } else {
916                                 return alert($('hold_dup_exists').innerHTML);
917                         }
918                 }
919
920                 if( grep(res, function(e) { return (e.textcode == 'HOLD_ITEM_CHECKED_OUT'); }) ) {
921                         if( fetchPermOrgs('HOLD_ITEM_CHECKED_OUT.override')[0] != -1 ) {
922                                 if( confirm($('hold_checked_out_override').innerHTML) ) {
923                                         return holdsPlaceHold(hold, true);
924                                 }
925                 return;
926
927                         } else {
928                                 return alert($('hold_checked_out').innerHTML);
929                         }
930                 }
931
932
933                 alert($('holds_failure').innerHTML);
934         }
935 }
936
937
938 function holdsCancel(holdid, user) {
939         if(!user) user = G.user;
940         var req = new Request(CANCEL_HOLD, user.session, holdid, /* Patron via OPAC */ 6);
941         req.send(true);
942         return req.result();
943         runEvt('common', 'holdUpdated');
944 }
945
946 function holdsUpdate(hold, user) {
947         if(!user) user = G.user;
948         var req = new Request(UPDATE_HOLD, user.session, hold);
949         req.send(true);
950         var x = req.result(); // cause an exception if there is one 
951         runEvt('common', 'holdUpdated');
952 }
953
954 /* verify that the thaw date is valid and after today */
955 function holdsVerifyThawDate(dateString, isGreater) {
956     thawDate = dojo.date.stamp.fromISOString(dateString);
957     if(thawDate) {
958         if(isGreater) {
959             if(dojo.date.compare(thawDate) > 0) {
960                 return dojo.date.stamp.toISOString(thawDate);
961             }
962         } else {
963             return dojo.date.stamp.toISOString(thawDate);
964         }
965     }
966     return null;
967 }
968
969 function holdsVerifyThawDateUI(element) {
970     value = dojo.date.stamp.toISOString(dijit.byId(element).getValue());
971
972     if(!value) {
973         removeCSSClass($(element), 'invalid_field');
974         return;
975     }
976
977     if(!holdsVerifyThawDate(value, true)) {
978         addCSSClass($(element), 'invalid_field');
979     } else {
980         removeCSSClass($(element), 'invalid_field');
981     }
982 }
983