]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/extras/selfcheck/selfcheck.js
Upped the default patron timeout to 10 minutes
[Evergreen.git] / Open-ILS / web / opac / extras / selfcheck / selfcheck.js
1 /* -----------------------------------------------------------------
2 * Copyright (C) 2008  Equinox Software, Inc.
3 * Bill Erickson <erickson@esilibrary.com>
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
18 * 02110-1301, USA
19 ----------------------------------------------------------------- */
20
21 var STAFF_SES_PARAM = 'ses';
22 var patron = null
23 var itemBarcode = null;
24 var itemsOutTemplate = null;
25 var isRenewal = false;
26 var pendingXact = false;
27 var patronTimeout = 600000; /* 10 minutes */
28 var timerId = null;
29 var printWrapper;
30 var printTemplate;
31 var successfulItems = {};
32 var scanTimeout = 800;
33 var scanTimeoutId;
34
35
36 function selfckInit() {
37     var cgi = new CGI();
38     var staff = grabUser(cookieManager.read(STAFF_SES_PARAM) || cgi.param(STAFF_SES_PARAM));
39
40     /*
41     XXX we need org information (from the proxy?)
42     var t = fetchOrgSettingDefault(1, 'circ.selfcheck.patron_login_timeout');
43     patronTimeout = (t) ? parseInt(t) * 1000 : patronTimeout;
44     */
45
46     if(!staff) {
47         // should not happen when behind the proxy
48         return alert('Staff must login');
49     }
50
51     unHideMe($('selfck-patron-login-container'));
52     $('selfck-patron-login-input').focus();
53
54     $('selfck-patron-login-input').onkeypress = function(evt) {
55         if(userPressedEnter(evt)) 
56             selfckPatronLogin();
57     };
58
59     $('selfck-item-barcode-input').onkeypress = selfckItemBarcodeKeypress;
60
61     // for debugging, allow passing the user barcode via param
62     var urlbc = new CGI().param('patron');
63     if(urlbc)
64         selfckPatronLogin(urlbc);
65
66     selfckStartTimer();
67
68     printWrapper = $('selfck-print-items-list');
69     printTemplate = printWrapper.removeChild($n(printWrapper, 'selfck-print-items-template'));
70     itemsOutTemplate = $('selfck-items-out-tbody').removeChild($('selfck-items-out-row'));
71
72 //    selfckMkDummyCirc(); // testing only
73 }
74
75
76 function selfckItemBarcodeKeypress(evt) {
77     if(userPressedEnter(evt)) {
78         clearTimeout(scanTimeoutId);
79         selfckCheckout();
80     } else {
81         /*  If scanTimeout milliseconds have passed and there is
82             still data in the input box, it's a likely indication
83             of a partial scan. Select the text so the next scan
84             will replace the value */
85         clearTimeout(scanTimeoutId);
86         scanTimeoutId = setTimeout(
87             function() {
88                 if($('selfck-item-barcode-input').value) {
89                     $('selfck-item-barcode-input').select();
90                 }
91             },
92             scanTimeout
93         );
94     }
95 }
96
97 /*
98  * Start the logout timer
99  */
100 function selfckStartTimer() {
101     timerId = setTimeout(
102         function() {
103             selfckLogoutPatron();
104         },
105         patronTimeout
106     );
107
108 }
109
110 /*
111  * Reset the logout timer
112  */
113 function selfckResetTimer() {
114     clearTimeout(timerId);
115     selfckStartTimer();
116 }
117
118 /*
119  * Clears fields and "logs out" the patron by reloading the page
120  */
121 function selfckLogoutPatron() {
122     $('selfck-item-barcode-input').value = ''; // prevent browser caching
123     $('selfck-patron-login-input').value = '';
124     if(patron) {
125         selfckPrint();
126         setTimeout(
127             function() { location.href = location.href; },
128             800
129         );
130     }
131 }
132
133 /*
134  * Fetches the user by barcode and displays the item barcode input
135  */
136
137 function selfckPatronLogin(barcode) {
138     barcode = barcode || $('selfck-patron-login-input').value;
139     if(!barcode) return;
140
141     var bcReq = new Request(
142         'open-ils.actor:open-ils.actor.user.fleshed.retrieve_by_barcode',
143         G.user.session, barcode);
144
145         bcReq.request.alertEvent = false;
146
147     bcReq.callback(function(r) {
148         patron = r.getResultObject();
149         if(checkILSEvent(patron)) {
150             if(patron.textcode == 'ACTOR_USER_NOT_FOUND') {
151                 unHideMe($('selfck-patron-not-found'));
152                 $('selfck-patron-login-input').select();
153                 return;
154             }
155             return alert(patron.textcode);
156         }
157         $('selfck-patron-login-input').value = ''; // reset the input
158         hideMe($('selfck-patron-login-container'));
159         unHideMe($('selfck-patron-checkout-container'));
160         $('selfck-patron-name-span').appendChild(text(patron.usrname()));
161         $('selfck-item-barcode-input').focus();
162     });
163
164     bcReq.send();
165 }
166
167 /**
168   * Sends the checkout request
169   */
170 function selfckCheckout() {
171     if(pendingXact) return;
172     selfckResetTimer();
173     pendingXact = true;
174     isRenewal = false;
175
176     removeChildren($('selfck-event-time'));
177     removeChildren($('selfck-event-span'));
178
179     itemBarcode = $('selfck-item-barcode-input').value;
180     if(!itemBarcode) return;
181
182     if (itemBarcode in successfulItems) {
183         selfckShowMsgNode({textcode:'dupe-barcode'});
184         $('selfck-item-barcode-input').select();
185         pendingXact = false;
186         return;
187     }
188
189     var coReq = new Request(
190         'open-ils.circ:open-ils.circ.checkout.full',
191         G.user.session, {patron_id:patron.id(), copy_barcode:itemBarcode});
192
193         coReq.request.alertEvent = false;
194     coReq.callback(selfckHandleCoResult);
195     coReq.send();
196 }
197
198 /**
199   * Handles the resulting event.  If the item is already checked out,
200   * attempts renewal.  Any other events will display a message
201   */
202 function selfckHandleCoResult(r) {
203     var evt = r.getResultObject();
204
205     if(evt.textcode == 'SUCCESS') {
206         selfckDislplayCheckout(evt);
207         selfckShowMsgNode(evt);
208         successfulItems[itemBarcode] = 1;
209
210     } else if(evt.textcode == 'OPEN_CIRCULATION_EXISTS') {
211         selfckRenew();
212
213     } else {
214         pendingXact = false;
215         selfckShowMsgNode(evt);
216         $('selfck-item-barcode-input').select();
217     }
218 }
219
220 /**
221   * Display event text in the messages block
222   */
223 function selfckShowMsgNode(evt) {
224     var code = evt.textcode;
225     var msgspan = $('selfck-event-span');
226
227     // if we're not explicitly handling the event, just say "copy cannot circ"
228     if(!$('selfck-event-' + code)) 
229         code = 'COPY_CIRC_NOT_ALLOWED';
230
231     appendClear($('selfck-event-time'), text(new Date().toLocaleString()));
232     appendClear($('selfck-event-span'), text($('selfck-event-' + code).innerHTML));
233 }
234
235 /**
236   * Renders a row in the checkouts table for the current circulation
237   */
238 function selfckDislplayCheckout(evt) {
239     unHideMe($('selfck-items-out-table-wrapper'));
240
241     var template = itemsOutTemplate.cloneNode(true);
242     var copy = evt.payload.copy;
243     var record = evt.payload.record;
244     var circ = evt.payload.circ;
245
246     if(record.isbn()) {
247             var pic = $n(template, 'selfck.jacket');
248             pic.setAttribute('src', '../ac/jacket/small/'+cleanISBN(record.isbn()));
249     }
250     $n(template, 'selfck.barcode').appendChild(text(copy.barcode()));
251     $n(template, 'selfck.title').appendChild(text(record.title()));
252     $n(template, 'selfck.author').appendChild(text(record.author()));
253     $n(template, 'selfck.due_date').appendChild(text(circ.due_date().replace(/T.*/,'')));
254     $n(template, 'selfck.remaining').appendChild(text(circ.renewal_remaining()));
255     if(isRenewal) {
256         hideMe($n(template, 'selfck.cotype_co'));
257         unHideMe($n(template, 'selfck.cotype_rn'));
258     }
259
260     $('selfck-items-out-tbody').appendChild(template);
261     $('selfck-item-barcode-input').value = '';
262
263
264     // flesh out the printable version of the page as well
265     var ptemplate = printTemplate.cloneNode(true);
266     $n(ptemplate, 'title').appendChild(text(record.title()));
267     $n(ptemplate, 'barcode').appendChild(text(copy.barcode()));
268     $n(ptemplate, 'due_date').appendChild(text(circ.due_date().replace(/T.*/,'')));
269     printWrapper.appendChild(ptemplate);
270
271     pendingXact = false;
272 }
273
274 /**
275   * Checks to see if this item is checked out to the current patron.  If so, 
276   * this sends the renewal request.
277   */
278 function selfckRenew() {
279
280     // first, make sure the item is checked out to this patron
281     var detailReq = new Request(
282         'open-ils.circ:open-ils.circ.copy_details.retrieve.barcode',
283         G.user.session, itemBarcode);
284
285     detailReq.callback(
286         function(r) {
287             var details = r.getResultObject();
288             if(details.circ.usr() == patron.id()) {
289                 // OK, this is our item, renew it
290                 isRenewal = true;
291                 var rnReq = new Request(
292                     'open-ils.circ:open-ils.circ.renew',
293                     G.user.session, {copy_barcode:itemBarcode});
294                 rnReq.request.alertEvent = false;
295                 rnReq.callback(selfckHandleCoResult);
296                 rnReq.send();
297             }
298         }
299     );
300
301     detailReq.send();
302 }
303
304 /**
305   * Sets the print date and prints the page
306   */
307 function selfckPrint() {
308     for(var x in successfulItems) { // make sure we've checked out at least one item
309         appendClear($('selfck-print-date'), text(new Date().toLocaleString()));
310         window.print();
311         return;
312     }
313 }
314
315
316 /**
317   * Test method for generating dummy data in the checkout tables
318   */
319 function selfckMkDummyCirc() {
320     unHideMe($('selfck-items-out-table'));
321
322     var template = itemsOutTemplate.cloneNode(true);
323     $n(template, 'selfck.barcode').appendChild(text('123456789'));
324     $n(template, 'selfck.title').appendChild(text('Test Title'));
325     $n(template, 'selfck.author').appendChild(text('Test Author'));
326     $n(template, 'selfck.due_date').appendChild(text('2008-08-01'));
327     $n(template, 'selfck.remaining').appendChild(text('1'));
328     $('selfck-items-out-tbody').appendChild(template);
329
330     // flesh out the printable version of the page as well
331     var ptemplate = printTemplate.cloneNode(true);
332     $n(ptemplate, 'title').appendChild(text('Test Title'));
333     $n(ptemplate, 'barcode').appendChild(text('123456789'));
334     $n(ptemplate, 'due_date').appendChild(text('2008-08-01'));
335     printWrapper.appendChild(ptemplate);
336 }