nicer spinner animation, some cleaning
[wl-mobile.git] / assets / www / js / view.js
1 /*
2  * This file is part of WolneLektury-Mobile, licensed under GNU Affero GPLv3 or later.
3  * Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4  */
5
6 var View = new function() {
7         var self = this;
8         //self.minOffset = 1000;
9         self.categories = {
10                         autor: 'Autorzy', 
11                         rodzaj: 'Rodzaje',
12                         gatunek: 'Gatunki',
13                         epoka: 'Epoki'
14         };
15         self.category_msc = {
16                 autor: 'autorze',
17                 rodzaj: 'rodzaju',
18                 gatunek: 'gatunku',
19                 epoka: 'epoce'
20         };
21         
22
23         self.init = function(success, error) {
24                 console.log('View.init');
25
26                 self._searchbox = document.getElementById("searchbox");
27                 self._searchinput = document.getElementById("search");
28                 self._content = document.getElementById("content");
29
30                 self.current = '';
31                 self.currentView = '';
32                 self.currentPar = '';
33                 self.currentTitle = '';
34
35                 document.getElementById("cover").style.display = 'none';
36
37                 self.checkNightMode();
38
39                 self.at_spinner = false;
40                 self.enter('');
41
42                 success && success();
43         };
44
45
46         this.sanitize = function(text) {
47                 return text.replace(/&/g, "&amp;").replace(/</g, "&lt;");
48         };
49
50         this.showSearch = function() {
51                 self._searchbox.style.display = "block";
52         };
53
54         this.hideSearch = function() {
55                 self._searchbox.style.display = "none";
56         };
57
58         this.spinner = function(text) {
59                 if (!text)
60                         text = "Ładowanie";
61                 if (self.at_spinner) {
62                         document.getElementById("spinnertext").innerHTML = text;
63                 }
64                 else {
65                         self._content.innerHTML = "<div class='spinner'><img src='img/spinner.png' /><div id='spinnertext'>" + text +"</div></div>";
66                         self.at_spinner = true;
67                 }
68                 setOffset(0);
69         };
70
71         this.content = function(text, offset) {
72                 console.log('content');
73                 self.at_spinner = false;
74
75                 self._content.innerHTML = '';
76                 self._content.innerHTML = text;
77                 setOffset(offset);
78         }
79
80         this.enter = function(url, offset) {
81                 console.log('View.enter: ' + url);
82
83                 var view = 'Index';
84                 var arg = null;
85
86                 if (url.length) {
87                         var slash_index = url.indexOf('/');
88                         if (slash_index != -1) {
89                                 view = url.substr(0, slash_index);
90                                 arg = url.substr(slash_index + 1);
91                         }
92                         else {
93                                 view = url;
94                         }
95                 }
96                 console.log('View.enter: ' + view + ' ' + arg);
97                 self.current = url;
98                 self.currentView = view;
99                 self.currentPar = arg;
100                 self['enter' + view](arg, offset);
101         }
102         
103         this.enterIndex = function(arg, offset) {
104                 console.log('enterIndex');
105                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
106                 self.showSearch();
107                 self.currentTitle = "Początek";
108                 var html = "";
109
110                 html += "<div class='buttons'>";
111                 html += Links.button('Last', '', 'Ostatnio czytane');
112                 html += Links.button('Bookmarks', '', 'Zakładki');
113
114                 for (category in self.categories)
115                         html += Links.button('Category', category, self.categories[category], 0);
116                 html += "</div>";
117                 
118                 html += "</div>" +"";
119                                 /*"<p id='logo'><img src='img/logo-wl-nq8.png' alt='Wolne Lektury' /><br/>\n" +
120                                 "szkolna biblioteka internetowa" +
121                                 "</p>";*/
122                 self.content(html, offset);
123         };
124         
125         this.enterBook = function(id, offset) {
126                 id = parseInt(id);
127                 console.log('enterBook: ' + id);
128                 Menu.setInfoButton("BookInfo", "Informacje o utworze", true);
129                 self.showSearch();
130
131                 Catalogue.withBook(id, function(book) {
132                         self.currentTitle = book.authors + ', ' + book.title;
133
134                         Catalogue.withChildren(id, function(children) {
135                                 var html = "<h1><span class='subheader'>";
136                                 html += book.authors;
137                                 html += "</span>" + book.title + "</h1>\n";
138                                 if (book.html_file) {
139                                         html += "<div class='buttons'>" + Links.button('BookText', id, "Czytaj tekst") + "</div>";
140                                 }
141                                 if (children.length) {
142                                         html += "<div class='buttons'>";
143                                         for (c in children) {
144                                                 child = children[c];
145                                                 html += Links.bookLink(child);
146                                         }
147                                         html += "</div>";
148                                 }
149                                 self.content(html, offset);                             
150                         });
151                 }, function() {
152                         History.goBack();
153                 });
154         };
155         
156         this.enterBookText = function(id, offset) {
157                 self.hideSearch();
158                 self.spinner("Otwieranie utworu");
159                 console.log('enterBookText: ' + id);
160                 Menu.setInfoButton("BookInfo", "Informacje o utworze", true);
161                 id = parseInt(id);
162
163                 setTimeout("History.addRead("+id+");", 0);
164                 
165                 FileRepo.withHtml(id, function(data) {
166                         self.content(data, offset);
167                 }, function(err) {
168                         alert("Błąd pobierania: nie udało się pobrać treści utworu.");
169                         History.goBack();
170                 });
171                 Catalogue.withBook(id, function(book) {
172                         self.currentTitle = book.authors + ', ' + book.title;
173                 });
174         };
175
176
177         this.enterLast = function(ignored, offset) {
178                 console.log("enterLast");
179                 self.showSearch();
180                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
181                 self.currentTitle = 'Ostatnio czytane';
182                 var html = "<h1><span class='subheader'>Ostatnio czytane</h1>\n";
183
184                 var last_read = History.lastRead();
185                 var some_books = false;
186
187                 html += "<div class='buttons'>";
188                 var add_books = function() {
189                         if (last_read.length) {
190                                 var id = last_read.shift();
191                                 Catalogue.withBook(id, function(book) {
192                                         html += Links.bookLink(book);
193                                         some_books = true;
194                                         add_books();
195                                 }, function() {
196                                         add_books();
197                                 });
198                         }
199                         else {
200                                 if (!some_books) {
201                                         html += "<p>Nie przeczytano żadnych utworów.</p>";
202                                 }
203                                 html += "</div>";
204                                 self.content(html, offset);
205                         }
206                 };
207                 add_books();
208         };
209
210
211         this.enterBookmarks = function(ignored, offset) {
212                 console.log("enterBookmarks");
213                 self.showSearch();
214                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
215                 self.currentTitle = 'Zakładki';
216                 var html = "<h1><span class='subheader'>Zakładki</h1>\n";
217
218                 var bookmarks = History.bookmarks();
219                 if (!bookmarks.length) {
220                         html += "<p>Nie utworzono żadnych zakładek.</p>";
221                         self.content(html, offset);
222                         return;
223                 }
224
225                 html += "<div class='buttons bookmarks'>";
226                 for (i in bookmarks) {
227                         var bm = bookmarks[i];
228
229                         var text = bm.name;
230                         text += "<div class='sub'>" + bm.title + "</div>";
231                         html += Links.deleteButton(bm.id);
232                         html += Links.button(bm.view, bm.par, text, bm.offset);
233                 }
234                 html += "</div>";
235                 self.content(html, offset);
236         };
237
238         this.onBookmarkChange = function() {
239                 // TODO: preserve offset
240                 if (self.currentView == 'Bookmarks') {
241                         self.enterBookmarks();
242                 }
243         };
244
245         this.enterTag = function(id, offset) {
246                 id = parseInt(id);
247                 console.log('enterTag: ' + id);
248                 Menu.setInfoButton("TagInfo", "Informacje o...", true);
249                 self.showSearch();
250
251                 self.spinner("Otwieranie listy utworów");
252
253                 Catalogue.withTag(id, function(tag) {
254                         Menu.setInfoButton("TagInfo", "Informacje o " + self.category_msc[tag.category], true);
255                         self.currentTitle = tag.category + ': ' + tag.name;
256                         var html = "<h1><span class='subheader upper'>" + tag.category + ': </span>' + tag.name + "</h1>\n";
257                         html += "<div class='buttons'>";
258                         if (tag.books) {
259                                 Catalogue.withBooks(tag.books, function(books) {
260                                         for (var i in books) {
261                                                 var book = books[i];
262                                                 html += Links.bookLink(book);
263                                         }
264                                         html += "</div>";
265                                         self.content(html, offset);
266                                 });
267                         }
268                 }, function() {
269                         History.goBack();
270                 });
271         };
272
273
274         this.enterCategory = function(category, offset) {
275                 console.log('enterCategory: ' + category);
276                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
277                 self.spinner("Otwieranie katalogu");
278                 self.showSearch();
279                 self.currentTitle = self.categories[category];
280
281                 Catalogue.withCategory(category, function(tags) {
282                         var html = "<h1>" + self.categories[category] + "</h1>\n";
283                         html += "<div class='buttons'>";
284                         for (i in tags) {
285                                 tag = tags[i];
286                                 html += Links.button('Tag', tag.id, tag.name);
287                         }
288                         html += "</div>";
289                         self.content(html, offset);
290                 });
291         };
292
293
294         this.enterSearch = function(query, offset) {
295                 console.log('enterSearch: ' + query);
296                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
297                 self.currentTitle = 'Szukaj: ' + query;
298                 self.showSearch();
299
300                 var html = "<h1><span class='subheader'>Szukana fraza:</span>" + View.sanitize(query) + "</h1>\n";
301
302                 if (query.length < 2) {
303                         html += "<p>Szukana fraza musi mieć co najmniej dwa znaki</p>";
304                         self.content(html, offset);
305                         return;
306                 }
307
308                 Catalogue.withSearch(query, function(results) {
309                         if (results.length == 1) {
310                             var result = results[0];
311                             if (result.view == 'Book' && result.item.html_file) {
312                                 self.enter(Links.href('BookText', result.item.id));
313                             }
314                             else {
315                                         self.enter(Links.href(result.view, result.item.id));
316                                 }
317                                 return;
318                         }
319                         if (results.length == 0) {
320                                 html += "<p>Brak wyników wyszukiwania</p>";
321                         }
322                         else {
323                                 html += "<div class='buttons'>";
324                                 for (var i in results) {
325                                         var result = results[i];
326                                         if (result.view == 'Book')
327                                                 html += Links.bookLink(result.item)
328                                         else
329                                                 html += Links.button(result.view, result.item.id, result.item.name+"<div class='sub'>"+result.item.category+"</div>");
330                                 }
331                                 html += "</div>";
332                         }
333                         self.content(html, offset);
334                 });
335         };
336
337
338         /* info */
339
340         this.enterProjectInfo = function(arg, offset) {
341                 console.log('enterProjectInfo');
342                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", false);
343                 self.hideSearch();
344                 self.currentTitle = "Informacje o projekcie";
345
346                 var html = "";
347
348                 html += '<div class="info">';
349
350
351                 html += "<p style='text-align:center'><img src='img/logo-wl.png' /></p>";
352                 html += "<p>Biblioteka internetowa Wolne Lektury "+
353 " udostępnia w swoich zbiorach lektury szkolne zalecane do użytku przez" + 
354 " Ministerstwo Edukacji Narodowej i inne dzieła literatury.</p>";
355
356                 html += "<p style='text-align:center'><img src='img/logo-fnp.png' /></p>";
357
358                 html += "<img style='float:left;' src='img/procent.png' />" +
359                         "<p style='margin-left: 50px'>" + 
360                         "Przekaż 1% podatku na rozwój Wolnych Lektur.<br/>" +
361                         "Fundacja Nowoczesna Polska<br/>" +
362                         "KRS 0000070056</p>";
363
364                 html += "<p>Większość pozycji w bibliotece należy do domeny publicznej "+
365                         "co oznacza, że nie są już chronione majatkowym prawem autorskim, "+
366                         "a więc można je swobodnie wykorzystywać, publikować i rozpowszechniać. "+
367                         "Publikujemy również kilka utworów, które autorzy udostępnili na wolnej licencji "+
368                         "<a href='http://creativecommons.org/licenses/by-sa/3.0/deed.pl'>"+
369                         "Creative Commons Uznanie Autorstwa - Na Tych Samych Warunkach 3.0.PL</a>.</p>";
370
371                 html += "<p style='text-align:center'><img src='img/cc-by-sa.png' /></p>";
372
373                 html += "<p>Copyright © 2011 Fundacja Nowoczesna Polska. Aplikacja jest wolnym oprogramowaniem "+
374                                 "dostępnym na licencji GNU Affero GPL w wersji 3 lub późniejszej.</p>";
375
376                 html += "<p>Więcej informacji o projekcie znajduje sie na stronie <a href='http://www.wolnelektury.pl'>http://www.wolnelektury.pl</a>.</p>";
377
378                 html += '</div>';
379
380
381                 self.content(html, offset);
382         };
383         
384         
385         this.enterBookInfo = function(id, offset) {
386                 id = parseInt(id);
387                 console.log('enterBookInfo: ' + id);
388                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
389                 self.hideSearch();
390
391                 Catalogue.withBook(id, function(book) {
392                         self.currentTitle = "Informacje o: " + book.title;
393
394                         var html = '<h2>' + book.authors + ', ' + book.title + '</h2>';
395
396                         var url = WL + '/api/book/' + id + '/info.html';
397
398                         var xhr = new XMLHttpRequest();
399                         xhr.open("GET", url);
400                         xhr.onload = function() {
401                                 console.log('BookInfo: fetched by ajax: ' + url);
402
403                                 html += '<div class="info">';
404                                 html += xhr.responseText;
405                                 html += '</div>';
406
407                                 self.content(html, offset);
408                         }
409                         xhr.onerror = function(e) {
410                                 self.content("Brak informacji.", offset);
411                         }
412                         xhr.send();
413                 }, function() {
414                         History.goBack();
415                 });
416         };
417
418
419         this.enterTagInfo = function(id, offset) {
420                 id = parseInt(id);
421                 console.log('enterTagInfo: ' + id);
422                 Menu.setInfoButton("ProjectInfo", "Informacje o projekcie", true);
423                 self.hideSearch();
424
425                 Catalogue.withTag(id, function(tag) {
426                         self.currentTitle = "Informacje o " + tag.name;
427                         var html = '<h2>' + tag.name + '</h2>';
428
429                         var url = WL + '/api/tag/' + id + '/info.html';
430
431                         var xhr = new XMLHttpRequest();
432                         xhr.open("GET", url);
433                         xhr.onload = function() {
434                                 console.log('TagInfo: fetched by ajax: ' + url);
435
436                                 html += '<div class="info">';
437                                 html += xhr.responseText;
438                                 html += '</div>';
439
440                                 self.content(html, offset);
441                         }
442                         xhr.onerror = function(e) {
443                                 self.content("Brak informacji.", offset);
444                         }
445                         xhr.send();
446                 }, function() {
447                         History.goBack();
448                 });
449         };
450
451
452         /* search form submit callback */
453         this.search = function() {
454                 History.visit('Search/' + self._searchinput.value);
455                 return false;
456         }
457         
458
459         self.getNightMode = function() {
460                 night_mode = window.localStorage.getItem('View.night_mode');
461                 if (night_mode === undefined)
462                         return false;
463                 else
464                         return !!night_mode;
465         };
466
467         self.checkNightMode = function() {
468         night_mode = self.getNightMode();
469                 if (night_mode) {
470                         document.body.setAttribute("class", "night-mode");
471                 }
472                 else {
473                         document.body.setAttribute("class", "");
474                 }
475         };
476
477         self.setNightMode = function(night_mode) {
478                 night_mode = night_mode ? "1" :  "";
479         window.localStorage.setItem('View.night_mode', night_mode);
480         self.checkNightMode();
481         };
482
483         self.toggleNightMode = function(night_mode) {
484                 self.setNightMode(!self.getNightMode());
485         };
486 }