mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
new namespaces, strict mode, toc updated, jump to links
This commit is contained in:
parent
78e1c05ab0
commit
ce18f4ff15
13 changed files with 439 additions and 155 deletions
BIN
.DS_Store
vendored
BIN
.DS_Store
vendored
Binary file not shown.
77
css/main.css
77
css/main.css
|
@ -4,7 +4,7 @@ body {
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
/* height: 500px; */
|
/* height: 500px; */
|
||||||
position: fixed;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
/* left: 40px; */
|
/* left: 40px; */
|
||||||
|
@ -23,10 +23,11 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar {
|
#titlebar {
|
||||||
width: 100%;
|
|
||||||
height: 8%;
|
height: 8%;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
padding: 10px;
|
padding: 10px 0 10px 0;
|
||||||
|
margin: 0 50px 0 50px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #4f4f4f;
|
color: #4f4f4f;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
|
@ -84,7 +85,7 @@ body {
|
||||||
|
|
||||||
#sidebar {
|
#sidebar {
|
||||||
background: #6b6b6b;
|
background: #6b6b6b;
|
||||||
position: fixed;
|
position: absolute;
|
||||||
/* left: -260px; */
|
/* left: -260px; */
|
||||||
/* -webkit-transform: translate(-260px, 0);
|
/* -webkit-transform: translate(-260px, 0);
|
||||||
-moz-transform: translate(-260px, 0); */
|
-moz-transform: translate(-260px, 0); */
|
||||||
|
@ -92,15 +93,15 @@ body {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-webkit-transition: -webkit-transform .5s;
|
-webkit-transition: -webkit-transform .5s;
|
||||||
-moz-transition: transform .5s;
|
-moz-transition: -moz-transform .5s;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar.open {
|
#sidebar.open {
|
||||||
/* left: 0; */
|
/* left: 0; */
|
||||||
-webkit-transform: translate(0, 0);
|
/* -webkit-transform: translate(0, 0);
|
||||||
-moz-transform: translate(0, 0);
|
-moz-transform: translate(0, 0); */
|
||||||
}
|
}
|
||||||
|
|
||||||
#main.closed {
|
#main.closed {
|
||||||
|
@ -169,23 +170,28 @@ input:-moz-placeholder {
|
||||||
box-shadow: -2px 0 15px rgba(0, 0, 0, 1);
|
box-shadow: -2px 0 15px rgba(0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#toc-scroll {
|
#toc {
|
||||||
overflow-y: auto;
|
overflow-x: hidden;
|
||||||
|
overflow-y: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: none;
|
visibility: hidden;
|
||||||
|
-webkit-transition: visibility 0 ease .5s;
|
||||||
|
-moz-transition: visibility 0 ease .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar.open #toc-scroll {
|
#sidebar.open #toc {
|
||||||
display: block;
|
overflow-y: auto;
|
||||||
|
visibility: visible;
|
||||||
|
-webkit-transition: visibility 0 ease 0;
|
||||||
|
-moz-transition: visibility 0 ease 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toc {
|
#toc > ul{
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
margin-bottom: 50px;
|
margin-bottom: 50px;
|
||||||
padding-left: 40px;
|
padding-left: 40px;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#toc li {
|
#toc li {
|
||||||
|
@ -197,7 +203,7 @@ input:-moz-placeholder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#toc li:active,
|
#toc li:active,
|
||||||
#toc li.current
|
#toc li.currentChapter
|
||||||
{
|
{
|
||||||
list-style: square;
|
list-style: square;
|
||||||
}
|
}
|
||||||
|
@ -207,8 +213,19 @@ input:-moz-placeholder {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toc a:hover {
|
#toc li.currentChapter > a,
|
||||||
text-decoration: underline;
|
#toc li a:hover {
|
||||||
|
color: #f1f1f1
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc li ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc li.currentChapter > ul,
|
||||||
|
#toc li.openChapter > ul
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1040px) {
|
@media only screen and (max-width: 1040px) {
|
||||||
|
@ -243,5 +260,31 @@ input:-moz-placeholder {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
-webkit-transform: translate(0, 0);
|
||||||
|
-moz-transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar {
|
||||||
|
font-size: 10px;
|
||||||
|
margin: 0 50px 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#open {
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
left: 0;
|
||||||
|
z-index: 110;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
-webkit-transition: -webkit-transform .5s;
|
||||||
|
-moz-transition: -moz-transform .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar.open #open {
|
||||||
|
-webkit-transform: translate(300px, 0);
|
||||||
|
-moz-transform: translate(300px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
FP.app = {};
|
var FPR = FPR || {};
|
||||||
|
|
||||||
FP.app.init = (function($){
|
FPR.app = {};
|
||||||
|
|
||||||
|
FPR.app.init = (function($){
|
||||||
|
"use strict";
|
||||||
var Book,
|
var Book,
|
||||||
offline = false;
|
offline = false,
|
||||||
|
sidebarWidth = 40,
|
||||||
|
windowWidth;
|
||||||
|
|
||||||
function init(bookURL){
|
function init(bookURL){
|
||||||
var search = window.location.search.match(/book=(.*)/),
|
var search = window.location.search.match(/book=(.*)/),
|
||||||
|
@ -13,16 +17,24 @@ FP.app.init = (function($){
|
||||||
FP.core.crossBrowserColumnCss();
|
FP.core.crossBrowserColumnCss();
|
||||||
|
|
||||||
//-- Set up our sidebar
|
//-- Set up our sidebar
|
||||||
$("#main").width($(window).width()-40);
|
windowWidth = $(window).width();
|
||||||
|
if(windowWidth > 550){
|
||||||
|
$("#main").width(windowWidth-sidebarWidth);
|
||||||
|
}else{
|
||||||
|
$("#main").width(windowWidth);
|
||||||
|
}
|
||||||
|
|
||||||
Book = new FP.Book("area");
|
Book = new FP.Book("area");
|
||||||
//Book = new FP.Book("area", "/the-hound-of-the-baskervilles/");
|
//Book = new FP.Book("area", "/the-hound-of-the-baskervilles/");
|
||||||
|
|
||||||
Book.listen("book:metadataReady", meta);
|
Book.listen("book:metadataReady", meta);
|
||||||
Book.listen("book:tocReady", toc);
|
Book.listen("book:tocReady", toc);
|
||||||
|
Book.listen("book:chapterReady", chapterChange);
|
||||||
Book.listen("book:online", goOnline);
|
Book.listen("book:online", goOnline);
|
||||||
Book.listen("book:offline", goOffline);
|
Book.listen("book:offline", goOffline);
|
||||||
|
|
||||||
|
//Book.setFootnotes(["glossterm", "footnote"]);//["glossterm", "footnote"]);
|
||||||
|
|
||||||
Book.start(bookURL + "/");
|
Book.start(bookURL + "/");
|
||||||
|
|
||||||
//-- Wait for Dom ready to handle jquery
|
//-- Wait for Dom ready to handle jquery
|
||||||
|
@ -34,7 +46,7 @@ FP.app.init = (function($){
|
||||||
}
|
}
|
||||||
|
|
||||||
function meta(){
|
function meta(){
|
||||||
var title = Book.getTitle();
|
var title = Book.getTitle(),
|
||||||
author = Book.getCreator(),
|
author = Book.getCreator(),
|
||||||
$title = $("#book-title"),
|
$title = $("#book-title"),
|
||||||
$author = $("#chapter-title");
|
$author = $("#chapter-title");
|
||||||
|
@ -46,41 +58,86 @@ FP.app.init = (function($){
|
||||||
}
|
}
|
||||||
|
|
||||||
function toc(){
|
function toc(){
|
||||||
var contents = Book.getTOC();
|
var contents = Book.getTOC(),
|
||||||
$toc = $("#toc");
|
$toc = $("#toc"),
|
||||||
|
$items;
|
||||||
|
|
||||||
$toc.empty();
|
$toc.empty();
|
||||||
|
$items = generateTocItems(contents);
|
||||||
|
|
||||||
contents.forEach(function(item){
|
$toc.append($items);
|
||||||
$wrapper = $("<li>");
|
|
||||||
|
|
||||||
$item = $("<a href='#"+item.href+"' data-spinepos='"+item.spinePos+"'>"+item.label+"</a>");
|
// contents.forEach(function(item){
|
||||||
|
// $wrapper = $("<li id='toc-"+item.id+"'>");
|
||||||
//-- Handle sub items later
|
//
|
||||||
/*
|
// $item = $("<a href='#"+item.href+"' data-spinepos='"+item.spinePos+"'>"+item.label+"</a>");
|
||||||
if(item.subitems.length){
|
//
|
||||||
$subitems = $("<ul>");
|
//
|
||||||
item.subitems.forEach(function(subitem){
|
// $item.on("click", function(e){
|
||||||
$subitem = $("<li><a href='#"+subitem.href+"' data-spinepos='"+subitem.spinePos+"'>"+subitem.label+"</a></li>");
|
// $this = $(this);
|
||||||
$subitems.append($subitem);
|
// Book.displayChapter($this.data("spinepos"));
|
||||||
});
|
// e.preventDefault();
|
||||||
$item.append($subitems);
|
// });
|
||||||
}
|
//
|
||||||
*/
|
// $wrapper.append($item);
|
||||||
|
//
|
||||||
$item.on("click", function(e){
|
// if(item.subitems && item.subitems.length){
|
||||||
$this = $(this);
|
// $subitems = $("<ul>");
|
||||||
Book.displayChapter($this.data("spinepos"));
|
// item.subitems.forEach(function(subitem){
|
||||||
e.preventDefault();
|
// //console.log("subitem", subitem)
|
||||||
});
|
// $subitem = $("<li id='toc-"+subitem.id+"'><a href='#"+subitem.href+"' data-spinepos='"+subitem.spinePos+"'>"+subitem.label+"</a></li>");
|
||||||
|
// $subitems.append($subitem);
|
||||||
$wrapper.append($item);
|
// });
|
||||||
$toc.append($wrapper);
|
// $wrapper.append($subitems);
|
||||||
});
|
// }
|
||||||
|
//
|
||||||
|
// $toc.append($wrapper);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateTocItems(contents){
|
||||||
|
var $container = $("<ul>");
|
||||||
|
|
||||||
|
|
||||||
|
contents.forEach(function(item){
|
||||||
|
var $subitems,
|
||||||
|
$wrapper = $("<li id='toc-"+item.id+"'>"),
|
||||||
|
$item = $("<a href='"+item.href+"'>"+item.label+"</a>");
|
||||||
|
|
||||||
|
$item.data("spinepos", item.spinePos);
|
||||||
|
|
||||||
|
if(item.section) {
|
||||||
|
$item.data("section", item.section);
|
||||||
|
}
|
||||||
|
|
||||||
|
$item.on("click", function(e){
|
||||||
|
var $this = $(this),
|
||||||
|
url = $this.attr("href");
|
||||||
|
//spinepos = $this.data("spinepos"),
|
||||||
|
//section = $this.data("section") || false;
|
||||||
|
|
||||||
|
$(".openChapter").removeClass("openChapter");
|
||||||
|
$this.parent().addClass("openChapter");
|
||||||
|
|
||||||
|
Book.show(url);
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
$wrapper.append($item);
|
||||||
|
|
||||||
|
if(item.subitems && item.subitems.length){
|
||||||
|
$subitems = generateTocItems(item.subitems);
|
||||||
|
$wrapper.append($subitems);
|
||||||
|
}
|
||||||
|
|
||||||
|
$container.append($wrapper);
|
||||||
|
});
|
||||||
|
return $container;
|
||||||
|
}
|
||||||
|
|
||||||
function goOnline(){
|
function goOnline(){
|
||||||
var $icon = $("#store");
|
var $icon = $("#store");
|
||||||
offline = false;
|
offline = false;
|
||||||
|
@ -95,21 +152,37 @@ FP.app.init = (function($){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function chapterChange(e) {
|
||||||
|
var id = e.msg,
|
||||||
|
$item = $("#toc-"+id),
|
||||||
|
$current = $(".currentChapter");
|
||||||
|
|
||||||
|
if($item.length){
|
||||||
|
$current.removeClass("currentChapter");
|
||||||
|
$item.addClass("currentChapter");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function controls(){
|
function controls(){
|
||||||
var $next = $("#next"),
|
var $next = $("#next"),
|
||||||
$prev = $("#prev"),
|
$prev = $("#prev"),
|
||||||
$main = $("#main"),
|
$main = $("#main"),
|
||||||
|
$book = $("#area"),
|
||||||
$sidebar = $("#sidebar"),
|
$sidebar = $("#sidebar"),
|
||||||
$open = $("#open"),
|
$open = $("#open"),
|
||||||
$icon = $open.find("img"),
|
$icon = $open.find("img"),
|
||||||
$network = $("#network"),
|
$network = $("#network"),
|
||||||
$window = $(window),
|
$window = $(window);
|
||||||
sidebarWidth = 40;
|
|
||||||
|
|
||||||
|
|
||||||
$window.on("resize", function(){
|
$window.on("resize", function(){
|
||||||
$main.width($window.width()-sidebarWidth);
|
windowWidth = $(window).width();
|
||||||
|
if(windowWidth > 550){
|
||||||
|
$main.width(windowWidth-sidebarWidth);
|
||||||
|
}else{
|
||||||
|
$main.width(windowWidth);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$next.on("click", function(){
|
$next.on("click", function(){
|
||||||
|
@ -144,20 +217,34 @@ FP.app.init = (function($){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function showSidebar(){
|
||||||
|
$book.css("pointer-events", "none"); //-- Avoid capture by ifrmae
|
||||||
|
$sidebar.addClass("open");
|
||||||
|
$main.addClass("closed");
|
||||||
|
$icon.attr("src", "img/close.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideSidebar(){
|
||||||
|
$book.css("pointer-events", "visible");
|
||||||
|
$sidebar.removeClass("open");
|
||||||
|
$main.removeClass("closed");
|
||||||
|
$icon.attr("src", "img/menu-icon.png");
|
||||||
|
}
|
||||||
|
|
||||||
$open.on("click", function(){
|
$open.on("click", function(){
|
||||||
if($sidebar.hasClass("open")){
|
if($sidebar.hasClass("open")){
|
||||||
setTimeout(function(){
|
hideSidebar();
|
||||||
$sidebar.removeClass("open");
|
|
||||||
}, 500);
|
|
||||||
$main.removeClass("closed");
|
|
||||||
$icon.attr("src", "img/menu-icon.png");
|
|
||||||
}else{
|
}else{
|
||||||
$sidebar.addClass("open");
|
showSidebar();
|
||||||
$main.addClass("closed");
|
|
||||||
$icon.attr("src", "img/close.png");
|
$open.clickOutside(function(){
|
||||||
|
hideSidebar();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$network.on("click", function(){
|
$network.on("click", function(){
|
||||||
offline = !offline;
|
offline = !offline;
|
||||||
Book.fromStorage(offline);
|
Book.fromStorage(offline);
|
||||||
|
|
33
fpjs/reader/utils.js
Normal file
33
fpjs/reader/utils.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//-- http://stackoverflow.com/questions/2124684/jquery-how-click-anywhere-outside-of-the-div-the-div-fades-out
|
||||||
|
|
||||||
|
jQuery.fn.extend({
|
||||||
|
// Calls the handler function if the user has clicked outside the object (and not on any of the exceptions)
|
||||||
|
clickOutside: function(handler, exceptions) {
|
||||||
|
var $this = this;
|
||||||
|
|
||||||
|
jQuery(document).on("click.offer", function(event) {
|
||||||
|
if (exceptions && jQuery.inArray(event.target, exceptions) > -1) {
|
||||||
|
return;
|
||||||
|
} else if (jQuery.contains($this[0], event.target)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
jQuery(document).off("click.offer");
|
||||||
|
handler(event, $this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Modernizr.addTest('filesystem', function(){
|
||||||
|
|
||||||
|
var prefixes = Modernizr._domPrefixes;
|
||||||
|
|
||||||
|
for ( var i = -1, len = prefixes.length; ++i < len; ){
|
||||||
|
if ( window[prefixes[i] + 'RequestFileSystem'] ) return true;
|
||||||
|
}
|
||||||
|
return 'requestFileSystem' in window;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
@ -14,11 +14,16 @@ FP.Book = function(elem, bookUrl){
|
||||||
this.createEvent("book:spineReady");
|
this.createEvent("book:spineReady");
|
||||||
this.createEvent("book:bookReady");
|
this.createEvent("book:bookReady");
|
||||||
this.createEvent("book:chapterReady");
|
this.createEvent("book:chapterReady");
|
||||||
|
this.createEvent("book:chapterDisplayed");
|
||||||
this.createEvent("book:resized");
|
this.createEvent("book:resized");
|
||||||
this.createEvent("book:stored");
|
this.createEvent("book:stored");
|
||||||
this.createEvent("book:online");
|
this.createEvent("book:online");
|
||||||
this.createEvent("book:offline");
|
this.createEvent("book:offline");
|
||||||
|
|
||||||
|
this.hooks = {
|
||||||
|
"beforeChapterDisplay" : []
|
||||||
|
};
|
||||||
|
|
||||||
this.initialize(this.el);
|
this.initialize(this.el);
|
||||||
|
|
||||||
this.online = navigator.onLine;
|
this.online = navigator.onLine;
|
||||||
|
@ -30,7 +35,7 @@ FP.Book = function(elem, bookUrl){
|
||||||
|
|
||||||
// BookUrl is optional, but if present start loading process
|
// BookUrl is optional, but if present start loading process
|
||||||
if(bookUrl) {
|
if(bookUrl) {
|
||||||
this.start(bookUrl);
|
this.display(bookUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,6 +133,11 @@ FP.Book.prototype.isSaved = function(force) {
|
||||||
this.spine = JSON.parse(localStorage.getItem("spine"));
|
this.spine = JSON.parse(localStorage.getItem("spine"));
|
||||||
this.toc = JSON.parse(localStorage.getItem("toc"));
|
this.toc = JSON.parse(localStorage.getItem("toc"));
|
||||||
|
|
||||||
|
if(!this.assets.length || !this.spine.length){
|
||||||
|
this.stored = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,10 +191,10 @@ FP.Book.prototype.parseContainer = function(callback){
|
||||||
var fullpath;
|
var fullpath;
|
||||||
|
|
||||||
//-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/>
|
//-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/>
|
||||||
rootfiles = container.getElementsByTagName("rootfile");
|
rootfile = container.querySelector("rootfile");
|
||||||
|
|
||||||
//-- Should only be one
|
//-- Should only be one
|
||||||
rootfile = rootfiles[0];
|
//rootfile = rootfiles[0];
|
||||||
|
|
||||||
fullpath = rootfile.getAttribute('full-path').split("/");
|
fullpath = rootfile.getAttribute('full-path').split("/");
|
||||||
|
|
||||||
|
@ -206,9 +216,9 @@ FP.Book.prototype.parseContents = function(){
|
||||||
url = this.basePath + this.contentsPath;
|
url = this.basePath + this.contentsPath;
|
||||||
|
|
||||||
FP.core.loadXML(url, function(contents){
|
FP.core.loadXML(url, function(contents){
|
||||||
var metadata = contents.getElementsByTagName("metadata")[0],
|
var metadata = contents.querySelector("metadata"),
|
||||||
manifest = contents.getElementsByTagName("manifest")[0],
|
manifest = contents.querySelector("manifest"),
|
||||||
spine = contents.getElementsByTagName("spine")[0];
|
spine = contents.querySelector("spine");
|
||||||
|
|
||||||
that.parseMetadata(metadata);
|
that.parseMetadata(metadata);
|
||||||
that.parseManifest(manifest);
|
that.parseManifest(manifest);
|
||||||
|
@ -259,7 +269,8 @@ FP.Book.prototype.parseSpine = function(spine){
|
||||||
|
|
||||||
this.spine = [];
|
this.spine = [];
|
||||||
|
|
||||||
this.spineIndex = {}; //-- For quick reference by id, might be a better way
|
this.spineIndexByID = {}; //-- For quick reference by id and url, might be a better way
|
||||||
|
this.spineIndexByURL = {};
|
||||||
|
|
||||||
//-- Turn items into an array
|
//-- Turn items into an array
|
||||||
items = Array.prototype.slice.call(spine.getElementsByTagName("itemref"));
|
items = Array.prototype.slice.call(spine.getElementsByTagName("itemref"));
|
||||||
|
@ -270,7 +281,8 @@ FP.Book.prototype.parseSpine = function(spine){
|
||||||
href = that.assets[id];
|
href = that.assets[id];
|
||||||
|
|
||||||
that.spine.push({"id": id, "href": href});
|
that.spine.push({"id": id, "href": href});
|
||||||
that.spineIndex[id] = index;
|
that.spineIndexByID[id] = index;
|
||||||
|
that.spineIndexByURL[href] = index;
|
||||||
});
|
});
|
||||||
|
|
||||||
localStorage.setItem("spine", JSON.stringify(this.spine));
|
localStorage.setItem("spine", JSON.stringify(this.spine));
|
||||||
|
@ -296,7 +308,7 @@ FP.Book.prototype.parseTOC = function(path){
|
||||||
"id": coverID,
|
"id": coverID,
|
||||||
"href": that.assets[coverID],
|
"href": that.assets[coverID],
|
||||||
"label": coverID,
|
"label": coverID,
|
||||||
"spinePos": parseInt(that.spineIndex[coverID])
|
"spinePos": parseInt(that.spineIndexByID[coverID])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,14 +320,18 @@ FP.Book.prototype.parseTOC = function(path){
|
||||||
|
|
||||||
items.forEach(function(item){
|
items.forEach(function(item){
|
||||||
var id = item.getAttribute('id'),
|
var id = item.getAttribute('id'),
|
||||||
href = that.assets[id],
|
content = item.querySelector("content"),
|
||||||
|
src = content.getAttribute('src'), //that.assets[id],
|
||||||
|
split = src.split("#"),
|
||||||
|
href = that.basePath + split[0],
|
||||||
|
hash = split[1] || false,
|
||||||
|
spinePos = parseInt(that.spineIndexByID[id] || that.spineIndexByURL[href]),
|
||||||
navLabel = item.querySelector("navLabel"),
|
navLabel = item.querySelector("navLabel"),
|
||||||
text = navLabel.textContent ? navLabel.textContent : "",
|
text = navLabel.textContent ? navLabel.textContent : "",
|
||||||
subitems = item.querySelectorAll("navPoint") || false,
|
subitems = item.querySelectorAll("navPoint") || false,
|
||||||
subs = false,
|
subs = false,
|
||||||
childof = (item.parentNode == parent);
|
childof = (item.parentNode == parent);
|
||||||
|
|
||||||
|
|
||||||
if(!childof) return; //-- Only get direct children, should xpath for this eventually?
|
if(!childof) return; //-- Only get direct children, should xpath for this eventually?
|
||||||
|
|
||||||
if(subitems){
|
if(subitems){
|
||||||
|
@ -324,10 +340,11 @@ FP.Book.prototype.parseTOC = function(path){
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
"id": id,
|
"id": id,
|
||||||
"href": href,
|
"href": src,
|
||||||
"label": text,
|
"label": text,
|
||||||
"spinePos": parseInt(that.spineIndex[id]),
|
"spinePos": spinePos,
|
||||||
"subitems" : subs
|
"section" : hash || false,
|
||||||
|
"subitems" : subs || false
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -373,18 +390,40 @@ FP.Book.prototype.startDisplay = function(){
|
||||||
|
|
||||||
|
|
||||||
this.tell("book:bookReady");
|
this.tell("book:bookReady");
|
||||||
this.displayChapter(this.spinePos, false, function(){
|
this.displayChapter(this.spinePos, function(chapter){
|
||||||
|
|
||||||
if(this.online){
|
if(this.online){
|
||||||
this.storeOffline();
|
this.storeOffline();
|
||||||
}
|
}
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FP.Book.prototype.displayChapter = function(pos, end, callback){
|
FP.Book.prototype.show = function(url){
|
||||||
|
var split = url.split("#"),
|
||||||
|
chapter = split[0],
|
||||||
|
section = split[1] || false,
|
||||||
|
absoluteURL = this.basePath + chapter,
|
||||||
|
spinePos = this.spineIndexByURL[absoluteURL];
|
||||||
|
|
||||||
|
if(!chapter){
|
||||||
|
spinePos = this.spinePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!spinePos) return false;
|
||||||
|
|
||||||
|
if(spinePos != this.spinePos){
|
||||||
|
this.displayChapter(spinePos, function(chap){
|
||||||
|
if(section) chap.section(section);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
if(section) this.currentChapter.section(section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FP.Book.prototype.displayChapter = function(pos, callback){
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
if(pos >= this.spine.length){
|
if(pos >= this.spine.length){
|
||||||
|
@ -409,12 +448,10 @@ FP.Book.prototype.displayChapter = function(pos, end, callback){
|
||||||
//-- TODO: Choose between single and spread
|
//-- TODO: Choose between single and spread
|
||||||
//that.formatSpread();
|
//that.formatSpread();
|
||||||
|
|
||||||
if(end) chapter.goToChapterEnd();
|
that.tell("book:chapterReady", chapter.getID());
|
||||||
|
|
||||||
that.tell("book:chapterReady");
|
|
||||||
|
|
||||||
if(callback){
|
if(callback){
|
||||||
callback();
|
callback(chapter);
|
||||||
}
|
}
|
||||||
//that.preloadNextChapter();
|
//that.preloadNextChapter();
|
||||||
|
|
||||||
|
@ -445,7 +482,9 @@ FP.Book.prototype.nextChapter = function() {
|
||||||
FP.Book.prototype.prevChapter = function() {
|
FP.Book.prototype.prevChapter = function() {
|
||||||
this.spinePos--;
|
this.spinePos--;
|
||||||
|
|
||||||
this.displayChapter(this.spinePos, true);
|
this.displayChapter(this.spinePos, function(chapter){
|
||||||
|
chapter.goToChapterEnd();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -464,6 +503,7 @@ FP.Book.prototype.preloadNextChapter = function() {
|
||||||
|
|
||||||
FP.Book.prototype.storeOffline = function(callback) {
|
FP.Book.prototype.storeOffline = function(callback) {
|
||||||
var assets = FP.core.toArray(this.assets);
|
var assets = FP.core.toArray(this.assets);
|
||||||
|
|
||||||
FP.storage.batch(assets, function(){
|
FP.storage.batch(assets, function(){
|
||||||
this.stored = 1;
|
this.stored = 1;
|
||||||
localStorage.setItem("stored", 1);
|
localStorage.setItem("stored", 1);
|
||||||
|
@ -510,13 +550,39 @@ FP.Book.prototype.determineStorageMethod = function(override) {
|
||||||
FP.storage.storageMethod(method);
|
FP.storage.storageMethod(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
Modernizr.addTest('filesystem', function(){
|
FP.Book.prototype.triggerHooks = function(type, callback){
|
||||||
|
var hooks, count;
|
||||||
|
|
||||||
var prefixes = Modernizr._domPrefixes;
|
if(typeof(this.hooks[type]) == "undefined") return false;
|
||||||
|
|
||||||
for ( var i = -1, len = prefixes.length; ++i < len; ){
|
hooks = this.hooks[type];
|
||||||
if ( window[prefixes[i] + 'RequestFileSystem'] ) return true;
|
count = hooks.length;
|
||||||
}
|
|
||||||
return 'requestFileSystem' in window;
|
|
||||||
|
|
||||||
});
|
function countdown(){
|
||||||
|
count--;
|
||||||
|
if(count <= 0 && callback) callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
hooks.forEach(function(hook){
|
||||||
|
hook(countdown);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
FP.Book.prototype.registerHook = function(type, toAdd){
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
if(typeof(this.hooks[type]) != "undefined"){
|
||||||
|
|
||||||
|
if(typeof(toAdd) === "function"){
|
||||||
|
this.hooks[type].push(toAdd);
|
||||||
|
}else if(Array.isArray(toAdd)){
|
||||||
|
toAdd.forEach(function(hook){
|
||||||
|
that.hooks[type].push(hook);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
this.hooks[type] = [func]; //or maybe this should error?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
FP.Chapter = function(book){
|
FP.Chapter = function(book, pos){
|
||||||
|
|
||||||
this.book = book;
|
this.book = book;
|
||||||
this.iframe = this.book.iframe;
|
this.iframe = this.book.iframe;
|
||||||
|
|
||||||
|
this.chapInfo = this.book.spine[pos || this.book.spinePos];
|
||||||
//-- Get the url to the book from the spine
|
//-- Get the url to the book from the spine
|
||||||
this.path = this.book.spine[this.book.spinePos].href;
|
this.path = this.chapInfo.href;
|
||||||
|
this.ID = this.chapInfo.id;
|
||||||
|
|
||||||
this.chapterPos = 1;
|
this.chapterPos = 1;
|
||||||
this.leftPos = 0;
|
this.leftPos = 0;
|
||||||
|
|
||||||
|
this.book.registerHook("beforeChapterDisplay",
|
||||||
|
[this.replaceLinks.bind(this), this.replaceResources.bind(this)]);
|
||||||
|
|
||||||
|
|
||||||
this.load();
|
this.load();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -34,14 +40,16 @@ FP.Chapter.prototype.setIframeSrc = function(url){
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
//-- Not sure if this is the best time to do this, but hide current text
|
//-- Not sure if this is the best time to do this, but hide current text
|
||||||
if(this.bodyEl) this.bodyEl.style.visibility = "hidden";
|
//if(this.bodyEl) this.bodyEl.style.visibility = "hidden";
|
||||||
|
this.visible(false);
|
||||||
|
|
||||||
this.iframe.src = url;
|
this.iframe.src = url;
|
||||||
|
|
||||||
this.iframe.onload = function() {
|
this.iframe.onload = function() {
|
||||||
//that.bodyEl = that.iframe.contentDocument.documentElement.getElementsByTagName('body')[0];
|
//that.bodyEl = that.iframe.contentDocument.documentElement.getElementsByTagName('body')[0];
|
||||||
//that.bodyEl = that.iframe.contentDocument.querySelector('body, html');
|
//that.bodyEl = that.iframe.contentDocument.querySelector('body, html');
|
||||||
that.bodyEl = that.book.bodyEl = that.iframe.contentDocument.body;
|
that.doc = that.iframe.contentDocument;
|
||||||
|
that.bodyEl = that.doc.body;
|
||||||
|
|
||||||
//-- TODO: Choose between single and spread
|
//-- TODO: Choose between single and spread
|
||||||
that.formatSpread();
|
that.formatSpread();
|
||||||
|
@ -109,14 +117,21 @@ FP.Chapter.prototype.formatSpread = function(){
|
||||||
|
|
||||||
this.calcPages();
|
this.calcPages();
|
||||||
|
|
||||||
if(!this.book.online){
|
|
||||||
//-- Temp place to parse Links
|
|
||||||
this.replaceLinks(function(){
|
// if(!this.book.online){
|
||||||
this.visible(true);
|
// //-- Temp place to parse Links
|
||||||
}.bind(this));
|
// this.replaceLinks(function(){
|
||||||
}else{
|
// this.visible(true);
|
||||||
|
// }.bind(this));
|
||||||
|
// }else{
|
||||||
|
// this.visible(true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
this.beforeDisplay(function(){
|
||||||
|
this.book.tell("book:chapterDisplayed");
|
||||||
this.visible(true);
|
this.visible(true);
|
||||||
}
|
});
|
||||||
|
|
||||||
//-- Go to current page after resize
|
//-- Go to current page after resize
|
||||||
if(this.OldcolWidth){
|
if(this.OldcolWidth){
|
||||||
|
@ -130,6 +145,8 @@ FP.Chapter.prototype.goToChapterEnd = function(){
|
||||||
}
|
}
|
||||||
|
|
||||||
FP.Chapter.prototype.visible = function(bool){
|
FP.Chapter.prototype.visible = function(bool){
|
||||||
|
if(!this.bodyEl) return false;
|
||||||
|
|
||||||
if(bool){
|
if(bool){
|
||||||
this.bodyEl.style.visibility = "visible";
|
this.bodyEl.style.visibility = "visible";
|
||||||
}else{
|
}else{
|
||||||
|
@ -142,7 +159,7 @@ FP.Chapter.prototype.calcPages = function(){
|
||||||
|
|
||||||
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
||||||
|
|
||||||
|
//console.log("Pages:", this.displayedPages)
|
||||||
//-- I work for Chrome
|
//-- I work for Chrome
|
||||||
//this.iframe.contentDocument.body.scrollLeft = 200;
|
//this.iframe.contentDocument.body.scrollLeft = 200;
|
||||||
|
|
||||||
|
@ -185,9 +202,9 @@ FP.Chapter.prototype.prevPage = function(){
|
||||||
}
|
}
|
||||||
|
|
||||||
FP.Chapter.prototype.chapterEnd = function(){
|
FP.Chapter.prototype.chapterEnd = function(){
|
||||||
this.chapterPos = this.displayedPages;
|
this.page(this.displayedPages);
|
||||||
this.leftPos = this.spreadWidth * (this.displayedPages - 1);//this.totalWidth - this.colWidth;
|
//this.leftPos = this.spreadWidth * (this.displayedPages - 1);//this.totalWidth - this.colWidth;
|
||||||
this.setLeft(this.leftPos);
|
//this.setLeft(this.leftPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
FP.Chapter.prototype.setLeft = function(leftPos){
|
FP.Chapter.prototype.setLeft = function(leftPos){
|
||||||
|
@ -195,26 +212,42 @@ FP.Chapter.prototype.setLeft = function(leftPos){
|
||||||
}
|
}
|
||||||
|
|
||||||
FP.Chapter.prototype.replaceLinks = function(callback){
|
FP.Chapter.prototype.replaceLinks = function(callback){
|
||||||
var doc = this.iframe.contentDocument,
|
var hrefs = this.doc.querySelectorAll('[href]'),
|
||||||
links = doc.querySelectorAll('[href], [src]'),
|
links = Array.prototype.slice.call(hrefs),
|
||||||
items = Array.prototype.slice.call(links),
|
that = this;
|
||||||
count = items.length;
|
|
||||||
|
|
||||||
if(FP.storage.getStorageType() == "filesystem") {
|
links.forEach(function(link){
|
||||||
|
var path,
|
||||||
|
href = link.getAttribute("href");
|
||||||
|
|
||||||
|
link.onclick = function(){
|
||||||
|
that.book.show(href);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if(callback) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
FP.Chapter.prototype.replaceResources = function(callback){
|
||||||
|
var srcs, resources, count;
|
||||||
|
|
||||||
|
if(this.book.online || FP.storage.getStorageType() == "filesystem") {
|
||||||
//-- filesystem api links are relative, so no need to fix
|
//-- filesystem api links are relative, so no need to fix
|
||||||
if(callback) callback();
|
if(callback) callback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
items.forEach(function(link){
|
srcs = this.doc.querySelectorAll('[src]');
|
||||||
var path,
|
resources = Array.prototype.slice.call(srcs);
|
||||||
href = link.getAttribute("href"),
|
count = resources.length;
|
||||||
src = link.getAttribute("src"),
|
|
||||||
full = href ? this.book.basePath + href : this.book.basePath + src;
|
resources.forEach(function(link){
|
||||||
|
var src = link.getAttribute("src"),
|
||||||
|
full = this.book.basePath + src;
|
||||||
|
|
||||||
FP.storage.get(full, function(url){
|
FP.storage.get(full, function(url){
|
||||||
if(href) link.setAttribute("href", url);
|
link.setAttribute("src", url);
|
||||||
if(src) link.setAttribute("src", url);
|
|
||||||
count--;
|
count--;
|
||||||
if(count <= 0 && callback) callback();
|
if(count <= 0 && callback) callback();
|
||||||
});
|
});
|
||||||
|
@ -223,4 +256,31 @@ FP.Chapter.prototype.replaceLinks = function(callback){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FP.Chapter.prototype.getID = function(){
|
||||||
|
return this.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
FP.Chapter.prototype.page = function(pg){
|
||||||
|
if(pg >= 1 && pg <= this.displayedPages){
|
||||||
|
this.chapterPos = pg;
|
||||||
|
this.leftPos = this.spreadWidth * (pg-1);
|
||||||
|
this.setLeft(this.leftPos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FP.Chapter.prototype.section = function(fragment){
|
||||||
|
var el = this.doc.getElementById(fragment),
|
||||||
|
left = this.leftPos + el.offsetLeft,
|
||||||
|
pg = Math.floor(left / this.spreadWidth) + 1;
|
||||||
|
|
||||||
|
this.page(pg);
|
||||||
|
}
|
||||||
|
|
||||||
|
FP.Chapter.prototype.beforeDisplay = function(callback){
|
||||||
|
this.book.triggerHooks("beforeChapterDisplay", callback.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,3 +162,4 @@ FP.core.dataURLToBlob = function(dataURL) {
|
||||||
|
|
||||||
return new Blob([uInt8Array], {type: contentType});
|
return new Blob([uInt8Array], {type: contentType});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,14 @@ FP.storage = function(){
|
||||||
function storageMethod(storageType){
|
function storageMethod(storageType){
|
||||||
console.log("storageMethod", storageType)
|
console.log("storageMethod", storageType)
|
||||||
//-- Pick store type
|
//-- Pick store type
|
||||||
if(!storageType || typeof(FP.storage[storageType]) == "undefined"){
|
if(!storageType || typeof(FP.store[storageType]) == "undefined"){
|
||||||
this.storageType = "none";
|
this.storageType = "none";
|
||||||
}else{
|
}else{
|
||||||
this.storageType = storageType;
|
this.storageType = storageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-- Create a new store of that type
|
//-- Create a new store of that type
|
||||||
this._store = new FP.storage[this.storageType];
|
this._store = new FP.store[this.storageType];
|
||||||
|
|
||||||
//-- Handle load errors
|
//-- Handle load errors
|
||||||
this._store.failed = _error;
|
this._store.failed = _error;
|
||||||
|
@ -173,7 +173,9 @@ FP.storage.ram = function() {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FP.storage.none = function() {
|
FP.store = FP.store || {};
|
||||||
|
|
||||||
|
FP.store.none = function() {
|
||||||
var _store = {};
|
var _store = {};
|
||||||
|
|
||||||
//-- Used for preloading
|
//-- Used for preloading
|
||||||
|
@ -185,6 +187,8 @@ FP.storage.none = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-- need to add batch!
|
||||||
|
|
||||||
//-- Fetches url
|
//-- Fetches url
|
||||||
function get(path, callback) {
|
function get(path, callback) {
|
||||||
var fromCache = check(path),
|
var fromCache = check(path),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FP.storage = FP.storage || {}
|
FP.store = FP.store || {};
|
||||||
|
|
||||||
FP.storage.filesystem = function() {
|
FP.store.filesystem = function() {
|
||||||
var _urls = {},
|
var _urls = {},
|
||||||
_queue = new FP.Queue("fpjs/render/loader_filesystem.js", 6),
|
_queue = new FP.Queue("fpjs/render/loader_filesystem.js", 6),
|
||||||
_requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem,
|
_requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FP.storage = FP.storage || {}
|
FP.store = FP.store || {};
|
||||||
|
|
||||||
FP.storage.indexedDB = function() {
|
FP.store.indexedDB = function() {
|
||||||
var _store = {},
|
var _store = {},
|
||||||
_blobs = {},
|
_blobs = {},
|
||||||
_queue = new FP.Queue(loader, 6),
|
_queue = new FP.Queue(loader, 6),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FP.storage = FP.storage || {};
|
FP.store = FP.store || {};
|
||||||
|
|
||||||
FP.storage.ram = function() {
|
FP.store.ram = function() {
|
||||||
var _store = {},
|
var _store = {},
|
||||||
_blobs = {},
|
_blobs = {},
|
||||||
_queue = new FP.Queue(loader, 6);
|
_queue = new FP.Queue(loader, 6);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FP.storage = FP.storage || {}
|
FP.store = FP.store || {};
|
||||||
|
|
||||||
FP.storage.websql = function() {
|
FP.store.websql = function() {
|
||||||
var _blobs = {},
|
var _blobs = {},
|
||||||
_queue = new FP.Queue(loader, 6),
|
_queue = new FP.Queue(loader, 6),
|
||||||
_db;
|
_db;
|
||||||
|
|
22
index.html
22
index.html
|
@ -15,27 +15,18 @@
|
||||||
<script>window.jQuery || document.write('<script src="fpjs/libs/jquery-1.9.0.min.js"><\/script>')</script>
|
<script>window.jQuery || document.write('<script src="fpjs/libs/jquery-1.9.0.min.js"><\/script>')</script>
|
||||||
<script src="fpjs/libs/modernizr-2.6.2.min.js"></script>
|
<script src="fpjs/libs/modernizr-2.6.2.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
//-- Define Global
|
"use strict";
|
||||||
// var FP = (function(){
|
|
||||||
// "use strict";
|
var FP = FP || {};
|
||||||
// return {
|
|
||||||
// namespace: function(name) {
|
|
||||||
// if(this[name] === undefined) { this[name] = {}; }
|
|
||||||
// if(typeof this[name] !== 'object') { throw "Namespace Error: "+name; }
|
|
||||||
// return this[name];
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// })();
|
|
||||||
var FP = {};
|
|
||||||
document.onreadystatechange = function () {
|
document.onreadystatechange = function () {
|
||||||
if (document.readyState == "complete") {
|
if (document.readyState == "complete") {
|
||||||
FP.app.init();
|
FPR.app.init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script async src="fpjs/reader/utils.js"></script>
|
||||||
<script async src="fpjs/render/core.js"></script>
|
<script async src="fpjs/render/core.js"></script>
|
||||||
<script async src="fpjs/render/queue.js"></script>
|
<script async src="fpjs/render/queue.js"></script>
|
||||||
<script async src="fpjs/render/storage.js"></script>
|
<script async src="fpjs/render/storage.js"></script>
|
||||||
|
@ -58,8 +49,7 @@
|
||||||
<a id="setting"><img id="settings" src="img/settings.png"></a>
|
<a id="setting"><img id="settings" src="img/settings.png"></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="toc-scroll">
|
<div id="toc">
|
||||||
<ul id="toc"></ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue