Bug 21082: Update OverDrive authentication method
[koha.git] / koha-tmpl / opac-tmpl / bootstrap / js / overdrive.js
1 if ( typeof KOHA == "undefined" || !KOHA ) {
2     var KOHA = {};
3 }
4
5 KOHA.OverDrive = ( function() {
6     var proxy_base_url = '/cgi-bin/koha/svc/overdrive_proxy';
7     var library_base_url = 'http://api.overdrive.com/v1/libraries/';
8     return {
9         Get: function( url, params, callback ) {
10             $.ajax( {
11                 type: 'GET',
12                 url: url.replace( /https?:\/\/api.overdrive.com\/v1/, proxy_base_url ),
13                 dataType: 'json',
14                 data: params,
15                 error: function( xhr, error ) {
16                     try {
17                         callback( JSON.parse( xhr.responseText ));
18                     } catch ( e ) {
19                         callback( {error: xhr.responseText || true} );
20                     }
21                 },
22                 success: callback
23             } );
24         },
25         GetCollectionURL: function( library_id, callback ) {
26             if ( KOHA.OverDrive.collection_url ) {
27                 callback( KOHA.OverDrive.collection_url );
28                 return;
29             }
30
31             KOHA.OverDrive.Get(
32                 library_base_url + library_id,
33                 {},
34                 function ( data ) {
35                     if ( data.error ) {
36                         callback( data );
37                         return;
38                     }
39
40                     KOHA.OverDrive.collection_url = data.links.products.href;
41
42                     callback( data.links.products.href );
43                 }
44             );
45         },
46         Search: function( library_id, q, limit, offset, callback ) {
47             KOHA.OverDrive.GetCollectionURL( library_id, function( data ) {
48                 if ( data.error ) {
49                     callback( data );
50                     return;
51                 }
52
53                 KOHA.OverDrive.Get(
54                     data,
55                     {q: q, limit: limit, offset: offset},
56                     callback
57                 );
58             } );
59         }
60     };
61 } )();
62
63 KOHA.OverDriveCirculation = new function() {
64     var svc_url = '/cgi-bin/koha/svc/overdrive';
65
66     var error_div = $('<div class="overdrive-error">');
67     function display_error ( error ) {
68         error_div.text(error);
69     }
70
71     var login_link = $('<a href="#">')
72         .click(function(e) {
73             e.preventDefault();
74             var passwd = OD_password_required ? prompt("Please enter your password") : "";
75             login(passwd);
76         })
77         .text(_("Login to OverDrive account"));
78     var login_div = $('<div class="overdrive-login">').append(login_link);
79
80     var details = null;
81
82     function is_logged_in() {
83         return details ? details.is_logged_in : false;
84     }
85
86     var checkout_popup = null;
87     $( document ).ready(function() {
88         var p = window.opener;
89         if (p) {
90             try { cb = p.refresh_overdrive_account_details;}
91             catch(err){ return; } //Catch error if opener is not accessible
92             if (cb) {
93                 cb();
94             } else {
95                 p.location.reload();
96             }
97             window.close();
98         }
99         checkout_popup = $("#overdrive-checkout");
100     });
101
102     function display_account (container, data) {
103         if (!data.is_logged_in) {
104             $(container).append(login_div);
105             return;
106         }
107
108         var overdrive_link = $('<a href="https://www.overdrive.com/account/" target="overdrive-account" class="overdrive-link" style="float:right">')
109             .text("OverDrive Account Page");
110         $(container).append(overdrive_link);
111
112         var logout_link = $('<a href="#logout" class="overdrive-logout" style="float:left">')
113             .click(function(e) {
114                 e.preventDefault();
115                 $(container).empty().append(error_div);
116                 logout(function(data) {
117                     display_account(container, data);
118                 });
119             }).text(_("Logout from OverDrive account"));
120         $(container).append(logout_link);
121         $(container).append('<br style="clear:both;"/>');
122
123         if (data.checkouts) {
124             var checkouts_div = $('<div class="overdrive-div">').html('<h3>' + _("Checkouts") + '</h3>');
125             var checkouts_list = $('<ul class="overdrive-list">');
126             data.checkouts.items.forEach(function(item) {
127                 item_line(checkouts_list, item);
128             });
129             checkouts_div.append(checkouts_list);
130             $(container).append(checkouts_div);
131         }
132
133         if (data.holds) {
134             var holds_div = $('<div class="overdrive-div">').html('<h3>' + _("Holds") + '</h3>');
135             var holds_list = $('<ul class="overdrive-list">');
136             data.holds.items.forEach(function(item) {
137                 item_line(holds_list, item);
138             });
139             holds_div.append(holds_list);
140             $(container).append(holds_div);
141         }
142     }
143
144     function item_line(ul_el, item) {
145         var line = $('<li class="overdrive-item">');
146         if (item.images) {
147             var thumb_url = item.images.thumbnail;
148             if (thumb_url) {
149                 $('<img class="overdrive-item-thumbnail">')
150                     .attr("src", thumb_url)
151                     .appendTo(line);
152             }
153         }
154         $('<div class="overdrive-item-title">')
155             .text(item.title)
156             .appendTo(line);
157         $('<div class="overdrive-item-subtitle">')
158             .html(item.subtitle)
159             .appendTo(line);
160         $('<div class="overdrive-item-author">')
161             .text(item.author)
162             .appendTo(line);
163         var actions = $('<span class="actions">');
164         display_actions(actions, item.id);
165         $('<div id="action_'+item.id+'" class="actions-menu">')
166             .append(actions)
167             .appendTo(line);
168
169         $(ul_el).append(line);
170     }
171
172     function svc_ajax ( method, params, success_callback ) {
173         return $.ajax({
174             method: method,
175             dataType: "json",
176             url: svc_url,
177             data: params,
178             success: function (data) {
179                 if (data.error) {
180                     display_error(data.error);
181                 }
182                 success_callback(data);
183             },
184             error: function(jqXHR, textStatus, errorThrown) {
185                 display_error(errorThrown);
186             }
187         });
188     }
189
190     function load_account_details ( callback ) {
191         svc_ajax('get', { action: "account" }, function(data) {
192             details = data;
193             callback(data);
194         });
195     }
196
197     function login(p) {
198         svc_ajax('get', { action: "login", password: p }, function(data) {
199             details = null;
200             if( data.login_success ){
201                 $(login_div).detach();
202                 if( $("#overdrive-results-page").length > 0 ){
203                     location.reload();
204                 } else {
205                 KOHA.OverDriveCirculation.display_account_details( $("#opac-user-overdrive") );
206                 }
207             }
208         });
209     }
210
211     function logout (callback) {
212         svc_ajax('post', { action: "logout" }, function(data) {
213             details = null;
214             callback(data);
215         });
216     }
217
218     function item_action (params, el, copies_available) {
219         var id = params.id;
220         svc_ajax('post', params, function(data) {
221             if (data.checkouts) {
222                 details.checkouts = data.checkouts;
223             }
224             if (data.holds) {
225                 details.holds = data.holds;
226             }
227             display_actions(el, id, copies_available);
228         });
229     }
230
231     function item_is_checked_out (id) {
232         if ( !(details && details.checkouts) ) {
233             return null;
234         }
235         var id_uc = id.toUpperCase();
236         var items = details.checkouts.items;
237         for (var i = 0; i < items.length; i++) {
238             if ( items[i].id.toUpperCase() == id_uc ) {
239                 return items[i];
240             }
241         }
242         return null;
243     }
244
245     function item_is_on_hold (id) {
246         if ( !(details && details.holds) ) {
247             return false;
248         }
249         var id_uc = id.toUpperCase();
250         var items = details.holds.items;
251         for (var i = 0; i < items.length; i++) {
252             if ( items[i].id.toUpperCase() == id_uc ) {
253                 return items[i];
254             }
255         }
256         return null;
257     }
258
259     function display_actions(el, id, copies_available) {
260         $(el).empty();
261         if (is_logged_in()) {
262
263             var item = item_is_checked_out(id);
264             if (item) {
265                 var expires = new Date(item.expires);
266                 $('<span class="overdrive-item-status">')
267                     .text(_("Checked out until") + " " + expires.toLocaleString())
268                     .appendTo(el);
269                 $(el).append(" ");
270
271                 if (item.format) {
272                     var download = $('<a href="#">').appendTo(el);
273                     decorate_button(download, _("Download") + " " + item.format);
274                     svc_ajax('get', {action: "download-url", id: id, format: item.format}, function(data) {
275                         download.attr("href", data.action);
276                     });
277                     $(el).append(" ");
278                 }
279
280                 if (item.formats) {
281                     var lockable_formats = [];
282                     for (var f in item.formats) {
283                         if (f == item.format) continue;
284
285                         if (item.formats[f]) {
286                             var access = $('<a target="_blank">').appendTo(el);
287                             decorate_button(access, _("Access online") + " " + f);
288                             svc_ajax('get', {action: "download-url", id: id, format: f}, function(data) {
289                                 access.attr("href", data.action);
290                             });
291                             $(el).append(" ");
292                         }
293                         else {
294                             lockable_formats.push(f);
295                         }
296                     }
297                     if (lockable_formats.length > 0 && checkout_popup) {
298                         $(el).append( ajax_button(_("Download as"), function() {
299                             checkout_format(el, id, lockable_formats, copies_available);
300                         }) ).append(" ");
301                     }
302                 }
303
304                 if (item.format) return item;
305
306                 $(el).append( ajax_button(_("Check in"), function() {
307                     if( confirm(_("Are you sure you want to return this item?")) ) {
308                         item_action({action: "return", id: id}, el, copies_available + 1);
309                     }
310                 }) );
311
312                 return item;
313             }
314
315             item = item_is_on_hold(id);
316             if (item) {
317                 $('<span class="overdrive-status">')
318                     .text(_("On hold"))
319                     .appendTo(el);
320                 $(el).append(" ");
321             }
322
323             if(copies_available && checkout_popup) {
324                 $(el).append( ajax_button(_("Check out"), function() {
325                     if( confirm(_("Are you sure you want to checkout this item?")) ) {
326                         svc_ajax('post', {action: "checkout", id: id}, function(data) {
327                             if (data.checkouts) {
328                                 details.checkouts = data.checkouts;
329                             }
330                             if (data.holds) {
331                                 details.holds = data.holds;
332                             }
333                             item = display_actions(el, id, copies_available - 1);
334                             if (item && item.formats && !item.format) {
335                                 var has_available_formats = false;
336                                 var lockable_formats = [];
337                                 for (var f in item.formats) {
338                                     if (item.formats[f]) {
339                                         has_available_formats = true;
340                                         break;
341                                     }
342                                     lockable_formats.push(f);
343                                 }
344
345                                 if (!has_available_formats) {
346                                     checkout_format(el, id, lockable_formats, copies_available - 1);
347                                 }
348                             }
349                         });
350                     }
351                 }) );
352             }
353             else if (!item) {
354                 $(el).append( ajax_button(_("Place hold"), function() {
355                     item_action({action: "place-hold", id: id}, el, copies_available);
356                 }) );
357             }
358
359             if (item) {
360                 $(el).append( ajax_button(_("Cancel"), function() {
361                     if( confirm(_("Are you sure you want to cancel this hold?")) ) {
362                         item_action({action: "remove-hold", id: id}, el, copies_available);
363                     }
364                 }) );
365             }
366             return item;
367         }
368     }
369
370     function ajax_button(label, on_click) {
371         var button = $('<a href="#">')
372             .click(function(e) {
373                 e.preventDefault();
374                 on_click();
375             });
376         decorate_button(button, label);
377         return button;
378     }
379
380     function decorate_button(button, label) {
381         $(button)
382             .addClass("btn btn-primary btn-mini")
383             .css("color","white")
384             .text(label);
385     }
386
387     function checkout_format(el, id, formats, copies_available) {
388         if (formats.length == 0) {
389             alert(_("Item cannot be checked out - no available formats"));
390             return false;
391         }
392
393         var checkout_format_list = checkout_popup.find("ul.overdrive-format-list").empty();
394         formats.forEach(function (item) {
395             var li = $('<li>').appendTo(checkout_format_list);
396             $('<input name="checkout-format" type="radio">')
397                 .val(item)
398                 .appendTo(li);
399             li.append(item);
400         });
401         checkout_popup.modal("show");
402         checkout_popup.find(".overdrive-checkout-submit").click(function(e) {
403             e.preventDefault();
404             var format = checkout_format_list.find("input[type='radio'][name='checkout-format']:checked").val();
405             item_action({action: "checkout-format", id: id, format: format}, el, copies_available);
406             $(this).unbind( e );
407             checkout_popup.modal("hide");
408         });
409     }
410
411     this.with_account_details = function( el, callback ) {
412         $(el).append(error_div);
413         load_account_details(function(data) {
414             if (!data.is_logged_in) {
415                 $(el).append(login_div);
416             }
417             callback(data);
418         });
419     }
420
421     this.display_account_details = function( el ) {
422         window.refresh_overdrive_account_details = function () {
423             KOHA.OverDriveCirculation.display_account_details( el );
424         }
425         $(el).empty().append(error_div);
426         load_account_details(function(data) {
427             display_account(el, data);
428         });
429     };
430
431     this.display_error = function( el, error ) {
432         $(el).empty().append(error_div);
433         display_error(error);
434     };
435
436     this.is_logged_in = is_logged_in;
437
438     this.add_actions = function(el, id, copies_available) {
439         var actions = $('<span class="actions">');
440         display_actions(actions, id, copies_available);
441         $('<div id="action_'+id+'" class="actions-menu">')
442             .append(actions)
443             .appendTo(el);
444     };
445 }