1 var holdsOrgSelectorBuilt = false;
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
12 var noEmailMessageXUL;
14 function holdsHandleStaff() {
16 // if we know the recipient's barcode, use it
17 if(xulG.patron_barcode) return _holdsHandleStaff();
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;
26 $('xul_recipient_barcode').onkeyup = function(evt) {
27 if($('xul_recipient_barcode').value == '')
28 $('xul_recipient_me').disabled = false;
30 $('xul_recipient_me').disabled = true;
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');}
39 function _holdsHandleStaffMe() {
40 holdArgs.recipient = G.user;
44 function _holdsHandleStaff() {
45 var barcode = xulG.patron_barcode || $('xul_recipient_barcode').value;
46 var user = grabUserByBarcode( G.user.session, barcode );
49 if(evt = checkILSEvent(user)) {
54 if(!barcode || !user) {
55 alertId('holds_invalid_recipient', barcode);
59 holdArgs.recipient = user;
66 * record, volume, copy (ids)
67 * request, recipient, editHold (objects)
70 function holdsDrawEditor(args) {
72 holdArgs = (args) ? args : holdArgs;
75 noEmailMessage = $('holds_email').removeChild($('holds.no_email'));
77 if(!noEmailMessageXUL)
78 noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));
80 if(isXUL() && holdArgs.recipient == null
81 && holdArgs.editHold == null) {
86 if(!holdArgs.recipient) holdArgs.recipient = G.user;
87 if(!holdArgs.requestor) holdArgs.requestor = G.user;
89 if(!(holdArgs.requestor && holdArgs.requestor.session)) {
90 detachAllEvt('common','locationChanged');
91 attachEvt('common','loggedIn', holdsDrawEditor)
96 if(holdArgs.editHold) // flesh the args with the existing hold
97 holdArgsFromHold(holdArgs.editHold, holdArgs);
103 // updates the edit window with the existing hold's data
104 function _holdsUpdateEditHold() {
106 var hold = holdArgs.editHold;
107 var qstats = holdArgs.status;
109 var orgsel = $('holds_org_selector');
110 var frozenbox = $('holds_frozen_chkbox');
112 setSelector(orgsel, hold.pickup_lib());
114 if( hold.capture_time() || qstats.status > 2 ) {
115 frozenbox.disabled = true;
116 $('holds_frozen_thaw_input').disabled = true;
117 if(qstats.status == 3) {
118 // no pickup lib changes while in-transit
119 orgsel.disabled = true;
121 var orgs = fetchPermOrgs('UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF');
123 orgsel.disabled = true;
126 orgsel.disabled = false;
127 frozenbox.disabled = false;
131 $('holds_submit').onclick = holdsEditHold;
132 $('holds_update').onclick = holdsEditHold;
134 if(hold.phone_notify()) {
135 $('holds_enable_phone').checked = true;
136 $('holds_phone').value = hold.phone_notify();
139 $('holds_phone').disabled = true;
140 $('holds_enable_phone').checked = false;
143 if(isTrue(hold.email_notify())) {
144 $('holds_enable_email').checked = true;
147 $('holds_enable_email').checked = false;
150 dijit.byId('holds_expire_time').setValue(dojo.date.stamp.fromISOString(hold.expire_time()));
152 /* populate the hold freezing info */
153 if(!frozenbox.disabled && isTrue(hold.frozen())) {
154 frozenbox.checked = true;
155 unHideMe($('hold_frozen_thaw_row'));
156 if(hold.thaw_date()) {
157 dijit.byId('holds_frozen_thaw_input').setValue(dojo.date.stamp.fromISOString(hold.thaw_date()));
159 dijit.byId('holds_frozen_thaw_input').setValue('');
162 frozenbox.checked = false;
163 dijit.byId('holds_frozen_thaw_input').setValue('');
164 hideMe($('hold_frozen_thaw_row'));
168 function holdsEditHold() {
169 var hold = holdsBuildHoldFromWindow();
173 if(holdArgs.onComplete)
174 holdArgs.onComplete(hold);
177 function holdArgsFromHold(hold, oargs) {
178 var args = (oargs) ? oargs : {};
179 args.type = hold.hold_type();
180 var target = hold.target();
184 args.metarecord = target;
187 args.record = target;
190 args.volume = target;
199 function holdFetchObjects(hold, doneCallback) {
201 var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
203 var type = args.type;
207 if( args.copyObject ) {
209 args.copy = args.copyObject.id();
210 args.volume = args.copyObject.call_number();
211 _h_set_vol(args, doneCallback);
214 var creq = new Request(FETCH_COPY, args.copy);
218 var cp = r.getResultObject();
219 args.copyObject = cp;
220 args.volume = args.copyObject.call_number();
221 _h_set_vol(args, doneCallback);
228 _h_set_vol(args, doneCallback);
232 _h_set_rec(args, doneCallback);
234 _h_set_rec_descriptors(args, doneCallback);
242 function _h_set_vol(args, doneCallback) {
244 if( args.volumeObject ) {
245 args.volume = args.volumeObject.id();
246 args.record = args.volumeObject.record();
247 _h_set_rec(args, doneCallback);
251 var vreq = new Request(FETCH_VOLUME, args.volume);
254 var vol = r.getResultObject();
255 args.volumeObject = vol;
256 args.record = vol.record();
257 _h_set_rec(args, doneCallback);
264 function _h_set_rec(args, doneCallback) {
266 if(args.recordObject)
267 args.record = args.recordObject.doc_id();
269 args.recordObject = findRecord( args.record, 'T' );
271 if( args.type == 'T' || args.type == 'M' )
272 _h_set_rec_descriptors(args, doneCallback);
274 if(doneCallback) doneCallback(args);
278 function _h_set_rec_descriptors(args, doneCallback) {
280 // grab the list of record desciptors attached to this records metarecord
281 if( ! args.recordDescriptors ) {
282 var params = { record: args.record };
284 if( ! args.record ) {
285 if( args.metarecord )
286 params = { metarecord : args.metarecord };
288 params = { metarecord : args.metarecordObject.doc_id() };
291 var req = new Request(FETCH_MR_DESCRIPTORS, params );
294 var data = r.getResultObject();
295 args.recordDescriptors = data.descriptors;
296 args.metarecord = data.metarecord;
297 if( args.type == 'M' && ! args.metarecordObject)
298 args.metarecordObject = findRecord(args.metarecord, 'M');
300 if(doneCallback) doneCallback(args);
306 if(doneCallback) doneCallback(args);
314 function holdsDrawWindow() {
315 swapCanvas($('holds_box'));
316 $('holds_cancel').onclick = function(){ runEvt('common', 'holdUpdateCanceled'), showCanvas() };
317 $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
318 $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
319 holdFetchObjects(null,
323 if(holdArgs.editHold) {
324 hideMe($('holds_submit'));
325 unHideMe($('holds_update'));
326 var req = new Request(FETCH_HOLD_STATUS,
327 G.user.session, holdArgs.editHold.id());
329 holdArgs.status = req.result();
330 _holdsUpdateEditHold();
336 function __holdsDrawWindow() {
338 var rec = holdArgs.recordObject;
339 var vol = holdArgs.volumeObject;
340 var copy = holdArgs.copyObject;
341 var mr = holdArgs.metarecordObject;
343 rec = (rec) ? rec : mr;
345 if(!holdsOrgSelectorBuilt) {
346 holdsBuildOrgSelector(null,0);
347 holdsOrgSelectorBuilt = true;
348 var selector = $('holds_org_selector');
351 var o_loc = findOrgUnit(getOrigLocation());
352 var t = findOrgType(o_loc.ou_type());
353 if( t.can_have_users() )
354 setSelector(selector, o_loc.id());
358 setSelector(selector, holdArgs.recipient.home_ou());
364 var dsel = $('holds_depth_selector');
365 unHideMe($('holds_depth_selector_row'));
366 if(dsel.getElementsByTagName('option').length == 0) {
367 var types = globalOrgTypes;
368 var depth = findOrgDepth(G.user.ws_ou());
371 if(t.depth() > depth) return;
372 insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
379 appendClear($('holds_recipient'), text(
380 holdArgs.recipient.family_name() + ', ' +
381 holdArgs.recipient.first_given_name()));
382 appendClear($('holds_title'), text(rec.title()));
383 appendClear($('holds_author'), text(rec.author()));
385 if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
387 unHideMe($('holds_type_row'));
388 unHideMe($('holds_cn_row'));
389 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
391 if( holdArgs.type == 'V' ) {
392 unHideMe($('holds_is_cn'));
393 hideMe($('holds_is_copy'));
396 hideMe($('holds_is_cn'));
397 unHideMe($('holds_is_copy'));
398 unHideMe($('holds_copy_row'));
399 appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
403 hideMe($('holds_type_row'));
404 hideMe($('holds_copy_row'));
405 hideMe($('holds_cn_row'));
408 removeChildren($('holds_format'));
410 var mods_formats = rec.types_of_resource();
413 if(holdArgs.recordDescriptors)
414 formats = holdArgs.recordDescriptors[0].item_type();
416 if( holdArgs.type == 'T' ) {
417 var desc = grep( holdArgs.recordDescriptors,
419 return (i.record() == holdArgs.record);
422 formats = desc[0].item_type();
425 if( holdArgs.type == 'M' ) {
426 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());
427 mods_formats = data.mods_formats;
428 formats = data.formats;
432 for( var i in mods_formats ) {
433 var res = mods_formats[i];
434 var img = elem("img");
435 setResourcePic(img, res);
436 $('holds_format').appendChild(img);
438 $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
440 $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
441 $('holds_format').appendChild(elem('br'));
445 $('holds_phone').value = holdArgs.recipient.day_phone();
446 appendClear( $('holds_email'), text(holdArgs.recipient.email()));
448 var pref = G.user.prefs[PREF_HOLD_NOTIFY];
451 if( ! pref.match(/email/i) )
452 $('holds_enable_email').checked = false;
454 if( ! pref.match(/phone/i) ) {
455 $('holds_phone').disabled = true;
456 $('holds_enable_phone').checked = false;
460 if(!holdArgs.recipient.email()) {
461 $('holds_enable_email').checked = false;
462 $('holds_enable_email').disabled = true;
465 message = noEmailMessageXUL.cloneNode(true);
466 appendClear($('holds_email'), message);
468 message = noEmailMessage.cloneNode(true);
469 appendClear($('holds_email'), message);
470 $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));
475 if(!$('holds_phone').value)
476 $('holds_enable_phone').checked = false;
478 appendClear($('holds_physical_desc'), text(rec.physical_description()));
480 if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
482 holdsSetFormatSelector();
484 $('holds_frozen_chkbox').checked = false;
485 hideMe($('hold_frozen_thaw_row'));
487 var interval = fetchOrgSettingDefault(holdArgs.recipient.home_ou(), 'circ.hold_expire_interval');
490 secs = interval_to_seconds(interval);
491 var expire = new Date();
492 expire.setTime(expire.getTime() + Number(secs + '000'));
493 dijit.byId('holds_expire_time').setValue(expire);
497 function holdsParseMRFormats(str) {
498 var data = str.split(/-/);
501 var mods_formats = [];
503 for( var i = 0; i < data[0].length; i++ ) {
504 formats.push( data[0].charAt(i) );
505 mods_formats.push( MARCFormatToMods( formats[i] ) );
508 formats = uniquify(formats);
509 mods_formats = uniquify(mods_formats);
513 mods_formats : mods_formats,
520 function holdsSetFormatSelector() {
521 var type = holdArgs.type;
522 if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
524 var data = holdsGetFormats();
525 var avail_formats = data.avail_formats;
526 var sel_formats = data.sel_formats;
527 holdArgs.language = data.lang;
529 unHideMe($('holds_alt_formats_row_extras'));
530 var selector = $('hold_alt_form_selector');
532 for( var i = 0; i < avail_formats.length; i++ ) {
533 var form = avail_formats[i];
534 unHideMe(findSelectorOptByValue(selector, form));
539 function holdsGetFormats() {
543 var sformats = []; // selected formats
545 var type = holdArgs.type;
546 var desc = holdArgs.recordDescriptors;
547 var rec = holdArgs.record;
548 var mrec = holdArgs.metarecord;
552 for( var i = 0; i < desc.length; i++ ) {
554 if( d.record() == holdArgs.record ) {
555 lang = d.item_lang();
556 holdArgs.myFormat = _t_f_2_format(d.item_type(), d.item_form());
557 sformats.push(holdArgs.myFormat);
563 for( var i = 0; i < desc.length; i++ ) {
565 if( d.item_lang() != lang ) continue;
566 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
569 formats = uniquify(formats);
573 avail_formats : formats,
574 sel_formats : sformats
580 function _t_f_2_format(type, form) {
581 if( form == 'd' ) return 'at-d';
582 return (type == 'a' || type == 't') ? 'at' :
583 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
586 function holdsSetSelectedFormats() {
588 var cn = $('holds_alt_formats_row').className;
589 if( cn && cn.match(/hide_me/) ) return;
591 var selector = $('hold_alt_form_selector');
592 var vals = getSelectedList(selector);
594 if(vals.length == 0) return;
598 if( contains(vals, 'at-d') ) {
599 if( contains(vals, 'at') )
604 if( contains(vals, 'at') )
608 for( var i = 0; i < vals.length; i++ ) {
610 if( !val.match(/at/) ) fstring = val + fstring;
613 if( holdArgs.language ) {
614 if( fstring.match(/-/) )
615 fstring = fstring + '-' + holdArgs.language;
617 fstring = fstring + '--' + holdArgs.language;
625 function holdsCheckPossibility(pickuplib, hold, recurse) {
628 titleid : holdArgs.record,
629 volume_id : holdArgs.volume,
630 copy_id : holdArgs.copy,
631 hold_type : holdArgs.type,
632 patronid : holdArgs.recipient.id(),
634 pickup_lib : pickuplib
638 /* if we're calling create again (recursing),
639 we know that the hold possibility check already succeeded */
640 holdHandleCreateResponse({_recurse:true, _hold:hold}, true );
643 _debug("hold possible args = "+js2JSON(args));
645 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );
647 req.request.alertEvent = false;
648 req.request._hold = hold;
649 req.request._recurse = recurse;
650 req.callback(holdHandleCreateResponse);
656 function holdsBuildOrgSelector(node) {
658 if(!node) node = globalOrgTree;
659 if(!isTrue(node.opac_visible())) return;
661 var selector = $('holds_org_selector');
662 var index = selector.options.length;
664 var type = findOrgType(node.ou_type());
665 var indent = type.depth() - 1;
666 var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
667 if(!type.can_have_users()) {
669 addCSSClass(opt, 'disabled_option');
672 for( var i in node.children() ) {
673 var child = node.children()[i];
674 if(child) holdsBuildOrgSelector(child);
678 function holdsBuildHoldFromWindow() {
680 var org = getSelectorVal($('holds_org_selector'));
681 var node = findOrgUnit(org);
682 var ntype = findOrgType(node.ou_type());
683 if(!ntype.can_have_users()) {
684 alertId('holds_pick_good_org');
688 var hold = new ahr();
689 if(holdArgs.editHold) {
690 hold = holdArgs.editHold;
691 holdArgs.editHold = null;
694 if( $('holds_enable_phone').checked ) {
695 var phone = $('holds_phone').value;
696 if( !phone || !phone.match(REGEX_PHONE) ) {
697 alert($('holds_bad_phone').innerHTML);
700 hold.phone_notify(phone);
703 hold.phone_notify("");
706 if( $('holds_enable_email').checked )
707 hold.email_notify(1);
709 hold.email_notify(0);
713 switch(holdArgs.type) {
715 target = holdArgs.metarecord; break;
717 target = holdArgs.record; break;
719 target = holdArgs.volume; break;
721 target = holdArgs.copy; break;
726 hold.pickup_lib(org);
727 //hold.request_lib(org);
728 hold.requestor(holdArgs.requestor.id());
729 hold.usr(holdArgs.recipient.id());
731 hold.hold_type(holdArgs.type);
733 var expDate = dijit.byId('holds_expire_time').getValue();
735 var expireDate = dojo.date.stamp.toISOString(expDate);
736 expireDate = holdsVerifyThawDate(expireDate);
738 hold.expire_time(expireDate);
743 // see if this hold should be frozen and for how long
744 if($('holds_frozen_chkbox').checked) {
746 unHideMe($('hold_frozen_thaw_row'));
747 thawDate = dojo.date.stamp.toISOString(dijit.byId('holds_frozen_thaw_input').getValue());
749 thawDate = holdsVerifyThawDate(thawDate);
751 hold.thaw_date(thawDate);
755 hold.thaw_date(null);
759 hold.thaw_date(null);
762 //check for alternate hold formats
763 var fstring = holdsSetSelectedFormats();
766 hold.holdable_formats(fstring);
767 hold.target(holdArgs.metarecord);
772 function holdsPlaceHold(hold, recurse) {
774 swapCanvas($('check_holds_box'));
775 holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
779 function holdHandleCreateResponse(r, recurse) {
782 var res = r.getResultObject();
783 if(checkILSEvent(res) || res.success != 1) {
784 if(res.success != 1) {
785 alert($('hold_not_allowed').innerHTML);
787 if( res.textcode == 'PATRON_BARRED' ) {
788 alertId('hold_failed_patron_barred');
790 alert($('hold_not_allowed').innerHTML);
793 swapCanvas($('holds_box'));
796 r._hold.selection_depth(res.depth);
799 holdCreateHold(r._recurse, r._hold);
803 function holdCreateHold( recurse, hold ) {
804 var method = CREATE_HOLD;
805 if(recurse) method = CREATE_HOLD_OVERRIDE;
806 var req = new Request( method, holdArgs.requestor.session, hold );
807 req.request.alertEvent = false;
809 var res = req.result();
810 holdProcessResult(hold, res, recurse);
814 runEvt('common', 'holdUpdated');
818 function holdProcessResult( hold, res, recurse ) {
821 alert($('holds_success').innerHTML);
827 alert($('holds_failure').innerHTML);
831 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
832 if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {
833 if( confirm($('hold_dup_exists_override').innerHTML) ) {
834 return holdsPlaceHold(hold, true);
838 return alert($('hold_dup_exists').innerHTML);
842 alert($('holds_failure').innerHTML);
847 function holdsCancel(holdid, user) {
848 if(!user) user = G.user;
849 var req = new Request(CANCEL_HOLD, user.session, holdid, /* Patron via OPAC */ 6);
852 runEvt('common', 'holdUpdated');
855 function holdsUpdate(hold, user) {
856 if(!user) user = G.user;
857 var req = new Request(UPDATE_HOLD, user.session, hold);
859 var x = req.result(); // cause an exception if there is one
860 runEvt('common', 'holdUpdated');
863 /* verify that the thaw date is valid and after today */
864 function holdsVerifyThawDate(dateString, isGreater) {
865 thawDate = dojo.date.stamp.fromISOString(dateString);
868 if(dojo.date.compare(thawDate) > 0) {
869 return dojo.date.stamp.toISOString(thawDate);
872 return dojo.date.stamp.toISOString(thawDate);
878 function holdsVerifyThawDateUI(element) {
879 value = dojo.date.stamp.toISOString(dijit.byId(element).getValue());
882 removeCSSClass($(element), 'invalid_field');
886 if(!holdsVerifyThawDate(value, true)) {
887 addCSSClass($(element), 'invalid_field');
889 removeCSSClass($(element), 'invalid_field');