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);
61 holdArgs.recipient = user;
68 * record, volume, copy (ids)
69 * request, recipient, editHold (objects)
72 function holdsDrawEditor(args) {
74 holdArgs = (args) ? args : holdArgs;
77 noEmailMessage = $('holds_email').removeChild($('holds.no_email'));
79 if(!noEmailMessageXUL)
80 noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));
82 if(isXUL() && holdArgs.recipient == null
83 && holdArgs.editHold == null) {
88 if(!holdArgs.recipient) holdArgs.recipient = G.user;
89 if(!holdArgs.requestor) holdArgs.requestor = G.user;
91 if(!(holdArgs.requestor && holdArgs.requestor.session)) {
92 detachAllEvt('common','locationChanged');
93 attachEvt('common','loggedIn', holdsDrawEditor)
98 if(holdArgs.editHold) // flesh the args with the existing hold
99 holdArgsFromHold(holdArgs.editHold, holdArgs);
105 // updates the edit window with the existing hold's data
106 function _holdsUpdateEditHold() {
108 var hold = holdArgs.editHold;
109 var qstats = holdArgs.status;
111 var orgsel = $('holds_org_selector');
112 var frozenbox = $('holds_frozen_chkbox');
114 setSelector(orgsel, hold.pickup_lib());
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;
123 var orgs = fetchPermOrgs('UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF');
125 orgsel.disabled = true;
128 orgsel.disabled = false;
129 frozenbox.disabled = false;
133 $('holds_submit').onclick = holdsEditHold;
134 $('holds_update').onclick = holdsEditHold;
136 if(hold.phone_notify()) {
137 $('holds_enable_phone').checked = true;
138 $('holds_phone').value = hold.phone_notify();
141 $('holds_phone').disabled = true;
142 $('holds_enable_phone').checked = false;
145 if(isTrue(hold.email_notify())) {
146 $('holds_enable_email').checked = true;
149 $('holds_enable_email').checked = false;
152 dijit.byId('holds_expire_time').setValue(dojo.date.stamp.fromISOString(hold.expire_time()));
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()));
161 dijit.byId('holds_frozen_thaw_input').setValue('');
164 frozenbox.checked = false;
165 dijit.byId('holds_frozen_thaw_input').setValue('');
166 hideMe($('hold_frozen_thaw_row'));
170 function holdsEditHold() {
171 var hold = holdsBuildHoldFromWindow();
175 if(holdArgs.onComplete)
176 holdArgs.onComplete(hold);
179 function holdArgsFromHold(hold, oargs) {
180 var args = (oargs) ? oargs : {};
181 args.type = hold.hold_type();
182 var target = hold.target();
186 args.metarecord = target;
189 args.record = target;
192 args.volume = target;
201 function holdFetchObjects(hold, doneCallback) {
203 var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
205 var type = args.type;
209 if( args.copyObject ) {
211 args.copy = args.copyObject.id();
212 args.volume = args.copyObject.call_number();
213 _h_set_vol(args, doneCallback);
216 var creq = new Request(FETCH_COPY, args.copy);
220 var cp = r.getResultObject();
221 args.copyObject = cp;
222 args.volume = args.copyObject.call_number();
223 _h_set_vol(args, doneCallback);
230 _h_set_vol(args, doneCallback);
234 _h_set_rec(args, doneCallback);
236 _h_set_rec_descriptors(args, doneCallback);
244 function _h_set_vol(args, doneCallback) {
246 if( args.volumeObject ) {
247 args.volume = args.volumeObject.id();
248 args.record = args.volumeObject.record();
249 _h_set_rec(args, doneCallback);
253 var vreq = new Request(FETCH_VOLUME, args.volume);
256 var vol = r.getResultObject();
257 args.volumeObject = vol;
258 args.record = vol.record();
259 _h_set_rec(args, doneCallback);
266 function _h_set_rec(args, doneCallback) {
268 if(args.recordObject)
269 args.record = args.recordObject.doc_id();
271 args.recordObject = findRecord( args.record, 'T' );
273 if( args.type == 'T' || args.type == 'M' )
274 _h_set_rec_descriptors(args, doneCallback);
276 if(doneCallback) doneCallback(args);
280 function _h_set_rec_descriptors(args, doneCallback) {
282 // grab the list of record desciptors attached to this records metarecord
283 if( ! args.recordDescriptors ) {
286 if (args.type == 'M') {
287 if( !args.metarecord && args.record) {
288 params.metarecord = args.metarecord = args.record;
291 params = { metarecord : args.metarecordObject.doc_id() };
294 params = { record: args.record };
297 if( ! args.record ) {
298 if( args.metarecord )
299 params = { metarecord : args.metarecord };
301 params = { metarecord : args.metarecordObject.doc_id() };
304 var req = new Request(FETCH_MR_DESCRIPTORS, params );
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');
313 if(doneCallback) doneCallback(args);
319 if(doneCallback) doneCallback(args);
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,
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());
342 holdArgs.status = req.result();
343 _holdsUpdateEditHold();
349 function __holdsDrawWindow() {
351 var rec = holdArgs.recordObject;
352 var vol = holdArgs.volumeObject;
353 var copy = holdArgs.copyObject;
354 var mr = holdArgs.metarecordObject;
356 rec = (rec) ? rec : mr;
358 if(!holdsOrgSelectorBuilt) {
359 holdsBuildOrgSelector(null,0);
360 holdsOrgSelectorBuilt = true;
361 var selector = $('holds_org_selector');
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());
371 setSelector(selector, holdArgs.recipient.home_ou());
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());
384 if(t.depth() > depth) return;
385 insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
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()));
398 if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
400 unHideMe($('holds_type_row'));
401 unHideMe($('holds_cn_row'));
402 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
404 if( holdArgs.type == 'V' ) {
405 unHideMe($('holds_is_cn'));
406 hideMe($('holds_is_copy'));
409 hideMe($('holds_is_cn'));
410 unHideMe($('holds_is_copy'));
411 unHideMe($('holds_copy_row'));
412 appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
416 hideMe($('holds_type_row'));
417 hideMe($('holds_copy_row'));
418 hideMe($('holds_cn_row'));
421 removeChildren($('holds_format'));
423 var mods_formats = rec.types_of_resource();
426 if(holdArgs.recordDescriptors)
427 formats = holdArgs.recordDescriptors[0].item_type();
429 if( holdArgs.type == 'T' ) {
430 var desc = grep( holdArgs.recordDescriptors,
432 return (i.record() == holdArgs.record);
435 formats = desc[0].item_type();
438 if( holdArgs.type == 'M' ) {
440 if(holdArgs.editHold){
441 mr_formats = holdArgs.editHold.holdable_formats();
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();
450 for(var desc in holdArgs.recordDescriptors){
451 if (!holdArgs.recordDescriptors[desc].item_form()) continue;
456 mr_formats += holdArgs.recordDescriptors[desc].item_form();
462 var data = holdsParseMRFormats(mr_formats);
463 mods_formats = data.mods_formats;
464 formats = data.formats;
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);
474 $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
476 $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
477 $('holds_format').appendChild(elem('br'));
481 $('holds_phone').value = holdArgs.recipient.day_phone();
482 appendClear( $('holds_email'), text(holdArgs.recipient.email()));
484 var pref = holdArgs.recipient.prefs[PREF_HOLD_NOTIFY];
487 if( ! pref.match(/email/i) ) {
488 $('holds_enable_email').checked = false;
490 $('holds_enable_email').checked = true;
493 if( ! pref.match(/phone/i) ) {
494 $('holds_phone').disabled = true;
495 $('holds_enable_phone').checked = false;
497 $('holds_phone').disabled = false;
498 $('holds_enable_phone').checked = true;
502 if(!holdArgs.recipient.email()) {
503 $('holds_enable_email').checked = false;
504 $('holds_enable_email').disabled = true;
507 message = noEmailMessageXUL.cloneNode(true);
508 appendClear($('holds_email'), message);
510 message = noEmailMessage.cloneNode(true);
511 appendClear($('holds_email'), message);
512 $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));
517 if(!$('holds_phone').value)
518 $('holds_enable_phone').checked = false;
520 appendClear($('holds_physical_desc'), text(rec.physical_description()));
522 if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
524 holdsSetFormatSelector();
526 $('holds_frozen_chkbox').checked = false;
527 hideMe($('hold_frozen_thaw_row'));
529 var interval = fetchOrgSettingDefault(holdArgs.recipient.home_ou(), 'circ.hold_expire_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);
539 function holdsParseMRFormats(str) {
540 var data = str.split(/-/);
543 var mods_formats = [];
545 for( var i = 0; i < data[0].length; i++ ) {
546 formats.push( data[0].charAt(i) );
547 mods_formats.push( MARCFormatToMods( formats[i] ) );
550 formats = uniquify(formats);
551 mods_formats = uniquify(mods_formats);
555 mods_formats : mods_formats,
562 function holdsSetFormatSelector() {
563 var type = holdArgs.type;
564 if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
566 var data = holdsGetFormats();
567 var avail_formats = data.avail_formats;
568 var sel_formats = data.sel_formats;
569 holdArgs.language = data.lang;
571 hideMe($('holds_alt_formats_row_extras'));
572 unHideMe($('holds_alt_formats_row'));
574 unHideMe($('holds_alt_formats_row_extras'));
577 var selector = $('hold_alt_form_selector');
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]);
584 for( var i = 0; i < avail_formats.length; i++ ) {
585 var form = avail_formats[i];
586 var opt = findFormatSelectorOptByParts(selector,form);
587 if(type=='M') opt.selected=true;
592 function findFormatSelectorOptByParts( sel, val ) {
593 var parts = val.split('-');
594 for( var i = 0; i < sel.options.length; i++ ) {
595 var opt = sel.options[i];
596 var oval = opt.value;
597 var oparts = oval.split('-');
598 if( oparts[0].indexOf(parts[0]) > -1 && ((!oparts[1] && !parts[1]) || (oparts[1].indexOf(parts[1]) > -1)) ) return opt;
603 function holdsGetFormats() {
607 var sformats = []; // selected formats
609 var type = holdArgs.type;
610 var desc = holdArgs.recordDescriptors;
611 var rec = holdArgs.record;
612 var mrec = holdArgs.metarecord;
614 for( var i = 0; i < desc.length; i++ ) {
616 if( type == 'T' && d.item_lang() != lang ) continue;
617 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
620 formats = uniquify(formats);
624 for( var i = 0; i < desc.length; i++ ) {
626 if( d.record() == holdArgs.record ) {
627 lang = d.item_lang();
628 holdArgs.myFormat = _t_f_2_format(d.item_type(), d.item_form());
629 sformats.push(holdArgs.myFormat);
633 } else if( type =='M') {
635 // All available formats are selected by default in MR holds
636 for( var i = 0; i < formats.length; i++ ) {
637 sformats.push(formats[i]);
643 avail_formats : formats,
644 sel_formats : sformats
650 function _t_f_2_format(type, form) {
651 if( (type == 'a' || type == 't') && form == 's' ) return 'at-s';
652 if( form == 'd' ) return 'at-d';
653 return (type == 'a' || type == 't') ? 'at' :
654 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
657 function holdsSetSelectedFormats() {
659 var cn = $('holds_alt_formats_row').className;
660 if( cn && cn.match(/hide_me/) ) return;
662 var selector = $('hold_alt_form_selector');
663 var vals = getSelectedList(selector);
665 if(vals.length == 0) return;
669 if( contains(vals, 'at-d') || contains(vals, 'at-s')) {
670 if( contains(vals, 'at') ) {
672 } else if (contains(vals, 'at-s') && contains(vals, 'at-d')) {
674 } else if (!contains(vals, 'at-s')) {
681 for( var i = 0; i < vals.length; i++ ) {
683 if( !val.match(/at/) ) fstring = val + fstring;
686 if( holdArgs.language ) {
687 if( fstring.match(/-/) )
688 fstring = fstring + '-' + holdArgs.language;
690 fstring = fstring + '--' + holdArgs.language;
698 function holdsCheckPossibility(pickuplib, hold, recurse) {
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(),
708 pickup_lib : pickuplib
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 );
717 _debug("hold possible args = "+js2JSON(args));
719 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );
721 req.request.alertEvent = false;
722 req.request._hold = hold;
723 req.request._recurse = recurse;
724 req.callback(holdHandleCreateResponse);
730 function holdsBuildOrgSelector(node) {
732 if(!node) node = globalOrgTree;
733 if(!isTrue(node.opac_visible())) return;
735 var selector = $('holds_org_selector');
736 var index = selector.options.length;
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()) {
743 addCSSClass(opt, 'disabled_option');
746 for( var i in node.children() ) {
747 var child = node.children()[i];
748 if(child) holdsBuildOrgSelector(child);
752 function holdsBuildHoldFromWindow() {
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');
762 var hold = new ahr();
763 if(holdArgs.editHold) {
764 hold = holdArgs.editHold;
765 holdArgs.editHold = null;
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);
774 hold.phone_notify(phone);
777 hold.phone_notify("");
780 if( $('holds_enable_email').checked )
781 hold.email_notify(1);
783 hold.email_notify(0);
787 switch(holdArgs.type) {
789 target = holdArgs.metarecord; break;
791 target = holdArgs.record; break;
793 target = holdArgs.volume; break;
795 target = holdArgs.copy; break;
800 hold.pickup_lib(org);
801 //hold.request_lib(org);
802 hold.requestor(holdArgs.requestor.id());
803 hold.usr(holdArgs.recipient.id());
805 hold.hold_type(holdArgs.type);
807 var expDate = dijit.byId('holds_expire_time').getValue();
809 var expireDate = dojo.date.stamp.toISOString(expDate);
810 expireDate = holdsVerifyThawDate(expireDate);
812 hold.expire_time(expireDate);
817 // see if this hold should be frozen and for how long
818 if($('holds_frozen_chkbox').checked) {
820 unHideMe($('hold_frozen_thaw_row'));
821 thawDate = dojo.date.stamp.toISOString(dijit.byId('holds_frozen_thaw_input').getValue());
823 thawDate = holdsVerifyThawDate(thawDate);
825 hold.thaw_date(thawDate);
829 hold.thaw_date(null);
833 hold.thaw_date(null);
836 //check for alternate hold formats
837 var fstring = holdsSetSelectedFormats();
840 hold.holdable_formats(fstring);
841 hold.target(holdArgs.metarecord);
846 function holdsPlaceHold(hold, recurse) {
848 swapCanvas($('check_holds_box'));
849 holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
853 function holdHandleCreateResponse(r, recurse) {
856 var res = r.getResultObject();
857 if(checkILSEvent(res) || res.success != 1) {
858 if(res.success != 1) {
859 alert($('hold_not_allowed').innerHTML);
861 if( res.textcode == 'PATRON_BARRED' ) {
862 alertId('hold_failed_patron_barred');
864 alert($('hold_not_allowed').innerHTML);
867 swapCanvas($('holds_box'));
870 r._hold.selection_depth(res.depth);
873 holdCreateHold(r._recurse, r._hold);
877 function holdCreateHold( recurse, hold ) {
878 var method = CREATE_HOLD;
879 if(recurse) method = CREATE_HOLD_OVERRIDE;
880 var req = new Request( method, holdArgs.requestor.session, hold );
881 req.request.alertEvent = false;
883 var res = req.result();
884 holdProcessResult(hold, res, recurse);
888 runEvt('common', 'holdUpdated');
892 function holdProcessResult( hold, res, recurse ) {
894 if( res && res > -1 ) {
895 alert($('holds_success').innerHTML);
897 if(isXUL() && typeof xulG.opac_hold_placed == 'function')
898 xulG.opac_hold_placed(res);
903 alert($('holds_failure').innerHTML);
907 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
908 if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {
909 if( confirm($('hold_dup_exists_override').innerHTML) ) {
910 return holdsPlaceHold(hold, true);
915 return alert($('hold_dup_exists').innerHTML);
919 if( grep(res, function(e) { return (e.textcode == 'HOLD_ITEM_CHECKED_OUT'); }) ) {
920 if( fetchPermOrgs('HOLD_ITEM_CHECKED_OUT.override')[0] != -1 ) {
921 if( confirm($('hold_checked_out_override').innerHTML) ) {
922 return holdsPlaceHold(hold, true);
927 return alert($('hold_checked_out').innerHTML);
932 alert($('holds_failure').innerHTML);
937 function holdsCancel(holdid, user) {
938 if(!user) user = G.user;
939 var req = new Request(CANCEL_HOLD, user.session, holdid, /* Patron via OPAC */ 6);
942 runEvt('common', 'holdUpdated');
945 function holdsUpdate(hold, user) {
946 if(!user) user = G.user;
947 var req = new Request(UPDATE_HOLD, user.session, hold);
949 var x = req.result(); // cause an exception if there is one
950 runEvt('common', 'holdUpdated');
953 /* verify that the thaw date is valid and after today */
954 function holdsVerifyThawDate(dateString, isGreater) {
955 thawDate = dojo.date.stamp.fromISOString(dateString);
958 if(dojo.date.compare(thawDate) > 0) {
959 return dojo.date.stamp.toISOString(thawDate);
962 return dojo.date.stamp.toISOString(thawDate);
968 function holdsVerifyThawDateUI(element) {
969 value = dojo.date.stamp.toISOString(dijit.byId(element).getValue());
972 removeCSSClass($(element), 'invalid_field');
976 if(!holdsVerifyThawDate(value, true)) {
977 addCSSClass($(element), 'invalid_field');
979 removeCSSClass($(element), 'invalid_field');