summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2020-10-08 16:30:03 +0300
committerAndrew Dolgov <[email protected]>2020-10-08 16:30:03 +0300
commit8d57b9a5df1ea82e037aa31dd843f999df155b05 (patch)
treeca3786ebbb41ea5d6f9ada5c38d0192f9df5e929
parent37fadab4eb67d20fe0689eeff914cbeecb20e5d4 (diff)
even more gulp-related stuff
-rw-r--r--css/reader.css44
-rw-r--r--dist/app.min.js2
-rw-r--r--gulpfile.js8
-rw-r--r--index.php7
-rw-r--r--js/reader.js4
-rw-r--r--lib/fetch.js418
-rw-r--r--lib/promise.js233
-rw-r--r--offline.html4
-rw-r--r--read.html6
-rw-r--r--worker.js1
10 files changed, 20 insertions, 707 deletions
diff --git a/css/reader.css b/css/reader.css
deleted file mode 100644
index 1b222ea..0000000
--- a/css/reader.css
+++ /dev/null
@@ -1,44 +0,0 @@
-a {
- color : #007d71;
- text-decoration : none;
-}
-
-a:visited {
- text-decoration: underline;
-}
-
-a:hover,
-a:focus {
- color: #00302c;
- text-decoration: underline;
-}
-
-blockquote {
- font-style : italic;
-}
-
-/* ugly hack: this assumes default prefix used for epube - /books/
- * since CSS is loaded inline, relative urls won't work properly so
- * it's hardcoded for the time being (the alternative is pointing to
- * website root) */
-
-/* fonts below are freely available although license is likely proprietary
- * so i'm not bundling the files */
-
-@font-face {
- font-family: Caecilia;
- src: local('PMN Caecilia 55'), url('/books/lib/fonts/pmn-caecilia-55.ttf') format('truetype');
- font-weight : normal;
-}
-
-@font-face {
- font-family: Caecilia;
- src: local('PMN Caecilia 75'), url('/books/lib/fonts/pmn-caecilia-75.ttf') format('truetype');
- font-weight : bold;
-}
-
-@font-face {
- font-family: Caecilia;
- src: local('PMN Caecilia 56'), url('/books/lib/fonts/pmn-caecilia-56.ttf') format('truetype');
- font-style : italic;
-}
diff --git a/dist/app.min.js b/dist/app.min.js
index 6ced0f2..352db5e 100644
--- a/dist/app.min.js
+++ b/dist/app.min.js
@@ -1 +1 @@
-"use strict";$.urlParam=function(e){try{const t=new RegExp("[?&]"+e+"=([^&#]*)").exec(window.location.href);return decodeURIComponent(t[1].replace(/\+/g," "))||0}catch(e){return 0}};const Cookie={set:function(e,t,o){const n=new Date;n.setTime(n.getTime()+1e3*o);const a="expires="+n.toUTCString();document.cookie=e+"="+encodeURIComponent(t)+"; "+a},get:function(e){e+="=";const t=document.cookie.split(";");for(let o=0;o<t.length;o++){let n=t[o];for(;" "==n.charAt(0);)n=n.substring(1);if(0==n.indexOf(e))return decodeURIComponent(n.substring(e.length,n.length))}return""},delete:function(e){document.cookie=e+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT"}},App={_dl_progress_timeout:!1,index_mode:"",last_mtime:-1,init:function(){let e=0;"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),$(".separate-search").show(),"favorites"==$.urlParam("mode")?EpubeApp.setPage("PAGE_FAVORITES"):EpubeApp.setPage("PAGE_LIBRARY")),App.initNightMode(),App.initOfflineEvents(),"serviceWorker"in navigator?navigator.serviceWorker.addEventListener("message",(function(t){"refresh-started"==t.data&&(console.log("cache refresh started"),e=0,$(".dl-progress").fadeIn().text("Loading, please wait...")),t.data&&0==t.data.indexOf("refreshed:")&&(++e,$(".dl-progress").fadeIn().text("Updated "+e+" files...")),"client-reload"==t.data&&(localforage.setItem("epube.cache-timestamp",App.last_mtime),window.location.reload())})):$(".container-main").addClass("alert alert-danger").html("Service worker support missing in browser (are you using plain HTTP?)."),App.showCovers(),App.Offline.markBooks(),App.refreshCache()},showSummary:function(e){const t=e.getAttribute("data-book-id");return $.post("backend.php",{op:"getinfo",id:t},(function(e){const t=e.comment?e.comment:"No description available";$("#summary-modal .modal-title").html(e.title),$("#summary-modal .book-summary").html(t),$("#summary-modal").modal()})),!1},showCovers:function(){$("img[data-book-id]").each((e,t)=>{if((t=$(t)).attr("data-cover-link")){const e=$("<img>").on("load",(function(){t.css("background-image","url("+t.attr("data-cover-link")+")").fadeIn(),e.attr("src",null)})).attr("src",t.attr("data-cover-link"))}else t.attr("src","holder.js/130x190?auto=yes").fadeIn()}),Holder.run()},toggleFavorite:function(e){const t=e.getAttribute("data-book-id");return("0"==e.getAttribute("data-is-fav")||confirm("Remove favorite?"))&&$.post("backend.php",{op:"togglefav",id:t},(function(o){if(o){let n="[Error]";0==o.status?n="Add to favorites":1==o.status&&(n="Remove from favorites"),$(e).html(n).attr("data-is-fav",o.status),"favorites"==App.index_mode&&0==o.status&&$("#cell-"+t).remove()}})),!1},refreshCache:function(e){"serviceWorker"in navigator?localforage.getItem("epube.cache-timestamp").then((function(t){(e||t!=App.last_mtime)&&(console.log("asking worker to refresh cache"),navigator.serviceWorker.controller?navigator.serviceWorker.controller.postMessage("refresh-cache"):localforage.getItem("epube.initial-load-done").then((function(e){console.log("initial load done",e),e?$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page."):localforage.setItem("epube.initial-load-done",!0).then((function(){$(".dl-progress").show().addClass("alert-info").html("Page will reload to activate service worker..."),window.setTimeout((function(){window.location.reload()}),3e3)}))})))})):$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page.")},appCheckOffline:function(){EpubeApp.setOffline(!navigator.onLine)},initOfflineEvents:function(){"undefined"!=typeof EpubeApp&&($(window).on("online",(function(){EpubeApp.setOffline(!1)})),$(window).on("offline",(function(){EpubeApp.setOffline(!0)})),EpubeApp.setOffline(!navigator.onLine))},initNightMode:function(){if("undefined"==typeof EpubeApp){if(window.matchMedia){const e=window.matchMedia("(prefers-color-scheme: dark)");e.addEventListener("change",()=>{App.applyNightMode(e.matches)}),App.applyNightMode(e.matches)}}else App.applyNightMode(EpubeApp.isNightMode())},applyNightMode:function(e){console.log("night mode changed to",e),$("#theme_css").attr("href","lib/bootstrap/v3/css/"+(e?"theme-dark.min.css":"bootstrap-theme.min.css"))},Offline:{init:function(){"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),EpubeApp.setPage("PAGE_OFFLINE")),App.initNightMode(),App.initOfflineEvents();const e=$.urlParam("query");e&&$(".search_query").val(e),App.Offline.populateList()},get:function(e,t){console.log("offline cache: "+e),$.post("backend.php",{op:"getinfo",id:e},(function(o){if(o){const n="epube-book."+e;localforage.setItem(n,o).then((function(o){console.log(n+" got data");const a=[];a.push(fetch("backend.php?op=download&id="+o.epub_id,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got book"),t(),localforage.setItem(n+".book",e.blob()))}))),a.push(fetch("backend.php?op=getpagination&id="+o.epub_id,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got pagination"),e.text().then((function(e){localforage.setItem(n+".locations",JSON.parse(e))})))}))),a.push(fetch("backend.php?op=getlastread&id="+o.epub_id,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got lastread"),e.text().then((function(e){localforage.setItem(n+".lastread",JSON.parse(e))})))}))),o.has_cover&&a.push(fetch("backend.php?op=cover&id="+e,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got cover"),localforage.setItem(n+".cover",e.blob()))}))),Promise.all(a).then((function(){$(".dl-progress").show().html("Finished downloading <b>"+o.title+"</b>"),window.clearTimeout(App._dl_progress_timeout),App._dl_progress_timeout=window.setTimeout((function(){$(".dl-progress").fadeOut()}),5e3)}))}))}}))},getAll:function(){confirm("Download all books on this page?")&&$(".row > div").each((function(e,t){const o=$(t).attr("id").replace("cell-",""),n=$(t).find(".offline_dropitem")[0];if(o){const e="epube-book."+o;localforage.getItem(e).then((function(e){e||App.Offline.get(o,(function(){App.Offline.mark(n)}))}))}}))},markBooks:function(){const e=$(".offline_dropitem");$.each(e,(function(e,t){App.Offline.mark(t)}))},mark:function(e){const t=e.getAttribute("data-book-id"),o="epube-book."+t;localforage.getItem(o).then((function(o){o?(e.onclick=function(){return App.Offline.remove(t,(function(){App.Offline.mark(e)})),!1},e.innerHTML="Remove offline data"):(e.onclick=function(){return App.Offline.get(t,(function(){App.Offline.mark(e)})),!1},e.innerHTML="Make available offline")}))},removeFromList:function(e){const t=e.getAttribute("data-book-id");return App.Offline.remove(t,(function(){$("#cell-"+t).remove()}))},remove:function(e,t){if(confirm("Remove download?")){const o="epube-book."+e,n=[];console.log("offline remove: "+e),localforage.iterate((function(e,t){t.match(o)&&n.push(localforage.removeItem(t))})),Promise.all(n).then((function(){window.setTimeout((function(){t()}),500)}))}},search:function(){const e=$(".search_query").val();return localforage.setItem("epube.search-query",e).then((function(){App.Offline.populateList()})),!1},removeAll:function(){if(confirm("Remove all downloaded books?")){const e=[];localforage.iterate((function(t,o){o.match("epube-book")&&e.push(localforage.removeItem(o))})),Promise.all(e).then((function(){window.setTimeout((function(){App.Offline.populateList()}),500)}))}},showSummary:function(e){const t=e.getAttribute("data-book-id");return localforage.getItem("epube-book."+t).then((function(e){const t=e.comment?e.comment:"No description available";$("#summary-modal .modal-title").html(e.title),$("#summary-modal .book-summary").html(t),$("#summary-modal").modal()})),!1},populateList:function(){let e=$.urlParam("query");e&&(e=e.toLowerCase());const t=$("#books_container");t.html(""),localforage.iterate((function(o,n){n.match(/epube-book\.\d{1,}$/)&&Promise.all([localforage.getItem(n),localforage.getItem(n+".cover"),localforage.getItem(n+".lastread"),localforage.getItem(n+".book")]).then((function(o){if(o[0]&&o[3]){const n=o[0];if(e){if(!(n.series_name&&n.series_name.toLowerCase().match(e)||n.title&&n.title.toLowerCase().match(e)||n.author_sort&&n.author_sort.toLowerCase().match(e)))return}let a=!1;o&&o[1]&&(a=URL.createObjectURL(o[1]));let i=!1,r=!1;const l=o[2];l&&(i=l.page>0,r=l.total>0&&l.total-l.page<5);const c=r?"read":"",s=i?"in_progress":"",d=n.series_name?`<div><a class="series_link" href="#">${n.series_name+" ["+n.series_index+"]"}</a></div>`:"",p=$(`<div class="col-xxs-6 col-xs-4 col-sm-3 col-md-2" id="cell-${n.id}">\n\t\t\t\t\t\t\t<a class="thumbnail ${c}" href="read.html?id=${n.epub_id}&b=${n.id}">\n\t\t\t\t\t\t\t\t<img style="display : none">\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<div class="caption">\n\t\t\t\t\t\t\t\t<div><a class="${s}" href="read.html?id=${n.epub_id}&b=${n.id}">${n.title}</a></div>\n\t\t\t\t\t\t\t\t<div><a class="author_link" href="#">${n.author_sort}</a></div>\n\t\t\t\t\t\t\t\t${d}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class="dropdown" style="white-space : nowrap">\n\t\t\t\t\t\t\t\t<a href="#" data-toggle="dropdown" role="button">More...<span class="caret"></span></a>\n\t\t\t\t\t\t\t\t<ul class="dropdown-menu">\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="return App.Offline.showSummary(this)">Summary</a></li>\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="App.Offline.removeFromList(this)">Remove offline data</a></li>\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>`);a?p.find("img").css("background-image","url("+a+")").fadeIn():p.find("img").attr("data-src","holder.js/130x190?auto=yes").fadeIn(),p.find(".series_link").attr("title",n.series_name+" ["+n.series_index+"]").attr("href","offline.html?query="+encodeURIComponent(n.series_name)),p.find(".author_link").attr("title",n.author_sort).attr("href","offline.html?query="+encodeURIComponent(n.author_sort)),t.append(p),Holder.run()}}))}))}}},DEFAULT_FONT_SIZE=16,DEFAULT_FONT_FAMILY="Georgia",DEFAULT_LINE_HEIGHT=140,MIN_LENGTH_TO_JUSTIFY=32,Reader={init:function(){$(document).on("keyup",(function(e){Reader.hotkeyHandler(e)})),$("#left").on("mouseup",(function(){Reader.Page.prev()})),$("#right").on("mouseup",(function(){Reader.Page.next()})),Reader.Loader.init()},initSecondStage:function(){"undefined"!=typeof EpubeApp&&EpubeApp.setPage("PAGE_READER"),Reader.applyTheme(),"true"==Cookie.get("is-epube-app")&&$("body").addClass("is-epube-app"),$(window).on("online",(function(){console.log("we're online, storing lastread");const t=e.rendition.currentLocation().start.cfi,o=parseInt(100*e.locations.percentageFromCfi(t));$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:o,cfi:t},(function(e){e.cfi&&(Reader.Page._last_position_sync=(new Date).getTime()/1e3)})).fail((function(e){e&&401==e.status&&(window.location="index.php")}))})),localforage.getItem(Reader.cacheId("book")).then((function(t){if(/*!_is_ios &&*/t){console.log("loading from local storage");const o=new FileReader;o.onload=function(){try{e.open(this.result)}catch(e){$(".loading_message").html("Unable to load book (local)."),console.log(e)}},o.readAsArrayBuffer(t)}else if(console.log("loading from network"),navigator.onLine){const t="backend.php?op=download&id="+$.urlParam("id");$(".loading_message").html("Downloading..."),fetch(t,{credentials:"same-origin"}).then((function(t){if(200==t.status){const o=$.urlParam("b");t.blob().then((function(t){localforage.getItem(Reader.cacheId()).then((function(e){e||$.post("backend.php",{op:"getinfo",id:o},(function(e){e&&(localforage.setItem(Reader.cacheId(),e),e.has_cover&&fetch("backend.php?op=cover&id="+o,{credentials:"same-origin"}).then((function(e){200==e.status&&localforage.setItem(Reader.cacheId("cover"),e.blob())})))}))}));const n=new FileReader;n.onload=function(){e.open(this.result).then(()=>{localforage.setItem(Reader.cacheId("book"),t)}).catch(e=>{$(".loading_message").html("Unable to open book.<br/><small>"+e+"</small>")})},n.onerror=function(e){console.log("filereader error",e),$(".loading_message").html("Unable to open book.<br/><small>"+e+"</small>")},n.readAsArrayBuffer(t)})).catch(e=>{console.log("blob error",e),$(".loading_message").html("Unable to download book.<br/><small>"+e+"</small>")})}else $(".loading_message").html("Unable to download book: "+t.status+".")})).catch((function(e){console.warn(e),$(".loading").is(":visible")&&$(".loading_message").html("Unable to load book (remote).<br/><small>"+e+"</small>")}))}else $(".loading_message").html("This book is not available offline.")}));const e=ePub();window.book=e;const t=e.renderTo("reader",{width:"100%",height:"100%",minSpreadWidth:961});function o(t){try{const o=e.spine.get(t).cfiBase,n=e.locations._locations.find((function(e){return-1!=e.indexOf(o)}));return window.book.locations.locationFromCfi(n)}catch(e){console.warn(e)}return""}localforage.getItem("epube.enable-hyphens").then((function(e){e&&(Reader.hyphenateHTML=createHyphenator(hyphenationPatternsEnUs,{html:!0})),Reader.applyStyles(!0),t.display().then((function(){console.log("book displayed")}))})),t.hooks.content.register((function(t){t.on("linkClicked",(function(t){console.log("linkClicked",t),-1==t.indexOf("://")&&($(".prev_location_btn").attr("data-location-cfi",e.rendition.currentLocation().start.cfi).show(),window.setTimeout((function(){Reader.showUI(!0)}),50))}));const o=window.location.href.match(/^.*\//)[0],n=["dist/app-libs.min.js","js/reader_iframe.js"],a=t.document;for(let e=0;e<n.length;e++){const t=a.createElement("script");t.type="text/javascript",t.text=Reader.Loader._res_data[o+n[e]],a.head.appendChild(t)}return $(t.document.head).append($("<style type='text/css'>").text(Reader.Loader._res_data[o+"css/reader.css"])),localforage.getItem("epube.theme").then((function(e){e||(e="default");const n=o+"themes/"+e+".css";$(t.document.head).append($("<style type='text/css' id='theme_css'>").text(Reader.Loader._res_data[n]))}))})),$("#settings-modal").on("shown.bs.modal",(function(){localforage.getItem(Reader.cacheId("lastread")).then(e=>{e&&e.cfi&&$(".lastread_input").val(e.page+"%"),$.post("backend.php",{op:"getlastread",id:$.urlParam("id")},(function(e){$(".lastread_input").val(e.page+"%")}))}),localforage.getItem("epube.enable-hyphens").then((function(e){$(".enable_hyphens_checkbox").attr("checked",e).off("click").on("click",(function(e){localforage.setItem("epube.enable-hyphens",e.target.checked),confirm("Toggling hyphens requires page reload. Reload now?")&&window.location.reload()}))})),localforage.getItem("epube.keep-ui-visible").then((function(e){$(".keep_ui_checkbox").attr("checked",e).off("click").on("click",(function(e){localforage.setItem("epube.keep-ui-visible",e.target.checked)}))})),localforage.getItem("epube.cache-timestamp").then((function(e){let t="V: ";parseInt(e)?t+=new Date(1e3*e).toLocaleString("en-GB"):t+="Unknown",t+=" ("+(navigator.onLine?"Online":"Offline")+")",$(".last-mod-timestamp").text(t)})),localforage.getItem("epube.fontFamily").then((function(e){e||(e="Georgia"),$(".font_family").val(e)})),localforage.getItem("epube.theme").then((function(e){$(".theme_name").val(e)})),localforage.getItem("epube.fontSize").then((function(e){e||(e=16);const t=$(".font_size").html("");for(let e=10;e<=32;e++){const o=$("<option>").val(e).html(e+" px");t.append(o)}t.val(e)})),localforage.getItem("epube.lineHeight").then((function(e){e||(e=140);const t=$(".line_height").html("");for(let e=100;e<=220;e+=10){const o=$("<option>").val(e).html(e+"%");t.append(o)}t.val(e)}))})),$("#dict-modal").on("shown.bs.modal",(function(){$(".dict_result").scrollTop(0)})),$(".dict_search_btn").on("click",(function(){$("#dict-modal").modal("hide"),window.open("https://duckduckgo.com/?q="+$(".dict_query").val())})),$(".wiki_search_btn").on("click",(function(){$(".dict_result").html("Loading, please wait..."),$.post("backend.php",{op:"wikisearch",query:$(".dict_query").val()}).then(e=>{try{let t="";$.each(e.query.pages,(e,o)=>{t+=o.extract}),$(".dict_result").html(t&&"undefined"!=t?t:"No definition found for "+$(".dict_query").val()+".")}catch(e){console.error(e),$(".dict_result").text("Error while processing data: "+e)}}).fail(e=>{console.error(e),$(".dict_result").text("Error while retrieving data.")})})),$("#toc-modal").on("shown.bs.modal",(function(){const t=e.navigation.toc,n=$(".toc_list");n.html(""),$.each(t,(function(t,a){try{const t=$("<a>").attr("href","#").html("<b class='pull-right'>"+o(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){e.rendition.display(t.attr("data-href"))}));n.append($("<li>").append(t)),function t(n,a,i){if(3==i)return!1;if(n.subitems){const r=$("<ul class='toc_sublist list-unstyled'>");$.each(n.subitems,(function(n,a){const l=$("<a>").attr("href","#").html("<b class='pull-right'>"+o(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){e.rendition.display(l.attr("data-href"))}));r.append($("<li>").append(l)),t(a,r,i+1)})),a.append(r)}}(a,n,0)}catch(e){console.warn(e)}})),n.children().length<=1&&(n.html(""),$.each(e.spine.items,(function(t,o){const a=$("<a>").attr("href","#").attr("title",o.url).html("Section "+(t+1)).attr("data-href",o.href).click((function(){e.rendition.display(a.attr("data-href"))}));n.append($("<li>").append(a))})))})),e.spine.hooks.content.register((function(e){$(e).find("p").filter((e,t)=>{if($(t).text().length>=32)return t}).css("text-align","justify"),$(e).find("p, span, em, strong, body, div").attr("class","").css("color","").css("background","").css("background-color",""),void 0!==Reader.hyphenateHTML&&$(e).find("p").each((e,t)=>{(t=$(t)).html(Reader.hyphenateHTML(t.html()))})})),e.ready.then((function(){const t=e.package.metadata;return document.title=t.title+" – "+t.creator+" – The Epube",$(".title").text(t.title),"undefined"!=typeof EpubeApp&&(EpubeApp.setTitle(t.title),EpubeApp.showActionBar(!1)),localforage.getItem(Reader.cacheId("locations")).then((function(t){if(console.log("stored pagination",null!=t),t&&"string"==typeof t[0])return Reader.Page._pagination_stored=1,e.locations.load(t);{console.log("requesting pagination...");const t="backend.php?op=getpagination&id="+encodeURIComponent($.urlParam("id"));return fetch(t,{credentials:"same-origin"}).then((function(t){return t.ok?t.json().then((function(t){return t&&"string"==typeof t[0]?(Reader.Page._pagination_stored=1,e.locations.load(t)):($(".loading_message").html("Paginating..."),e.locations.generate(1600))})):($(".loading_message").html("Paginating..."),e.locations.generate(1600))})).catch((function(){return $(".loading_message").html("Paginating..."),e.locations.generate(1600)}))}}))})).then((function(t){console.log("locations ready, stored=",Reader.Page._pagination_stored),t?(navigator.onLine&&!Reader.Page._pagination_stored&&$.post("backend.php",{op:"storepagination",id:$.urlParam("id"),payload:JSON.stringify(t),total:100}),localforage.getItem(Reader.cacheId("locations")).then((function(e){e||localforage.setItem(Reader.cacheId("locations"),t)})),$(".location").click((function(){const t=e.rendition.currentLocation().start.location,o=e.locations.length(),n=prompt("Jump to location [1-"+o+"]",t);n&&e.rendition.display(e.locations._locations[n])})),Reader.Page.openLastRead(),window.setTimeout((function(){Reader.Page.openLastRead(),$(".loading").hide()}),250)):$(".loading_message").html("Pagination failed.")})),t.on("keyup",e=>{Reader.hotkeyHandler(e)}),t.on("resized",(function(){console.log("resized"),$(".loading").show(),$(".loading_message").html("Opening chapter..."),window.setTimeout((function(){Reader.resizeSideColumns(),Reader.Page.openLastRead(),$(".loading").hide()}),250)})),t.on("rendered",(function(){$(".chapter").html($("<span>").addClass("glyphicon glyphicon-th-list")),Reader.applyTheme(),Reader.resizeSideColumns();try{const t=e.rendition.currentLocation();if(t.start){const o=e.canonical(t.start.href);let n=!1;$.each(Reader.flattenToc(e),(function(t,a){e.spine.get(a.href).canonical!=o||(n=a)})),n&&n.label&&$(".chapter").append("&nbsp;"+n.label.trim()+" | "),Reader.generateTocBar(e,Reader.flattenToc(e))}}catch(e){console.warn(e)}})),t.on("relocated",(function(t){if(0==e.locations.length())return;const o=t.start.cfi,n=parseInt(100*e.locations.percentageFromCfi(o));$("#cur_page").text(t.start.location),$("#total_pages").text(e.locations.length()),$("#page_pct").text(parseInt(100*e.locations.percentageFromCfi(o))+"%"),Reader.updateTocBarPosition(e,t);const a=t.start.displayed;a&&($("#chapter_cur_page").text(a.page),$("#chapter_total_pages").text(a.total),a.total>0&&$("#chapter_pct").text(parseInt(a.page/a.total*100)+"%")),Reader.Page._store_position&&(new Date).getTime()/1e3-Reader.Page._last_position_sync>15&&(console.log("storing lastread",n,o),navigator.onLine?($.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:n,cfi:o},(function(e){e.cfi&&(Reader.Page._last_position_sync=(new Date).getTime()/1e3)})).fail((function(e){e&&401==e.status&&(window.location="index.php")})),Reader.Page._store_position=0):Reader.Page._last_position_sync=0,localforage.setItem(Reader.cacheId("lastread"),{cfi:o,page:n,total:100}))}))},flattenTocSubItems:function(e,t){let o=[];return 3!=t&&(e.subitems&&$.each(e.subitems,(function(e,n){n._nest=t,o.push(n),o=o.concat(Reader.flattenTocSubItems(n,t+1))})),o)},flattenToc:function(e){if(this._flattened_toc)return this._flattened_toc;{let t=[];return $.each(e.navigation.toc,(function(e,o){o._nest=0,t.push(o),t=t.concat(Reader.flattenTocSubItems(o,1))})),this._flattened_toc=t,t}},generateTocBar:function(e,t){$(".spacer").html(""),$.each(t,(function(t,o){try{const t=e.spine.get(o.href).cfiBase,n=e.locations._locations.find((function(e){return-1!=e.indexOf(t)}));if(n){const t=Math.round(100*e.locations.percentageFromCfi(n));$(".spacer").append($("<div class='toc-bar-entry'>").attr("data-nest-level",o._nest).css("left",t+"%").css("_width",3-o._nest+"px").attr("title",o.label))}}catch(e){console.warn(e)}})),$(".spacer").append($("<div class='toc-bar-entry current-position'>")),Reader.updateTocBarPosition(e,e.rendition.currentLocation())},updateTocBarPosition:function(e,t){const o=Math.round(t.start.location/e.locations.length()*100);$(".toc-bar-entry.current-position").css("left",o+"%")},applyStyles:function(e){Promise.all([localforage.getItem("epube.fontSize"),localforage.getItem("epube.fontFamily"),localforage.getItem("epube.lineHeight"),localforage.getItem("epube.theme")]).then((function(t){const o=t[0]?t[0]+"px":"16px",n=t[1]?t[1]:"Georgia",a=t[2]?t[2]+"%":"140%";console.log("style",n,o,a),console.log("applying default theme..."),window.book.rendition.themes.default({html:{"font-size":o,"font-family":"'"+n+"'","line-height":a,"text-align":"justify","text-indent":"1em"}}),e||(console.log("applying rendition themes..."),$.each(window.book.rendition.getContents(),(function(e,t){t.css("font-size",o),t.css("font-family","'"+n+"'"),t.css("line-height",a),t.css("text-align","justify")}))),Reader.applyTheme()}))},applyTheme:function(){localforage.getItem("epube.theme").then((function(e){const t=window.location.href.match(/^.*\//)[0];e||(e="default"),console.log("called for theme",e),"default"==e&&"undefined"!=typeof EpubeApp&&EpubeApp.isNightMode()&&(e="night"),console.log("setting main UI theme",e);const o=t+"themes/"+e+".css";Reader.Loader._res_data[o]?($("#theme_css").attr("href",o),"undefined"!=typeof EpubeApp&&window.setTimeout((function(){const e=window.getComputedStyle(document.querySelector("body"),null).getPropertyValue("background-color").match(/rgb\((\d{1,}), (\d{1,}), (\d{1,})\)/);e&&(console.log("sending bgcolor",e),EpubeApp.setStatusBarColor(parseInt(e[1]),parseInt(e[2]),parseInt(e[3])))}),250),$.each(window.book.rendition.getContents(),(function(t,n){console.log("applying rendition theme",e,"to",n,n.document),$(n.document).find("#theme_css").text(Reader.Loader._res_data[o])}))):console.error("theme data not found for",e,"- check resource loader configuration")}))},hotkeyHandler:function(e){try{if($(".modal").is(":visible"))return;39!=e.which&&32!=e.which&&34!=e.which||(e.preventDefault(),Reader.Page.next()),37!=e.which&&33!=e.which||(e.preventDefault(),Reader.Page.prev()),27==e.which&&(e.preventDefault(),Reader.showUI(!0))}catch(e){console.warn(e)}},resizeSideColumns:function(){let e=$("#reader").position().left;const t=$("#reader iframe")[0];t&&t.contentWindow.$&&(e+=parseInt(t.contentWindow.$("body").css("padding-left"))),$("#left, #right").width(e)},markAsRead:function(){if(confirm("Mark book as read?")){const e=100,t=window.book.locations.cfiFromPercentage(1);navigator.onLine&&$.post("backend.php",{op:"storelastread",page:e,cfi:t,id:$.urlParam("id")},(function(e){$(".lastread_input").val(e.page+"%")})),localforage.setItem(Reader.cacheId("lastread"),{cfi:t,page:e,total:e})}},close:function(){const e=window.book.rendition.currentLocation().start.cfi,t=parseInt(100*window.book.locations.percentageFromCfi(e));localforage.setItem(Reader.cacheId("lastread"),{cfi:e,page:t,total:100}),navigator.onLine?$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:t,cfi:e},(function(){window.location=$.urlParam("rt")?"index.php?mode="+$.urlParam("rt"):"index.php"})).fail((function(){window.location="index.php"})):window.location="index.php"},cacheId:function(e){return"epube-book."+$.urlParam("b")+(e?"."+e:"")},toggleFullscreen:function(){if("undefined"!=typeof EpubeApp);else{const e=document.documentElement,t=document.webkitIsFullScreen||document.mozFullScreen||!1;e.requestFullScreen=e.requestFullScreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||function(){return!1},document.cancelFullScreen=document.cancelFullScreen||document.webkitCancelFullScreen||document.mozCancelFullScreen||function(){return!1},t?document.cancelFullScreen():e.requestFullScreen()}},showUI:function(e){e?$(".header,.footer").fadeIn():$(".header,.footer").fadeOut()},toggleUI:function(){$(".header").is(":visible")?$(".header,.footer").fadeOut():$(".header,.footer").fadeIn()},lookupWord:function(e,t){e=e.replace(/­/g,""),$(".dict_result").html("Loading, please wait..."),$("#dict-modal").modal("show"),$.post("backend.php",{op:"define",word:e},(function(o){o&&($(".dict_result").html(o.result.join("<br/>")),$(".dict_query").val(e),t&&t())})).fail((function(e){console.warn(e),$(".dict_result").html("Network error while looking up word: "+e.statusText)}))},search:function(){const e=$(".search_input").val(),t=$(".search_results");t.html(""),e&&Promise.all(window.book.spine.spineItems.map(t=>t.load(window.book.load.bind(window.book)).then(t.find.bind(t,e)).finally(t.unload.bind(t)))).then(e=>Promise.resolve([].concat.apply([],e))).then((function(e){$.each(e,(function(e,o){const n=$("<a>").attr("href","#").html("<b class='pull-right'>"+window.book.locations.locationFromCfi(o.cfi)+"</b>"+o.excerpt).attr("data-cfi",o.cfi).attr("data-id",o.id).click((function(){window.book.rendition.display(n.attr("data-cfi"))}));t.append($("<li>").append(n))}))}))},Loader:{_res_data:[],init:function(){const e=["dist/app-libs.min.js","js/reader_iframe.js","css/reader.css"];for(let t=0;t<e.length;t++)fetch(e[t],{credentials:"same-origin"}).then((function(o){200==o.status?o.text().then((function(e){const t=new URL(o.url);t.searchParams.delete("ts"),Reader.Loader._res_data[t.toString()]=e})):console.warn("loader failed for resource",e[t],o)}));Reader.Loader.checkProgress(e,Reader.Loader._res_data,0)},checkProgress:function(e,t,o){console.log("check_resource_load",o,e.length,Object.keys(t).length,Reader,Reader.Loader),5!=o?e.length!=Object.keys(t).length?window.setTimeout((function(){Reader.Loader.checkProgress(e,t,o+1)}),250):Reader.initSecondStage():$(".loading_message").html("Unable to load resources.")}},Page:{_store_position:0,_last_position_sync:0,_pagination_stored:0,next:function(){Reader.Page._store_position=1,window.book.rendition.next(),"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(e){e||Reader.showUI(!1)}))},prev:function(){window.book.rendition.prev(),"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(e){e||Reader.showUI(!1)}))},openPrevious:function(e){const t=$(e).attr("data-location-cfi");t&&window.book.rendition.display(t),$(e).fadeOut()},clearLastRead:function(){if(confirm("Clear stored last read location?")){const e=window.book.locations.length();navigator.onLine&&$.post("backend.php",{op:"storelastread",page:-1,cfi:"",id:$.urlParam("id")},(function(e){$(".lastread_input").val(e.page+"%")})),localforage.setItem(Reader.cacheId("lastread"),{cfi:"",page:0,total:e}),window.setTimeout((function(){window.book.rendition.display(window.book.locations.cfiFromPercentage(0))}),250)}},openLastRead:function(e){localforage.getItem(Reader.cacheId("lastread")).then((function(t){console.log("lr local",t),t=t||{};try{t.cfi&&window.book.rendition.display(t.cfi).then(()=>{$(".loading").hide(),window.book.rendition.display(t.cfi)})}catch(e){console.warn(e)}navigator.onLine&&!e&&$.post("backend.php",{op:"getlastread",id:$.urlParam("id")},(function(e){if(console.log("lr remote",e),navigator.onLine&&e)try{t.cfi!=e.cfi&&(!t.page||e.page>=t.page)&&console.log("using remote lastread..."),localforage.setItem(Reader.cacheId("lastread"),{cfi:e.cfi,page:e.page,total:e.total}),window.book.rendition.display(e.cfi).then(()=>{window.book.rendition.display(e.cfi)})}catch(e){console.warn(e)}})).fail((function(e){e&&401==e.status&&(window.location="index.php")}))}))}},Settings:{onThemeChanged:function(e){const t=$(e).val();localforage.setItem("epube.theme",t).then((function(){Reader.applyTheme()}))},onLineHeightChanged:function(e){const t=$(e).val();localforage.setItem("epube.lineHeight",t).then((function(){Reader.applyStyles()}))},onTextSizeChanged:function(e){const t=$(e).val();localforage.setItem("epube.fontSize",t).then((function(){Reader.applyStyles()}))},onFontChanged:function(e){const t=$(e).val();localforage.setItem("epube.fontFamily",t).then((function(){Reader.applyStyles()}))}}};function __get_reader(){return Reader} \ No newline at end of file
+"use strict";$.urlParam=function(e){try{const t=new RegExp("[?&]"+e+"=([^&#]*)").exec(window.location.href);return decodeURIComponent(t[1].replace(/\+/g," "))||0}catch(e){return 0}};const Cookie={set:function(e,t,o){const n=new Date;n.setTime(n.getTime()+1e3*o);const a="expires="+n.toUTCString();document.cookie=e+"="+encodeURIComponent(t)+"; "+a},get:function(e){e+="=";const t=document.cookie.split(";");for(let o=0;o<t.length;o++){let n=t[o];for(;" "==n.charAt(0);)n=n.substring(1);if(0==n.indexOf(e))return decodeURIComponent(n.substring(e.length,n.length))}return""},delete:function(e){document.cookie=e+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT"}},App={_dl_progress_timeout:!1,index_mode:"",last_mtime:-1,init:function(){let e=0;"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),$(".separate-search").show(),"favorites"==$.urlParam("mode")?EpubeApp.setPage("PAGE_FAVORITES"):EpubeApp.setPage("PAGE_LIBRARY")),App.initNightMode(),App.initOfflineEvents(),"serviceWorker"in navigator?navigator.serviceWorker.addEventListener("message",(function(t){"refresh-started"==t.data&&(console.log("cache refresh started"),e=0,$(".dl-progress").fadeIn().text("Loading, please wait...")),t.data&&0==t.data.indexOf("refreshed:")&&(++e,$(".dl-progress").fadeIn().text("Updated "+e+" files...")),"client-reload"==t.data&&(localforage.setItem("epube.cache-timestamp",App.last_mtime),window.location.reload())})):$(".container-main").addClass("alert alert-danger").html("Service worker support missing in browser (are you using plain HTTP?)."),App.showCovers(),App.Offline.markBooks(),App.refreshCache()},showSummary:function(e){const t=e.getAttribute("data-book-id");return $.post("backend.php",{op:"getinfo",id:t},(function(e){const t=e.comment?e.comment:"No description available";$("#summary-modal .modal-title").html(e.title),$("#summary-modal .book-summary").html(t),$("#summary-modal").modal()})),!1},showCovers:function(){$("img[data-book-id]").each((e,t)=>{if((t=$(t)).attr("data-cover-link")){const e=$("<img>").on("load",(function(){t.css("background-image","url("+t.attr("data-cover-link")+")").fadeIn(),e.attr("src",null)})).attr("src",t.attr("data-cover-link"))}else t.attr("src","holder.js/130x190?auto=yes").fadeIn()}),Holder.run()},toggleFavorite:function(e){const t=e.getAttribute("data-book-id");return("0"==e.getAttribute("data-is-fav")||confirm("Remove favorite?"))&&$.post("backend.php",{op:"togglefav",id:t},(function(o){if(o){let n="[Error]";0==o.status?n="Add to favorites":1==o.status&&(n="Remove from favorites"),$(e).html(n).attr("data-is-fav",o.status),"favorites"==App.index_mode&&0==o.status&&$("#cell-"+t).remove()}})),!1},refreshCache:function(e){"serviceWorker"in navigator?localforage.getItem("epube.cache-timestamp").then((function(t){(e||t!=App.last_mtime)&&(console.log("asking worker to refresh cache"),navigator.serviceWorker.controller?navigator.serviceWorker.controller.postMessage("refresh-cache"):localforage.getItem("epube.initial-load-done").then((function(e){console.log("initial load done",e),e?$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page."):localforage.setItem("epube.initial-load-done",!0).then((function(){$(".dl-progress").show().addClass("alert-info").html("Page will reload to activate service worker..."),window.setTimeout((function(){window.location.reload()}),3e3)}))})))})):$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page.")},appCheckOffline:function(){EpubeApp.setOffline(!navigator.onLine)},initOfflineEvents:function(){"undefined"!=typeof EpubeApp&&($(window).on("online",(function(){EpubeApp.setOffline(!1)})),$(window).on("offline",(function(){EpubeApp.setOffline(!0)})),EpubeApp.setOffline(!navigator.onLine))},initNightMode:function(){if("undefined"==typeof EpubeApp){if(window.matchMedia){const e=window.matchMedia("(prefers-color-scheme: dark)");e.addEventListener("change",()=>{App.applyNightMode(e.matches)}),App.applyNightMode(e.matches)}}else App.applyNightMode(EpubeApp.isNightMode())},applyNightMode:function(e){console.log("night mode changed to",e),$("#theme_css").attr("href","lib/bootstrap/v3/css/"+(e?"theme-dark.min.css":"bootstrap-theme.min.css"))},Offline:{init:function(){"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),EpubeApp.setPage("PAGE_OFFLINE")),App.initNightMode(),App.initOfflineEvents();const e=$.urlParam("query");e&&$(".search_query").val(e),App.Offline.populateList()},get:function(e,t){console.log("offline cache: "+e),$.post("backend.php",{op:"getinfo",id:e},(function(o){if(o){const n="epube-book."+e;localforage.setItem(n,o).then((function(o){console.log(n+" got data");const a=[];a.push(fetch("backend.php?op=download&id="+o.epub_id,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got book"),t(),localforage.setItem(n+".book",e.blob()))}))),a.push(fetch("backend.php?op=getpagination&id="+o.epub_id,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got pagination"),e.text().then((function(e){localforage.setItem(n+".locations",JSON.parse(e))})))}))),a.push(fetch("backend.php?op=getlastread&id="+o.epub_id,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got lastread"),e.text().then((function(e){localforage.setItem(n+".lastread",JSON.parse(e))})))}))),o.has_cover&&a.push(fetch("backend.php?op=cover&id="+e,{credentials:"same-origin"}).then((function(e){200==e.status&&(console.log(n+" got cover"),localforage.setItem(n+".cover",e.blob()))}))),Promise.all(a).then((function(){$(".dl-progress").show().html("Finished downloading <b>"+o.title+"</b>"),window.clearTimeout(App._dl_progress_timeout),App._dl_progress_timeout=window.setTimeout((function(){$(".dl-progress").fadeOut()}),5e3)}))}))}}))},getAll:function(){confirm("Download all books on this page?")&&$(".row > div").each((function(e,t){const o=$(t).attr("id").replace("cell-",""),n=$(t).find(".offline_dropitem")[0];if(o){const e="epube-book."+o;localforage.getItem(e).then((function(e){e||App.Offline.get(o,(function(){App.Offline.mark(n)}))}))}}))},markBooks:function(){const e=$(".offline_dropitem");$.each(e,(function(e,t){App.Offline.mark(t)}))},mark:function(e){const t=e.getAttribute("data-book-id"),o="epube-book."+t;localforage.getItem(o).then((function(o){o?(e.onclick=function(){return App.Offline.remove(t,(function(){App.Offline.mark(e)})),!1},e.innerHTML="Remove offline data"):(e.onclick=function(){return App.Offline.get(t,(function(){App.Offline.mark(e)})),!1},e.innerHTML="Make available offline")}))},removeFromList:function(e){const t=e.getAttribute("data-book-id");return App.Offline.remove(t,(function(){$("#cell-"+t).remove()}))},remove:function(e,t){if(confirm("Remove download?")){const o="epube-book."+e,n=[];console.log("offline remove: "+e),localforage.iterate((function(e,t){t.match(o)&&n.push(localforage.removeItem(t))})),Promise.all(n).then((function(){window.setTimeout((function(){t()}),500)}))}},search:function(){const e=$(".search_query").val();return localforage.setItem("epube.search-query",e).then((function(){App.Offline.populateList()})),!1},removeAll:function(){if(confirm("Remove all downloaded books?")){const e=[];localforage.iterate((function(t,o){o.match("epube-book")&&e.push(localforage.removeItem(o))})),Promise.all(e).then((function(){window.setTimeout((function(){App.Offline.populateList()}),500)}))}},showSummary:function(e){const t=e.getAttribute("data-book-id");return localforage.getItem("epube-book."+t).then((function(e){const t=e.comment?e.comment:"No description available";$("#summary-modal .modal-title").html(e.title),$("#summary-modal .book-summary").html(t),$("#summary-modal").modal()})),!1},populateList:function(){let e=$.urlParam("query");e&&(e=e.toLowerCase());const t=$("#books_container");t.html(""),localforage.iterate((function(o,n){n.match(/epube-book\.\d{1,}$/)&&Promise.all([localforage.getItem(n),localforage.getItem(n+".cover"),localforage.getItem(n+".lastread"),localforage.getItem(n+".book")]).then((function(o){if(o[0]&&o[3]){const n=o[0];if(e){if(!(n.series_name&&n.series_name.toLowerCase().match(e)||n.title&&n.title.toLowerCase().match(e)||n.author_sort&&n.author_sort.toLowerCase().match(e)))return}let a=!1;o&&o[1]&&(a=URL.createObjectURL(o[1]));let i=!1,r=!1;const l=o[2];l&&(i=l.page>0,r=l.total>0&&l.total-l.page<5);const c=r?"read":"",s=i?"in_progress":"",d=n.series_name?`<div><a class="series_link" href="#">${n.series_name+" ["+n.series_index+"]"}</a></div>`:"",p=$(`<div class="col-xxs-6 col-xs-4 col-sm-3 col-md-2" id="cell-${n.id}">\n\t\t\t\t\t\t\t<a class="thumbnail ${c}" href="read.html?id=${n.epub_id}&b=${n.id}">\n\t\t\t\t\t\t\t\t<img style="display : none">\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<div class="caption">\n\t\t\t\t\t\t\t\t<div><a class="${s}" href="read.html?id=${n.epub_id}&b=${n.id}">${n.title}</a></div>\n\t\t\t\t\t\t\t\t<div><a class="author_link" href="#">${n.author_sort}</a></div>\n\t\t\t\t\t\t\t\t${d}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class="dropdown" style="white-space : nowrap">\n\t\t\t\t\t\t\t\t<a href="#" data-toggle="dropdown" role="button">More...<span class="caret"></span></a>\n\t\t\t\t\t\t\t\t<ul class="dropdown-menu">\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="return App.Offline.showSummary(this)">Summary</a></li>\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="App.Offline.removeFromList(this)">Remove offline data</a></li>\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>`);a?p.find("img").css("background-image","url("+a+")").fadeIn():p.find("img").attr("data-src","holder.js/130x190?auto=yes").fadeIn(),p.find(".series_link").attr("title",n.series_name+" ["+n.series_index+"]").attr("href","offline.html?query="+encodeURIComponent(n.series_name)),p.find(".author_link").attr("title",n.author_sort).attr("href","offline.html?query="+encodeURIComponent(n.author_sort)),t.append(p),Holder.run()}}))}))}}},DEFAULT_FONT_SIZE=16,DEFAULT_FONT_FAMILY="Georgia",DEFAULT_LINE_HEIGHT=140,MIN_LENGTH_TO_JUSTIFY=32,Reader={init:function(){$(document).on("keyup",(function(e){Reader.hotkeyHandler(e)})),$("#left").on("mouseup",(function(){Reader.Page.prev()})),$("#right").on("mouseup",(function(){Reader.Page.next()})),Reader.Loader.init()},initSecondStage:function(){"undefined"!=typeof EpubeApp&&EpubeApp.setPage("PAGE_READER"),Reader.applyTheme(),"true"==Cookie.get("is-epube-app")&&$("body").addClass("is-epube-app"),$(window).on("online",(function(){console.log("we're online, storing lastread");const t=e.rendition.currentLocation().start.cfi,o=parseInt(100*e.locations.percentageFromCfi(t));$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:o,cfi:t},(function(e){e.cfi&&(Reader.Page._last_position_sync=(new Date).getTime()/1e3)})).fail((function(e){e&&401==e.status&&(window.location="index.php")}))})),localforage.getItem(Reader.cacheId("book")).then((function(t){if(/*!_is_ios &&*/t){console.log("loading from local storage");const o=new FileReader;o.onload=function(){try{e.open(this.result)}catch(e){$(".loading_message").html("Unable to load book (local)."),console.log(e)}},o.readAsArrayBuffer(t)}else if(console.log("loading from network"),navigator.onLine){const t="backend.php?op=download&id="+$.urlParam("id");$(".loading_message").html("Downloading..."),fetch(t,{credentials:"same-origin"}).then((function(t){if(200==t.status){const o=$.urlParam("b");t.blob().then((function(t){localforage.getItem(Reader.cacheId()).then((function(e){e||$.post("backend.php",{op:"getinfo",id:o},(function(e){e&&(localforage.setItem(Reader.cacheId(),e),e.has_cover&&fetch("backend.php?op=cover&id="+o,{credentials:"same-origin"}).then((function(e){200==e.status&&localforage.setItem(Reader.cacheId("cover"),e.blob())})))}))}));const n=new FileReader;n.onload=function(){e.open(this.result).then(()=>{localforage.setItem(Reader.cacheId("book"),t)}).catch(e=>{$(".loading_message").html("Unable to open book.<br/><small>"+e+"</small>")})},n.onerror=function(e){console.log("filereader error",e),$(".loading_message").html("Unable to open book.<br/><small>"+e+"</small>")},n.readAsArrayBuffer(t)})).catch(e=>{console.log("blob error",e),$(".loading_message").html("Unable to download book.<br/><small>"+e+"</small>")})}else $(".loading_message").html("Unable to download book: "+t.status+".")})).catch((function(e){console.warn(e),$(".loading").is(":visible")&&$(".loading_message").html("Unable to load book (remote).<br/><small>"+e+"</small>")}))}else $(".loading_message").html("This book is not available offline.")}));const e=ePub();window.book=e;const t=e.renderTo("reader",{width:"100%",height:"100%",minSpreadWidth:961});function o(t){try{const o=e.spine.get(t).cfiBase,n=e.locations._locations.find((function(e){return-1!=e.indexOf(o)}));return window.book.locations.locationFromCfi(n)}catch(e){console.warn(e)}return""}localforage.getItem("epube.enable-hyphens").then((function(e){e&&(Reader.hyphenateHTML=createHyphenator(hyphenationPatternsEnUs,{html:!0})),Reader.applyStyles(!0),t.display().then((function(){console.log("book displayed")}))})),t.hooks.content.register((function(t){t.on("linkClicked",(function(t){console.log("linkClicked",t),-1==t.indexOf("://")&&($(".prev_location_btn").attr("data-location-cfi",e.rendition.currentLocation().start.cfi).show(),window.setTimeout((function(){Reader.showUI(!0)}),50))}));const o=window.location.href.match(/^.*\//)[0],n=["dist/app-libs.min.js","js/reader_iframe.js"],a=t.document;for(let e=0;e<n.length;e++){const t=a.createElement("script");t.type="text/javascript",t.text=Reader.Loader._res_data[o+n[e]],a.head.appendChild(t)}return $(t.document.head).append($("<style type='text/css'>").text(Reader.Loader._res_data[o+"dist/reader_iframe.min.css"])),localforage.getItem("epube.theme").then((function(e){e||(e="default");const n=o+"themes/"+e+".css";$(t.document.head).append($("<style type='text/css' id='theme_css'>").text(Reader.Loader._res_data[n]))}))})),$("#settings-modal").on("shown.bs.modal",(function(){localforage.getItem(Reader.cacheId("lastread")).then(e=>{e&&e.cfi&&$(".lastread_input").val(e.page+"%"),$.post("backend.php",{op:"getlastread",id:$.urlParam("id")},(function(e){$(".lastread_input").val(e.page+"%")}))}),localforage.getItem("epube.enable-hyphens").then((function(e){$(".enable_hyphens_checkbox").attr("checked",e).off("click").on("click",(function(e){localforage.setItem("epube.enable-hyphens",e.target.checked),confirm("Toggling hyphens requires page reload. Reload now?")&&window.location.reload()}))})),localforage.getItem("epube.keep-ui-visible").then((function(e){$(".keep_ui_checkbox").attr("checked",e).off("click").on("click",(function(e){localforage.setItem("epube.keep-ui-visible",e.target.checked)}))})),localforage.getItem("epube.cache-timestamp").then((function(e){let t="V: ";parseInt(e)?t+=new Date(1e3*e).toLocaleString("en-GB"):t+="Unknown",t+=" ("+(navigator.onLine?"Online":"Offline")+")",$(".last-mod-timestamp").text(t)})),localforage.getItem("epube.fontFamily").then((function(e){e||(e="Georgia"),$(".font_family").val(e)})),localforage.getItem("epube.theme").then((function(e){$(".theme_name").val(e)})),localforage.getItem("epube.fontSize").then((function(e){e||(e=16);const t=$(".font_size").html("");for(let e=10;e<=32;e++){const o=$("<option>").val(e).html(e+" px");t.append(o)}t.val(e)})),localforage.getItem("epube.lineHeight").then((function(e){e||(e=140);const t=$(".line_height").html("");for(let e=100;e<=220;e+=10){const o=$("<option>").val(e).html(e+"%");t.append(o)}t.val(e)}))})),$("#dict-modal").on("shown.bs.modal",(function(){$(".dict_result").scrollTop(0)})),$(".dict_search_btn").on("click",(function(){$("#dict-modal").modal("hide"),window.open("https://duckduckgo.com/?q="+$(".dict_query").val())})),$(".wiki_search_btn").on("click",(function(){$(".dict_result").html("Loading, please wait..."),$.post("backend.php",{op:"wikisearch",query:$(".dict_query").val()}).then(e=>{try{let t="";$.each(e.query.pages,(e,o)=>{t+=o.extract}),$(".dict_result").html(t&&"undefined"!=t?t:"No definition found for "+$(".dict_query").val()+".")}catch(e){console.error(e),$(".dict_result").text("Error while processing data: "+e)}}).fail(e=>{console.error(e),$(".dict_result").text("Error while retrieving data.")})})),$("#toc-modal").on("shown.bs.modal",(function(){const t=e.navigation.toc,n=$(".toc_list");n.html(""),$.each(t,(function(t,a){try{const t=$("<a>").attr("href","#").html("<b class='pull-right'>"+o(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){e.rendition.display(t.attr("data-href"))}));n.append($("<li>").append(t)),function t(n,a,i){if(3==i)return!1;if(n.subitems){const r=$("<ul class='toc_sublist list-unstyled'>");$.each(n.subitems,(function(n,a){const l=$("<a>").attr("href","#").html("<b class='pull-right'>"+o(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){e.rendition.display(l.attr("data-href"))}));r.append($("<li>").append(l)),t(a,r,i+1)})),a.append(r)}}(a,n,0)}catch(e){console.warn(e)}})),n.children().length<=1&&(n.html(""),$.each(e.spine.items,(function(t,o){const a=$("<a>").attr("href","#").attr("title",o.url).html("Section "+(t+1)).attr("data-href",o.href).click((function(){e.rendition.display(a.attr("data-href"))}));n.append($("<li>").append(a))})))})),e.spine.hooks.content.register((function(e){$(e).find("p").filter((e,t)=>{if($(t).text().length>=32)return t}).css("text-align","justify"),$(e).find("p, span, em, strong, body, div").attr("class","").css("color","").css("background","").css("background-color",""),void 0!==Reader.hyphenateHTML&&$(e).find("p").each((e,t)=>{(t=$(t)).html(Reader.hyphenateHTML(t.html()))})})),e.ready.then((function(){const t=e.package.metadata;return document.title=t.title+" – "+t.creator+" – The Epube",$(".title").text(t.title),"undefined"!=typeof EpubeApp&&(EpubeApp.setTitle(t.title),EpubeApp.showActionBar(!1)),localforage.getItem(Reader.cacheId("locations")).then((function(t){if(console.log("stored pagination",null!=t),t&&"string"==typeof t[0])return Reader.Page._pagination_stored=1,e.locations.load(t);{console.log("requesting pagination...");const t="backend.php?op=getpagination&id="+encodeURIComponent($.urlParam("id"));return fetch(t,{credentials:"same-origin"}).then((function(t){return t.ok?t.json().then((function(t){return t&&"string"==typeof t[0]?(Reader.Page._pagination_stored=1,e.locations.load(t)):($(".loading_message").html("Paginating..."),e.locations.generate(1600))})):($(".loading_message").html("Paginating..."),e.locations.generate(1600))})).catch((function(){return $(".loading_message").html("Paginating..."),e.locations.generate(1600)}))}}))})).then((function(t){console.log("locations ready, stored=",Reader.Page._pagination_stored),t?(navigator.onLine&&!Reader.Page._pagination_stored&&$.post("backend.php",{op:"storepagination",id:$.urlParam("id"),payload:JSON.stringify(t),total:100}),localforage.getItem(Reader.cacheId("locations")).then((function(e){e||localforage.setItem(Reader.cacheId("locations"),t)})),$(".location").click((function(){const t=e.rendition.currentLocation().start.location,o=e.locations.length(),n=prompt("Jump to location [1-"+o+"]",t);n&&e.rendition.display(e.locations._locations[n])})),Reader.Page.openLastRead(),window.setTimeout((function(){Reader.Page.openLastRead(),$(".loading").hide()}),250)):$(".loading_message").html("Pagination failed.")})),t.on("keyup",e=>{Reader.hotkeyHandler(e)}),t.on("resized",(function(){console.log("resized"),$(".loading").show(),$(".loading_message").html("Opening chapter..."),window.setTimeout((function(){Reader.resizeSideColumns(),Reader.Page.openLastRead(),$(".loading").hide()}),250)})),t.on("rendered",(function(){$(".chapter").html($("<span>").addClass("glyphicon glyphicon-th-list")),Reader.applyTheme(),Reader.resizeSideColumns();try{const t=e.rendition.currentLocation();if(t.start){const o=e.canonical(t.start.href);let n=!1;$.each(Reader.flattenToc(e),(function(t,a){e.spine.get(a.href).canonical!=o||(n=a)})),n&&n.label&&$(".chapter").append("&nbsp;"+n.label.trim()+" | "),Reader.generateTocBar(e,Reader.flattenToc(e))}}catch(e){console.warn(e)}})),t.on("relocated",(function(t){if(0==e.locations.length())return;const o=t.start.cfi,n=parseInt(100*e.locations.percentageFromCfi(o));$("#cur_page").text(t.start.location),$("#total_pages").text(e.locations.length()),$("#page_pct").text(parseInt(100*e.locations.percentageFromCfi(o))+"%"),Reader.updateTocBarPosition(e,t);const a=t.start.displayed;a&&($("#chapter_cur_page").text(a.page),$("#chapter_total_pages").text(a.total),a.total>0&&$("#chapter_pct").text(parseInt(a.page/a.total*100)+"%")),Reader.Page._store_position&&(new Date).getTime()/1e3-Reader.Page._last_position_sync>15&&(console.log("storing lastread",n,o),navigator.onLine?($.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:n,cfi:o},(function(e){e.cfi&&(Reader.Page._last_position_sync=(new Date).getTime()/1e3)})).fail((function(e){e&&401==e.status&&(window.location="index.php")})),Reader.Page._store_position=0):Reader.Page._last_position_sync=0,localforage.setItem(Reader.cacheId("lastread"),{cfi:o,page:n,total:100}))}))},flattenTocSubItems:function(e,t){let o=[];return 3!=t&&(e.subitems&&$.each(e.subitems,(function(e,n){n._nest=t,o.push(n),o=o.concat(Reader.flattenTocSubItems(n,t+1))})),o)},flattenToc:function(e){if(this._flattened_toc)return this._flattened_toc;{let t=[];return $.each(e.navigation.toc,(function(e,o){o._nest=0,t.push(o),t=t.concat(Reader.flattenTocSubItems(o,1))})),this._flattened_toc=t,t}},generateTocBar:function(e,t){$(".spacer").html(""),$.each(t,(function(t,o){try{const t=e.spine.get(o.href).cfiBase,n=e.locations._locations.find((function(e){return-1!=e.indexOf(t)}));if(n){const t=Math.round(100*e.locations.percentageFromCfi(n));$(".spacer").append($("<div class='toc-bar-entry'>").attr("data-nest-level",o._nest).css("left",t+"%").css("_width",3-o._nest+"px").attr("title",o.label))}}catch(e){console.warn(e)}})),$(".spacer").append($("<div class='toc-bar-entry current-position'>")),Reader.updateTocBarPosition(e,e.rendition.currentLocation())},updateTocBarPosition:function(e,t){const o=Math.round(t.start.location/e.locations.length()*100);$(".toc-bar-entry.current-position").css("left",o+"%")},applyStyles:function(e){Promise.all([localforage.getItem("epube.fontSize"),localforage.getItem("epube.fontFamily"),localforage.getItem("epube.lineHeight"),localforage.getItem("epube.theme")]).then((function(t){const o=t[0]?t[0]+"px":"16px",n=t[1]?t[1]:"Georgia",a=t[2]?t[2]+"%":"140%";console.log("style",n,o,a),console.log("applying default theme..."),window.book.rendition.themes.default({html:{"font-size":o,"font-family":"'"+n+"'","line-height":a,"text-align":"justify","text-indent":"1em"}}),e||(console.log("applying rendition themes..."),$.each(window.book.rendition.getContents(),(function(e,t){t.css("font-size",o),t.css("font-family","'"+n+"'"),t.css("line-height",a),t.css("text-align","justify")}))),Reader.applyTheme()}))},applyTheme:function(){localforage.getItem("epube.theme").then((function(e){const t=window.location.href.match(/^.*\//)[0];e||(e="default"),console.log("called for theme",e),"default"==e&&"undefined"!=typeof EpubeApp&&EpubeApp.isNightMode()&&(e="night"),console.log("setting main UI theme",e);const o=t+"themes/"+e+".css";Reader.Loader._res_data[o]?($("#theme_css").attr("href",o),"undefined"!=typeof EpubeApp&&window.setTimeout((function(){const e=window.getComputedStyle(document.querySelector("body"),null).getPropertyValue("background-color").match(/rgb\((\d{1,}), (\d{1,}), (\d{1,})\)/);e&&(console.log("sending bgcolor",e),EpubeApp.setStatusBarColor(parseInt(e[1]),parseInt(e[2]),parseInt(e[3])))}),250),$.each(window.book.rendition.getContents(),(function(t,n){console.log("applying rendition theme",e,"to",n,n.document),$(n.document).find("#theme_css").text(Reader.Loader._res_data[o])}))):console.error("theme data not found for",e,"- check resource loader configuration")}))},hotkeyHandler:function(e){try{if($(".modal").is(":visible"))return;39!=e.which&&32!=e.which&&34!=e.which||(e.preventDefault(),Reader.Page.next()),37!=e.which&&33!=e.which||(e.preventDefault(),Reader.Page.prev()),27==e.which&&(e.preventDefault(),Reader.showUI(!0))}catch(e){console.warn(e)}},resizeSideColumns:function(){let e=$("#reader").position().left;const t=$("#reader iframe")[0];t&&t.contentWindow.$&&(e+=parseInt(t.contentWindow.$("body").css("padding-left"))),$("#left, #right").width(e)},markAsRead:function(){if(confirm("Mark book as read?")){const e=100,t=window.book.locations.cfiFromPercentage(1);navigator.onLine&&$.post("backend.php",{op:"storelastread",page:e,cfi:t,id:$.urlParam("id")},(function(e){$(".lastread_input").val(e.page+"%")})),localforage.setItem(Reader.cacheId("lastread"),{cfi:t,page:e,total:e})}},close:function(){const e=window.book.rendition.currentLocation().start.cfi,t=parseInt(100*window.book.locations.percentageFromCfi(e));localforage.setItem(Reader.cacheId("lastread"),{cfi:e,page:t,total:100}),navigator.onLine?$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:t,cfi:e},(function(){window.location=$.urlParam("rt")?"index.php?mode="+$.urlParam("rt"):"index.php"})).fail((function(){window.location="index.php"})):window.location="index.php"},cacheId:function(e){return"epube-book."+$.urlParam("b")+(e?"."+e:"")},toggleFullscreen:function(){if("undefined"!=typeof EpubeApp);else{const e=document.documentElement,t=document.webkitIsFullScreen||document.mozFullScreen||!1;e.requestFullScreen=e.requestFullScreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||function(){return!1},document.cancelFullScreen=document.cancelFullScreen||document.webkitCancelFullScreen||document.mozCancelFullScreen||function(){return!1},t?document.cancelFullScreen():e.requestFullScreen()}},showUI:function(e){e?$(".header,.footer").fadeIn():$(".header,.footer").fadeOut()},toggleUI:function(){$(".header").is(":visible")?$(".header,.footer").fadeOut():$(".header,.footer").fadeIn()},lookupWord:function(e,t){e=e.replace(/­/g,""),$(".dict_result").html("Loading, please wait..."),$("#dict-modal").modal("show"),$.post("backend.php",{op:"define",word:e},(function(o){o&&($(".dict_result").html(o.result.join("<br/>")),$(".dict_query").val(e),t&&t())})).fail((function(e){console.warn(e),$(".dict_result").html("Network error while looking up word: "+e.statusText)}))},search:function(){const e=$(".search_input").val(),t=$(".search_results");t.html(""),e&&Promise.all(window.book.spine.spineItems.map(t=>t.load(window.book.load.bind(window.book)).then(t.find.bind(t,e)).finally(t.unload.bind(t)))).then(e=>Promise.resolve([].concat.apply([],e))).then((function(e){$.each(e,(function(e,o){const n=$("<a>").attr("href","#").html("<b class='pull-right'>"+window.book.locations.locationFromCfi(o.cfi)+"</b>"+o.excerpt).attr("data-cfi",o.cfi).attr("data-id",o.id).click((function(){window.book.rendition.display(n.attr("data-cfi"))}));t.append($("<li>").append(n))}))}))},Loader:{_res_data:[],init:function(){const e=["dist/app-libs.min.js","js/reader_iframe.js","dist/reader_iframe.min.css"];for(let t=0;t<e.length;t++)fetch(e[t],{credentials:"same-origin"}).then((function(o){200==o.status?o.text().then((function(e){const t=new URL(o.url);t.searchParams.delete("ts"),Reader.Loader._res_data[t.toString()]=e})):console.warn("loader failed for resource",e[t],o)}));Reader.Loader.checkProgress(e,Reader.Loader._res_data,0)},checkProgress:function(e,t,o){console.log("check_resource_load",o,e.length,Object.keys(t).length,Reader,Reader.Loader),5!=o?e.length!=Object.keys(t).length?window.setTimeout((function(){Reader.Loader.checkProgress(e,t,o+1)}),250):Reader.initSecondStage():$(".loading_message").html("Unable to load resources.")}},Page:{_store_position:0,_last_position_sync:0,_pagination_stored:0,next:function(){Reader.Page._store_position=1,window.book.rendition.next(),"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(e){e||Reader.showUI(!1)}))},prev:function(){window.book.rendition.prev(),"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(e){e||Reader.showUI(!1)}))},openPrevious:function(e){const t=$(e).attr("data-location-cfi");t&&window.book.rendition.display(t),$(e).fadeOut()},clearLastRead:function(){if(confirm("Clear stored last read location?")){const e=window.book.locations.length();navigator.onLine&&$.post("backend.php",{op:"storelastread",page:-1,cfi:"",id:$.urlParam("id")},(function(e){$(".lastread_input").val(e.page+"%")})),localforage.setItem(Reader.cacheId("lastread"),{cfi:"",page:0,total:e}),window.setTimeout((function(){window.book.rendition.display(window.book.locations.cfiFromPercentage(0))}),250)}},openLastRead:function(e){localforage.getItem(Reader.cacheId("lastread")).then((function(t){console.log("lr local",t),t=t||{};try{t.cfi&&window.book.rendition.display(t.cfi).then(()=>{$(".loading").hide(),window.book.rendition.display(t.cfi)})}catch(e){console.warn(e)}navigator.onLine&&!e&&$.post("backend.php",{op:"getlastread",id:$.urlParam("id")},(function(e){if(console.log("lr remote",e),navigator.onLine&&e)try{t.cfi!=e.cfi&&(!t.page||e.page>=t.page)&&console.log("using remote lastread..."),localforage.setItem(Reader.cacheId("lastread"),{cfi:e.cfi,page:e.page,total:e.total}),window.book.rendition.display(e.cfi).then(()=>{window.book.rendition.display(e.cfi)})}catch(e){console.warn(e)}})).fail((function(e){e&&401==e.status&&(window.location="index.php")}))}))}},Settings:{onThemeChanged:function(e){const t=$(e).val();localforage.setItem("epube.theme",t).then((function(){Reader.applyTheme()}))},onLineHeightChanged:function(e){const t=$(e).val();localforage.setItem("epube.lineHeight",t).then((function(){Reader.applyStyles()}))},onTextSizeChanged:function(e){const t=$(e).val();localforage.setItem("epube.fontSize",t).then((function(){Reader.applyStyles()}))},onFontChanged:function(e){const t=$(e).val();localforage.setItem("epube.fontFamily",t).then((function(){Reader.applyStyles()}))}}};function __get_reader(){return Reader} \ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
index 843df14..81304dc 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -58,6 +58,14 @@ gulp.task('minifyCSS', function(cb) {
.on('error', swallowError)
.pipe(gulp.dest('dist/'));
+ gulp
+ .src(['css/reader_iframe.css'])
+ .pipe(less())
+ .pipe(minifyCSS())
+ .pipe(rename("reader_iframe.min.css"))
+ .on('error', swallowError)
+ .pipe(gulp.dest('dist/'));
+
cb();
});
diff --git a/index.php b/index.php
index 5a94b47..07d023f 100644
--- a/index.php
+++ b/index.php
@@ -49,7 +49,8 @@
'dist/reader_iframe.min.js',
'dist/app.min.css',
'dist/app-libs.min.js',
- 'offline.html',
+ 'offline.html',
+ 'dist/reader_iframe.min.css',
'lib/bootstrap/v3/css/bootstrap-theme.min.css',
'lib/bootstrap/v3/css/bootstrap.min.css',
'lib/bootstrap/v3/css/theme-dark.min.css',
@@ -78,7 +79,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="dist/app-libs.min.js"></script>
<title>The Epube</title>
- <link type="text/css" rel="stylesheet" media="screen" href="css/index.css" />
+ <link type="text/css" rel="stylesheet" media="screen" href="dist/app.min.css" />
<link rel="shortcut icon" type="image/png" href="img/favicon.png" />
<link rel="manifest" href="manifest.json">
<meta name="mobile-web-app-capable" content="yes">
@@ -103,7 +104,7 @@
}
</script>
</head>
-<body>
+<body class="epube-index">
<?php
@$query = $_REQUEST["query"];
diff --git a/js/reader.js b/js/reader.js
index 3947ec6..52ded34 100644
--- a/js/reader.js
+++ b/js/reader.js
@@ -214,7 +214,7 @@ const Reader = {
$(contents.document.head)
.append($("<style type='text/css'>")
- .text(Reader.Loader._res_data[base_url + 'css/reader.css']));
+ .text(Reader.Loader._res_data[base_url + 'dist/reader_iframe.min.css']));
return localforage.getItem("epube.theme").then(function(theme) {
if (!theme) theme = 'default';
@@ -995,7 +995,7 @@ const Reader = {
// we need to preload resources for reader iframe because it can't utilize our
// service worker because while offline it is created outside our base server context
const res_names = [ "dist/app-libs.min.js",
- "js/reader_iframe.js", "css/reader.css" ];
+ "js/reader_iframe.js", "dist/reader_iframe.min.css" ];
for (let i = 0; i < res_names.length; i++) {
fetch(res_names[i], {credentials: 'same-origin'}).then(function(resp) {
diff --git a/lib/fetch.js b/lib/fetch.js
deleted file mode 100644
index 3791e48..0000000
--- a/lib/fetch.js
+++ /dev/null
@@ -1,418 +0,0 @@
-(function(self) {
- 'use strict';
-
- // if __disableNativeFetch is set to true, the it will always polyfill fetch
- // with Ajax.
- if (!self.__disableNativeFetch && self.fetch) {
- return
- }
-
- function normalizeName(name) {
- if (typeof name !== 'string') {
- name = String(name)
- }
- if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
- throw new TypeError('Invalid character in header field name')
- }
- return name.toLowerCase()
- }
-
- function normalizeValue(value) {
- if (typeof value !== 'string') {
- value = String(value)
- }
- return value
- }
-
- function Headers(headers) {
- this.map = {}
-
- if (headers instanceof Headers) {
- headers.forEach(function(value, name) {
- this.append(name, value)
- }, this)
-
- } else if (headers) {
- Object.getOwnPropertyNames(headers).forEach(function(name) {
- this.append(name, headers[name])
- }, this)
- }
- }
-
- Headers.prototype.append = function(name, value) {
- name = normalizeName(name)
- value = normalizeValue(value)
- var list = this.map[name]
- if (!list) {
- list = []
- this.map[name] = list
- }
- list.push(value)
- }
-
- Headers.prototype['delete'] = function(name) {
- delete this.map[normalizeName(name)]
- }
-
- Headers.prototype.get = function(name) {
- var values = this.map[normalizeName(name)]
- return values ? values[0] : null
- }
-
- Headers.prototype.getAll = function(name) {
- return this.map[normalizeName(name)] || []
- }
-
- Headers.prototype.has = function(name) {
- return this.map.hasOwnProperty(normalizeName(name))
- }
-
- Headers.prototype.set = function(name, value) {
- this.map[normalizeName(name)] = [normalizeValue(value)]
- }
-
- Headers.prototype.forEach = function(callback, thisArg) {
- Object.getOwnPropertyNames(this.map).forEach(function(name) {
- this.map[name].forEach(function(value) {
- callback.call(thisArg, value, name, this)
- }, this)
- }, this)
- }
-
- function consumed(body) {
- if (body.bodyUsed) {
- return Promise.reject(new TypeError('Already read'))
- }
- body.bodyUsed = true
- }
-
- function fileReaderReady(reader) {
- return new Promise(function(resolve, reject) {
- reader.onload = function() {
- resolve(reader.result)
- }
- reader.onerror = function() {
- reject(reader.error)
- }
- })
- }
-
- function readBlobAsArrayBuffer(blob) {
- var reader = new FileReader()
- reader.readAsArrayBuffer(blob)
- return fileReaderReady(reader)
- }
-
- function readBlobAsText(blob, options) {
- var reader = new FileReader()
- var contentType = options.headers.map['content-type'] ? options.headers.map['content-type'].toString() : ''
- var regex = /charset\=[0-9a-zA-Z\-\_]*;?/
- var _charset = blob.type.match(regex) || contentType.match(regex)
- var args = [blob]
-
- if(_charset) {
- args.push(_charset[0].replace(/^charset\=/, '').replace(/;$/, ''))
- }
-
- reader.readAsText.apply(reader, args)
- return fileReaderReady(reader)
- }
-
- var support = {
- blob: 'FileReader' in self && 'Blob' in self && (function() {
- try {
- new Blob();
- return true
- } catch(e) {
- return false
- }
- })(),
- formData: 'FormData' in self,
- arrayBuffer: 'ArrayBuffer' in self
- }
-
- function Body() {
- this.bodyUsed = false
-
-
- this._initBody = function(body, options) {
- this._bodyInit = body
- if (typeof body === 'string') {
- this._bodyText = body
- } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
- this._bodyBlob = body
- this._options = options
- } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
- this._bodyFormData = body
- } else if (!body) {
- this._bodyText = ''
- } else if (support.arrayBuffer && ArrayBuffer.prototype.isPrototypeOf(body)) {
- // Only support ArrayBuffers for POST method.
- // Receiving ArrayBuffers happens via Blobs, instead.
- } else {
- throw new Error('unsupported BodyInit type')
- }
- }
-
- if (support.blob) {
- this.blob = function() {
- var rejected = consumed(this)
- if (rejected) {
- return rejected
- }
-
- if (this._bodyBlob) {
- return Promise.resolve(this._bodyBlob)
- } else if (this._bodyFormData) {
- throw new Error('could not read FormData body as blob')
- } else {
- return Promise.resolve(new Blob([this._bodyText]))
- }
- }
-
- this.arrayBuffer = function() {
- return this.blob().then(readBlobAsArrayBuffer)
- }
-
- this.text = function() {
- var rejected = consumed(this)
- if (rejected) {
- return rejected
- }
-
- if (this._bodyBlob) {
- return readBlobAsText(this._bodyBlob, this._options)
- } else if (this._bodyFormData) {
- throw new Error('could not read FormData body as text')
- } else {
- return Promise.resolve(this._bodyText)
- }
- }
- } else {
- this.text = function() {
- var rejected = consumed(this)
- return rejected ? rejected : Promise.resolve(this._bodyText)
- }
- }
-
- if (support.formData) {
- this.formData = function() {
- return this.text().then(decode)
- }
- }
-
- this.json = function() {
- return this.text().then(JSON.parse)
- }
-
- return this
- }
-
- // HTTP methods whose capitalization should be normalized
- var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
-
- function normalizeMethod(method) {
- var upcased = method.toUpperCase()
- return (methods.indexOf(upcased) > -1) ? upcased : method
- }
-
- function Request(input, options) {
- options = options || {}
- var body = options.body
- if (Request.prototype.isPrototypeOf(input)) {
- if (input.bodyUsed) {
- throw new TypeError('Already read')
- }
- this.url = input.url
- this.credentials = input.credentials
- if (!options.headers) {
- this.headers = new Headers(input.headers)
- }
- this.method = input.method
- this.mode = input.mode
- if (!body) {
- body = input._bodyInit
- input.bodyUsed = true
- }
- } else {
- this.url = input
- }
-
- this.credentials = options.credentials || this.credentials || 'omit'
- if (options.headers || !this.headers) {
- this.headers = new Headers(options.headers)
- }
- this.method = normalizeMethod(options.method || this.method || 'GET')
- this.mode = options.mode || this.mode || null
- this.referrer = null
-
- if ((this.method === 'GET' || this.method === 'HEAD') && body) {
- throw new TypeError('Body not allowed for GET or HEAD requests')
- }
- this._initBody(body, options)
- }
-
- Request.prototype.clone = function() {
- return new Request(this)
- }
-
- function decode(body) {
- var form = new FormData()
- body.trim().split('&').forEach(function(bytes) {
- if (bytes) {
- var split = bytes.split('=')
- var name = split.shift().replace(/\+/g, ' ')
- var value = split.join('=').replace(/\+/g, ' ')
- form.append(decodeURIComponent(name), decodeURIComponent(value))
- }
- })
- return form
- }
-
- function headers(xhr) {
- var head = new Headers()
- var pairs = xhr.getAllResponseHeaders().trim().split('\n')
- pairs.forEach(function(header) {
- var split = header.trim().split(':')
- var key = split.shift().trim()
- var value = split.join(':').trim()
- head.append(key, value)
- })
- return head
- }
-
- Body.call(Request.prototype)
-
- function Response(bodyInit, options) {
- if (!options) {
- options = {}
- }
-
- this._initBody(bodyInit, options)
- this.type = 'default'
- this.status = options.status
- this.ok = this.status >= 200 && this.status < 300
- this.statusText = options.statusText
- this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
- this.url = options.url || ''
- }
-
- Body.call(Response.prototype)
-
- Response.prototype.clone = function() {
- return new Response(this._bodyInit, {
- status: this.status,
- statusText: this.statusText,
- headers: new Headers(this.headers),
- url: this.url
- })
- }
-
- Response.error = function() {
- var response = new Response(null, {status: 0, statusText: ''})
- response.type = 'error'
- return response
- }
-
- var redirectStatuses = [301, 302, 303, 307, 308]
-
- Response.redirect = function(url, status) {
- if (redirectStatuses.indexOf(status) === -1) {
- throw new RangeError('Invalid status code')
- }
-
- return new Response(null, {status: status, headers: {location: url}})
- }
-
- self.Headers = Headers;
- self.Request = Request;
- self.Response = Response;
-
- self.fetch = function(input, init) {
- return new Promise(function(resolve, reject) {
- var request
- if (Request.prototype.isPrototypeOf(input) && !init) {
- request = input
- } else {
- request = new Request(input, init)
- }
-
- var xhr = new XMLHttpRequest()
-
- function responseURL() {
- if ('responseURL' in xhr) {
- return xhr.responseURL
- }
-
- // Avoid security warnings on getResponseHeader when not allowed by CORS
- if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
- return xhr.getResponseHeader('X-Request-URL')
- }
-
- return;
- }
-
- var __onLoadHandled = false;
-
- function onload() {
- if (xhr.readyState !== 4) {
- return
- }
- var status = (xhr.status === 1223) ? 204 : xhr.status
- if (status < 100 || status > 599) {
- if (__onLoadHandled) { return; } else { __onLoadHandled = true; }
- reject(new TypeError('Network request failed'))
- return
- }
- var options = {
- status: status,
- statusText: xhr.statusText,
- headers: headers(xhr),
- url: responseURL()
- }
- var body = 'response' in xhr ? xhr.response : xhr.responseText;
-
- if (__onLoadHandled) { return; } else { __onLoadHandled = true; }
- resolve(new Response(body, options))
- }
- xhr.onreadystatechange = onload;
- xhr.onload = onload;
- xhr.onerror = function() {
- if (__onLoadHandled) { return; } else { __onLoadHandled = true; }
- reject(new TypeError('Network request failed'))
- }
-
- xhr.open(request.method, request.url, true)
-
- // `withCredentials` should be setted after calling `.open` in IE10
- // http://stackoverflow.com/a/19667959/1219343
- try {
- if (request.credentials === 'include') {
- if ('withCredentials' in xhr) {
- xhr.withCredentials = true;
- } else {
- console && console.warn && console.warn('withCredentials is not supported, you can ignore this warning');
- }
- }
- } catch (e) {
- console && console.warn && console.warn('set withCredentials error:' + e);
- }
-
- if ('responseType' in xhr && support.blob) {
- xhr.responseType = 'blob'
- }
-
- request.headers.forEach(function(value, name) {
- xhr.setRequestHeader(name, value)
- })
-
- xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
- })
- }
- self.fetch.polyfill = true
-
- // Support CommonJS
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = self.fetch;
- }
-})(typeof self !== 'undefined' ? self : this);
diff --git a/lib/promise.js b/lib/promise.js
deleted file mode 100644
index cf0c81d..0000000
--- a/lib/promise.js
+++ /dev/null
@@ -1,233 +0,0 @@
-(function (root) {
-
- // Store setTimeout reference so promise-polyfill will be unaffected by
- // other code modifying setTimeout (like sinon.useFakeTimers())
- var setTimeoutFunc = setTimeout;
-
- function noop() {}
-
- // Polyfill for Function.prototype.bind
- function bind(fn, thisArg) {
- return function () {
- fn.apply(thisArg, arguments);
- };
- }
-
- function Promise(fn) {
- if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
- if (typeof fn !== 'function') throw new TypeError('not a function');
- this._state = 0;
- this._handled = false;
- this._value = undefined;
- this._deferreds = [];
-
- doResolve(fn, this);
- }
-
- function handle(self, deferred) {
- while (self._state === 3) {
- self = self._value;
- }
- if (self._state === 0) {
- self._deferreds.push(deferred);
- return;
- }
- self._handled = true;
- Promise._immediateFn(function () {
- var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
- if (cb === null) {
- (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
- return;
- }
- var ret;
- try {
- ret = cb(self._value);
- } catch (e) {
- reject(deferred.promise, e);
- return;
- }
- resolve(deferred.promise, ret);
- });
- }
-
- function resolve(self, newValue) {
- try {
- // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
- if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
- if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
- var then = newValue.then;
- if (newValue instanceof Promise) {
- self._state = 3;
- self._value = newValue;
- finale(self);
- return;
- } else if (typeof then === 'function') {
- doResolve(bind(then, newValue), self);
- return;
- }
- }
- self._state = 1;
- self._value = newValue;
- finale(self);
- } catch (e) {
- reject(self, e);
- }
- }
-
- function reject(self, newValue) {
- self._state = 2;
- self._value = newValue;
- finale(self);
- }
-
- function finale(self) {
- if (self._state === 2 && self._deferreds.length === 0) {
- Promise._immediateFn(function() {
- if (!self._handled) {
- Promise._unhandledRejectionFn(self._value);
- }
- });
- }
-
- for (var i = 0, len = self._deferreds.length; i < len; i++) {
- handle(self, self._deferreds[i]);
- }
- self._deferreds = null;
- }
-
- function Handler(onFulfilled, onRejected, promise) {
- this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
- this.onRejected = typeof onRejected === 'function' ? onRejected : null;
- this.promise = promise;
- }
-
- /**
- * Take a potentially misbehaving resolver function and make sure
- * onFulfilled and onRejected are only called once.
- *
- * Makes no guarantees about asynchrony.
- */
- function doResolve(fn, self) {
- var done = false;
- try {
- fn(function (value) {
- if (done) return;
- done = true;
- resolve(self, value);
- }, function (reason) {
- if (done) return;
- done = true;
- reject(self, reason);
- });
- } catch (ex) {
- if (done) return;
- done = true;
- reject(self, ex);
- }
- }
-
- Promise.prototype['catch'] = function (onRejected) {
- return this.then(null, onRejected);
- };
-
- Promise.prototype.then = function (onFulfilled, onRejected) {
- var prom = new (this.constructor)(noop);
-
- handle(this, new Handler(onFulfilled, onRejected, prom));
- return prom;
- };
-
- Promise.all = function (arr) {
- var args = Array.prototype.slice.call(arr);
-
- return new Promise(function (resolve, reject) {
- if (args.length === 0) return resolve([]);
- var remaining = args.length;
-
- function res(i, val) {
- try {
- if (val && (typeof val === 'object' || typeof val === 'function')) {
- var then = val.then;
- if (typeof then === 'function') {
- then.call(val, function (val) {
- res(i, val);
- }, reject);
- return;
- }
- }
- args[i] = val;
- if (--remaining === 0) {
- resolve(args);
- }
- } catch (ex) {
- reject(ex);
- }
- }
-
- for (var i = 0; i < args.length; i++) {
- res(i, args[i]);
- }
- });
- };
-
- Promise.resolve = function (value) {
- if (value && typeof value === 'object' && value.constructor === Promise) {
- return value;
- }
-
- return new Promise(function (resolve) {
- resolve(value);
- });
- };
-
- Promise.reject = function (value) {
- return new Promise(function (resolve, reject) {
- reject(value);
- });
- };
-
- Promise.race = function (values) {
- return new Promise(function (resolve, reject) {
- for (var i = 0, len = values.length; i < len; i++) {
- values[i].then(resolve, reject);
- }
- });
- };
-
- // Use polyfill for setImmediate for performance gains
- Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
- function (fn) {
- setTimeoutFunc(fn, 0);
- };
-
- Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
- if (typeof console !== 'undefined' && console) {
- console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
- }
- };
-
- /**
- * Set the immediate function to execute callbacks
- * @param fn {function} Function to execute
- * @deprecated
- */
- Promise._setImmediateFn = function _setImmediateFn(fn) {
- Promise._immediateFn = fn;
- };
-
- /**
- * Change the function to execute on unhandled rejection
- * @param {function} fn Function to execute on unhandled rejection
- * @deprecated
- */
- Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
- Promise._unhandledRejectionFn = fn;
- };
-
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = Promise;
- } else if (!root.Promise) {
- root.Promise = Promise;
- }
-
-})(this);
diff --git a/offline.html b/offline.html
index 74e103c..3545127 100644
--- a/offline.html
+++ b/offline.html
@@ -7,7 +7,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="dist/app-libs.min.js"></script>
<title>The Epube</title>
- <link type="text/css" rel="stylesheet" media="screen" href="css/index.css" />
+ <link type="text/css" rel="stylesheet" media="screen" href="dist/app.min.css" />
<link rel="shortcut icon" type="image/png" href="img/favicon.png" />
<link rel="manifest" href="manifest.json">
<meta name="mobile-web-app-capable" content="yes">
@@ -30,7 +30,7 @@
}
</script>
</head>
-<body>
+<body class="epube-index">
<div class="navbar navbar-default navbar-static-top">
<div class="container">
diff --git a/read.html b/read.html
index 65172e5..48d5128 100644
--- a/read.html
+++ b/read.html
@@ -10,9 +10,7 @@
<script src="dist/app.min.js"></script>
<link id="favicon" rel="shortcut icon" type="image/png" href="img/favicon.png" />
- <link type="text/css" rel="stylesheet" media="screen" href="css/read.css" />
-
- <link type="text/css" rel="stylesheet" media="screen" href="themes/default.css" id="theme_css" />
+ <link type="text/css" rel="stylesheet" media="screen" href="dist/app.min.css" />
<script type="text/javascript">
'use strict';
@@ -32,7 +30,7 @@
}
</script>
</head>
-<body>
+<body class="epube-reader">
<div class="modal fade" id="settings-modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
diff --git a/worker.js b/worker.js
index a7de435..1020a94 100644
--- a/worker.js
+++ b/worker.js
@@ -13,6 +13,7 @@ const CACHE_URLS = [
'dist/app.min.css',
'dist/app-libs.min.js',
'offline.html',
+ 'dist/reader_iframe.min.css',
'lib/bootstrap/v3/css/bootstrap-theme.min.css',
'lib/bootstrap/v3/css/bootstrap.min.css',
'lib/bootstrap/v3/css/theme-dark.min.css',