Bug 26037: openlibrary.org is hit on every Koha requests
[koha.git] / koha-tmpl / opac-tmpl / bootstrap / js / openlibrary.js
1 if (typeof KOHA == "undefined" || !KOHA) {
2     var KOHA = {};
3 }
4
5 /**
6  * A namespace for OpenLibrary related functions.
7  */
8 KOHA.OpenLibrary = new function() {
9
10     /**
11      * Search all:
12      *    <div title="biblionumber" id="isbn" class="openlibrary-thumbnail"></div>
13      * or
14      *    <div title="biblionumber" id="isbn" class="openlibrary-thumbnail-preview"></div>
15      * and run a search with all collected isbns to Open Library Book Search.
16      * The result is asynchronously returned by OpenLibrary and catched by
17      * olCallBack().
18      */
19     this.GetCoverFromIsbn = function() {
20         var bibkeys = [];
21         $("[id^=openlibrary-thumbnail]").each(function(i) {
22             bibkeys.push("ISBN:" + $(this).attr("class")); // id=isbn
23         });
24         bibkeys = bibkeys.join(',');
25         var scriptElement = document.createElement("script");
26         scriptElement.setAttribute("id", "jsonScript");
27         scriptElement.setAttribute("src",
28             "https://openlibrary.org/api/books?bibkeys=" + escape(bibkeys) +
29             "&callback=KOHA.OpenLibrary.olCallBack&jscmd=data");
30         scriptElement.setAttribute("type", "text/javascript");
31         document.documentElement.firstChild.appendChild(scriptElement);
32     }
33
34     /**
35      * Add cover pages <div
36      * and link to preview if div id is gbs-thumbnail-preview
37      */
38     this.olCallBack = function(booksInfo) {
39         for (id in booksInfo) {
40             var book = booksInfo[id];
41             var isbn = id.substring(5);
42             $("[id^=openlibrary-thumbnail]."+isbn).each(function() {
43                 var is_opacdetail = /openlibrary-thumbnail-preview/.exec($(this).attr("id"));
44                 var a = document.createElement("a");
45                 a.href = booksInfo.url;
46                 if (book.cover) {
47                     var img = document.createElement("img");
48                     if (is_opacdetail) {
49                         img.src = book.cover.medium;
50                         $(this).empty().append(img);
51                         $(this).append('<div class="results_summary">' + '<a href="' + book.url + '">' + OL_PREVIEW + '</a></div>');
52                     } else {
53                         img.src = book.cover.medium;
54                         img.height = '110';
55                         $(this).append(img);
56                     }
57                 } else {
58                     var message =  document.createElement("span");
59                     $(message).attr("class","no-image");
60                     $(message).html(NO_OL_JACKET);
61                     $(this).append(message);
62                 }
63             });
64         }
65     }
66
67     var search_url = 'https://openlibrary.org/search?';
68     this.searchUrl = function( q ) {
69         var params = {q: q};
70         return search_url + $.param(params);
71     };
72
73     var search_url_json = 'https://openlibrary.org/search.json';
74     this.search = function( q, page_no, callback ) {
75         var params = {q: q};
76         if (page_no) {
77             params.page = page_no;
78         }
79         $.ajax( {
80             type: 'GET',
81             url: search_url_json,
82             dataType: 'json',
83             data: params,
84             error: function( xhr, error ) {
85                 try {
86                     callback( JSON.parse( xhr.responseText ));
87                 } catch ( e ) {
88                     callback( {error: xhr.responseText || true} );
89                 }
90             },
91             success: callback
92         } );
93     };
94 };
95 /* readapi_automator.js */
96
97 /*
98 This script helps to put readable links to Open Library books into
99 online book catalogs.
100 When loaded, it searches the DOM for <div> elements with class
101 "ol_readapi_book", extracts book identifiers from them (e.g. isbn,
102 lccn, etc.) and puts those into an asynchronous call to the Read API.
103 When the call returns, the results are used to add clickable links
104 to the "ol_readapi_book" elements found earlier.
105 A demonstration use of this script is available here:
106 http://internetarchive.github.com/read_api_extras/readapi_demo.html
107 */
108
109 var ol_readapi_automator =
110 (function () { // open anonymous scope for tidiness
111
112 // 'constants'
113 var readapi_bibids = ['isbn', 'lccn', 'oclc', 'olid', 'iaid', 'bibkeys'];
114 var magic_classname = 'ol_readapi_book';
115 var ol_readapi_books = $("." + magic_classname );
116 var result;
117
118 // added to book divs to correlate with API results
119 var magic_bookid = 'ol_bookid';
120 var ol_button_classname = 'ol_readapi_button';
121
122 // Find all book divs and concatenate ids from them to create a read
123 // API query url
124 function create_query() {
125     var q = 'https://openlibrary.org/api/volumes/brief/json/';
126
127     function add_el(i, el) {
128         // tag with number found so it's easy to discover later
129         // (necessary?  just go by index?)
130         // (choose better name?)
131         $(el).attr(magic_bookid, i);
132
133         if (i > 0) {
134             q += '|';
135         }
136         q += 'id:' + i;
137
138         for (bi in readapi_bibids) {
139             bibid = readapi_bibids[bi];
140             if ($(el).attr(bibid)) {
141                 q += ';' + bibid + ':' + $(el).attr(bibid);
142             }
143         }
144     }
145
146     $('.' + magic_classname).each(add_el);
147     return q;
148 }
149
150 function make_read_button(bookdata) {
151     buttons = {
152         'full access':
153         "http://openlibrary.org/images/button-read-open-library.png",
154         'lendable':
155         "http://openlibrary.org/images/button-borrow-open-library.png",
156         'checked out':
157         "http://openlibrary.org/images/button-checked-out-open-library.png"
158     };
159     if (bookdata.items.length == 0) {
160         return false;
161     }
162     first = bookdata.items[0];
163     if (!(first.status in buttons)) {
164         return false;
165     }
166     result = '<a href="' + first.itemURL + '">' +
167       '<img class="' + ol_button_classname +
168       '" src="' + buttons[first.status] + '"/></a>';
169     return result;
170 }
171
172 // Default function for decorating document elements with read API data
173 function default_decorate_el_fn(el, bookdata) {
174     // Note that 'bookdata' may be undefined, if the Read API call
175     // didn't return results for this book
176     var decoration;
177     if (bookdata) {
178         decoration = make_read_button(bookdata);
179     }
180     if (decoration) {
181         el.innerHTML += decoration;
182     } else {
183         el.style.visibility = 'hidden';
184     }
185 }
186
187 function do_query(q, decorate_el_fn) {
188     if (!decorate_el_fn) {
189         decorate_el_fn = default_decorate_el_fn;
190     }
191     var starttime = (new Date()).getTime();
192
193     // Call a function on each <div class="ol_readapi_book"> element
194     // with the target element and the data found for that element.
195     // Use decorate_el_fn if supplied, falling back to
196     // default_decorate_el_fn, above.
197     function query_callback(data, textStatus, jqXHR) {
198         var endtime = (new Date()).getTime();
199         var duration = (endtime - starttime) / 1000;
200         // console.log('took ' + duration + ' seconds');
201
202         $('.' + magic_classname).each(function(i, el) {
203                 var bookid = $(el).attr(magic_bookid);
204                 if (bookid && bookid in data) {
205                     decorate_el_fn(el, data[bookid]);
206                 } else {
207                     decorate_el_fn(el);
208                 }
209             });
210     }
211
212     // console.log('calling ' + q);
213     $.ajax({ url: q,
214                 data: { 'show_all_items': 'true' },
215                 dataType: 'jsonp',
216                 success: query_callback
217                 });
218 }
219
220 if( ol_readapi_books.length > 0 ){
221     // Do stuff
222     var q = create_query();
223     do_query(q);
224
225     result = {
226         do_query: do_query,
227         create_query: create_query,
228         make_read_button: make_read_button
229     };
230 }
231
232 return result;
233 })(); // close anonymous scope
234
235 /*
236 Possible futures:
237 * Support alternate query targets, e.g. Hathi
238 * show_all_items
239 * show_inlibrary
240 * ezproxy prefix (implies show_inlibrary?)
241 * console debug output? (check all console.log)
242 */