1 //QuanLib: eBook Library
2 //(C) 2017 by Christian Jaekl (cejaekl@yahoo.com)
10 map: {}, // map from book.Id to index into cache[]
14 milliSecs: 500, // time to wait before displaying tooltip
19 function adjustPos(setting) {
20 var value = parseInt(setting)
22 if (g_state.first === value) {
27 var maxFirst = g_state.count - g_state.pageSize;
31 } else if (value > maxFirst) {
32 g_state.first = maxFirst;
34 g_state.first = value;
37 g_state.last = g_state.first + g_state.pageSize - 1;
38 if (g_state.last >= g_state.count) {
39 g_state.last = g_state.count - 1;
42 document.getElementById('slider').value = setting;
47 function bookHtml(book) {
48 var result = '<div class="book">'
51 + '<td><a href="/book/' + book.Id + '">';
52 if (0 == book.CoverId) {
53 result += '(No cover available)'
55 result += '<img class="cover-thumb" src="/download/' + book.CoverId + '"/>'
58 + '<td onclick="displayDetails(' + book.Id + ');" '
59 + ' onmouseout="stopTooltipTimer(); hideDetails();" '
60 + ' onmouseover="startTooltipTimer(' + book.Id + ');">'
61 + '<p><b>' + book.Title + '</b></p>'
63 + '<i>' + book.AuthorReading + '</i>';
64 if (typeof(book.SeriesName) !== 'undefined' && book.SeriesName.length > 0) {
65 result += '<br/><i>' + book.SeriesName + ' ' + book.Volume + '</i>';
75 //ce(s): "clear if empty()"
76 //return s, unless it's undefined, in which case return an empty ("clear") string
78 if (typeof s !== 'undefined') {
84 function constructSearchUrl() {
85 var url = window.location.protocol + '//' + window.location.host + '/search/';
88 var terms = ['aut', 'tit', 'ser'];
91 var term = terms[idx];
92 var elem = document.getElementById(term);
94 console.log('Error: could not find form element for search term "' + term + '".');
98 var value = elem.value;
99 if (value.length > 0) {
107 url += term + '=' + encodeURIComponent('%' + value + '%');
114 // Set the book ID for the details pane, and then show it
115 function displayDetails(bookId) {
116 console.log('displayDetails()', bookId);
117 g_state.tooltip.bookId = bookId;
121 function hideDetails() {
122 var elem = document.getElementById('details');
124 elem.style.display = 'none';
128 if (g_state.last < (g_state.count - 1)) {
129 adjustPos(g_state.first + g_state.pageSize);
134 if (g_state.first > 0) {
135 adjustPos(g_state.first - g_state.pageSize);
139 function onSlide(value) {
143 function onSearch() {
144 console.log('onSearch()');
146 var url = constructSearchUrl();
148 report('Loading data from server, please wait...')
149 console.log('Fetching: "' + url + '"...')
151 fetch(url, {method:'GET', cache:'default'})
152 .then(response => response.json())
153 .then((jsonValue) => {
154 console.log('JSON response: ', jsonValue);
155 g_state.ids = jsonValue
156 g_state.count = g_state.ids.length;
159 var elem = document.getElementById('slider');
160 elem.max = g_state.count;
165 var msg = 'Error fetching JSON from URL: ' + url + ': ' + err + ':' + err.stack;
171 function refreshData() {
172 report('Loading details for books ' + g_state.first + ' through ' + g_state.last + ', please wait...');
175 var url = '/info/?ids=';
177 for (i = g_state.first; i <= g_state.last; ++i) {
178 if (i > g_state.first) {
181 var id = g_state.ids[i];
183 g_state.map[id] = i - g_state.first;
186 fetch(url, {method:'GET', cache:'default'})
187 .then(response => response.json())
188 .then((jsonValue) => {
189 console.log('JSON response for info: ', jsonValue);
191 g_state.cache = jsonValue;
195 var msg = 'Error fetching book details via URL: ' + url + ': ' + err;
196 console.log(msg, err.stack);
201 function refreshLayout() {
204 var limit = g_state.last - g_state.first;
205 for (i = 0; i <= limit; ++i) {
206 var book = g_state.cache[i];
207 html += bookHtml(book);
210 document.getElementById('books').innerHTML = html;
211 document.getElementById('first').innerHTML = (g_state.first + 1);
212 document.getElementById('last').innerHTML = (g_state.last + 1);
213 document.getElementById('count').innerHTML = g_state.count;
216 function report(message) {
217 document.getElementById('books').innerHTML = message;
220 function showDetails() {
221 console.log('showDetails()', g_state.tooltip.bookId);
223 var id = g_state.tooltip.bookId;
224 var elem = document.getElementById('details');
225 var index = g_state.map[id];
226 var book = g_state.cache[index];
227 var html = '<div><p><b>' + book.Title + '</b></p>'
228 + '<p><i>' + ce(book.AuthorReading) + '<br/>' + ce(book.Series) + ' ' + ce(book.Volume) + '</i></p></div><div>'
229 + ce(book.Description)
232 elem.innerHTML = html;
233 elem.style.display = 'block';
236 function startTooltipTimer(bookId) {
237 if (typeof g_state.tooltip.timer !== 'undefined') {
238 clearTimer(g_state.tooltip.timer);
240 g_state.tooltip.bookId = bookId;
241 g_state.tooltip.timer = setTimeout(showDetails, g_state.tooltip.milliSecs);
244 function stopTooltipTimer() {
245 if (typeof g_state.tooltip.timer === 'undefined') {
248 clearTimeout(g_state.tooltip.timer);
249 g_state.tooltip.timer = undefined;