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').onchange =
31 function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}
32 $('holds_frozen_thaw_input').onkeyup =
33 function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}
35 function _holdsHandleStaffMe() {
36 holdArgs.recipient = G.user;
40 function _holdsHandleStaff() {
41 var barcode = $('xul_recipient_barcode').value;
42 var user = grabUserByBarcode( G.user.session, barcode );
45 if(evt = checkILSEvent(user)) {
50 if(!barcode || !user) {
51 alertId('holds_invalid_recipient', barcode);
55 holdArgs.recipient = user;
62 * record, volume, copy (ids)
63 * request, recipient, editHold (objects)
66 function holdsDrawEditor(args) {
68 holdArgs = (args) ? args : holdArgs;
71 noEmailMessage = $('holds_email').removeChild($('holds.no_email'));
73 if(!noEmailMessageXUL)
74 noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));
76 if(isXUL() && holdArgs.recipient == null
77 && holdArgs.editHold == null) {
82 if(!holdArgs.recipient) holdArgs.recipient = G.user;
83 if(!holdArgs.requestor) holdArgs.requestor = G.user;
85 if(!(holdArgs.requestor && holdArgs.requestor.session)) {
86 detachAllEvt('common','locationChanged');
87 attachEvt('common','loggedIn', holdsDrawEditor)
92 if(holdArgs.editHold) // flesh the args with the existing hold
93 holdArgsFromHold(holdArgs.editHold, holdArgs);
99 // updates the edit window with the existing hold's data
100 function _holdsUpdateEditHold() {
102 var hold = holdArgs.editHold;
103 var status = holdArgs.status;
105 var orgsel = $('holds_org_selector');
106 var frozenbox = $('holds_frozen_chkbox');
108 setSelector(orgsel, hold.pickup_lib());
110 if( hold.capture_time() || status > 2 ) {
111 frozenbox.disabled = true;
112 $('holds_frozen_thaw_input').disabled = true;
114 // no pickup lib changes while in-transit
115 orgsel.disabled = true;
117 var orgs = fetchPermOrgs('UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF');
119 orgsel.disabled = true;
122 orgsel.disabled = false;
123 frozenbox.disabled = false;
127 $('holds_submit').onclick = holdsEditHold;
128 $('holds_update').onclick = holdsEditHold;
130 if(hold.phone_notify()) {
131 $('holds_enable_phone').checked = true;
132 $('holds_phone').value = hold.phone_notify();
135 $('holds_phone').disabled = true;
136 $('holds_enable_phone').checked = false;
139 if(isTrue(hold.email_notify())) {
140 $('holds_enable_email').checked = true;
143 $('holds_enable_email').checked = false;
146 dijit.byId('holds_expire_time').setValue(dojo.date.stamp.fromISOString(hold.expire_time()));
148 /* populate the hold freezing info */
149 if(!frozenbox.disabled && isTrue(hold.frozen())) {
150 frozenbox.checked = true;
151 unHideMe($('hold_frozen_thaw_row'));
152 if(hold.thaw_date()) {
153 dijit.byId('holds_frozen_thaw_input').setValue(dojo.date.stamp.fromISOString(hold.thaw_date()));
155 dijit.byId('holds_frozen_thaw_input').setValue('');
158 frozenbox.checked = false;
159 dijit.byId('holds_frozen_thaw_input').setValue('');
160 hideMe($('hold_frozen_thaw_row'));
164 function holdsEditHold() {
165 var hold = holdsBuildHoldFromWindow();
169 if(holdArgs.onComplete)
170 holdArgs.onComplete(hold);
173 function holdArgsFromHold(hold, oargs) {
174 var args = (oargs) ? oargs : {};
175 args.type = hold.hold_type();
176 var target = hold.target();
180 args.metarecord = target;
183 args.record = target;
186 args.volume = target;
195 function holdFetchObjects(hold, doneCallback) {
197 var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
199 var type = args.type;
203 if( args.copyObject ) {
205 args.copy = args.copyObject.id();
206 args.volume = args.copyObject.call_number();
207 _h_set_vol(args, doneCallback);
210 var creq = new Request(FETCH_COPY, args.copy);
214 var cp = r.getResultObject();
215 args.copyObject = cp;
216 args.volume = args.copyObject.call_number();
217 _h_set_vol(args, doneCallback);
224 _h_set_vol(args, doneCallback);
228 _h_set_rec(args, doneCallback);
230 _h_set_rec_descriptors(args, doneCallback);
238 function _h_set_vol(args, doneCallback) {
240 if( args.volumeObject ) {
241 args.volume = args.volumeObject.id();
242 args.record = args.volumeObject.record();
243 _h_set_rec(args, doneCallback);
247 var vreq = new Request(FETCH_VOLUME, args.volume);
250 var vol = r.getResultObject();
251 args.volumeObject = vol;
252 args.record = vol.record();
253 _h_set_rec(args, doneCallback);
260 function _h_set_rec(args, doneCallback) {
262 if(args.recordObject)
263 args.record = args.recordObject.doc_id();
265 args.recordObject = findRecord( args.record, 'T' );
267 if( args.type == 'T' || args.type == 'M' )
268 _h_set_rec_descriptors(args, doneCallback);
270 if(doneCallback) doneCallback(args);
274 function _h_set_rec_descriptors(args, doneCallback) {
276 // grab the list of record desciptors attached to this records metarecord
277 if( ! args.recordDescriptors ) {
278 var params = { record: args.record };
280 if( ! args.record ) {
281 if( args.metarecord )
282 params = { metarecord : args.metarecord };
284 params = { metarecord : args.metarecordObject.doc_id() };
287 var req = new Request(FETCH_MR_DESCRIPTORS, params );
290 var data = r.getResultObject();
291 args.recordDescriptors = data.descriptors;
292 args.metarecord = data.metarecord;
293 if( args.type == 'M' && ! args.metarecordObject)
294 args.metarecordObject = findRecord(args.metarecord, 'M');
296 if(doneCallback) doneCallback(args);
302 if(doneCallback) doneCallback(args);
310 function holdsDrawWindow() {
311 swapCanvas($('holds_box'));
312 $('holds_cancel').onclick = function(){ runEvt('common', 'holdUpdateCanceled'), showCanvas() };
313 $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
314 $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
315 holdFetchObjects(null,
319 if(holdArgs.editHold) {
320 hideMe($('holds_submit'));
321 unHideMe($('holds_update'));
322 var req = new Request(FETCH_HOLD_STATUS,
323 G.user.session, holdArgs.editHold.id());
325 holdArgs.status = req.result();
326 _holdsUpdateEditHold();
332 function __holdsDrawWindow() {
334 var rec = holdArgs.recordObject;
335 var vol = holdArgs.volumeObject;
336 var copy = holdArgs.copyObject;
337 var mr = holdArgs.metarecordObject;
339 rec = (rec) ? rec : mr;
341 if(!holdsOrgSelectorBuilt) {
342 holdsBuildOrgSelector(null,0);
343 holdsOrgSelectorBuilt = true;
344 var selector = $('holds_org_selector');
347 var o_loc = findOrgUnit(getOrigLocation());
348 var t = findOrgType(o_loc.ou_type());
349 if( t.can_have_users() )
350 setSelector(selector, o_loc.id());
354 setSelector(selector, holdArgs.recipient.home_ou());
360 var dsel = $('holds_depth_selector');
361 unHideMe($('holds_depth_selector_row'));
362 if(dsel.getElementsByTagName('option').length == 0) {
363 var types = globalOrgTypes;
364 var depth = findOrgDepth(G.user.ws_ou());
367 if(t.depth() > depth) return;
368 insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
375 appendClear($('holds_recipient'), text(
376 holdArgs.recipient.family_name() + ', ' +
377 holdArgs.recipient.first_given_name()));
378 appendClear($('holds_title'), text(rec.title()));
379 appendClear($('holds_author'), text(rec.author()));
381 if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
383 unHideMe($('holds_type_row'));
384 unHideMe($('holds_cn_row'));
385 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
387 if( holdArgs.type == 'V' ) {
388 unHideMe($('holds_is_cn'));
389 hideMe($('holds_is_copy'));
392 hideMe($('holds_is_cn'));
393 unHideMe($('holds_is_copy'));
394 unHideMe($('holds_copy_row'));
395 appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
399 hideMe($('holds_type_row'));
400 hideMe($('holds_copy_row'));
401 hideMe($('holds_cn_row'));
404 removeChildren($('holds_format'));
406 var mods_formats = rec.types_of_resource();
409 if(holdArgs.recordDescriptors)
410 formats = holdArgs.recordDescriptors[0].item_type();
412 if( holdArgs.type == 'T' ) {
413 var desc = grep( holdArgs.recordDescriptors,
415 return (i.record() == holdArgs.record);
418 formats = desc[0].item_type();
421 if( holdArgs.type == 'M' ) {
422 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());
423 mods_formats = data.mods_formats;
424 formats = data.formats;
428 for( var i in mods_formats ) {
429 var res = mods_formats[i];
430 var img = elem("img");
431 setResourcePic(img, res);
432 $('holds_format').appendChild(img);
434 $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
436 $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
437 $('holds_format').appendChild(elem('br'));
441 $('holds_phone').value = holdArgs.recipient.day_phone();
442 appendClear( $('holds_email'), text(holdArgs.recipient.email()));
444 var pref = G.user.prefs[PREF_HOLD_NOTIFY];
447 if( ! pref.match(/email/i) )
448 $('holds_enable_email').checked = false;
450 if( ! pref.match(/phone/i) ) {
451 $('holds_phone').disabled = true;
452 $('holds_enable_phone').checked = false;
456 if(!holdArgs.recipient.email()) {
457 $('holds_enable_email').checked = false;
458 $('holds_enable_email').disabled = true;
461 message = noEmailMessageXUL.cloneNode(true);
462 appendClear($('holds_email'), message);
464 message = noEmailMessage.cloneNode(true);
465 appendClear($('holds_email'), message);
466 $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));
471 if(!$('holds_phone').value)
472 $('holds_enable_phone').checked = false;
474 appendClear($('holds_physical_desc'), text(rec.physical_description()));
476 if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
478 holdsSetFormatSelector();
480 $('holds_frozen_chkbox').checked = false;
481 hideMe($('hold_frozen_thaw_row'));
483 var interval = fetchOrgSettingDefault(holdArgs.recipient.home_ou(), 'circ.hold_expire_interval');
486 secs = interval_to_seconds(interval);
487 var expire = new Date();
488 expire.setTime(expire.getTime() + Number(secs + '000'));
489 dijit.byId('holds_expire_time').setValue(expire);
492 function holdsParseMRFormats(str) {
493 var data = str.split(/-/);
496 var mods_formats = [];
498 for( var i = 0; i < data[0].length; i++ ) {
499 formats.push( data[0].charAt(i) );
500 mods_formats.push( MARCFormatToMods( formats[i] ) );
503 formats = uniquify(formats);
504 mods_formats = uniquify(mods_formats);
508 mods_formats : mods_formats,
515 function holdsSetFormatSelector() {
516 var type = holdArgs.type;
517 if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
519 var data = holdsGetFormats();
520 var avail_formats = data.avail_formats;
521 var sel_formats = data.sel_formats;
522 holdArgs.language = data.lang;
524 unHideMe($('holds_alt_formats_row_extras'));
525 var selector = $('hold_alt_form_selector');
527 for( var i = 0; i < avail_formats.length; i++ ) {
528 var form = avail_formats[i];
529 unHideMe(findSelectorOptByValue(selector, form));
534 function holdsGetFormats() {
538 var sformats = []; // selected formats
540 var type = holdArgs.type;
541 var desc = holdArgs.recordDescriptors;
542 var rec = holdArgs.record;
543 var mrec = holdArgs.metarecord;
547 for( var i = 0; i < desc.length; i++ ) {
549 if( d.record() == holdArgs.record ) {
550 lang = d.item_lang();
551 holdArgs.myFormat = _t_f_2_format(d.item_type(), d.item_form());
552 sformats.push(holdArgs.myFormat);
558 for( var i = 0; i < desc.length; i++ ) {
560 if( d.item_lang() != lang ) continue;
561 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
564 formats = uniquify(formats);
568 avail_formats : formats,
569 sel_formats : sformats
575 function _t_f_2_format(type, form) {
576 if( form == 'd' ) return 'at-d';
577 return (type == 'a' || type == 't') ? 'at' :
578 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
581 function holdsSetSelectedFormats() {
583 var cn = $('holds_alt_formats_row').className;
584 if( cn && cn.match(/hide_me/) ) return;
586 var selector = $('hold_alt_form_selector');
587 var vals = getSelectedList(selector);
589 if(vals.length == 0) return;
593 if( contains(vals, 'at-d') ) {
594 if( contains(vals, 'at') )
599 if( contains(vals, 'at') )
603 for( var i = 0; i < vals.length; i++ ) {
605 if( !val.match(/at/) ) fstring = val + fstring;
608 if( holdArgs.language ) {
609 if( fstring.match(/-/) )
610 fstring = fstring + '-' + holdArgs.language;
612 fstring = fstring + '--' + holdArgs.language;
620 function holdsCheckPossibility(pickuplib, hold, recurse) {
623 titleid : holdArgs.record,
624 volume_id : holdArgs.volume,
625 copy_id : holdArgs.copy,
626 hold_type : holdArgs.type,
627 patronid : holdArgs.recipient.id(),
629 pickup_lib : pickuplib
633 /* if we're calling create again (recursing),
634 we know that the hold possibility check already succeeded */
635 holdHandleCreateResponse({_recurse:true, _hold:hold}, true );
638 _debug("hold possible args = "+js2JSON(args));
640 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );
642 req.request.alertEvent = false;
643 req.request._hold = hold;
644 req.request._recurse = recurse;
645 req.callback(holdHandleCreateResponse);
651 function holdsBuildOrgSelector(node) {
653 if(!node) node = globalOrgTree;
654 if(!isTrue(node.opac_visible())) return;
656 var selector = $('holds_org_selector');
657 var index = selector.options.length;
659 var type = findOrgType(node.ou_type());
660 var indent = type.depth() - 1;
661 var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
662 if(!type.can_have_users()) {
664 addCSSClass(opt, 'disabled_option');
667 for( var i in node.children() ) {
668 var child = node.children()[i];
669 if(child) holdsBuildOrgSelector(child);
673 function holdsBuildHoldFromWindow() {
675 var org = getSelectorVal($('holds_org_selector'));
676 var node = findOrgUnit(org);
677 var ntype = findOrgType(node.ou_type());
678 if(!ntype.can_have_users()) {
679 alertId('holds_pick_good_org');
683 var hold = new ahr();
684 if(holdArgs.editHold) {
685 hold = holdArgs.editHold;
686 holdArgs.editHold = null;
689 if( $('holds_enable_phone').checked ) {
690 var phone = $('holds_phone').value;
691 if( !phone || !phone.match(REGEX_PHONE) ) {
692 alert($('holds_bad_phone').innerHTML);
695 hold.phone_notify(phone);
698 hold.phone_notify("");
701 if( $('holds_enable_email').checked )
702 hold.email_notify(1);
704 hold.email_notify(0);
708 switch(holdArgs.type) {
710 target = holdArgs.metarecord; break;
712 target = holdArgs.record; break;
714 target = holdArgs.volume; break;
716 target = holdArgs.copy; break;
721 hold.pickup_lib(org);
722 //hold.request_lib(org);
723 hold.requestor(holdArgs.requestor.id());
724 hold.usr(holdArgs.recipient.id());
726 hold.hold_type(holdArgs.type);
728 var expireDate = dojo.date.stamp.toISOString(dijit.byId('holds_expire_time').getValue())
729 expireDate = holdsVerifyThawDate(expireDate);
731 hold.expire_time(expireDate);
735 // see if this hold should be frozen and for how long
736 if($('holds_frozen_chkbox').checked) {
738 unHideMe($('hold_frozen_thaw_row'));
739 thawDate = dojo.date.stamp.toISOString(dijit.byId('holds_frozen_thaw_input').getValue());
741 thawDate = holdsVerifyThawDate(thawDate);
743 hold.thaw_date(thawDate);
747 hold.thaw_date(null);
751 hold.thaw_date(null);
754 //check for alternate hold formats
755 var fstring = holdsSetSelectedFormats();
758 hold.holdable_formats(fstring);
759 hold.target(holdArgs.metarecord);
764 function holdsPlaceHold(hold, recurse) {
766 swapCanvas($('check_holds_box'));
767 holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
771 function holdHandleCreateResponse(r, recurse) {
774 var res = r.getResultObject();
775 if(checkILSEvent(res) || res.success != 1) {
776 if(res.success != 1) {
777 alert($('hold_not_allowed').innerHTML);
779 if( res.textcode == 'PATRON_BARRED' ) {
780 alertId('hold_failed_patron_barred');
782 alert($('hold_not_allowed').innerHTML);
785 swapCanvas($('holds_box'));
788 r._hold.selection_depth(res.depth);
791 holdCreateHold(r._recurse, r._hold);
795 function holdCreateHold( recurse, hold ) {
796 var method = CREATE_HOLD;
797 if(recurse) method = CREATE_HOLD_OVERRIDE;
798 var req = new Request( method, holdArgs.requestor.session, hold );
799 req.request.alertEvent = false;
801 var res = req.result();
802 holdProcessResult(hold, res, recurse);
806 runEvt('common', 'holdUpdated');
810 function holdProcessResult( hold, res, recurse ) {
813 alert($('holds_success').innerHTML);
819 alert($('holds_failure').innerHTML);
823 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
824 if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {
825 if( confirm($('hold_dup_exists_override').innerHTML) ) {
826 return holdsPlaceHold(hold, true);
830 return alert($('hold_dup_exists').innerHTML);
834 alert($('holds_failure').innerHTML);
839 function holdsCancel(holdid, user) {
840 if(!user) user = G.user;
841 var req = new Request(CANCEL_HOLD, user.session, holdid);
844 runEvt('common', 'holdUpdated');
847 function holdsUpdate(hold, user) {
848 if(!user) user = G.user;
849 var req = new Request(UPDATE_HOLD, user.session, hold);
851 var x = req.result(); // cause an exception if there is one
852 runEvt('common', 'holdUpdated');
855 /* verify that the thaw date is valid and after today */
856 function holdsVerifyThawDate(dateString) {
857 thawDate = dojo.date.stamp.fromISOString(dateString);
858 if(thawDate && (dojo.date.compare(thawDate) > 0))
859 return dojo.date.stamp.toISOString(thawDate);
863 function holdsVerifyThawDateUI(element) {
864 value = dojo.date.stamp.toISOString(dijit.byId(element).getValue());
867 removeCSSClass($(element), 'invalid_field');
871 if(!holdsVerifyThawDate(value)) {
872 addCSSClass($(element), 'invalid_field');
874 removeCSSClass($(element), 'invalid_field');