kamishibai 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/LICENSE +29 -0
  4. data/README.md +91 -0
  5. data/bin/kamishibai +59 -0
  6. data/changelogs.txt +6 -0
  7. data/images/reading.jpg +0 -0
  8. data/images/settings.jpg +0 -0
  9. data/images/view_browse.jpg +0 -0
  10. data/images/view_dir.jpg +0 -0
  11. data/kamishibai.gemspec +31 -0
  12. data/lib/kamishibai.rb +35 -0
  13. data/lib/kamishibai/book.rb +97 -0
  14. data/lib/kamishibai/config.rb +90 -0
  15. data/lib/kamishibai/database.rb +330 -0
  16. data/lib/kamishibai/functions.rb +332 -0
  17. data/lib/kamishibai/patches.rb +58 -0
  18. data/lib/kamishibai/version.rb +7 -0
  19. data/lib/kamishibai/webserver.rb +502 -0
  20. data/lib/kamishibai/webserver_cmds.rb +26 -0
  21. data/lib/kamishibai/webserver_config.rb +91 -0
  22. data/lib/kamishibai/webserver_filemanager.rb +29 -0
  23. data/lib/kamishibai/webserver_tablet.rb +259 -0
  24. data/lib/kamishibai/workers.rb +39 -0
  25. data/public/css/browse.css +390 -0
  26. data/public/css/config.css +3 -0
  27. data/public/css/reader.css +119 -0
  28. data/public/css/styles.css +30 -0
  29. data/public/css/tablet_browse.css +247 -0
  30. data/public/css/tablet_reader.css +323 -0
  31. data/public/css/tablet_reader_input.css +191 -0
  32. data/public/images/ajax-loader.gif +0 -0
  33. data/public/images/delete.png +0 -0
  34. data/public/images/folder-mini-up.png +0 -0
  35. data/public/images/folder-mini.png +0 -0
  36. data/public/images/spinner.gif +0 -0
  37. data/public/images/trash-empty-mini.png +0 -0
  38. data/public/images/trash-full-mini.png +0 -0
  39. data/public/js/browse.js +391 -0
  40. data/public/js/config.js +190 -0
  41. data/public/js/reader.js +497 -0
  42. data/public/js/swipeview-k.js +478 -0
  43. data/public/js/tablet3.js +241 -0
  44. data/public/js/tablet3_browse.js +173 -0
  45. data/public/js/tablet3_reader.js +534 -0
  46. data/public/js/utilities.js +170 -0
  47. data/public/lang/k-cn.json +82 -0
  48. data/public/lang/k-en.json +82 -0
  49. data/public/lang/k-ja.json +82 -0
  50. data/public/vendor/css/bootstrap-slider.css +252 -0
  51. data/public/vendor/css/bootstrap-theme.css +476 -0
  52. data/public/vendor/css/bootstrap-theme.css.map +1 -0
  53. data/public/vendor/css/bootstrap-theme.min.css +5 -0
  54. data/public/vendor/css/bootstrap.css +6584 -0
  55. data/public/vendor/css/bootstrap.css.map +1 -0
  56. data/public/vendor/css/bootstrap.min.css +5 -0
  57. data/public/vendor/css/jquery-ui-1.10.0.custom.css +1614 -0
  58. data/public/vendor/css/jquery.mobile-1.3.1.min.css +3 -0
  59. data/public/vendor/css/jqueryFileTree.css +91 -0
  60. data/public/vendor/fonts/glyphicons-halflings-regular.eot +0 -0
  61. data/public/vendor/fonts/glyphicons-halflings-regular.svg +288 -0
  62. data/public/vendor/fonts/glyphicons-halflings-regular.ttf +0 -0
  63. data/public/vendor/fonts/glyphicons-halflings-regular.woff +0 -0
  64. data/public/vendor/fonts/glyphicons-halflings-regular.woff2 +0 -0
  65. data/public/vendor/images/application.png +0 -0
  66. data/public/vendor/images/code.png +0 -0
  67. data/public/vendor/images/css.png +0 -0
  68. data/public/vendor/images/db.png +0 -0
  69. data/public/vendor/images/dim.png +0 -0
  70. data/public/vendor/images/directory.png +0 -0
  71. data/public/vendor/images/doc.png +0 -0
  72. data/public/vendor/images/file.png +0 -0
  73. data/public/vendor/images/film.png +0 -0
  74. data/public/vendor/images/flash.png +0 -0
  75. data/public/vendor/images/folder_open.png +0 -0
  76. data/public/vendor/images/grey.png +0 -0
  77. data/public/vendor/images/html.png +0 -0
  78. data/public/vendor/images/icons-18-black.png +0 -0
  79. data/public/vendor/images/icons-18-white.png +0 -0
  80. data/public/vendor/images/icons-36-black.png +0 -0
  81. data/public/vendor/images/icons-36-white.png +0 -0
  82. data/public/vendor/images/java.png +0 -0
  83. data/public/vendor/images/linux.png +0 -0
  84. data/public/vendor/images/music.png +0 -0
  85. data/public/vendor/images/pdf.png +0 -0
  86. data/public/vendor/images/php.png +0 -0
  87. data/public/vendor/images/picture.png +0 -0
  88. data/public/vendor/images/ppt.png +0 -0
  89. data/public/vendor/images/psd.png +0 -0
  90. data/public/vendor/images/ruby.png +0 -0
  91. data/public/vendor/images/script.png +0 -0
  92. data/public/vendor/images/spinner.gif +0 -0
  93. data/public/vendor/images/txt.png +0 -0
  94. data/public/vendor/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  95. data/public/vendor/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  96. data/public/vendor/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  97. data/public/vendor/images/ui-bg_flat_10_000000_40x100.png +0 -0
  98. data/public/vendor/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
  99. data/public/vendor/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  100. data/public/vendor/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  101. data/public/vendor/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  102. data/public/vendor/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  103. data/public/vendor/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  104. data/public/vendor/images/ui-bg_glass_20_555555_1x400.png +0 -0
  105. data/public/vendor/images/ui-bg_glass_40_0078a3_1x400.png +0 -0
  106. data/public/vendor/images/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  107. data/public/vendor/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  108. data/public/vendor/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  109. data/public/vendor/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  110. data/public/vendor/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  111. data/public/vendor/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  112. data/public/vendor/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  113. data/public/vendor/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  114. data/public/vendor/images/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  115. data/public/vendor/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  116. data/public/vendor/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  117. data/public/vendor/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  118. data/public/vendor/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  119. data/public/vendor/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  120. data/public/vendor/images/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  121. data/public/vendor/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  122. data/public/vendor/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  123. data/public/vendor/images/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  124. data/public/vendor/images/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  125. data/public/vendor/images/ui-icons_217bc0_256x240.png +0 -0
  126. data/public/vendor/images/ui-icons_222222_256x240.png +0 -0
  127. data/public/vendor/images/ui-icons_228ef1_256x240.png +0 -0
  128. data/public/vendor/images/ui-icons_2e83ff_256x240.png +0 -0
  129. data/public/vendor/images/ui-icons_454545_256x240.png +0 -0
  130. data/public/vendor/images/ui-icons_469bdd_256x240.png +0 -0
  131. data/public/vendor/images/ui-icons_4b8e0b_256x240.png +0 -0
  132. data/public/vendor/images/ui-icons_6da8d5_256x240.png +0 -0
  133. data/public/vendor/images/ui-icons_888888_256x240.png +0 -0
  134. data/public/vendor/images/ui-icons_a83300_256x240.png +0 -0
  135. data/public/vendor/images/ui-icons_cccccc_256x240.png +0 -0
  136. data/public/vendor/images/ui-icons_cd0a0a_256x240.png +0 -0
  137. data/public/vendor/images/ui-icons_d8e7f3_256x240.png +0 -0
  138. data/public/vendor/images/ui-icons_ef8c08_256x240.png +0 -0
  139. data/public/vendor/images/ui-icons_f9bd01_256x240.png +0 -0
  140. data/public/vendor/images/ui-icons_ffd27a_256x240.png +0 -0
  141. data/public/vendor/images/ui-icons_ffffff_256x240.png +0 -0
  142. data/public/vendor/images/xls.png +0 -0
  143. data/public/vendor/images/zip.png +0 -0
  144. data/public/vendor/js/bootstrap-slider.js +1550 -0
  145. data/public/vendor/js/bootstrap.js +2317 -0
  146. data/public/vendor/js/bootstrap.min.js +7 -0
  147. data/public/vendor/js/jquery-2.1.4.js +9210 -0
  148. data/public/vendor/js/jquery-2.1.4.min.js +4 -0
  149. data/public/vendor/js/jquery-2.1.4.min.map +1 -0
  150. data/public/vendor/js/jquery-ui-1.10.2.custom.min.js +7 -0
  151. data/public/vendor/js/jquery.cookie.js +72 -0
  152. data/public/vendor/js/jquery.hammer.min.js +7 -0
  153. data/public/vendor/js/jquery.lazyload.min.js +15 -0
  154. data/public/vendor/js/jquery.localize.js +180 -0
  155. data/public/vendor/js/jquery.mobile-1.3.1.min.js +7 -0
  156. data/public/vendor/js/jquery.scrollTo-1.4.3.1.js +218 -0
  157. data/public/vendor/js/jqueryFileTree.js +95 -0
  158. data/public/vendor/js/swipeview.js +471 -0
  159. data/views/browse.haml +97 -0
  160. data/views/config.haml +115 -0
  161. data/views/layout.haml +12 -0
  162. data/views/login.haml +51 -0
  163. data/views/reader.haml +70 -0
  164. data/views/statistics.haml +108 -0
  165. data/views/tablet3.haml +80 -0
  166. metadata +334 -0
@@ -0,0 +1,241 @@
1
+ /*!
2
+ License: refer to LICENSE file
3
+ */
4
+
5
+ // global variables
6
+ var hasTouch = 'ontouchstart' in window; //find out if device is touch device or not
7
+
8
+ // for saving cycle when typing keyword, delay search instead send immediately
9
+ var timerKeywordChange = 0;
10
+
11
+
12
+
13
+ // page init
14
+ $(function(e) {
15
+ /*
16
+ * Browse section
17
+ */
18
+
19
+ // load the text localization
20
+ reload_locale();
21
+
22
+ /*
23
+ **** NOTE ****
24
+ Seems like ios uses the noclick delay to detect div drag, so if this is enabled, the div navi would not work. need to come up alternative method.
25
+ */
26
+ // disable onclick delay on ipad/ios, it has dodgy handing on click event
27
+ if ((/iphone|ipod|ipad.*os 5/gi).test(navigator.appVersion)) {
28
+ //new NoClickDelay(document.body);
29
+ }
30
+
31
+ // set cookies
32
+ // load the book search query
33
+ var sb = $('#searchbox');
34
+ if ($.cookie(uport() + '.keyword') != undefined) {
35
+ sb.val( $.cookie(uport() + '.keyword') );
36
+ }
37
+
38
+
39
+ // re-select the remembered menu selection
40
+ var i = $.cookie(uport() + '.last_menu_selection_number') || 1;
41
+
42
+ // select menu selection
43
+ $('#bc' + i).button('toggle');
44
+
45
+ var bcs = $('#bcs');
46
+ if (i == 5) {
47
+ // author selected, load author
48
+
49
+ sb.val( bcs.attr('author') || $.cookie(uport() + '.author') || '' );
50
+ }
51
+ else {
52
+ // non author selected, load normal keyword
53
+
54
+ sb.val( bcs.attr('keyword') || $.cookie(uport() + '.keyword') || '' );
55
+ }
56
+
57
+
58
+ // swipe event for the browse page
59
+ $(window).bind('scroll', function() {
60
+ $('#scroll-pos').text(window.pageYOffset);
61
+ });
62
+ $('#books').bind('onscroll', function() {
63
+ $('#scroll-pos').text(window.pageYOffset);
64
+ });
65
+
66
+
67
+
68
+ // #searchbox event
69
+ $("#searchbox").on('change', function(e) {
70
+
71
+ // reload the list with keyword matches
72
+ prepare_lists();
73
+
74
+ }).on('keydown', function(e) {
75
+
76
+ // save cycles, stop the timer to send query when key is pressed
77
+ clearTimeout( timerKeywordChange );
78
+
79
+ }).on('keyup', function(e) {
80
+ e = e || window.event;
81
+
82
+ if (e.keyCode == 13) {
83
+ // enter key, unfocus the searchbox
84
+ $("#searchbox").blur();
85
+ return true;
86
+ }
87
+
88
+ // save cycles, only sent query when search is truly finished typing
89
+ timerKeywordChange = setTimeout( function() {
90
+ prepare_lists();
91
+
92
+ }, 1200);
93
+ });
94
+
95
+
96
+
97
+ // run if book choice is selected, load with delay for the button group DOM to catch up
98
+ $('.btn-group > button').on('click', function(e) {
99
+
100
+ var sb = $('#searchbox');
101
+ var bcs = $('#bcs');
102
+ // get menu selection
103
+ var i = $(this).attr('id').replace('bc', '');
104
+
105
+
106
+ if (i == 5) {
107
+ // author selected, load author
108
+
109
+ sb.val( bcs.attr('author') || $.cookie(uport() + '.author') || '' );
110
+ }
111
+ else {
112
+ // non author selected, load normal keyword
113
+
114
+ sb.val( bcs.attr('keyword') || $.cookie(uport() + '.keyword') || '' );
115
+ }
116
+
117
+ // remember last menu selection number
118
+ $.cookie(uport() + '.last_menu_selection_number', i, { path: '/' });
119
+
120
+
121
+ // change button high light
122
+ $('.btn-group > button').removeClass('active');
123
+ $(this).addClass('active');
124
+
125
+ // save cycles if search text isnt changed
126
+ // if ( sb.val() === $.cookie(uport() + '.keyword') || sb.val() === $.cookie(uport() + '.author') ) {
127
+ // return false;
128
+ // }
129
+
130
+ prepare_lists();
131
+ });
132
+
133
+
134
+ if (getHashParams().book) {
135
+ // load book if already specified in hash
136
+
137
+ var p = getHashParams().page || 1;
138
+
139
+ readBook( getHashParams().book, p );
140
+ }
141
+ else {
142
+ // reload leftbox
143
+ // prepare_lists( get_menu_url() );
144
+ }
145
+
146
+
147
+
148
+
149
+
150
+ /*
151
+ * Reader section
152
+ */
153
+
154
+ // disable other other tuochmove events from propagating causing issuing
155
+ // document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
156
+
157
+
158
+ // action when home button is pushed
159
+ $('#closeReader').on('click', function(event, ui) {
160
+ closeReader();
161
+ });
162
+
163
+ // show/hide menu
164
+ if (hasTouch) {
165
+ $('#wrapper').on('click', function(e) {
166
+ e.stopPropagation();
167
+ togglemenu();
168
+ });
169
+ }
170
+ else {
171
+
172
+ // prevent swipe triggering menu when using mouse
173
+ $('#wrapper').on('mousedown', function(e) {
174
+ window.wrapperMouseLastPos = {
175
+ x: e.originalEvent.pageX,
176
+ y: e.originalEvent.pageY
177
+ };
178
+ });
179
+ $('#wrapper').on('mouseup', function(e) {
180
+ var x = e.originalEvent.pageX;
181
+ var y = e.originalEvent.pageY;
182
+
183
+ // moved, so no menu
184
+ if (Math.abs(window.wrapperMouseLastPos.x - x) > 10) return;
185
+ if (Math.abs(window.wrapperMouseLastPos.y - y) > 10) return;
186
+
187
+ togglemenu();
188
+ });
189
+ }
190
+
191
+ // change page when slider is moved
192
+ $('#pageslider').on('change', function() {
193
+ goToPage( $(this).val() );
194
+
195
+ }).on('input', function() {
196
+ $('#pageinput').val( $(this).val() );
197
+
198
+ }).on('touchstart', function(e) {
199
+
200
+ // change page when slider is moved (touch)
201
+ var i = sliderValue(this, e);
202
+
203
+ $('#pageinput').val( i );
204
+ $(this).val(i);
205
+
206
+ }).on('touchmove', function(e) {
207
+ // console.log('slider move');
208
+ var i = sliderValue(this, e);
209
+
210
+ $('#pageinput').val( i );
211
+ $(this).val(i);
212
+
213
+ }).on('touchend', function(e) {
214
+ // goToPage( $(this).val() );
215
+ });
216
+
217
+ // change read direction when button is touched
218
+ $('#readdirection').change(function(e) {
219
+ destroyGallery();
220
+ createGallery();
221
+ // force trigger hashchange on load
222
+ window.dispatchEvent(new HashChangeEvent('hashchange'));
223
+ });
224
+
225
+ updateBatteryLevel();
226
+ updateDivCurrentInfo();
227
+ window.setInterval( function() {
228
+ // update battery level
229
+ updateBatteryLevel();
230
+
231
+ // show clock
232
+ updateDivCurrentInfo();
233
+ }, 1000 * 60);
234
+
235
+
236
+ // load full screen button if device supports it
237
+ if (!(/iphone|ipod|ipad/gi).test(navigator.appVersion)) {
238
+ $('#div-fs-btn').removeClass('hidden');
239
+ };
240
+
241
+ });
@@ -0,0 +1,173 @@
1
+ /*!
2
+ License: refer to LICENSE file
3
+ */
4
+
5
+
6
+ // global search result list
7
+ function reload_leftbox(url, keyword) {
8
+ // retrive data
9
+ $.post(url, { keyword: keyword }, function(data) {
10
+ var el = $('#leftbox');
11
+ el.empty();
12
+ el.append(data);
13
+
14
+ $('.li-title').on('click', function() {
15
+ // set the last title selected on cookie
16
+ $.cookie(uport() + '.lasttitle', $(this).text(), { path: '/' });
17
+
18
+ reload_books( $(this).attr('bookcodes'), $(this).attr('options') );
19
+ });
20
+
21
+ var elem = $('.li-title:contains("' + $.cookie(uport() + '.lasttitle') + '")');
22
+ if (elem.length > 0) {
23
+ // scroll to last selected title
24
+ $('#leftbox').scrollTo( elem.eq(0) );
25
+
26
+ // show books
27
+ var bookcodes = elem.eq(0).attr('bookcodes');
28
+ reload_books( bookcodes, elem.eq(0).attr('options') );
29
+ }
30
+ else {
31
+ // last selected title don't exist, select first available title
32
+ var el = $('.li-title');
33
+ if (el.length > 0) {
34
+ $('#leftbox').scrollTo( el.eq(0) );
35
+
36
+ var bookcodes = el.eq(0).attr('bookcodes');
37
+ reload_books( bookcodes, el.eq(0).attr('options') );
38
+ }
39
+ else {
40
+ reload_books();
41
+ }
42
+ }
43
+ });
44
+ }
45
+
46
+
47
+
48
+ // load books from the bookcodes
49
+ function reload_books( bookcodes, options ) {
50
+ if (bookcodes === undefined) {
51
+ $('#bookinfo').empty();
52
+ $('#books').empty();
53
+ return false;
54
+ }
55
+
56
+ var bookcode = bookcodes.split(',')[0];
57
+
58
+ $.get('/listbooks', { bookcodes: bookcodes, options: options }, function(jData) {
59
+
60
+ // show book title and author
61
+ var el = $('#bookinfo');
62
+ el.empty();
63
+ el.attr('bookcodes', bookcodes); // remember requested bookcodes
64
+ for (var bookcode in jData) {
65
+ var book = jData[bookcode];
66
+
67
+ var title = $('<div>');
68
+ title.html(book.title);
69
+ el.append(title);
70
+
71
+ var author = $('<div>');
72
+ author.html(book.author);
73
+ author.on('click', function() {
74
+ exe_show_author(book.author);
75
+ });
76
+ el.append(author);
77
+ break;
78
+ }
79
+
80
+ // list books
81
+ var el = $('#books');
82
+ el.empty();
83
+ for (var bookcode in jData) {
84
+ var book = jData[bookcode];
85
+
86
+ var li = $('<li>');
87
+ li.addClass('book');
88
+
89
+ var a = $('<a>');
90
+ a.attr('href', '#book=' + bookcode + '&page=' + book.page || 1);
91
+ a.on('click', { bookcode: bookcode }, function(event) {
92
+ // console.log(event.data.bookcode);
93
+ readBook(event.data.bookcode);
94
+ });
95
+
96
+ var img = $('<img>');
97
+ img.attr('src', '/thumbnail/' + bookcode);
98
+ img.attr('alt', 'Loading...');
99
+ a.append(img);
100
+
101
+ var span = $('<span>');
102
+ span.html(book.sname);
103
+ // set page progress
104
+ var page = book.page || 0;
105
+ var pages = book.pages;
106
+ var pc = Math.round(page / pages * 100); // percentage read
107
+ var pc2 = pc === 0 ? 0 : pc + 1; // if never read, then make it all 0
108
+ span.css('background', 'linear-gradient(to right, rgba(51,204,102,1) ' + pc + '%,rgba(234,234,234,1) ' + pc2 + '%)');
109
+ a.append(span);
110
+
111
+ li.append(a);
112
+ el.append(li);
113
+ }
114
+ });
115
+
116
+ }
117
+
118
+
119
+ function exe_show_author( author ) {
120
+
121
+ var sb = $('#searchbox');
122
+ var bcs = $('#bcs');
123
+
124
+ // save author and keyword
125
+ bcs.attr('keyword', sb.val());
126
+ bcs.attr('author', author);
127
+
128
+ // change search to author
129
+ sb.val(author);
130
+
131
+ $('#bc5').trigger('click');
132
+ }
133
+
134
+ function prepare_lists(url) {
135
+
136
+ if (typeof url === 'undefined') url = get_menu_url();
137
+
138
+
139
+ var sb = $('#searchbox');
140
+ var bcs = $('#bcs');
141
+ var i = get_menu_selection_number();
142
+
143
+ // remember keyword
144
+ var keyword;
145
+ if (i === 5) {
146
+ keyword = sb.val();
147
+ bcs.attr('author', keyword);
148
+ $.cookie(uport() + '.author', keyword, { path: '/' });
149
+ }
150
+ else {
151
+ keyword = sb.val();
152
+ bcs.attr('keyword', keyword);
153
+ $.cookie(uport() + '.keyword', keyword, { path: '/' });
154
+ }
155
+
156
+ // reload leftbox
157
+ reload_leftbox(url, keyword);
158
+ }
159
+
160
+ function get_menu_selection_number() {
161
+ var id = $('#bcs > button.active').attr('id');
162
+
163
+ var n;
164
+ if (id) {
165
+ n = parseInt( id.replace('bc','') );
166
+ }
167
+
168
+ return n || 1;
169
+ }
170
+
171
+ function get_menu_url() {
172
+ return $('#bcs > button.active').attr('link');
173
+ }
@@ -0,0 +1,534 @@
1
+ /*!
2
+ License: refer to LICENSE file
3
+ */
4
+
5
+
6
+ // last time the toggleMenu is called
7
+ var lastToggleMenu = (new Date()).getTime();
8
+
9
+ // initialize book object
10
+ var book;
11
+
12
+ // set gallery global variable so it can be accessed outside
13
+ var gallery;
14
+
15
+ // set date
16
+ var date = new Date();
17
+
18
+ // set battery
19
+ var battery_level = '-1';
20
+
21
+ // how long it takes to trigger actions in ms
22
+ var onFlipActionDelay = 1000;
23
+
24
+
25
+ function readBook(bc, bp) {
26
+ console.log('readBook', arguments)
27
+ // bc, bookcode
28
+ // bp, bookpage
29
+
30
+ // destroy exiting gallery already exists
31
+ destroyGallery(false);
32
+
33
+ // set screen size so if the image is resized, server remember the screen size
34
+ setScreenSize();
35
+
36
+ $.get('/listbooks', { bookcodes: bc }, function(jData) {
37
+ $('#container').removeClass('hidden');
38
+
39
+ book = jData[bc];
40
+
41
+ book.bookcode = bc;
42
+ book.lastpage = bp || book.page || 1;
43
+
44
+ $('#booktitle').html('<div>' + book.title + '</div>');
45
+
46
+ // set #pageslider max
47
+ $('#pageslider').attr('max', book.pages);
48
+ $('#pageslider').val(book.lastpage);
49
+
50
+ // set location hash if not set or diff
51
+ var hstr = '#book=' + book.bookcode + '&page=' + book.lastpage;
52
+ if (window.location.hash !== hstr) window.location.hash = hstr;
53
+
54
+ // create gallery
55
+ createGallery(bp);
56
+
57
+ // force trigger hashchange to load correct page
58
+ // window.dispatchEvent(new HashChangeEvent('hashchange'));
59
+ });
60
+ }
61
+
62
+
63
+ function updateDivCurrentInfo(page) {
64
+
65
+ if (typeof page === 'number') {
66
+ $('#pageCounter').html( gallery.pageIndex + '/' + book.pages );
67
+ }
68
+ $('#clock').html( date.toTimeString().slice(0,5) );
69
+ $('#battery').html( '&#128267;' + battery_level);
70
+ }
71
+
72
+ function sliderValue(el, e) {
73
+ var el = $(el);
74
+ var min = Number(el.attr('min'));
75
+ var max = Number(el.attr('max'));
76
+ var t;
77
+ if (e.originalEvent.touches) {
78
+ t = e.originalEvent.touches[0];
79
+ }
80
+ // else {
81
+ // t = e.originalEvent;
82
+ // }
83
+ var w = Number(el.width());
84
+ var x = w / max;
85
+ var l = el.position().left;
86
+
87
+ // approximate value on the slider position
88
+ var i = Math.ceil((t.pageX - l)/x );
89
+
90
+ if (i < min) {
91
+ i = min;
92
+ }
93
+ else if (i > max) {
94
+ i = max;
95
+ }
96
+
97
+ return i;
98
+ }
99
+
100
+
101
+ // destroy and remove the gallery
102
+ function destroyGallery(resetHash) {
103
+ if (gallery) gallery.destroy;
104
+ $('#wrapper').empty();
105
+
106
+ // remove listener
107
+ $(window).unbind('hashchange');
108
+ $(window).unbind('keydown');
109
+
110
+ if (resetHash === false) return;
111
+
112
+ // clear hash
113
+ window.location.hash = '';
114
+ }
115
+
116
+ // create the gallery
117
+ function createGallery(goPage) {
118
+ //document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
119
+
120
+ // initialize gallery
121
+ var el,
122
+ i,
123
+ page;
124
+ //dots = document.querySelectorAll('.thumbnails ul li');
125
+
126
+ // initialize pages
127
+ var slides = [];
128
+ for (i=1; i<=book.pages; i++) {
129
+
130
+ if (isEasternBook()) {
131
+ // eastern book
132
+ slides.push( {
133
+ img: "/cbz/" + book.bookcode + "/" + (book.pages - i + 1),
134
+ page: book.pages - i + 1
135
+ } );
136
+ }
137
+ else {
138
+ // western book
139
+ slides.push( {
140
+ img: "/cbz/" + book.bookcode + "/" + i,
141
+ page: i
142
+ } );
143
+ }
144
+ }
145
+
146
+ gallery = new SwipeView('#wrapper', { numberOfPages: slides.length, loop: false, zoom: true });
147
+
148
+ // Load initial data
149
+ for (i=0; i<3; i++) {
150
+ page = i==0 ? slides.length-1 : i-1;
151
+
152
+ el = document.createElement('div');
153
+ el.id = 'swipeview-div-' + i;
154
+ el.className = 'loading';
155
+ // el.innerHTML = i + 1;
156
+ gallery.masterPages[i].appendChild(el);
157
+
158
+ el = document.createElement('img');
159
+ el.id = 'swipeview-img-' + i;
160
+ el.className = 'loading';
161
+ el.removeAttribute('src');
162
+ // el.src = '';
163
+ // el.src = slides[page].img;
164
+ el.onload = function () {
165
+ this.className = '';
166
+ this.previousSibling.className = '';
167
+ }
168
+ gallery.masterPages[i].appendChild(el);
169
+ }
170
+ // stagger loading image to reduce load
171
+ staggerImages(goPage);
172
+
173
+ gallery.onFlip(function () {
174
+ console.log('flip event!');
175
+ // global
176
+ if (!window.timerOnFlipSlide) window.window.timerOnFlipSlide = {};
177
+
178
+ var el,
179
+ upcoming,
180
+ i;
181
+
182
+ for (i=0; i<3; i++) {
183
+ upcoming = gallery.masterPages[i].dataset.upcomingPageIndex;
184
+
185
+ if (upcoming != gallery.masterPages[i].dataset.pageIndex) {
186
+ el = gallery.masterPages[i].querySelector('div');
187
+ el.className = 'loading';
188
+ el.innerHTML = slides[upcoming].page;
189
+
190
+ el = gallery.masterPages[i].querySelector('img');
191
+ el.className = 'loading';
192
+
193
+ // called by staggerImages
194
+ if (window.stopOnFlipImg) {
195
+ el.removeAttribute('src');
196
+ }
197
+ // normal flip
198
+ else {
199
+ // if (window.timerOnFlipSlide[i]) {
200
+ // console.log('stop load image!', i)
201
+ // clearTimeout(window.timerOnFlipSlide[i]);
202
+ // window.timerOnFlipSlide[i] = false;
203
+ // }
204
+
205
+ // window.timerOnFlipSlide[i] = setTimeout(function() {
206
+ // console.log('load image!', this.src)
207
+ // this.el.src = this.src;
208
+ // }.bind({
209
+ // el: el,
210
+ // src: slides[upcoming].img
211
+ // }), onFlipActionDelay);
212
+
213
+ el.src = slides[upcoming].img;
214
+ }
215
+ }
216
+ // else {
217
+ // if (window.timerOnFlipSlide[i]) {
218
+ // console.log('stop load image!!!', i)
219
+ // clearTimeout(window.timerOnFlipSlide[i]);
220
+ // window.timerOnFlipSlide[i] = false;
221
+ // }
222
+ // }
223
+ }
224
+ // reset
225
+ window.stopOnFlipImg = false;
226
+
227
+ // get current page
228
+ var pg = gallery.pageIndex;
229
+ if (isEasternBook()) {
230
+ pg = book.pages - gallery.pageIndex;
231
+ }
232
+
233
+ // update div current info
234
+ updateDivCurrentInfo(pg);
235
+
236
+ // change title according to page
237
+ document.title = "(" + pg + "/" + book.pages + ")";
238
+
239
+ // set the page hash
240
+ window.noHashchange = true; // make sure no hashchange is triggered
241
+ window.location.hash = fullhash(pg);
242
+
243
+ // set bookmark only if stopped at page
244
+ if (window.timerOnFlipSlide.bookmark) {
245
+ clearTimeout(window.timerOnFlipSlide.bookmark);
246
+ window.timerOnFlipSlide.bookmark = false;
247
+ }
248
+ window.timerOnFlipSlide.bookmark = setTimeout(function() {
249
+ setBookmark(this.bookcode, this.pg);
250
+ }.bind({
251
+ bookcode: book.bookcode,
252
+ pg: pg
253
+ }), onFlipActionDelay);
254
+
255
+ // set the slider displayed page
256
+ $('#pageinput').val(pg);
257
+ $('#pageslider').val(pg);
258
+ });
259
+
260
+ gallery.onMoveOut(function () {
261
+ console.log('moveout');
262
+ gallery.masterPages[gallery.currentMasterPage].className = gallery.masterPages[gallery.currentMasterPage].className.replace(/(^|\s)swipeview-active(\s|$)/, '');
263
+
264
+ // get current page
265
+ var pg = gallery.pageIndex;
266
+ if (isEasternBook()) {
267
+ pg = book.pages - gallery.pageIndex;
268
+ }
269
+
270
+ var el = gallery.masterPages[gallery.currentMasterPage].querySelector('div');
271
+ el.innerHTML = pg;
272
+ el.className += 'loading';
273
+
274
+ // update current info
275
+ updateDivCurrentInfo(pg);
276
+ });
277
+
278
+ gallery.onMoveIn(function () {
279
+ console.log('movein');
280
+ var className = gallery.masterPages[gallery.currentMasterPage].className;
281
+ /(^|\s)swipeview-active(\s|$)/.test(className) || (gallery.masterPages[gallery.currentMasterPage].className = !className ? 'swipeview-active' : className + ' swipeview-active');
282
+ });
283
+ // end of gallery code
284
+
285
+ // go to page if specified
286
+ if (goPage) {
287
+ // launch a moment later, to go around loading issue
288
+ window.setTimeout( function(e) { goToPage(goPage); }, 300);
289
+ }
290
+
291
+ // now add listener
292
+
293
+ // hash change
294
+ $(window).bind('hashchange', function() {
295
+ // do no trigger, because of onFlip
296
+ if (window.noHashchange) {
297
+ // reset
298
+ window.noHashchange = false;
299
+ return;
300
+ }
301
+
302
+ // replace the history
303
+ if (getpage() < 1) {
304
+ window.location.replace( '#' + fullhash( 1 ) );
305
+ }
306
+ else if (getpage() > book.pages) {
307
+ window.location.replace( '#' + fullhash( book.pages ) );
308
+ }
309
+
310
+ // launch a moment later, to go around loading issue
311
+ window.setTimeout( function(e) { goToPage(getpage()); }, 50);
312
+ });
313
+
314
+ // // keyboard commands
315
+ $(window).bind('keydown', function h_kd(e) {
316
+ e = e || window.event;
317
+
318
+ switch (e.keyCode) {
319
+ case 37:
320
+ // left button, previous page
321
+ goToPage( getpage() - 1 );
322
+ break;
323
+ case 39:
324
+ // right button, next page
325
+ goToPage( getpage() + 1 );
326
+ break;
327
+ case 27:
328
+ // escape button, go back to browse
329
+ closeReader();
330
+ return false;
331
+ break;
332
+ case 13:
333
+ // enter key, show/hide menu
334
+ togglemenu();
335
+ break;
336
+ }
337
+ });
338
+ }
339
+
340
+ // set the bookmark
341
+ function setBookmark(bookcode, page) {
342
+ var page = getpage();
343
+
344
+ if (book.lastpage == page || page < 1 || page > book.pages) return false;
345
+
346
+ $.ajax({
347
+ url: "/setbookmark/" + bookcode + "/" + page,
348
+ beforeSend: function ( xhr ) {
349
+ xhr.overrideMimeType("text/plain; charset=x-user-defined");
350
+ }
351
+ }).done(function ( data ) {
352
+ if( 1==2 && console && console.log ) {
353
+ console.log("Sample of data:", data);
354
+ }
355
+ });
356
+
357
+ // update last rendered page
358
+ book.lastpage = page;
359
+ }
360
+
361
+
362
+ function closeReader() {
363
+ $('#container').addClass('hidden');
364
+
365
+ destroyGallery();
366
+
367
+ reload_books( $('#bookinfo').attr('bookcodes') );
368
+ }
369
+
370
+ function isEasternBook() {
371
+ return ( $('#readdirection :radio:checked').attr('id') == 'readtoleft' ) ? true : false;
372
+ }
373
+
374
+ // go to particular page
375
+ // in relative to book
376
+ // not relative to gallery, which u can find out by page - 1
377
+ function goToPage(page) {
378
+ page = Number(page);
379
+ console.log('going to page', page);
380
+ if (page < 1) return false;
381
+
382
+ if (isEasternBook()) {
383
+ gallery.goToPage(book.pages - page);
384
+ }
385
+ else {
386
+ gallery.goToPage(page - 1);
387
+ }
388
+
389
+ staggerImages(page);
390
+ }
391
+
392
+ function staggerImages(page) {
393
+ var i;
394
+ if (isEasternBook()) {
395
+ i = book.pages - page;
396
+ }
397
+ else {
398
+ i = page - 1;
399
+ }
400
+
401
+ // global
402
+ window.stopOnFlipImg = true;
403
+ window.imageQueue = [
404
+ // current page
405
+ {
406
+ igal: '[data-page-index=' + i + ']',
407
+ url: "/cbz/" + book.bookcode + "/" + page
408
+ },
409
+ // next page
410
+ {
411
+ igal: '[data-page-index=' + (i+1) + ']',
412
+ url: "/cbz/" + book.bookcode + "/" + (page + 1)
413
+ },
414
+ // prev page
415
+ {
416
+ igal: '[data-page-index=' + (i-1) + ']',
417
+ url: "/cbz/" + book.bookcode + "/" + (page - 1)
418
+ },
419
+ ];
420
+
421
+ // do first image
422
+ loadImage();
423
+ }
424
+
425
+ function loadImage() {
426
+ var dat = window.imageQueue.shift();
427
+
428
+ // double trigger, stop
429
+ if (window.currentImage && window.currentImage.url === dat.url) return;
430
+
431
+ window.currentImage = dat;
432
+
433
+ var img = el = $('<img>');
434
+ img.on('load', function() {
435
+ console.log('loaded image in background', this.dat)
436
+
437
+ // change img src
438
+ var el = $(this.dat.igal);
439
+ el.find('img').attr('src', this.dat.url).removeClass('loading');
440
+ el.find('div').removeClass('loading');
441
+ el.css('visibility','visible');
442
+
443
+ // do more if exists
444
+ if (window.imageQueue && window.imageQueue.length > 0) {
445
+ loadImage();
446
+ }
447
+ // all done, clear
448
+ else {
449
+ window.currentImage = false;
450
+ }
451
+ }.bind({
452
+ dat: dat
453
+ }));
454
+ // exec
455
+ console.log('starting image', dat)
456
+ img.attr('src', dat.url);
457
+ }
458
+
459
+ // get the page from hash
460
+ function getpage() {
461
+ var i = parseInt( getHashParams()['page'] );
462
+ if (typeof i == "number" && ! isNaN(i) ) {
463
+ return i;
464
+ }
465
+
466
+ return -1;
467
+ }
468
+
469
+ // toggle menu
470
+ function togglemenu() {
471
+ if ($('#readermenu').hasClass('showtop')) {
472
+ hidemenu();
473
+ }
474
+ else {
475
+ showmenu();
476
+ }
477
+
478
+ var t = new Date();
479
+ lastToggleMenu = t.getTime();
480
+ }
481
+
482
+ // show menu
483
+ function showmenu() {
484
+ // show the menu
485
+ $('#booktitle').addClass('showtop');
486
+ $('#readermenu').addClass('showtop');
487
+ }
488
+
489
+ function hidemenu() {
490
+ // set header & footer hidden
491
+ $('#booktitle').removeClass('showtop');
492
+ $('#readermenu').removeClass('showtop');
493
+ }
494
+
495
+ // show/hide menu when touch the page
496
+ function hasMoved(b,e) {
497
+ // move threshold
498
+ var mt = 5;
499
+
500
+ // shortcut for getting object
501
+ //var b = begin.originalEvent.changedTouches[0];
502
+ //var e = end.originalEvent.changedTouches[0];
503
+
504
+ // **hack**
505
+ // changed to array form because iOS+jQuery dont handle originalEvent and changedTouches correctly
506
+ // it doesn't store the last_touchstart correctly (it holds current one instead, so touchstart and touchend always ended up same value)
507
+ if (Math.abs(b[0] - e[0]) > mt || Math.abs(b[1] - e[1]) > mt) {
508
+ //console.log('moved');
509
+ return true;
510
+ }
511
+ else {
512
+ //console.log('not moved');
513
+ return false;
514
+ }
515
+ }
516
+
517
+ function toggleFullScreen(id) {
518
+ var elem = document.getElementById(id);
519
+ var btn = $('#gofullscreen'); // button for toggle full screen
520
+
521
+ if (isFullScreen()) {
522
+ btn.text('full screen');
523
+
524
+ exitFullScreen();
525
+ }
526
+ else {
527
+ btn.text('exit full screen');
528
+
529
+ goFullScreen(id);
530
+ }
531
+
532
+ // refresh button text
533
+ btn.button('refresh');
534
+ }