kamishibai 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }