2 * variables defined in base_js.tt2:
5 * vendor_list = [ 'ebook_test' ]
9 * progress_icon (probably not done right)
11 * base_js.tt2 also "imports" dojo.cookie and a bunch of ebook_api JS
14 // Array of objects representing this patron's relationship with a specific vendor.
25 // Ebook to perform actions on.
27 if (typeof ebook_action.title_id !== 'undefined') {
28 active_ebook = new Ebook(ebook_action.vendor, ebook_action.title_id);
31 dojo.addOnLoad(function() {
33 dojo.forEach(vendor_list, function(v) {
34 var rel = new Relation(v, patron_id);
38 // Pull patron transaction info from cache (cookie), if available.
39 // Otherwise, do a live lookup against all enabled vendors.
40 if (dojo.cookie('ebook_xact_cache')) {
41 getCachedTransactions();
43 addTransactionsToPage();
45 console.log('retrieving patron transaction info for all vendors');
46 dojo.forEach(relations, function(rel) {
47 checkSession(rel.vendor, function(ses) {
48 rel.getTransactions( function(r) {
49 addTransactionsToCache(r);
57 // Update current page with cross-vendor transaction totals.
58 function addTotalsToPage() {
59 console.log('updating page with transaction totals');
61 updateMyAccountSummary();
64 // Update current page with detailed transaction info, where appropriate.
65 function addTransactionsToPage() {
66 // ensure active ebook has access to session ID to avoid scoping issues during transactions
67 if (active_ebook && typeof active_ebook.vendor !== 'undefined') {
68 active_ebook.ses = active_ebook.ses || dojo.cookie(active_ebook.vendor);
70 if (dojo.byId('ebook_spinner')) dojo.addClass('ebook_spinner', "hidden");
72 console.log('updating page with cached transaction details, if applicable');
73 if (myopac_page === 'ebook_circs')
75 if (myopac_page === 'ebook_holds')
77 if (myopac_page === 'ebook_holds_ready')
79 if (myopac_page === 'ebook_checkout')
80 getReadyForCheckout();
81 if (myopac_page === 'ebook_place_hold')
86 function updateDashboard() {
87 console.log('updating dashboard');
88 var total_checkouts = (typeof xacts.checkouts === 'undefined') ? '-' : xacts.checkouts.length;
89 var total_holds_pending = (typeof xacts.holds_pending === 'undefined') ? '-' : xacts.holds_pending.length;
90 var total_holds_ready = (typeof xacts.holds_ready === 'undefined') ? '-' : xacts.holds_ready.length;
92 var eCheckout = document.getElementById('dash_e_checked');
93 var eHolds = document.getElementById('dash_e_holds');
94 var ePickup = document.getElementById('dash_e_pickup');
95 var eDash = document.getElementById('dashboard_e');
97 if(typeof(eCheckout) != 'undefined' && eCheckout != null)
99 dojo.byId('dash_e_checked').innerHTML = total_checkouts;
101 if(typeof(eHolds) != 'undefined' && eHolds != null)
103 dojo.byId('dash_e_holds').innerHTML = total_holds_pending;
105 if(typeof(ePickup) != 'undefined' && ePickup != null)
107 dojo.byId('dash_e_pickup').innerHTML = total_holds_ready;
109 if(typeof(eDash) != 'undefined' && eDash != null)
111 // unhide ebook dashboard
112 dojo.removeClass('dashboard_e', "hidden");
117 function updateMyAccountSummary() {
118 if (myopac_page === 'main') {
119 console.log('updating account summary');
120 var total_checkouts = (typeof xacts.checkouts === 'undefined') ? '-' : xacts.checkouts.length;
121 var total_holds_pending = (typeof xacts.holds_pending === 'undefined') ? '-' : xacts.holds_pending.length;
122 var total_holds_ready = (typeof xacts.holds_ready === 'undefined') ? '-' : xacts.holds_ready.length;
124 dojo.byId('acct_sum_ebook_circ_total').innerHTML = total_checkouts;
125 dojo.byId('acct_sum_ebook_hold_total').innerHTML = total_holds_pending;
126 dojo.byId('acct_sum_ebook_hold_ready_total').innerHTML = total_holds_ready;
127 // unhide display elements
128 dojo.removeClass('acct_sum_ebook_circs', "hidden");
129 dojo.removeClass('acct_sum_ebook_holds', "hidden");
130 dojo.removeClass('acct_sum_ebook_holds_ready', "hidden");
134 function updateCheckoutView() {
135 if (xacts.checkouts.length < 1) {
136 dojo.removeClass('no_ebook_circs', "hidden");
138 dojo.empty('ebook_circs_main_table_body');
139 dojo.forEach(xacts.checkouts, function(x) {
140 var ebook = new Ebook(x.vendor, x.title_id);
141 var tr = dojo.create("tr", null, dojo.byId('ebook_circs_main_table_body'));
142 dojo.create("td", { innerHTML: x.title }, tr);
143 dojo.create("td", { innerHTML: x.author }, tr);
144 dojo.create("td", { innerHTML: x.due_date }, tr);
145 var dl_td = dojo.create("td", null, tr);
146 if (x.download_url) {
147 dl_td.innerHTML = '<a href="' + x.download_url + '">' + l_strings.download + '</a>';
149 if (x.download_redirect) {
150 dl_td.innerHTML = '<a target="_blank" href="' + x.download_redirect + '">' + l_strings.download + '</a>';
151 } else if (x.formats) {
152 var select = dojo.create("select", { id: "download-format" }, dl_td);
153 for (f in x.formats) {
154 dojo.create("option", { value: x.formats[f], innerHTML: f }, select);
156 var button = dojo.create("input", { id: "download-button", type: "button", value: l_strings.download }, dl_td);
157 ebook.conns.download = dojo.connect(button, 'onclick', ebook, "download");
159 // TODO: more actions (renew, checkin)
162 dojo.addClass('no_ebook_circs', "hidden");
163 dojo.removeClass('ebook_circs_main', "hidden");
167 function updateHoldView() {
168 if (myopac_page === 'ebook_holds_ready') {
169 // only show holds that are ready for checkout
170 var holds = xacts.holds_ready;
172 var holds_pending = xacts.holds_pending;
173 var holds_ready = xacts.holds_ready;
175 // combine all holds into a single list, ready-for-checkout holds first
176 var holds = holds_ready.concat(holds_pending);
179 if (holds.length < 1) {
180 dojo.removeClass('no_ebook_holds', "hidden");
182 dojo.empty('ebook_holds_main_table_body');
183 dojo.forEach(holds, function(h) {
186 hold_status = l_strings.ready_for_checkout;
187 } else if (h.is_frozen) {
188 hold_status = l_strings.suspended;
190 hold_status = h.queue_position + ' / ' + h.queue_size;
192 h.doCancelHold = function() {
193 var vendor = this.vendor;
194 var title_id = this.title_id;
195 checkSession(vendor, function() {
196 var ebook = new Ebook(vendor, title_id);
197 ebook.cancelHold(authtoken, patron_id, function(resp) {
198 if (resp.error_msg) {
199 console.log('Cancel hold failed: ' + resp.error_msg);
200 dojo.removeClass('ebook_cancel_hold_failed', "hidden");
202 console.log('Cancel hold succeeded!');
203 dojo.destroy("hold-" + ebook.id);
204 dojo.removeClass('ebook_cancel_hold_succeeded', "hidden");
205 // Updating the transaction cache to remove the canceled hold
206 // is inconvenient, so we skip cleanupAfterAction() and merely
207 // clear transaction cache to force a refresh on next page load.
208 dojo.cookie('ebook_xact_cache', '', {path: '/', expires: '-1h'});
213 var tr = dojo.create("tr", { id: "hold-" + h.title_id }, dojo.byId('ebook_holds_main_table_body'));
214 dojo.create("td", { innerHTML: h.title }, tr);
215 dojo.create("td", { innerHTML: h.author }, tr);
216 dojo.create("td", { innerHTML: h.expire_date }, tr);
217 dojo.create("td", { innerHTML: hold_status }, tr);
218 var actions_td = dojo.create("td", null, tr);
219 var button = dojo.create("input", { id: "cancel-hold-" + h.title_id, type: "button", value: l_strings.cancel_hold }, actions_td);
220 dojo.connect(button, 'onclick', h, "doCancelHold");
222 dojo.addClass('no_ebook_holds', "hidden");
223 dojo.removeClass('ebook_holds_main', "hidden");
227 // set up page for user to perform a checkout
228 function getReadyForCheckout() {
229 if (typeof ebook_action.type === 'undefined')
231 if (typeof active_ebook === 'undefined') {
232 console.log('No active ebook specified, cannot prepare for checkout');
233 dojo.removeClass('ebook_checkout_failed', "hidden");
235 active_ebook.getDetails( function(ebook) {
236 dojo.empty('ebook_circs_main_table_body');
237 var tr = dojo.create("tr", null, dojo.byId('ebook_circs_main_table_body'));
238 dojo.create("td", { innerHTML: ebook.title }, tr);
239 dojo.create("td", { innerHTML: ebook.author }, tr);
240 dojo.create("td", null, tr);
241 dojo.create("td", { id: "checkout-button-td" }, tr);
242 if (typeof active_ebook.formats !== 'undefined') {
243 var select = dojo.create("select", { id: "checkout-format" }, dojo.byId('checkout-button-td'));
244 dojo.forEach(active_ebook.formats, function(f) {
245 dojo.create("option", { value: f.id, innerHTML: f.name }, select);
248 var button = dojo.create("input", { id: "checkout-button", type: "button", value: l_strings.checkout }, dojo.byId('checkout-button-td'));
249 ebook.conns.checkout = dojo.connect(button, 'onclick', "doCheckout");
250 dojo.removeClass('ebook_circs_main', "hidden");
255 // set up page for user to place a hold
256 function getReadyForHold() {
257 if (typeof ebook_action.type === 'undefined')
259 if (typeof active_ebook === 'undefined') {
260 console.log('No active ebook specified, cannot prepare for hold');
261 dojo.removeClass('ebook_hold_failed', "hidden");
263 active_ebook.getDetails( function(ebook) {
264 dojo.empty('ebook_holds_main_table_body');
265 var tr = dojo.create("tr", null, dojo.byId('ebook_holds_main_table_body'));
266 dojo.create("td", { innerHTML: ebook.title }, tr);
267 dojo.create("td", { innerHTML: ebook.author }, tr);
268 dojo.create("td", null, tr); // Expire Date
269 dojo.create("td", null, tr); // Status
270 dojo.create("td", { id: "hold-button-td" }, tr);
271 if (ebook_action.type == 'place_hold') {
272 var button = dojo.create("input", { id: "hold-button", type: "button", value: l_strings.place_hold }, dojo.byId('hold-button-td'));
273 ebook.conns.checkout = dojo.connect(button, 'onclick', "doPlaceHold");
275 dojo.removeClass('ebook_holds_main', "hidden");
280 function cleanupAfterAction() {
281 // unset variables related to the transaction we have performed,
282 // to avoid any weirdness on page reload
284 // update page to account for successful checkout
286 addTransactionsToPage();
287 // clear transaction cache to force a refresh on next page load
288 dojo.cookie('ebook_xact_cache', '', {path: '/', expires: '-1h'});
291 // check out our active ebook
292 function doCheckout() {
293 var ses = dojo.cookie(active_ebook.vendor); // required when inspecting checkouts for download_url
294 active_ebook.checkout(authtoken, patron_id, function(resp) {
295 if (resp.error_msg) {
296 console.log('Checkout failed: ' + resp.error_msg);
297 dojo.removeClass('ebook_checkout_failed', "hidden");
300 console.log('Checkout succeeded!');
301 dojo.destroy('checkout-button');
302 dojo.destroy('checkout-format'); // remove optional format selector
303 dojo.removeClass('ebook_checkout_succeeded', "hidden");
304 // add our successful checkout to top of transaction cache
306 title_id: active_ebook.id,
307 title: active_ebook.title,
308 author: active_ebook.author,
309 due_date: resp.due_date,
311 console.log('new_xact.finish()');
312 xacts.checkouts.unshift(this);
313 cleanupAfterAction();
314 // When we switch to jQuery, we can use .one() instead of .on(),
315 // obviating the need for an explicit disconnect here.
316 dojo.disconnect(active_ebook.conns.checkout);
319 if (resp.download_url) {
320 // Use download URL from checkout response, if available.
321 new_xact.download_url = resp.download_url;
322 dojo.create("a", { href: new_xact.download_url, innerHTML: l_strings.download }, dojo.byId('checkout-button-td'));
324 } else if (resp.download_redirect) {
325 // Use download URL from checkout response, if available.
326 new_xact.download_redirect = resp.download_redirect;
327 dojo.create("a", { target: "_blank", href: new_xact.download_redirect, innerHTML: l_strings.download }, dojo.byId('checkout-button-td'));
329 } else if (typeof resp.formats !== 'undefined') {
330 // User must select download format from list of options.
331 var select = dojo.create("select", { id: "download-format" }, dojo.byId('checkout-button-td'));
332 for (f in resp.formats) {
333 dojo.create("option", { value: resp.formats[f], innerHTML: f }, select);
335 var button = dojo.create("input", { id: "download-button", type: "button", value: l_strings.download }, dojo.byId('checkout-button-td'));
336 active_ebook.conns.download = dojo.connect(button, 'onclick', active_ebook, "download");
338 } else if (typeof resp.xact_id !== 'undefined') {
339 // No download URL provided by API checkout response. Grab fresh
340 // list of user checkouts from API, find the just-completed
341 // checkout by transaction ID, and get the download URL from that.
342 // We call the OpenSRF method directly because Relation.getCheckouts()
343 // results in scoping issues when retrieving the vendor session cookie.
344 new_xact.xact_id = resp.xact_id;
345 new OpenSRF.ClientSession('open-ils.ebook_api').request({
346 method: 'open-ils.ebook_api.patron.get_checkouts',
347 params: [ authtoken, ses, patron_id ],
349 oncomplete: function(r) {
352 dojo.forEach(resp.content(), function(x) {
353 if (x.xact_id === new_xact.xact_id) {
354 new_xact.download_url = x.download_url;
355 dojo.create("a", { href: new_xact.download_url, innerHTML: l_strings.download }, dojo.byId('checkout-button-td'));
367 // place hold on our active ebook
368 function doPlaceHold() {
369 active_ebook.placeHold(authtoken, patron_id, function(resp) {
370 if (resp.error_msg) {
371 console.log('Place hold failed: ' + resp.error_msg);
372 dojo.removeClass('ebook_place_hold_failed', "hidden");
374 console.log('Place hold succeeded!');
375 dojo.destroy('hold-button');
376 dojo.removeClass('ebook_place_hold_succeeded', "hidden");
378 title_id: active_ebook.id,
379 title: active_ebook.title,
380 author: active_ebook.author,
381 queue_position: resp.queue_position,
382 queue_size: resp.queue_size,
383 expire_date: resp.expire_date
385 if ( resp.is_ready || (resp.queue_position === 1 && resp.queue_size === 1) ) {
386 xacts.holds_ready.unshift(new_hold);
388 xacts.holds_pending.unshift(new_hold);
390 cleanupAfterAction();
395 // deserialize transactions from cache, returning them as a JS object
396 function getCachedTransactions() {
397 console.log('retrieving cached transaction details');
399 var current_cache = dojo.cookie('ebook_xact_cache');
401 cache_obj = JSON.parse(current_cache);
402 xacts.checkouts = cache_obj.checkouts;
403 xacts.holds_pending = cache_obj.holds_pending;
404 xacts.holds_ready = cache_obj.holds_ready;
409 // add a single vendor's transactions to transaction cache
410 function addTransactionsToCache(rel) {
411 console.log('updating transaction cache');
413 var updated_xacts = {
418 // preserve any transactions with other vendors
419 dojo.forEach(xacts.checkouts, function(xact) {
420 if (xact.vendor !== v)
421 updated_xacts.checkouts.push(xact);
423 dojo.forEach(xacts.holds_pending, function(xact) {
424 if (xact.vendor !== v)
425 updated_xacts.holds_pending.push(xact);
427 dojo.forEach(xacts.holds_ready, function(xact) {
428 if (xact.vendor !== v)
429 updated_xacts.holds_ready.push(xact);
431 // add transactions from current vendor
432 dojo.forEach(rel.checkouts, function(xact) {
433 updated_xacts.checkouts.push(xact);
435 dojo.forEach(rel.holds_pending, function(xact) {
436 updated_xacts.holds_pending.push(xact);
438 dojo.forEach(rel.holds_ready, function(xact) {
439 updated_xacts.holds_ready.push(xact);
441 // TODO sort transactions by date
442 // save transactions to cache
443 xacts = updated_xacts;
444 var new_cache = JSON.stringify(xacts);
445 dojo.cookie('ebook_xact_cache', new_cache, {path: '/'});
446 // update current page
448 addTransactionsToPage();