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() {
15 swapCanvas($('xulholds_box'));
16 $('xul_recipient_barcode').focus();
17 $('xul_recipient_barcode').onkeypress = function(evt)
18 {if(userPressedEnter(evt)) { _holdsHandleStaff(); } };
19 $('xul_recipient_barcode_submit').onclick = _holdsHandleStaff;
20 $('xul_recipient_me').onclick = _holdsHandleStaffMe;
22 $('xul_recipient_barcode').onkeyup = function(evt) {
23 if($('xul_recipient_barcode').value == '')
24 $('xul_recipient_me').disabled = false;
26 $('xul_recipient_me').disabled = true;
30 $('holds_frozen_thaw_input').onkeyup =
31 function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}
33 function _holdsHandleStaffMe() {
34 holdArgs.recipient = G.user;
38 function _holdsHandleStaff() {
39 var barcode = $('xul_recipient_barcode').value;
40 var user = grabUserByBarcode( G.user.session, barcode );
43 if(evt = checkILSEvent(user)) {
48 if(!barcode || !user) {
49 alertId('holds_invalid_recipient', barcode);
53 holdArgs.recipient = user;
60 * record, volume, copy (ids)
61 * request, recipient, editHold (objects)
64 function holdsDrawEditor(args) {
66 holdArgs = (args) ? args : holdArgs;
69 noEmailMessage = $('holds_email').removeChild($('holds.no_email'));
71 if(!noEmailMessageXUL)
72 noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));
74 if(isXUL() && holdArgs.recipient == null
75 && holdArgs.editHold == null) {
80 if(!holdArgs.recipient) holdArgs.recipient = G.user;
81 if(!holdArgs.requestor) holdArgs.requestor = G.user;
83 if(!(holdArgs.requestor && holdArgs.requestor.session)) {
84 detachAllEvt('common','locationChanged');
85 attachEvt('common','loggedIn', holdsDrawEditor)
90 if(holdArgs.editHold) // flesh the args with the existing hold
91 holdArgsFromHold(holdArgs.editHold, holdArgs);
97 // updates the edit window with the existing hold's data
98 function _holdsUpdateEditHold() {
100 var hold = holdArgs.editHold;
101 var status = holdArgs.status;
103 var orgsel = $('holds_org_selector');
104 var frozenbox = $('holds_frozen_chkbox');
106 setSelector(orgsel, hold.pickup_lib());
108 if( hold.capture_time() || status > 2 ) {
109 orgsel.disabled = true;
110 frozenbox.disabled = true;
111 $('holds_frozen_thaw_input').disabled = true;
114 orgsel.disabled = false;
115 frozenbox.disabled = false;
119 $('holds_submit').onclick = holdsEditHold;
120 $('holds_update').onclick = holdsEditHold;
122 if(hold.phone_notify()) {
123 $('holds_enable_phone').checked = true;
124 $('holds_phone').value = hold.phone_notify();
127 $('holds_phone').disabled = true;
128 $('holds_enable_phone').checked = false;
131 if(isTrue(hold.email_notify())) {
132 $('holds_enable_email').checked = true;
135 $('holds_enable_email').checked = false;
138 /* populate the hold freezing info */
139 if(!frozenbox.disabled && isTrue(hold.frozen())) {
140 frozenbox.checked = true;
141 unHideMe($('hold_frozen_thaw_row'));
142 if(hold.thaw_date()) {
143 $('holds_frozen_thaw_input').value = hold.thaw_date();
145 $('holds_frozen_thaw_input').value = '';
148 frozenbox.checked = false;
149 $('holds_frozen_thaw_input').value = '';
150 hideMe($('hold_frozen_thaw_row'));
154 function holdsEditHold() {
155 var hold = holdsBuildHoldFromWindow();
159 if(holdArgs.onComplete)
160 holdArgs.onComplete(hold);
163 function holdArgsFromHold(hold, oargs) {
164 var args = (oargs) ? oargs : {};
165 args.type = hold.hold_type();
166 var target = hold.target();
170 args.metarecord = target;
173 args.record = target;
176 args.volume = target;
185 function holdFetchObjects(hold, doneCallback) {
187 var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
189 var type = args.type;
193 if( args.copyObject ) {
195 args.copy = args.copyObject.id();
196 args.volume = args.copyObject.call_number();
197 _h_set_vol(args, doneCallback);
200 var creq = new Request(FETCH_COPY, args.copy);
204 var cp = r.getResultObject();
205 args.copyObject = cp;
206 args.volume = args.copyObject.call_number();
207 _h_set_vol(args, doneCallback);
214 _h_set_vol(args, doneCallback);
218 _h_set_rec(args, doneCallback);
220 _h_set_rec_descriptors(args, doneCallback);
228 function _h_set_vol(args, doneCallback) {
230 if( args.volumeObject ) {
231 args.volume = args.volumeObject.id();
232 args.record = args.volumeObject.record();
233 _h_set_rec(args, doneCallback);
237 var vreq = new Request(FETCH_VOLUME, args.volume);
240 var vol = r.getResultObject();
241 args.volumeObject = vol;
242 args.record = vol.record();
243 _h_set_rec(args, doneCallback);
250 function _h_set_rec(args, doneCallback) {
252 if(args.recordObject)
253 args.record = args.recordObject.doc_id();
255 args.recordObject = findRecord( args.record, 'T' );
257 if( args.type == 'T' || args.type == 'M' )
258 _h_set_rec_descriptors(args, doneCallback);
260 if(doneCallback) doneCallback(args);
264 function _h_set_rec_descriptors(args, doneCallback) {
266 // grab the list of record desciptors attached to this records metarecord
267 if( ! args.recordDescriptors ) {
268 var params = { record: args.record };
270 if( ! args.record ) {
271 if( args.metarecord )
272 params = { metarecord : args.metarecord };
274 params = { metarecord : args.metarecordObject.doc_id() };
277 var req = new Request(FETCH_MR_DESCRIPTORS, params );
280 var data = r.getResultObject();
281 args.recordDescriptors = data.descriptors;
282 args.metarecord = data.metarecord;
283 if( args.type == 'M' && ! args.metarecordObject)
284 args.metarecordObject = findRecord(args.metarecord, 'M');
286 if(doneCallback) doneCallback(args);
292 if(doneCallback) doneCallback(args);
300 function holdsDrawWindow() {
301 swapCanvas($('holds_box'));
302 $('holds_cancel').onclick = function(){ runEvt('common', 'holdUpdateCanceled'), showCanvas() };
303 $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
304 $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
305 holdFetchObjects(null,
309 if(holdArgs.editHold) {
310 hideMe($('holds_submit'));
311 unHideMe($('holds_update'));
312 var req = new Request(FETCH_HOLD_STATUS,
313 G.user.session, holdArgs.editHold.id());
315 holdArgs.status = req.result();
316 _holdsUpdateEditHold();
322 function __holdsDrawWindow() {
324 var rec = holdArgs.recordObject;
325 var vol = holdArgs.volumeObject;
326 var copy = holdArgs.copyObject;
327 var mr = holdArgs.metarecordObject;
329 rec = (rec) ? rec : mr;
331 if(!holdsOrgSelectorBuilt) {
332 holdsBuildOrgSelector(null,0);
333 holdsOrgSelectorBuilt = true;
334 var selector = $('holds_org_selector');
337 var o_loc = findOrgUnit(getOrigLocation());
338 var t = findOrgType(o_loc.ou_type());
339 if( t.can_have_users() )
340 setSelector(selector, o_loc.id());
344 setSelector(selector, holdArgs.recipient.home_ou());
350 var dsel = $('holds_depth_selector');
351 unHideMe($('holds_depth_selector_row'));
352 if(dsel.getElementsByTagName('option').length == 0) {
353 var types = globalOrgTypes;
354 var depth = findOrgDepth(G.user.ws_ou());
357 if(t.depth() > depth) return;
358 insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
365 appendClear($('holds_recipient'), text(
366 holdArgs.recipient.family_name() + ', ' +
367 holdArgs.recipient.first_given_name()));
368 appendClear($('holds_title'), text(rec.title()));
369 appendClear($('holds_author'), text(rec.author()));
371 if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
373 unHideMe($('holds_type_row'));
374 unHideMe($('holds_cn_row'));
375 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
377 if( holdArgs.type == 'V' ) {
378 unHideMe($('holds_is_cn'));
379 hideMe($('holds_is_copy'));
382 hideMe($('holds_is_cn'));
383 unHideMe($('holds_is_copy'));
384 unHideMe($('holds_copy_row'));
385 appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
389 hideMe($('holds_type_row'));
390 hideMe($('holds_copy_row'));
391 hideMe($('holds_cn_row'));
394 removeChildren($('holds_format'));
396 var mods_formats = rec.types_of_resource();
399 if(holdArgs.recordDescriptors)
400 formats = holdArgs.recordDescriptors[0].item_type();
402 if( holdArgs.type == 'T' ) {
403 var desc = grep( holdArgs.recordDescriptors,
405 return (i.record() == holdArgs.record);
408 formats = desc[0].item_type();
411 if( holdArgs.type == 'M' ) {
412 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());
413 mods_formats = data.mods_formats;
414 formats = data.formats;
418 for( var i in mods_formats ) {
419 var res = mods_formats[i];
420 var img = elem("img");
421 setResourcePic(img, res);
422 $('holds_format').appendChild(img);
424 $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
426 $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
427 $('holds_format').appendChild(elem('br'));
431 $('holds_phone').value = holdArgs.recipient.day_phone();
432 appendClear( $('holds_email'), text(holdArgs.recipient.email()));
434 var pref = G.user.prefs[PREF_HOLD_NOTIFY];
437 if( ! pref.match(/email/i) )
438 $('holds_enable_email').checked = false;
440 if( ! pref.match(/phone/i) ) {
441 $('holds_phone').disabled = true;
442 $('holds_enable_phone').checked = false;
446 //if(!G.user.email()) {
447 if(!holdArgs.recipient.email()) {
448 $('holds_enable_email').checked = false;
449 $('holds_enable_email').disabled = true;
452 message = noEmailMessageXUL.cloneNode(true);
453 appendClear($('holds_email'), message);
455 message = noEmailMessage.cloneNode(true);
456 appendClear($('holds_email'), message);
457 $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));
462 if(!$('holds_phone').value)
463 $('holds_enable_phone').checked = false;
465 appendClear($('holds_physical_desc'), text(rec.physical_description()));
467 if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
469 holdsSetFormatSelector();
472 function holdsParseMRFormats(str) {
473 var data = str.split(/-/);
476 var mods_formats = [];
478 for( var i = 0; i < data[0].length; i++ ) {
479 formats.push( data[0].charAt(i) );
480 mods_formats.push( MARCFormatToMods( formats[i] ) );
483 formats = uniquify(formats);
484 mods_formats = uniquify(mods_formats);
488 mods_formats : mods_formats,
495 function holdsSetFormatSelector() {
496 var type = holdArgs.type;
497 if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
499 var data = holdsGetFormats();
500 var avail_formats = data.avail_formats;
501 var sel_formats = data.sel_formats;
502 holdArgs.language = data.lang;
504 unHideMe($('holds_alt_formats_row_extras'));
505 var selector = $('hold_alt_form_selector');
507 for( var i = 0; i < avail_formats.length; i++ ) {
508 var form = avail_formats[i];
509 unHideMe(findSelectorOptByValue(selector, form));
514 function holdsGetFormats() {
518 var sformats = []; // selected formats
520 var type = holdArgs.type;
521 var desc = holdArgs.recordDescriptors;
522 var rec = holdArgs.record;
523 var mrec = holdArgs.metarecord;
527 for( var i = 0; i < desc.length; i++ ) {
529 if( d.record() == holdArgs.record ) {
530 lang = d.item_lang();
531 holdArgs.myFormat = _t_f_2_format(d.item_type(), d.item_form());
532 sformats.push(holdArgs.myFormat);
538 for( var i = 0; i < desc.length; i++ ) {
540 if( d.item_lang() != lang ) continue;
541 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
544 formats = uniquify(formats);
548 avail_formats : formats,
549 sel_formats : sformats
555 function _t_f_2_format(type, form) {
556 if( form == 'd' ) return 'at-d';
557 return (type == 'a' || type == 't') ? 'at' :
558 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
561 function holdsSetSelectedFormats() {
563 var cn = $('holds_alt_formats_row').className;
564 if( cn && cn.match(/hide_me/) ) return;
566 var selector = $('hold_alt_form_selector');
567 var vals = getSelectedList(selector);
569 if(vals.length == 0) return;
573 if( contains(vals, 'at-d') ) {
574 if( contains(vals, 'at') )
579 if( contains(vals, 'at') )
583 for( var i = 0; i < vals.length; i++ ) {
585 if( !val.match(/at/) ) fstring = val + fstring;
588 if( holdArgs.language ) {
589 if( fstring.match(/-/) )
590 fstring = fstring + '-' + holdArgs.language;
592 fstring = fstring + '--' + holdArgs.language;
600 function holdsCheckPossibility(pickuplib, hold, recurse) {
603 titleid : holdArgs.record,
604 volume_id : holdArgs.volume,
605 copy_id : holdArgs.copy,
606 hold_type : holdArgs.type,
607 patronid : holdArgs.recipient.id(),
609 pickup_lib : pickuplib
613 /* if we're calling create again (recursing),
614 we know that the hold possibility check already succeeded */
615 holdHandleCreateResponse({_recurse:true, _hold:hold}, true );
618 _debug("hold possible args = "+js2JSON(args));
620 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );
622 req.request.alertEvent = false;
623 req.request._hold = hold;
624 req.request._recurse = recurse;
625 req.callback(holdHandleCreateResponse);
631 function holdsBuildOrgSelector(node) {
633 if(!node) node = globalOrgTree;
634 if(!isTrue(node.opac_visible())) return;
636 var selector = $('holds_org_selector');
637 var index = selector.options.length;
639 var type = findOrgType(node.ou_type());
640 var indent = type.depth() - 1;
641 var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
642 if(!type.can_have_users()) {
644 addCSSClass(opt, 'disabled_option');
647 for( var i in node.children() ) {
648 var child = node.children()[i];
649 if(child) holdsBuildOrgSelector(child);
653 function holdsBuildHoldFromWindow() {
655 var org = getSelectorVal($('holds_org_selector'));
656 var node = findOrgUnit(org);
657 var ntype = findOrgType(node.ou_type());
658 if(!ntype.can_have_users()) {
659 alertId('holds_pick_good_org');
663 var hold = new ahr();
664 if(holdArgs.editHold) {
665 hold = holdArgs.editHold;
666 holdArgs.editHold = null;
669 if( $('holds_enable_phone').checked ) {
670 var phone = $('holds_phone').value;
671 if( !phone || !phone.match(REGEX_PHONE) ) {
672 alert($('holds_bad_phone').innerHTML);
675 hold.phone_notify(phone);
678 hold.phone_notify("");
681 if( $('holds_enable_email').checked )
682 hold.email_notify(1);
684 hold.email_notify(0);
688 switch(holdArgs.type) {
690 target = holdArgs.metarecord; break;
692 target = holdArgs.record; break;
694 target = holdArgs.volume; break;
696 target = holdArgs.copy; break;
701 hold.pickup_lib(org);
702 //hold.request_lib(org);
703 hold.requestor(holdArgs.requestor.id());
704 hold.usr(holdArgs.recipient.id());
706 hold.hold_type(holdArgs.type);
708 // see if this hold should be frozen and for how long
709 if($('holds_frozen_chkbox').checked) {
711 unHideMe($('hold_frozen_thaw_row'));
712 thawDate = $('holds_frozen_thaw_input').value;
714 if(holdsVerifyThawDate(thawDate)) {
715 hold.thaw_date(thawDate);
720 hold.thaw_date(null);
724 //check for alternate hold formats
725 var fstring = holdsSetSelectedFormats();
728 hold.holdable_formats(fstring);
729 hold.target(holdArgs.metarecord);
734 function holdsPlaceHold(hold, recurse) {
736 swapCanvas($('check_holds_box'));
737 holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
741 function holdHandleCreateResponse(r, recurse) {
744 var res = r.getResultObject();
745 if(checkILSEvent(res) || res.success != 1) {
746 if(res.success != 1) {
747 alert($('hold_not_allowed').innerHTML);
749 if( res.textcode == 'PATRON_BARRED' ) {
750 alertId('hold_failed_patron_barred');
752 alert($('hold_not_allowed').innerHTML);
755 swapCanvas($('holds_box'));
758 r._hold.selection_depth(res.depth);
761 holdCreateHold(r._recurse, r._hold);
765 function holdCreateHold( recurse, hold ) {
766 var method = CREATE_HOLD;
767 if(recurse) method = CREATE_HOLD_OVERRIDE;
768 var req = new Request( method, holdArgs.requestor.session, hold );
769 req.request.alertEvent = false;
771 var res = req.result();
772 holdProcessResult(hold, res, recurse);
776 runEvt('common', 'holdUpdated');
780 function holdProcessResult( hold, res, recurse ) {
783 alert($('holds_success').innerHTML);
789 alert($('holds_failure').innerHTML);
793 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
794 if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {
795 if( confirm($('hold_dup_exists_override').innerHTML) ) {
796 return holdsPlaceHold(hold, true);
800 return alert($('hold_dup_exists').innerHTML);
804 alert($('holds_failure').innerHTML);
809 function holdsCancel(holdid, user) {
810 if(!user) user = G.user;
811 var req = new Request(CANCEL_HOLD, user.session, holdid);
814 runEvt('common', 'holdUpdated');
817 function holdsUpdate(hold, user) {
818 if(!user) user = G.user;
819 var req = new Request(UPDATE_HOLD, user.session, hold);
821 var x = req.result(); // cause an exception if there is one
822 runEvt('common', 'holdUpdated');
826 /* verify that the thaw date is valid and after today */
827 function holdsVerifyThawDate(thawDate) {
828 thawDate = Date.parseIso8601(thawDate);
830 var today = new Date();
831 today = new Date(today.getFullYear(), today.getMonth(), today.getDate())
833 return thawDate.iso8601Format('YMD', false, false, true);
839 function holdsVerifyThawDateUI(element) {
840 value = $(element).value;
843 removeCSSClass($(element), 'invalid_field');
847 if(!holdsVerifyThawDate(value)) {
848 addCSSClass($(element), 'invalid_field');
850 removeCSSClass($(element), 'invalid_field');