1 [% PROCESS "opac/parts/misc_util.tt2";
2 PROCESS "opac/parts/hold_error_messages.tt2";
3 PROCESS "opac/parts/metarecord_hold_filters.tt2";
6 // Toggle the activation date input and check the suspend checkbox.
7 // If JavaScript is disabled, the CSS will handle the former, but
8 // the latter will not happen.
9 function toggleActivationDate() {
10 var cb = document.getElementById("hold_suspend");
11 var block = document.getElementById("toggled-block-suspend");
12 var anchor = document.getElementById("actDateToggle");
13 var actText = "[%- l('Hide activation date') -%]";
14 var inActText = "[%- l('Set activation date') -%]";
15 // Check for not equal to block so it works on first click.
16 if (block.style.display != "block") {
17 block.style.display = "block";
18 anchor.innerHTML = "<i class='fas fa-calendar' aria-hidden='true'></i> " + actText;
19 if (cb.checked != true) cb.checked = true;
21 block.style.display = "none";
22 anchor.innerHTML = "<i class='fas fa-calendar' aria-hidden='true'></i> " + inActText;
24 // Prevent the href from being followed, thus overriding the CSS.
28 // Maybe enable or disable the num_copies select when the user selects
29 // or deselects a part.
30 function maybeToggleNumCopies(obj) {
31 var numCopies = document.getElementById("num_copies");
32 // Only if numCopies exists.
35 if (obj.type == 'radio') {
36 if (obj.checked) objValue = obj.value;
41 if (objValue && objValue != '') {
42 if (numCopies.value != '1') numCopies.value = '1';
43 if (!numCopies.disabled) numCopies.disabled = true;
45 if (numCopies.disabled) numCopies.disabled = false;
50 //Doublecheck whether their default pickup library is valid. Should only be invalid if pulled from disabled home library when the page loads, but adding more checks just in case
51 function checkValidPickupLib()
53 let org_selector = document.getElementById('pickup_lib');
54 if (org_selector != null && org_selector[org_selector.selectedIndex].disabled == true) {
56 //Are they at the default message or the warning?
57 if (org_selector[org_selector.selectedIndex].value == -1){
58 document.getElementById("place_hold_submit").disabled = true;
59 org_selector.style.backgroundColor= "#FFF1A5";
60 org_selector.invalid = true;
63 org_selector.style.backgroundColor= "#FFF1A5";
64 org_selector.invalid = true;
65 document.getElementById("pickup-lib-unavailable-warning").hidden = false;
66 document.getElementById("place_hold_submit").disabled = true;
70 org_selector.invalid = false;
71 org_selector.style.backgroundColor = "#fff";
72 document.getElementById("pickup-lib-unavailable-warning").hidden = true;
73 document.getElementById("place_hold_submit").disabled = false;
77 //Create and add a generic option for the start of the selector
78 function createDefaultOption()
80 let org_selector = document.getElementById('pickup_lib');
82 let null_option = document.createElement("option");
83 null_option.innerText = "[% l('Choose a pickup location') %]";
84 null_option.disabled = true;
85 null_option.value = -1;
86 null_option.style.backgroundColor = "#fff";
87 org_selector.add(null_option, 0);
90 //Check if org valid once when the page loads and then every time you change it could be valid again, so check again
91 document.addEventListener("DOMContentLoaded", () => {
92 let org_selector = document.getElementById('pickup_lib');
94 //Keep original colors of org unit dropdown for the sake of readability
95 let options = org_selector.children;
96 //We also need the list of all orgs in the list
97 let lib_ids = Array(options.length).fill(0);
98 for (let i = 0; i < options.length; i++){
99 options[i].style.backgroundColor= "#fff";
100 lib_ids[i] = options[i].value;
103 //If the user's default pickup library is not in the dropdown (probably due to being hidden from the OPAC)
104 let default_lib = [% GET ctx.default_pickup_lib %];
105 if (!lib_ids.includes(default_lib.toString())){
106 //Create and use the default message instead
107 createDefaultOption();
108 org_selector.selectedIndex = 0;
111 checkValidPickupLib();
112 document.getElementById('pickup_lib').addEventListener("change", checkValidPickupLib);
118 <div class='container'>
120 <h3>[% l('Place Hold') %]</h3>
122 [% some_holds_allowed = -1 %]
124 <!-- loop through the holds and display status of request where appropriate -->
125 [% FOR hdata IN ctx.hold_data;
126 attrs = {marc_xml => hdata.marc_xml};
127 PROCESS get_marc_attrs args=attrs;
128 this_hold_disallowed = 0;
130 IF CGI.param('hold_type') == 'M';
131 IF hdata.metarecord_filters.formats.size == 0;
132 this_hold_disallowed = 1;
133 # if this is the first hold and it is disallowed,
134 # assume all holds are, until we proven otherwise
135 SET some_holds_allowed = 0 IF some_holds_allowed == -1;
136 ELSE; some_holds_allowed = 1; END;
140 <form method="post" name="PlaceHold" onsubmit="return validateHoldForm()" >
141 <input type="hidden" name="hold_type" value="[% CGI.param('hold_type') | html %]" />
143 redirect = CGI.param('hold_source_page') || CGI.param('redirect_to') || CGI.referer;
144 # since we have to be logged in to get this far, return to a secure page
145 redirect = redirect.replace('^http:', 'https:')
147 <input type="hidden" name="redirect_to" value="[% redirect | html %]" />
148 <input type="hidden" name="hold_source_page" value="[% CGI.param('hold_source_page') | html %]" />
150 <!-- Adding hidden fields so that parameters are maintained in
151 searchbar throughout the place hold process. -->
152 <input type="hidden" name="locg" value="[% CGI.param('locg') | html %]" />
153 <input type="hidden" name="qtype" value="[% CGI.param('qtype') | html %]" />
154 <input type="hidden" name="query" value="[% CGI.param('query') | html %]" />
156 usr_barcode = CGI.param('usr_barcode') | html;
157 is_requestor = CGI.param('is_requestor');
159 IF is_requestor == '';
163 IF is_requestor == '0' && usr_barcode == ctx.staff_recipient.card.barcode;
168 [% IF ctx.is_staff %]
169 <p class="staff-hold">
170 <input type="radio" id="hold_usr_is_requestor_not"
171 onchange="staff_hold_usr_input_disabler(this);"
172 name="hold_usr_is_requestor" value="0"
174 <label for="hold_usr_is_requestor_not">
175 [% l("Place hold for patron by barcode:") %]
177 <input type="text" name="hold_usr" id="hold_usr_input"
178 aria-label="[% l('Barcode') %]"
179 value="[% usr_barcode | html %]"
180 onpaste="return debounce_barcode_change(event)"
181 onkeydown="return debounce_barcode_change(event)" autofocus />
182 <span id="patron_name"></span>
183 <span id="patron_usr_barcode_not_found" style="display: none">
184 [% l('Patron barcode was not found') %]
186 [% IF ctx.is_browser_staff %]
187 <button id="hold_usr_search" type="button" class="btn btn-action" style="display: none;">[% l('Patron Search') %]</button>
190 <input type="hidden" id="staff_barcode"
191 value="[% ctx.staff_recipient.card.barcode | html %]"/>
193 <input type="radio" id="hold_usr_is_requestor"
194 onchange="staff_hold_usr_input_disabler(this);"
195 name="hold_usr_is_requestor" value="1" />
196 <label for="hold_usr_is_requestor">
197 [% l("Place this hold for me ([_1] [_2])", ctx.user.first_given_name, ctx.user.family_name) | html %]
200 [% IF CGI.param('hold_type') == 'T' AND ctx.hold_subscriptions.size > 0 AND NOT CGI.param('from_basket') %]
202 <!-- request for a reading group / subscription -->
203 <input type="radio" id="hold_usr_is_subscription"
204 onchange="staff_hold_usr_input_disabler(this);"
205 name="hold_usr_is_requestor" value="2"
207 <label for="hold_usr_is_subscription">
208 [% l("Place hold for patron Hold Group:") %]
210 <select id='select_hold_subscription' name='hold_subscription'>
211 <option selected='selected' value=''>[% l('- Hold Groups -') %]</option>
212 [% FOR sub IN ctx.hold_subscriptions %]
213 <option value='[% sub.id %]'>[% sub.name | html %]</option>
219 <input id="override_blocks_subscription" name="override" type="checkbox" checked="checked"/>
220 [% l("Override all hold-blocking conditions possible?") %]
229 [% IF !this_hold_disallowed %]
230 <input type="hidden" name="hold_target" value="[% hdata.target.id | html %]" />
232 <div class='hold-items-list-title'>
233 <!-- If hold is for grouped formats/editions (metarecord), show short title - else, show complete title -->
234 [% IF CGI.param('hold_type') == 'M' %]
235 [% attrs.title | html %]
237 [% attrs.title_extended | html %]
240 [% IF hdata.parts AND !this_hold_disallowed %]
241 [% IF hdata.parts.size > 0 %]
242 <div class='hold-div'>
243 [% IF enable.radio.parts == 'true' %]
244 <span class='hold-span'><label for='select_hold_part'>[%
247 <div class='radio-parts-selection'>
248 [% IF !hdata.part_required %]
249 <span class='parts-radio-option'>
250 <input type='radio' name='part' value='' onchange='maybeToggleNumCopies(this);' required>[% l('All Parts') %]</span>
252 [% FOR part IN hdata.parts %]
253 <span class='parts-radio-option'><input type='radio' name='part' id=[% part.id %] value=[% part.id %] onchange='maybeToggleNumCopies(this);' required>
254 <label for=[% part.id %]>[% part.label | html %]</label></span>
258 <span style='font-weight: bold;'><label for='select_hold_part'>[%
259 hdata.part_required ? l('Select a Part:') : l('Select a Part (optional):')
261 <select id='select_hold_part' name='part' onchange='maybeToggleNumCopies(this);'>
262 [% IF !hdata.part_required %]
263 <option selected='selected' value=''>[% l('- All Parts -') %]</option>
265 [% FOR part IN hdata.parts %]
266 <option value='[% part.id %]'>[% part.label | html %]</option>
272 <input type='hidden' name='part' value=''/>
275 [% INCLUDE "opac/parts/multi_hold_select.tt2" IF NOT (this_hold_disallowed AND hdata.part_required); %]
280 [% IF this_hold_disallowed %]
282 <div class="mr_holds_no_formats">
283 [% l('This item does not have any formats available for holds placement') %]
288 [% IF !loop.last AND ctx.hold_data.size > 1 %]
289 <tr class="holds_item_row_separator"><td> </td></tr>
295 [% IF some_holds_allowed %]
298 [%- org_select_id = 'pickup_lib'; -%]
299 <label for="[% org_select_id %]" class="font-weight-bold">[%l('Pickup location:') %]</label>
300 [% PROCESS "opac/parts/org_selector.tt2";
301 INCLUDE build_org_selector name='pickup_lib'
302 value=ctx.default_pickup_lib id=org_select_id
303 can_have_vols_only=1 hold_pickup_lib=1 %]
304 <label id="pickup-lib-unavailable-warning" for="[% org_select_id %]" class= "font-weight-bold" style= "color: #D0343A" aria-live="polite" hidden>[% l('* Pickup location unavailable. Please choose a different pickup location.') %]</label>
305 <!-- <label id="choose-pickup-lib-warning" for ="[% org_select_id %]" class="font-weight-light" aria-live="polite" hidden>[% l('* Please choose a pickup location') %]</label>
310 <span class="font-weight-bold">[% l('Notify when hold is ready for pickup?') %]</span>
312 <div class="form-check m-2">
313 <input class="form-check-input hold-alert-method" type="checkbox" value="t" id="email_notify" name="email_notify" [% IF !ctx.user.email %]disabled="true"[% ELSIF ctx.default_email_notify %]checked="checked"[% END %]>
314 <label class="form-check-label" for="email_notify">
315 [% l('Yes, by Email') %]
317 [% IF !ctx.user.email and !ctx.is_staff; l('<br>No configured Email address. See "My Account" for setting your Email address.'); ELSE; %] : <span id="email_address"><b name="email_address">[% ctx.user.email %]</b></span>[% END %]
325 [%- IF allow_phone_notifications == 'true' %]
326 <div class="form-check m-2">
327 <input class="form-check-input hold-alert-method" type="checkbox" id="phone_notify_checkbox" name="phone_notify_checkbox" [% IF ctx.default_phone_notify %]checked="checked"[% END %]>
328 <label class="form-check-label" for="phone_notify_checkbox">
329 [% l('Yes, by Phone') %]
334 <label>[% l('Phone Number:') %]<input type="text" class="form-control" name="phone_notify" [% setting = 'opac.default_phone';
335 IF ctx.user_setting_map.$setting; %] value='[% ctx.user_setting_map.$setting | html %]'
336 [%- ELSIF ctx.user.day_phone; %] value='[% ctx.user.day_phone | html %]' [% END %]/></label>
339 [% IF ctx.get_org_setting(ctx.search_ou, 'sms.enable') == 1 %]
340 <input class="hold-alert-method" type="checkbox" id="sms_notify_checkbox" name="sms_notify_checkbox"
341 [% IF ctx.default_sms_notify %]checked="checked"[% END %]/>
342 <label for="sms_notify_checkbox">[% l('Yes, by Text Messaging') %]</label><br/>
344 [% INCLUDE "opac/parts/sms_carrier_selector.tt2" %]<br/>
345 [% INCLUDE "opac/parts/sms_number_textbox.tt2" %]<br/>
351 [% IF ctx.hold_data.size > 0; %]
352 <div class="form-check m-2">
353 <input class="form-check-input" type="checkbox" value="t" id="hold_suspend" name="hold_suspend">
354 <label class="form-check-label" for="hold_suspend">
355 [% IF ctx.hold_data.size == 1;
356 l('Suspend this hold?');
358 l('Suspend these holds?');
360 <a href="#" aria-label="[% l('A suspended hold will retain its place in the queue, but will not be fulfilled until it has been activated.') %]" title="[% l('A suspended hold will retain its place in the queue, but will not be fulfilled until it has been activated.') %]" data-toggle="tooltip">
361 <i class="fas fa-question-circle" aria-hidden="true"></i>
370 <a class="btn btn-sm btn-action m-2" id="actDateToggle" href="#toggled-block-suspend" onclick="return toggleActivationDate();"><i class="fas fa-calendar" aria-hidden="true"></i> [% l('Set activation date') %]</a>
372 <blockquote id="toggled-block-suspend">
373 <label for="thaw_date">[% l('Activate on') %]
374 <div class="input-group date" data-provide="datepicker">
375 <input type="text" class="form-control" name="thaw_date" id="thaw_date" value="[% thaw_date | html %]" data-date-format="mm/dd/yyyy" />
376 <div class="input-group-addon">
377 <span class="glyphicon glyphicon-th"></span>
382 [% IF CGI.param('from_basket') %]
384 <div class="form-check m-2">
385 <input class="form-check-input" type="checkbox" value="" id="clear_cart" />
386 <label class="form-check-label" for="clear_cart">
387 [% l('Clear basket after holds are requested?') %]
391 [% IF NOT metarecords.disabled AND ctx.hold_data.size == 1 %]
392 [% IF CGI.param('hold_type') == 'T' AND hdata.record.metarecord AND !hdata.part_required %]
393 <!-- Grab the bre_id so that we can restore it if user accidentally clicks advanced options -->
394 [% bre_id = hdata.target.id %]
395 <a id='advanced_hold_link' class="btn btn-sm btn-link"
396 href="[% mkurl('', {hold_type => 'M', hold_target => hdata.record.metarecord.id, bre_id => bre_id}) %]"><i class="fas fa-cog" aria-hidden="true"></i>
397 [% l('Advanced Hold Options') %]</a>
399 [% IF CGI.param('hold_type') == 'M' AND CGI.param('bre_id') %]
400 <input type="hidden" name="bre_id" value="[% CGI.param('bre_id') %]" />
401 <a id='basic_hold_link' class="btn btn-sm btn-link"
402 href="[% mkurl('', {hold_target => CGI.param('bre_id'), hold_type => 'T'}) %]"><i class="fas fa-cog" aria-hidden="true"></i>
403 [% l('Basic Hold Options') %]</a>
405 [% IF hdata.metarecord_filters.formats.size OR # should this be size > 1
406 (hdata.metarecord_filters.langs.size && hdata.metarecord_filters.langs.size > 1);
407 PROCESS metarecord_hold_filters_selector hold_data=hdata;
411 <button id="place_hold_submit" type="submit" name="submit" class="btn btn-confirm" ><i class="fas fa-check"></i> [% l('Submit') %]</button>
412 [% END # some_holds_allowed %]
413 <button type="reset" name="cancel" onclick="window.location='[% redirect | html %]'" id="holds_cancel" class="btn btn-deny"><i class="fas fa-ban" aria-hidden="true"></i> [% l('Cancel') %]</button>