mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-05 15:32:55 +02:00
New book / renderTo methods, added promises, new render, cfi parsing, seperate package parsing, added settings, removed modernizr, disabled offline storage until it can return apromise
This commit is contained in:
parent
0780411e0c
commit
751a87ca4b
24 changed files with 5038 additions and 1745 deletions
1056
src/book.js
1056
src/book.js
File diff suppressed because it is too large
Load diff
344
src/chapter.js
344
src/chapter.js
|
@ -1,337 +1,43 @@
|
|||
EPUBJS.Chapter = function(book, pos){
|
||||
|
||||
this.book = book;
|
||||
this.iframe = this.book.iframe;
|
||||
|
||||
this.pos = pos || this.book.spinePos
|
||||
this.chapInfo = this.book.spine[this.pos];
|
||||
//-- Get the url to the book from the spine
|
||||
this.path = this.chapInfo.href;
|
||||
this.ID = this.chapInfo.id;
|
||||
|
||||
this.chapterPos = 1;
|
||||
this.leftPos = 0;
|
||||
localStorage.setItem("chapterPos", this.chapterPos);
|
||||
|
||||
|
||||
this.book.registerHook("beforeChapterDisplay",
|
||||
[this.replaceLinks.bind(this), this.replaceResources.bind(this)]);
|
||||
|
||||
|
||||
this.load();
|
||||
|
||||
return this;
|
||||
|
||||
EPUBJS.Chapter = function(spineObject){
|
||||
this.href = spineObject.href;
|
||||
this.id = spineObject.id;
|
||||
this.spinePos = spineObject.index;
|
||||
this.properties = spineObject.properties;
|
||||
this.linear = spineObject.linear;
|
||||
this.pages = 1;
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.load = function(){
|
||||
var path = this.path;
|
||||
|
||||
if(this.book.online && !this.book.contained){
|
||||
this.setIframeSrc(path);
|
||||
EPUBJS.Chapter.prototype.contents = function(store){
|
||||
// if(this.store && (!this.book.online || this.book.contained))
|
||||
if(store){
|
||||
return store.get(href);
|
||||
}else{
|
||||
this.loadFromStorage(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.loadFromStorage = function(path){
|
||||
var file = EPUBJS.storage.get(path, this.setIframeSrc.bind(this));
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.setIframeSrc = function(url){
|
||||
var that = this;
|
||||
|
||||
this.visible(false);
|
||||
|
||||
this.iframe.src = url;
|
||||
|
||||
|
||||
this.iframe.onload = function() {
|
||||
that.doc = that.iframe.contentDocument;
|
||||
that.bodyEl = that.doc.body;
|
||||
|
||||
|
||||
that.formatSpread();
|
||||
|
||||
//-- Trigger registered hooks before displaying
|
||||
that.beforeDisplay(function(){
|
||||
|
||||
that.calcPages();
|
||||
|
||||
that.book.tell("book:chapterDisplayed");
|
||||
|
||||
that.visible(true);
|
||||
|
||||
});
|
||||
|
||||
that.afterLoaded(that);
|
||||
|
||||
that.book.listen("book:resized", that.formatSpread, that);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.afterLoaded = function(chapter){
|
||||
//-- This is overwritten by the book object
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.error = function(err){
|
||||
console.log("error", error)
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.formatSpread = function(){
|
||||
|
||||
var divisor = 2,
|
||||
cutoff = 800;
|
||||
|
||||
if(this.colWidth){
|
||||
this.OldcolWidth = this.colWidth;
|
||||
this.OldspreadWidth = this.spreadWidth;
|
||||
return EPUBJS.core.request(href, 'xml');
|
||||
}
|
||||
|
||||
//-- Check the width and decied on columns
|
||||
//-- Todo: a better place for this?
|
||||
this.elWidth = this.iframe.width;
|
||||
}
|
||||
|
||||
this.gap = this.gap || Math.ceil(this.elWidth / 8);
|
||||
|
||||
if(this.elWidth < cutoff || this.book.single) {
|
||||
this.spread = false; //-- Single Page
|
||||
|
||||
divisor = 1;
|
||||
this.colWidth = Math.floor(this.elWidth / divisor);
|
||||
EPUBJS.Chapter.prototype.url = function(store){
|
||||
var promise = new RSVP.Promise();
|
||||
|
||||
if(store){
|
||||
return store.getUrl(href);
|
||||
}else{
|
||||
this.spread = true; //-- Double Page
|
||||
|
||||
this.colWidth = Math.floor((this.elWidth - this.gap) / divisor);
|
||||
|
||||
/* - Was causing jumps, doesn't seem to be needed anymore
|
||||
//-- Must be even for firefox
|
||||
if(this.colWidth % 2 != 0){
|
||||
this.colWidth -= 1;
|
||||
}
|
||||
*/
|
||||
promise.resolve(this.href); //-- this is less than ideal but keeps it a promise
|
||||
return promise;
|
||||
}
|
||||
|
||||
this.spreadWidth = (this.colWidth + this.gap) * divisor;
|
||||
|
||||
this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
|
||||
//-- Clear Margins
|
||||
//this.bodyEl.style.visibility = "hidden";
|
||||
this.bodyEl.style.margin = "0";
|
||||
this.bodyEl.style.overflow = "hidden";
|
||||
|
||||
this.bodyEl.style.width = this.elWidth;
|
||||
|
||||
//-- Adjust height
|
||||
this.bodyEl.style.height = this.book.el.clientHeight + "px";
|
||||
|
||||
//-- Add columns
|
||||
this.bodyEl.style[EPUBJS.core.columnAxis] = "horizontal";
|
||||
this.bodyEl.style[EPUBJS.core.columnGap] = this.gap+"px";
|
||||
this.bodyEl.style[EPUBJS.core.columnWidth] = this.colWidth+"px";
|
||||
|
||||
|
||||
//-- Go to current page after resize
|
||||
if(this.OldcolWidth){
|
||||
this.setLeft((this.chapterPos - 1 ) * this.spreadWidth);
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.fixedLayout = function(){
|
||||
this.paginated = false;
|
||||
console.log("off")
|
||||
this.setLeft(0);
|
||||
|
||||
this.bodyEl.style.width = this.elWidth;
|
||||
|
||||
//-- Adjust height
|
||||
this.bodyEl.style.height = "auto";
|
||||
|
||||
//-- Remove columns
|
||||
this.bodyEl.style[EPUBJS.core.columnWidth] = "auto";
|
||||
|
||||
//-- Scroll
|
||||
this.bodyEl.style.overflow = "auto";
|
||||
|
||||
this.displayedPages = 1;
|
||||
EPUBJS.Chapter.prototype.setPages = function(num){
|
||||
this.pages = num;
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.goToChapterEnd = function(){
|
||||
this.chapterEnd();
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.visible = function(bool){
|
||||
if(typeof(bool) == "undefined") {
|
||||
return this.iframe.style.visibility;
|
||||
}
|
||||
|
||||
if(bool == true){
|
||||
this.iframe.style.visibility = "visible";
|
||||
}else if(bool == false){
|
||||
this.iframe.style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.calcPages = function(){
|
||||
this.totalWidth = this.iframe.contentDocument.documentElement.scrollWidth; //this.bodyEl.scrollWidth;
|
||||
|
||||
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
||||
|
||||
|
||||
localStorage.setItem("displayedPages", this.displayedPages);
|
||||
//console.log("Pages:", this.displayedPages)
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.Chapter.prototype.nextPage = function(){
|
||||
if(this.chapterPos < this.displayedPages){
|
||||
this.chapterPos++;
|
||||
|
||||
this.leftPos += this.spreadWidth;
|
||||
|
||||
this.setLeft(this.leftPos);
|
||||
|
||||
localStorage.setItem("chapterPos", this.chapterPos);
|
||||
this.book.tell("book:pageChanged", this.chapterPos);
|
||||
|
||||
return this.chapterPos;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.prevPage = function(){
|
||||
if(this.chapterPos > 1){
|
||||
this.chapterPos--;
|
||||
|
||||
this.leftPos -= this.spreadWidth;
|
||||
|
||||
this.setLeft(this.leftPos);
|
||||
|
||||
localStorage.setItem("chapterPos", this.chapterPos);
|
||||
this.book.tell("book:pageChanged", this.chapterPos);
|
||||
|
||||
return this.chapterPos;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.chapterEnd = function(){
|
||||
this.page(this.displayedPages);
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.setLeft = function(leftPos){
|
||||
this.bodyEl.style.marginLeft = -leftPos + "px";
|
||||
|
||||
/*
|
||||
var left = "transform: " + (-leftPos) + "px";
|
||||
//-- Need to stardize this
|
||||
|
||||
this.bodyEl.style.webkitTransform = left; //Chrome and Safari
|
||||
this.bodyEl.style.MozTransform = left; //Firefox
|
||||
this.bodyEl.style.msTransform = left; //IE
|
||||
this.bodyEl.style.OTransform = left; //Opera
|
||||
this.bodyEl.style.transform = left;
|
||||
*/
|
||||
}
|
||||
|
||||
//-- Replaces the relative links within the book to use our internal page changer
|
||||
EPUBJS.Chapter.prototype.replaceLinks = function(callback){
|
||||
var hrefs = this.doc.querySelectorAll('[href]'),
|
||||
links = Array.prototype.slice.call(hrefs),
|
||||
that = this;
|
||||
|
||||
links.forEach(function(link){
|
||||
var path,
|
||||
href = link.getAttribute("href"),
|
||||
relative = href.search("://"),
|
||||
fragment = href[0] == "#";
|
||||
|
||||
if(relative != -1){
|
||||
|
||||
link.setAttribute("target", "_blank");
|
||||
|
||||
}else{
|
||||
|
||||
link.onclick = function(){
|
||||
if(that.book.useHash){
|
||||
window.location.hash = "#/"+href;
|
||||
}else{
|
||||
that.book.show(href);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
if(callback) callback();
|
||||
}
|
||||
|
||||
//-- Replaces assets src's to point to stored version if browser is offline
|
||||
EPUBJS.Chapter.prototype.replaceResources = function(callback){
|
||||
var srcs, resources, count;
|
||||
|
||||
//-- No need to replace if there is network connectivity
|
||||
//-- also Filesystem api links are relative, so no need to replace them
|
||||
if((this.book.online && !this.book.contained) || EPUBJS.storage.getStorageType() == "filesystem") {
|
||||
if(callback) callback();
|
||||
return false;
|
||||
}
|
||||
|
||||
srcs = this.doc.querySelectorAll('[src]');
|
||||
resources = Array.prototype.slice.call(srcs);
|
||||
count = resources.length;
|
||||
|
||||
resources.forEach(function(link){
|
||||
var src = link.getAttribute("src"),
|
||||
full = this.book.basePath + src;
|
||||
|
||||
EPUBJS.storage.get(full, function(url){
|
||||
link.setAttribute("src", url);
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
});
|
||||
|
||||
}.bind(this));
|
||||
|
||||
EPUBJS.Chapter.prototype.getPages = function(num){
|
||||
return this.pages;
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.getID = function(){
|
||||
return this.ID;
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.page = function(pg){
|
||||
if(pg >= 1 && pg <= this.displayedPages){
|
||||
this.chapterPos = pg;
|
||||
this.leftPos = this.spreadWidth * (pg-1); //-- pages start at 1
|
||||
this.setLeft(this.leftPos);
|
||||
|
||||
localStorage.setItem("chapterPos", pg);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-- Return false if page is greater than the total
|
||||
return false;
|
||||
}
|
||||
|
||||
//-- Find a section by fragement id
|
||||
EPUBJS.Chapter.prototype.section = function(fragment){
|
||||
var el = this.doc.getElementById(fragment),
|
||||
left, pg;
|
||||
|
||||
if(el){
|
||||
left = this.leftPos + el.getBoundingClientRect().left, //-- Calculate left offset compaired to scrolled position
|
||||
pg = Math.floor(left / this.spreadWidth) + 1; //-- pages start at 1
|
||||
this.page(pg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Chapter.prototype.beforeDisplay = function(callback){
|
||||
this.book.triggerHooks("beforeChapterDisplay", callback.bind(this), this);
|
||||
}
|
||||
|
||||
}
|
197
src/core.js
197
src/core.js
|
@ -12,19 +12,65 @@ EPUBJS.core.getEls = function(classes) {
|
|||
}
|
||||
|
||||
|
||||
EPUBJS.core.loadXML = function(url, callback){
|
||||
EPUBJS.core.request = function(url, type) {
|
||||
var promise = new RSVP.Promise();
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.overrideMimeType('text/xml');
|
||||
|
||||
xhr.onload = function(e) {
|
||||
if (this.status == 200) {
|
||||
callback(this.responseXML);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
xhr.open("GET", url);
|
||||
xhr.onreadystatechange = handler;
|
||||
|
||||
if(type == 'blob'){
|
||||
xhr.responseType = type;
|
||||
}
|
||||
|
||||
if(type == "json") {
|
||||
xhr.setRequestHeader("Accept", "application/json");
|
||||
}
|
||||
|
||||
if(type == 'xml') {
|
||||
xhr.overrideMimeType('text/xml');
|
||||
}
|
||||
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function handler() {
|
||||
if (this.readyState === this.DONE) {
|
||||
if (this.status === 200) {
|
||||
var r;
|
||||
|
||||
if(type == 'xml'){
|
||||
r = this.responseXML;
|
||||
}else
|
||||
if(type == 'json'){
|
||||
r = JSON.parse(this.response);
|
||||
}else{
|
||||
r = this.response;
|
||||
}
|
||||
|
||||
promise.resolve(r);
|
||||
}
|
||||
else { promise.reject(this); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
// EPUBJS.core.loadXML = function(url, callback){
|
||||
// var xhr = new XMLHttpRequest();
|
||||
// xhr.open('GET', url, true);
|
||||
// xhr.overrideMimeType('text/xml');
|
||||
//
|
||||
// xhr.onload = function(e) {
|
||||
// if (this.status == 200) {
|
||||
// callback(this.responseXML);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// xhr.send();
|
||||
// }
|
||||
|
||||
// EPUBJS.core.loadFile = function(url){
|
||||
// var xhr = new XMLHttpRequest(),
|
||||
|
@ -63,66 +109,47 @@ EPUBJS.core.loadXML = function(url, callback){
|
|||
// "error" : failed
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// EPUBJS.core.loadFile = function(url, callback){
|
||||
// var xhr = new XMLHttpRequest();
|
||||
//
|
||||
// this.succeeded = function(response){
|
||||
// if(callback){
|
||||
// callback(response);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// this.failed = function(err){
|
||||
// console.log("Error:", err);
|
||||
// }
|
||||
//
|
||||
// this.start = function(){
|
||||
// var that = this;
|
||||
//
|
||||
// xhr.open('GET', url, true);
|
||||
// xhr.responseType = 'blob';
|
||||
//
|
||||
// xhr.onload = function(e) {
|
||||
// if (this.status == 200) {
|
||||
// that.succeeded(this.response);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// xhr.onerror = function(e) {
|
||||
// that.failed(this.status); //-- TODO: better error message
|
||||
// };
|
||||
//
|
||||
// xhr.send();
|
||||
// }
|
||||
//
|
||||
// return {
|
||||
// "start": this.start,
|
||||
// "succeeded" : this.succeeded,
|
||||
// "failed" : this.failed
|
||||
// }
|
||||
// }
|
||||
|
||||
EPUBJS.core.loadFile = function(url, callback){
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
this.succeeded = function(response){
|
||||
if(callback){
|
||||
callback(response);
|
||||
}
|
||||
}
|
||||
|
||||
this.failed = function(err){
|
||||
console.log("Error:", err);
|
||||
}
|
||||
|
||||
this.start = function(){
|
||||
var that = this;
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
xhr.responseType = 'blob';
|
||||
|
||||
xhr.onload = function(e) {
|
||||
if (this.status == 200) {
|
||||
that.succeeded(this.response);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function(e) {
|
||||
that.failed(this.status); //-- TODO: better error message
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
return {
|
||||
"start": this.start,
|
||||
"succeeded" : this.succeeded,
|
||||
"failed" : this.failed
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.core.crossBrowserColumnCss = function(){
|
||||
//-- From Readium: reflowable_pagination_view.js
|
||||
|
||||
var cssIfy = function(str) {
|
||||
return str.replace(/([A-Z])/g, function(str,m1){
|
||||
return '-' + m1.toLowerCase();
|
||||
}).replace(/^ms-/,'-ms-');
|
||||
};
|
||||
|
||||
// ask modernizr for the vendor prefixed version
|
||||
EPUBJS.core.columnAxis = Modernizr.prefixed('columnAxis') || 'columnAxis';
|
||||
EPUBJS.core.columnGap = Modernizr.prefixed('columnGap') || 'columnGap';
|
||||
EPUBJS.core.columnWidth = Modernizr.prefixed('columnWidth') || 'columnWidth';
|
||||
|
||||
// we are interested in the css prefixed version
|
||||
// EPUBJS.core.columnAxis = cssIfy(EPUBJS.core.columnAxis);
|
||||
// EPUBJS.core.columnGap = cssIfy(EPUBJS.core.columnGap);
|
||||
// EPUBJS.core.columnWidth = cssIfy(EPUBJS.core.columnWidth);
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.core.toArray = function(obj) {
|
||||
var arr = [];
|
||||
|
@ -139,6 +166,16 @@ EPUBJS.core.toArray = function(obj) {
|
|||
return arr;
|
||||
};
|
||||
|
||||
//-- Parse out the folder
|
||||
EPUBJS.core.folder = function(url){
|
||||
|
||||
var slash = url.lastIndexOf('/'),
|
||||
folder = url.slice(0, slash + 1);
|
||||
|
||||
return folder;
|
||||
|
||||
};
|
||||
|
||||
//-- https://github.com/ebidel/filer.js/blob/master/src/filer.js#L128
|
||||
EPUBJS.core.dataURLToBlob = function(dataURL) {
|
||||
var BASE64_MARKER = ';base64,';
|
||||
|
@ -220,3 +257,25 @@ EPUBJS.core.addScript = function(src, callback, target) {
|
|||
target = target || document.body;
|
||||
target.appendChild(s);
|
||||
}
|
||||
|
||||
EPUBJS.core.prefixed = function(unprefixed) {
|
||||
var vendors = ["Webkit", "Moz", "O", "ms" ],
|
||||
prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],
|
||||
upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),
|
||||
length = vendors.length,
|
||||
i = 0;
|
||||
|
||||
if (typeof(document.body.style[unprefixed]) != 'undefined') {
|
||||
return unprefixed;
|
||||
}
|
||||
|
||||
for ( ; i < length; i++ ) {
|
||||
if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {
|
||||
return vendors[i] + upper;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
|
170
src/epubcfi.js
Normal file
170
src/epubcfi.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
EPUBJS.EpubCFI = function(cfiStr){
|
||||
if(cfiStr) return this.parse(cfiStr);
|
||||
}
|
||||
|
||||
EPUBJS.EpubCFI.prototype.generateChapter = function(spineNodeIndex, pos, id) {
|
||||
|
||||
var spineNodeIndex = spineNodeIndex + 1,
|
||||
cfi = '/'+spineNodeIndex+'/';
|
||||
|
||||
cfi += (pos + 1) * 2;
|
||||
|
||||
if(id) cfi += "[" + id + "]";
|
||||
|
||||
cfi += "!";
|
||||
|
||||
|
||||
return cfi;
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.EpubCFI.prototype.generateFragment = function(element, chapter) {
|
||||
var path = this.pathTo(element),
|
||||
parts = [];
|
||||
|
||||
if(chapter) parts.push(chapter);
|
||||
|
||||
path.forEach(function(part){
|
||||
parts.push((part.index + 1) * 2);
|
||||
|
||||
if(part.id &&
|
||||
part.id.slice(0, 7) != "@EPUBJS") { //-- ignore internal @EPUBJS ids
|
||||
|
||||
parts.push("[" + part.id + "]");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return parts.join('/');
|
||||
}
|
||||
|
||||
EPUBJS.EpubCFI.prototype.pathTo = function(node) {
|
||||
var stack = [],
|
||||
children;
|
||||
|
||||
while(node && node.parentNode !== null) {
|
||||
children = node.parentNode.children;
|
||||
|
||||
stack.unshift({
|
||||
'id' : node.id,
|
||||
// 'classList' : node.classList,
|
||||
'tagName' : node.tagName,
|
||||
'index' : children ? Array.prototype.indexOf.call(children, node) : 0
|
||||
});
|
||||
|
||||
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
EPUBJS.EpubCFI.prototype.getChapter = function(cfiStr) {
|
||||
|
||||
var splitStr = cfiStr.split("!");
|
||||
|
||||
return splitStr[0];
|
||||
}
|
||||
|
||||
EPUBJS.EpubCFI.prototype.getFragment = function(cfiStr) {
|
||||
|
||||
var splitStr = cfiStr.split("!");
|
||||
|
||||
return splitStr[1];
|
||||
}
|
||||
|
||||
EPUBJS.EpubCFI.prototype.getOffset = function(cfiStr) {
|
||||
|
||||
var splitStr = cfiStr.split(":");
|
||||
|
||||
return [splitStr[0], splitStr[1]];
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
|
||||
var cfi = {},
|
||||
chapId,
|
||||
path,
|
||||
end,
|
||||
text;
|
||||
|
||||
cfi.chapter = this.getChapter(cfiStr);
|
||||
|
||||
cfi.fragment = this.getFragment(cfiStr);
|
||||
|
||||
cfi.spinePos = (parseInt(cfi.chapter.split("/")[2]) / 2 - 1 ) || false;
|
||||
|
||||
chapId = cfi.chapter.match(/\[(.*)\]/);
|
||||
|
||||
cfi.spineId = chapId[1] || false;
|
||||
|
||||
path = cfi.fragment.split('/');
|
||||
end = path[path.length-1];
|
||||
cfi.sections = [];
|
||||
|
||||
//-- Check for Character Offset
|
||||
if(parseInt(end) % 2){
|
||||
text = this.getOffset();
|
||||
cfi.text = parseInt(text[0]);
|
||||
cfi.character = parseInt(text[1]);
|
||||
path.pop(); //-- remove from path to element
|
||||
}
|
||||
|
||||
path.forEach(function(part){
|
||||
var index, has_id, id;
|
||||
|
||||
if(!part) return;
|
||||
|
||||
index = parseInt(part) / 2 - 1;
|
||||
has_id = part.match(/\[(.*)\]/);
|
||||
|
||||
|
||||
if(has_id && has_id[1]){
|
||||
id = has_id[1];
|
||||
}
|
||||
|
||||
cfi.sections.push({
|
||||
'index' : index,
|
||||
'id' : id || false
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return cfi;
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.EpubCFI.prototype.getElement = function(cfi, doc) {
|
||||
var doc = doc || document,
|
||||
sections = cfi.sections,
|
||||
element = doc.getElementsByTagName('html')[0],
|
||||
children = Array.prototype.slice.call(element.children),
|
||||
num, index, part,
|
||||
has_id, id;
|
||||
|
||||
sections.shift() //-- html
|
||||
|
||||
while(sections.length > 0) {
|
||||
|
||||
part = sections.shift();
|
||||
|
||||
if(part.id){
|
||||
element = cfi.doc.querySelector("#" + part.id);
|
||||
}else{
|
||||
|
||||
element = children[part.index];
|
||||
|
||||
if(!children) console.error("No Kids", element);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(!element) console.error("No Element For", part);
|
||||
children = Array.prototype.slice.call(element.children);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
//-- Todo: function to remove IDs to sort
|
229
src/parser.js
Normal file
229
src/parser.js
Normal file
|
@ -0,0 +1,229 @@
|
|||
EPUBJS.Parser = function(baseUrl){
|
||||
this.baseUrl = baseUrl || '';
|
||||
}
|
||||
|
||||
EPUBJS.Parser.prototype.container = function(containerXml){
|
||||
|
||||
//-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/>
|
||||
var rootfile = containerXml.querySelector("rootfile"),
|
||||
fullpath = rootfile.getAttribute('full-path'),
|
||||
folder = EPUBJS.core.folder(fullpath);
|
||||
|
||||
//-- Now that we have the path we can parse the contents
|
||||
return {
|
||||
'packagePath' : fullpath,
|
||||
'basePath' : folder
|
||||
};
|
||||
|
||||
// localStorage.setItem("basePath", that.basePath);
|
||||
// localStorage.setItem("contentsPath", that.contentsPath);
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Parser.prototype.package = function(packageXml, baseUrl){
|
||||
var parse = this;
|
||||
|
||||
if(baseUrl) this.baseUrl = baseUrl;
|
||||
|
||||
var metadataNode = packageXml.querySelector("metadata"),
|
||||
manifestNode = packageXml.querySelector("manifest"),
|
||||
spineNode = packageXml.querySelector("spine");
|
||||
|
||||
var manifest = parse.manifest(manifestNode),
|
||||
tocPath = parse.findTocPath(manifestNode),
|
||||
coverPath = parse.findCoverPath(manifestNode);
|
||||
|
||||
var spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);
|
||||
|
||||
var spine = parse.spine(spineNode, manifest);
|
||||
|
||||
var spineIndexByURL = {};
|
||||
spine.forEach(function(item){
|
||||
spineIndexByURL[item.href] = item.index;
|
||||
});
|
||||
|
||||
return {
|
||||
'metadata' : parse.metadata(metadataNode),
|
||||
'spine' : spine,
|
||||
'manifest' : manifest,
|
||||
'tocPath' : tocPath,
|
||||
'coverPath': coverPath,
|
||||
'spineNodeIndex' : spineNodeIndex,
|
||||
'spineIndexByURL' : spineIndexByURL
|
||||
};
|
||||
}
|
||||
|
||||
//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
|
||||
EPUBJS.Parser.prototype.findTocPath = function(manifestNode){
|
||||
var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
|
||||
return node.getAttribute('href');
|
||||
}
|
||||
|
||||
//-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
|
||||
EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){
|
||||
var node = manifestNode.querySelector("item[properties='cover-image']");
|
||||
return node.getAttribute('href');
|
||||
}
|
||||
|
||||
// EPUBJS.Parser.prototype.findCover = function(manifest){
|
||||
// var leng = manifest.length,
|
||||
// i = 0
|
||||
// tocPath = false;
|
||||
//
|
||||
// while(found == false & i < leng) {
|
||||
// if(manifest[i].type == "application/x-dtbncx+xml"){
|
||||
// tocPath = manifest[i].href;
|
||||
// found = true;
|
||||
// }
|
||||
// i++;
|
||||
// }
|
||||
//
|
||||
// return tocPath;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
EPUBJS.Parser.prototype.metadata = function(metadataXml){
|
||||
var metadata = {};
|
||||
|
||||
var title = metadataXml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/","title")[0]
|
||||
creator = metadataXml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/","creator")[0];
|
||||
|
||||
metadata["bookTitle"] = title ? title.childNodes[0].nodeValue : "";
|
||||
metadata["creator"] = creator ? creator.childNodes[0].nodeValue : "";
|
||||
|
||||
//-- TODO: add more meta data items, such as ISBN
|
||||
|
||||
// localStorage.setItem("metadata", JSON.stringify(this.metadata));
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
EPUBJS.Parser.prototype.manifest = function(manifestXml){
|
||||
var baseUrl = this.baseUrl,
|
||||
manifest = {};
|
||||
|
||||
//-- Turn items into an array
|
||||
var selected = manifestXml.querySelectorAll("item"),
|
||||
items = Array.prototype.slice.call(selected);
|
||||
|
||||
//-- Create an object with the id as key
|
||||
items.forEach(function(item){
|
||||
var id = item.getAttribute('id'),
|
||||
href = item.getAttribute('href') || '',
|
||||
type = item.getAttribute('media-type') || '';
|
||||
|
||||
manifest[id] = {
|
||||
'href' : baseUrl + href, //-- Absolute URL for loading with a web worker
|
||||
'type' : type
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
return manifest;
|
||||
|
||||
// localStorage.setItem("assets", JSON.stringify(this.assets));
|
||||
}
|
||||
|
||||
EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
|
||||
var spine = [];
|
||||
|
||||
var selected = spineXml.getElementsByTagName("itemref"),
|
||||
items = Array.prototype.slice.call(selected);
|
||||
|
||||
//-- Add to array to mantain ordering and cross reference with manifest
|
||||
items.forEach(function(item, index){
|
||||
var Id = item.getAttribute('idref');
|
||||
|
||||
var vert = {
|
||||
'id' : Id,
|
||||
'linear' : item.getAttribute('linear') || '',
|
||||
'properties' : item.getAttribute('properties') || '',
|
||||
'href' : manifest[Id].href,
|
||||
'index' : index
|
||||
}
|
||||
|
||||
|
||||
spine.push(vert);
|
||||
});
|
||||
// localStorage.setItem("spine", JSON.stringify(this.spine));
|
||||
// localStorage.setItem("spineIndexByURL", JSON.stringify(this.spineIndexByURL));
|
||||
|
||||
return spine;
|
||||
}
|
||||
|
||||
EPUBJS.Parser.prototype.toc = function(tocXml){
|
||||
var toc = [];
|
||||
|
||||
var navMap = tocXml.querySelector("navMap");
|
||||
//cover = contents.querySelector("meta[name='cover']"),
|
||||
//coverID;
|
||||
|
||||
//-- Add cover
|
||||
/*
|
||||
if(cover){
|
||||
coverID = cover.getAttribute("content");
|
||||
that.toc.push({
|
||||
"id": coverID,
|
||||
"href": that.assets[coverID],
|
||||
"label": coverID
|
||||
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
function getTOC(nodes, parent, list){
|
||||
var list = list || [];
|
||||
|
||||
items = Array.prototype.slice.call(nodes);
|
||||
|
||||
items.forEach(function(item){
|
||||
var id = item.getAttribute('id'),
|
||||
content = item.querySelector("content"),
|
||||
src = content.getAttribute('src'),
|
||||
split = src.split("#"),
|
||||
navLabel = item.querySelector("navLabel"),
|
||||
text = navLabel.textContent ? navLabel.textContent : "",
|
||||
subitems = item.querySelectorAll("navPoint");
|
||||
// subs = false,
|
||||
// childof = (item.parentNode == parent);
|
||||
|
||||
//if(!childof) return; //-- Only get direct children, should xpath for this eventually?
|
||||
|
||||
|
||||
// if(item.hasChildNodes()){
|
||||
// subs = getTOC(subitems, item)
|
||||
// }
|
||||
|
||||
|
||||
list.push({
|
||||
"id": id,
|
||||
"href": src,
|
||||
"label": text,
|
||||
"subitems" : subitems.length ? getTOC(item.querySelectorAll("navPoint"), item, list) : false
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
return getTOC(navMap.querySelectorAll("navPoint"), navMap);
|
||||
|
||||
|
||||
// localStorage.setItem("toc", JSON.stringify(that.toc));
|
||||
|
||||
// that.tell("book:tocReady");
|
||||
/*
|
||||
<navPoint class="chapter" id="xtitlepage" playOrder="1">
|
||||
<navLabel><text>Moby-Dick</text></navLabel>
|
||||
<content src="titlepage.xhtml"/>
|
||||
</navPoint>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
566
src/renderer.js
Normal file
566
src/renderer.js
Normal file
|
@ -0,0 +1,566 @@
|
|||
EPUBJS.Renderer = function(book) {
|
||||
var elem = book.settings.element;
|
||||
this.book = book;
|
||||
|
||||
this.settings = book.settings;
|
||||
|
||||
//-- Takes a string or a element
|
||||
if(_.isElement(elem)) {
|
||||
this.el = elem;
|
||||
} else if (typeof elem == "string") {
|
||||
this.el = EPUBJS.core.getEl(elem);
|
||||
} else {
|
||||
console.error("Not an Element");
|
||||
return;
|
||||
}
|
||||
|
||||
book.registerHook("beforeChapterDisplay",
|
||||
[this.replaceLinks.bind(this), this.replaceResources.bind(this)]);
|
||||
|
||||
|
||||
this.crossBrowserColumnCss();
|
||||
|
||||
this.epubcfi = new EPUBJS.EpubCFI();
|
||||
|
||||
this.initialize();
|
||||
this.listeners();
|
||||
}
|
||||
|
||||
//-- Build up any html needed
|
||||
EPUBJS.Renderer.prototype.initialize = function(){
|
||||
this.iframe = document.createElement('iframe');
|
||||
//this.iframe.id = "epubjs-iframe";
|
||||
this.resizeIframe(false, this.el.clientWidth, this.el.clientHeight);
|
||||
|
||||
this.on("book:resized", this.resizeIframe, this);
|
||||
|
||||
this.el.appendChild(this.iframe);
|
||||
|
||||
}
|
||||
|
||||
//-- Listeners for browser events
|
||||
EPUBJS.Renderer.prototype.listeners = function(){
|
||||
this.resized = _.debounce(this.onResized.bind(this), 10);
|
||||
|
||||
window.addEventListener("resize", this.resized, false);
|
||||
|
||||
// window.addEventListener("hashchange", book.route.bind(this), false);
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.chapter = function(chapter){
|
||||
var renderer = this,
|
||||
store = this.settings.stored ? this.store : false;
|
||||
|
||||
this.currentChapter = chapter;
|
||||
this.chapterPos = 1;
|
||||
this.pageIds = {};
|
||||
this.leftPos = 0;
|
||||
|
||||
this.currentChapterCfi = this.epubcfi.generateChapter(this.book.spineNodeIndex, chapter.spinePos, chapter.id);
|
||||
this.visibileEl = false;
|
||||
|
||||
return chapter.url(store).
|
||||
then(function(url) {
|
||||
return renderer.setIframeSrc(url);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
EPUBJS.Renderer.prototype.route = function(hash, callback){
|
||||
var location = window.location.hash.replace('#/', '');
|
||||
if(this.useHash && location.length && location != this.prevLocation){
|
||||
this.show(location, callback);
|
||||
this.prevLocation = location;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.hideHashChanges = function(){
|
||||
this.useHash = false;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
EPUBJS.Renderer.prototype.onResized = function(){
|
||||
|
||||
this.trigger("book:resized", {
|
||||
width: this.el.clientWidth,
|
||||
height: this.el.clientHeight
|
||||
});
|
||||
|
||||
this.reformat();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.reformat = function(){
|
||||
var renderer = this;
|
||||
|
||||
//-- reformat
|
||||
this.formatSpread();
|
||||
|
||||
setTimeout(function(){
|
||||
|
||||
//-- re-calc number of pages
|
||||
renderer.calcPages();
|
||||
|
||||
|
||||
//-- Go to current page after resize
|
||||
if(renderer.currentLocationCfi){
|
||||
renderer.gotoCfiFragment(renderer.currentLocationCfi);
|
||||
}
|
||||
|
||||
}, 10);
|
||||
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.destroy = function(){
|
||||
window.removeEventListener("resize", this.resized, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.resizeIframe = function(e, cWidth, cHeight){
|
||||
var width, height;
|
||||
|
||||
//-- Can be resized by the window resize event, or by passed height
|
||||
if(!e){
|
||||
width = cWidth;
|
||||
height = cHeight;
|
||||
}else{
|
||||
width = e.width;
|
||||
height = e.height;
|
||||
}
|
||||
|
||||
this.iframe.height = height;
|
||||
|
||||
if(width % 2 != 0){
|
||||
width += 1; //-- Prevent cutting off edges of text in columns
|
||||
}
|
||||
|
||||
this.iframe.width = width;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.crossBrowserColumnCss = function(){
|
||||
|
||||
|
||||
EPUBJS.Renderer.columnAxis = EPUBJS.core.prefixed('columnAxis') || 'columnAxis';
|
||||
EPUBJS.Renderer.columnGap = EPUBJS.core.prefixed('columnGap') || 'columnGap';
|
||||
EPUBJS.Renderer.columnWidth = EPUBJS.core.prefixed('columnWidth') || 'columnWidth';
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.setIframeSrc = function(url){
|
||||
var renderer = this,
|
||||
promise = new RSVP.Promise();
|
||||
|
||||
this.visible(false);
|
||||
|
||||
this.iframe.src = url;
|
||||
|
||||
|
||||
this.iframe.onload = function() {
|
||||
renderer.doc = renderer.iframe.contentDocument;
|
||||
renderer.docEl = renderer.doc.documentElement;
|
||||
renderer.bodyEl = renderer.doc.body;
|
||||
|
||||
renderer.formatSpread();
|
||||
|
||||
//-- Trigger registered hooks before displaying
|
||||
renderer.beforeDisplay(function(){
|
||||
|
||||
renderer.calcPages();
|
||||
|
||||
renderer.currentLocationCfi = renderer.getPageCfi();
|
||||
|
||||
renderer.trigger("book:chapterDisplayed");
|
||||
|
||||
renderer.visible(true);
|
||||
|
||||
});
|
||||
|
||||
promise.resolve(renderer);
|
||||
// that.afterLoaded(that);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.formatSpread = function(){
|
||||
|
||||
var divisor = 2,
|
||||
cutoff = 800;
|
||||
|
||||
if(this.colWidth){
|
||||
this.OldcolWidth = this.colWidth;
|
||||
this.OldspreadWidth = this.spreadWidth;
|
||||
}
|
||||
|
||||
//-- Check the width and decied on columns
|
||||
//-- Todo: a better place for this?
|
||||
this.elWidth = this.iframe.width;
|
||||
|
||||
this.gap = this.gap || Math.ceil(this.elWidth / 8);
|
||||
|
||||
if(this.elWidth < cutoff || this.settings.single) {
|
||||
this.spread = false; //-- Single Page
|
||||
|
||||
divisor = 1;
|
||||
this.colWidth = Math.floor(this.elWidth / divisor);
|
||||
}else{
|
||||
this.spread = true; //-- Double Page
|
||||
|
||||
this.colWidth = Math.floor((this.elWidth - this.gap) / divisor);
|
||||
|
||||
/* - Was causing jumps, doesn't seem to be needed anymore
|
||||
//-- Must be even for firefox
|
||||
if(this.colWidth % 2 != 0){
|
||||
this.colWidth -= 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
this.spreadWidth = (this.colWidth + this.gap) * divisor;
|
||||
|
||||
// this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
|
||||
|
||||
//-- Clear Margins
|
||||
// this.bodyEl.style.margin = "0";
|
||||
|
||||
this.docEl.style.overflow = "hidden";
|
||||
|
||||
this.docEl.style.width = this.elWidth;
|
||||
|
||||
//-- Adjust height
|
||||
this.docEl.style.height = this.el.clientHeight + "px";
|
||||
|
||||
//-- Add columns
|
||||
this.docEl.style[EPUBJS.Renderer.columnAxis] = "horizontal";
|
||||
this.docEl.style[EPUBJS.Renderer.columnGap] = this.gap+"px";
|
||||
this.docEl.style[EPUBJS.Renderer.columnWidth] = this.colWidth+"px";
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.fixedLayout = function(){
|
||||
this.paginated = false;
|
||||
|
||||
this.setLeft(0);
|
||||
|
||||
this.docEl.style.width = this.elWidth;
|
||||
|
||||
//-- Adjust height
|
||||
this.docEl.style.height = "auto";
|
||||
|
||||
//-- Remove columns
|
||||
this.docEl.style[EPUBJS.core.columnWidth] = "auto";
|
||||
|
||||
//-- Scroll
|
||||
this.docEl.style.overflow = "auto";
|
||||
|
||||
this.displayedPages = 1;
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.gotoChapterEnd = function(){
|
||||
this.chapterEnd();
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.visible = function(bool){
|
||||
if(typeof(bool) == "undefined") {
|
||||
return this.iframe.style.visibility;
|
||||
}
|
||||
|
||||
if(bool == true){
|
||||
this.iframe.style.visibility = "visible";
|
||||
}else if(bool == false){
|
||||
this.iframe.style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.calcPages = function() {
|
||||
|
||||
this.totalWidth = this.docEl.scrollWidth;
|
||||
|
||||
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
||||
|
||||
this.currentChapter.pages = this.displayedPages;
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.nextPage = function(){
|
||||
if(this.chapterPos < this.displayedPages){
|
||||
this.chapterPos++;
|
||||
|
||||
this.leftPos += this.spreadWidth;
|
||||
|
||||
this.setLeft(this.leftPos);
|
||||
|
||||
this.currentLocationCfi = this.getPageCfi();
|
||||
|
||||
this.trigger("book:pageChanged", this.currentLocationCfi);
|
||||
|
||||
|
||||
return this.chapterPos;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.prevPage = function(){
|
||||
if(this.chapterPos > 1){
|
||||
this.chapterPos--;
|
||||
|
||||
this.leftPos -= this.spreadWidth;
|
||||
|
||||
this.setLeft(this.leftPos);
|
||||
|
||||
this.currentLocationCfi = this.getPageCfi();
|
||||
|
||||
this.trigger("book:pageChanged", this.currentLocationCfi);
|
||||
|
||||
return this.chapterPos;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.chapterEnd = function(){
|
||||
this.page(this.displayedPages);
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.setLeft = function(leftPos){
|
||||
// this.bodyEl.style.marginLeft = -leftPos + "px";
|
||||
this.doc.defaultView.scrollTo(leftPos, 0)
|
||||
}
|
||||
|
||||
//-- Replaces the relative links within the book to use our internal page changer
|
||||
EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
||||
var hrefs = this.doc.querySelectorAll('[href]'),
|
||||
links = Array.prototype.slice.call(hrefs),
|
||||
that = this;
|
||||
|
||||
links.forEach(function(link){
|
||||
var path,
|
||||
href = link.getAttribute("href"),
|
||||
relative = href.search("://"),
|
||||
fragment = href[0] == "#";
|
||||
|
||||
if(relative != -1){
|
||||
|
||||
link.setAttribute("target", "_blank");
|
||||
|
||||
}else{
|
||||
|
||||
link.onclick = function(){
|
||||
that.book.goto(href);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
if(callback) callback();
|
||||
}
|
||||
|
||||
//-- Replaces assets src's to point to stored version if browser is offline
|
||||
EPUBJS.Renderer.prototype.replaceResources = function(callback){
|
||||
var srcs, resources, count;
|
||||
|
||||
//-- No need to replace if there is network connectivity
|
||||
//-- also Filesystem api links are relative, so no need to replace them
|
||||
if((this.book.online && !this.book.contained) || EPUBJS.storage.getStorageType() == "filesystem") {
|
||||
if(callback) callback();
|
||||
return false;
|
||||
}
|
||||
|
||||
srcs = this.doc.querySelectorAll('[src]');
|
||||
resources = Array.prototype.slice.call(srcs);
|
||||
count = resources.length;
|
||||
|
||||
resources.forEach(function(link){
|
||||
var src = link.getAttribute("src"),
|
||||
full = this.book.basePath + src;
|
||||
|
||||
EPUBJS.storage.get(full, function(url){
|
||||
link.setAttribute("src", url);
|
||||
count--;
|
||||
if(count <= 0 && callback) callback();
|
||||
});
|
||||
|
||||
}.bind(this));
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.page = function(pg){
|
||||
if(pg >= 1 && pg <= this.displayedPages){
|
||||
this.chapterPos = pg;
|
||||
this.leftPos = this.spreadWidth * (pg-1); //-- pages start at 1
|
||||
this.setLeft(this.leftPos);
|
||||
|
||||
// localStorage.setItem("chapterPos", pg);
|
||||
return true;
|
||||
}
|
||||
console.log("false", pg, this.displayedPages)
|
||||
//-- Return false if page is greater than the total
|
||||
return false;
|
||||
}
|
||||
|
||||
//-- Find a section by fragement id
|
||||
EPUBJS.Renderer.prototype.section = function(fragment){
|
||||
var el = this.doc.getElementById(fragment),
|
||||
left, pg;
|
||||
|
||||
if(el){
|
||||
this.pageByElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-- Show the page containing an Element
|
||||
EPUBJS.Renderer.prototype.pageByElement = function(el){
|
||||
var left, pg;
|
||||
if(!el) return;
|
||||
|
||||
left = this.leftPos + el.getBoundingClientRect().left, //-- Calculate left offset compaired to scrolled position
|
||||
pg = Math.floor(left / this.spreadWidth) + 1; //-- pages start at 1
|
||||
this.page(pg);
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.beforeDisplay = function(callback){
|
||||
this.book.triggerHooks("beforeChapterDisplay", callback.bind(this), this);
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.walk = function(node) {
|
||||
var r,
|
||||
node, children, leng,
|
||||
startNode = node,
|
||||
prevNode,
|
||||
stack = [startNode];
|
||||
|
||||
var STOP = 10000, ITER=0;
|
||||
|
||||
while(!r && stack.length) {
|
||||
|
||||
node = stack.shift();
|
||||
|
||||
if( this.isElementVisible(node) ) {
|
||||
|
||||
r = node;
|
||||
|
||||
}
|
||||
|
||||
if(!r && node && node.childElementCount > 0){
|
||||
|
||||
children = node.children;
|
||||
leng = children.length;
|
||||
|
||||
|
||||
for (var i = 0; i < leng; i++) {
|
||||
if(children[i] != prevNode) stack.push(children[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(!r && stack.length == 0 && startNode && startNode.parentNode !== null){
|
||||
|
||||
stack.push(startNode.parentNode);
|
||||
prevNode = startNode;
|
||||
startNode = startNode.parentNode;
|
||||
}
|
||||
|
||||
|
||||
ITER++;
|
||||
if(ITER > STOP) {
|
||||
console.error("ENDLESS LOOP");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
EPUBJS.Renderer.prototype.getPageCfi = function(){
|
||||
var prevEl = this.visibileEl;
|
||||
this.visibileEl = this.findFirstVisible(prevEl);
|
||||
|
||||
if(!this.visibileEl.id) {
|
||||
this.visibileEl.id = "@EPUBJS-PAGE-" + this.chapterPos;
|
||||
}
|
||||
|
||||
this.pageIds[this.chapterPos] = this.visibileEl.id;
|
||||
|
||||
|
||||
return this.epubcfi.generateFragment(this.visibileEl, this.currentChapterCfi);
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.gotoCfiFragment = function(cfi){
|
||||
var element;
|
||||
|
||||
if(_.isString(cfi)){
|
||||
cfi = this.epubcfi.parse(cfi);
|
||||
}
|
||||
|
||||
element = this.epubcfi.getElement(cfi, this.doc);
|
||||
|
||||
this.pageByElement(element);
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
|
||||
var el = startEl || this.bodyEl,
|
||||
found;
|
||||
|
||||
found = this.walk(el);
|
||||
|
||||
if(found) {
|
||||
return found;
|
||||
}else{
|
||||
return startEl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EPUBJS.Renderer.prototype.isElementVisible = function(el){
|
||||
var left;
|
||||
|
||||
if(el){
|
||||
left = el.getBoundingClientRect().left;
|
||||
|
||||
if( left >= 0 &&
|
||||
left < this.spreadWidth ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-- Enable binding events to parser
|
||||
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
|
Loading…
Add table
Add a link
Reference in a new issue