mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
split rendering up into renderer, render, layout
This commit is contained in:
parent
a5d970bca2
commit
0398b5eedf
22 changed files with 1149 additions and 840 deletions
|
@ -56,6 +56,8 @@
|
||||||
<script src="../src/renderer.js"></script>
|
<script src="../src/renderer.js"></script>
|
||||||
<script src="../src/replace.js"></script>
|
<script src="../src/replace.js"></script>
|
||||||
<script src="../src/epubcfi.js"></script>
|
<script src="../src/epubcfi.js"></script>
|
||||||
|
<script src="../src/render_iframe.js"></script>
|
||||||
|
<script src="../src/layout.js"></script>
|
||||||
|
|
||||||
<!-- Hooks -->
|
<!-- Hooks -->
|
||||||
<script async src="../hooks/default/transculsions.js"></script>
|
<script async src="../hooks/default/transculsions.js"></script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chapter){
|
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, renderer){
|
||||||
|
|
||||||
var notes = chapter.doc.querySelectorAll('a[href]'),
|
var notes = renderer.contents.querySelectorAll('a[href]'),
|
||||||
items = Array.prototype.slice.call(notes), //[].slice.call()
|
items = Array.prototype.slice.call(notes), //[].slice.call()
|
||||||
attr = "epub:type",
|
attr = "epub:type",
|
||||||
type = "noteref",
|
type = "noteref",
|
||||||
|
@ -8,7 +8,7 @@ EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chap
|
||||||
cssPath = folder + EPUBJS.cssPath || folder,
|
cssPath = folder + EPUBJS.cssPath || folder,
|
||||||
popups = {};
|
popups = {};
|
||||||
|
|
||||||
EPUBJS.core.addCss(cssPath + "popup.css", false, chapter.doc.head);
|
EPUBJS.core.addCss(cssPath + "popup.css", false, renderer.render.document.head);
|
||||||
|
|
||||||
|
|
||||||
items.forEach(function(item){
|
items.forEach(function(item){
|
||||||
|
@ -26,7 +26,7 @@ EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chap
|
||||||
|
|
||||||
href = item.getAttribute("href");
|
href = item.getAttribute("href");
|
||||||
id = href.replace("#", '');
|
id = href.replace("#", '');
|
||||||
el = chapter.doc.getElementById(id);
|
el = renderer.render.document.getElementById(id);
|
||||||
|
|
||||||
|
|
||||||
item.addEventListener("mouseover", showPop, false);
|
item.addEventListener("mouseover", showPop, false);
|
||||||
|
@ -34,8 +34,8 @@ EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chap
|
||||||
|
|
||||||
function showPop(){
|
function showPop(){
|
||||||
var poppos,
|
var poppos,
|
||||||
iheight = chapter.iframe.height,
|
iheight = renderer.height,
|
||||||
iwidth = chapter.iframe.width,
|
iwidth = renderer.width,
|
||||||
tip,
|
tip,
|
||||||
pop,
|
pop,
|
||||||
maxHeight = 225;
|
maxHeight = 225;
|
||||||
|
@ -45,7 +45,7 @@ EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chap
|
||||||
txt = pop.querySelector("p");
|
txt = pop.querySelector("p");
|
||||||
}
|
}
|
||||||
|
|
||||||
chapter.replaceLinks.bind(this)
|
// chapter.replaceLinks.bind(this) //TODO:Fred - update?
|
||||||
//-- create a popup with endnote inside of it
|
//-- create a popup with endnote inside of it
|
||||||
if(!popups[id]) {
|
if(!popups[id]) {
|
||||||
popups[id] = document.createElement("div");
|
popups[id] = document.createElement("div");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
EPUBJS.Hooks.register("beforeChapterDisplay").mathml = function(callback, renderer){
|
EPUBJS.Hooks.register("beforeChapterDisplay").mathml = function(callback, renderer){
|
||||||
|
|
||||||
// check of currentChapter properties contains 'mathml'
|
// check of currentChapter properties contains 'mathml'
|
||||||
if(renderer.currentChapter.properties.indexOf("mathml") !== -1 ){
|
if(renderer.currentChapter.manifestProperties.indexOf("mathml") !== -1 ){
|
||||||
|
|
||||||
// Assign callback to be inside iframe window
|
// Assign callback to be inside iframe window
|
||||||
renderer.iframe.contentWindow.mathmlCallback = callback;
|
renderer.iframe.contentWindow.mathmlCallback = callback;
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, chapter){
|
EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, renderer){
|
||||||
var images = chapter.doc.querySelectorAll('img'),
|
var images = renderer.contents.querySelectorAll('img'),
|
||||||
items = Array.prototype.slice.call(images),
|
items = Array.prototype.slice.call(images),
|
||||||
iheight = chapter.bodyEl.clientHeight,//chapter.doc.body.getBoundingClientRect().height,
|
iheight = renderer.height,//chapter.bodyEl.clientHeight,//chapter.doc.body.getBoundingClientRect().height,
|
||||||
oheight;
|
oheight;
|
||||||
|
|
||||||
|
if(renderer.settings.layout != "reflowable") {
|
||||||
|
callback();
|
||||||
|
return; //-- Only adjust images for reflowable text
|
||||||
|
}
|
||||||
|
|
||||||
items.forEach(function(item){
|
items.forEach(function(item){
|
||||||
|
|
||||||
function size() {
|
function size() {
|
||||||
|
@ -14,7 +19,7 @@ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, c
|
||||||
height = oHeight || rectHeight,
|
height = oHeight || rectHeight,
|
||||||
newHeight;
|
newHeight;
|
||||||
|
|
||||||
iheight = chapter.docEl.clientHeight;
|
iheight = renderer.contents.clientHeight;
|
||||||
if(top < 0) top = 0;
|
if(top < 0) top = 0;
|
||||||
|
|
||||||
if(height + top >= iheight) {
|
if(height + top >= iheight) {
|
||||||
|
@ -28,7 +33,6 @@ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, c
|
||||||
item.style.maxHeight = newHeight + "px";
|
item.style.maxHeight = newHeight + "px";
|
||||||
item.style.marginTop = iheight - top + "px";
|
item.style.marginTop = iheight - top + "px";
|
||||||
item.style.width= "auto";
|
item.style.width= "auto";
|
||||||
console.log(newHeight)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item.setAttribute('data-height', newHeight);
|
item.setAttribute('data-height', newHeight);
|
||||||
|
@ -41,11 +45,11 @@ EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, c
|
||||||
|
|
||||||
item.addEventListener('load', size, false);
|
item.addEventListener('load', size, false);
|
||||||
|
|
||||||
chapter.on("renderer:resized", size);
|
renderer.on("renderer:resized", size);
|
||||||
|
|
||||||
chapter.on("renderer:chapterUnloaded", function(){
|
renderer.on("renderer:chapterUnloaded", function(){
|
||||||
item.removeEventListener('load', size);
|
item.removeEventListener('load', size);
|
||||||
chapter.off("renderer:resized", size);
|
renderer.off("renderer:resized", size);
|
||||||
});
|
});
|
||||||
|
|
||||||
size();
|
size();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
EPUBJS.Hooks.register("beforeChapterDisplay").transculsions = function(callback, chapter){
|
EPUBJS.Hooks.register("beforeChapterDisplay").transculsions = function(callback, renderer){
|
||||||
/*
|
/*
|
||||||
<aside ref="http://www.youtube.com/embed/DUL6MBVKVLI?html5=1" transclusion="video" width="560" height="315">
|
<aside ref="http://www.youtube.com/embed/DUL6MBVKVLI?html5=1" transclusion="video" width="560" height="315">
|
||||||
<a href="http://www.youtube.com/embed/DUL6MBVKVLI"> Watch the National Geographic: The Last Roll of Kodachrome</a>
|
<a href="http://www.youtube.com/embed/DUL6MBVKVLI"> Watch the National Geographic: The Last Roll of Kodachrome</a>
|
||||||
</aside>
|
</aside>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var trans = chapter.doc.querySelectorAll('[transclusion]'),
|
var trans = renderer.contents.querySelectorAll('[transclusion]'),
|
||||||
items = Array.prototype.slice.call(trans);
|
items = Array.prototype.slice.call(trans);
|
||||||
|
|
||||||
items.forEach(function(item){
|
items.forEach(function(item){
|
||||||
var src = item.getAttribute("ref"),
|
var src = item.getAttribute("ref"),
|
||||||
|
|
|
@ -5,7 +5,7 @@ EPUBJS.Hooks.register("beforeChapterDisplay").highlight = function(callback, ren
|
||||||
var s = document.createElement("style");
|
var s = document.createElement("style");
|
||||||
s.innerHTML =".highlight { background: yellow; font-weight: normal; }";
|
s.innerHTML =".highlight { background: yellow; font-weight: normal; }";
|
||||||
|
|
||||||
renderer.doc.head.appendChild(s);
|
renderer.render.document.head.appendChild(s);
|
||||||
|
|
||||||
if(callback) callback();
|
if(callback) callback();
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@ EPUBJS.reader.ControlsController = function(book) {
|
||||||
book.on('renderer:pageChanged', function(cfi){
|
book.on('renderer:pageChanged', function(cfi){
|
||||||
//-- Check if bookmarked
|
//-- Check if bookmarked
|
||||||
var bookmarked = reader.isBookmarked(cfi);
|
var bookmarked = reader.isBookmarked(cfi);
|
||||||
|
|
||||||
if(bookmarked === -1) { //-- Not bookmarked
|
if(bookmarked === -1) { //-- Not bookmarked
|
||||||
$bookmark
|
$bookmark
|
||||||
.removeClass("icon-bookmark")
|
.removeClass("icon-bookmark")
|
||||||
|
|
|
@ -30,9 +30,9 @@ EPUBJS.reader.ReaderController = function(book) {
|
||||||
$loader.hide();
|
$loader.hide();
|
||||||
|
|
||||||
//-- If the book is using spreads, show the divider
|
//-- If the book is using spreads, show the divider
|
||||||
if(book.settings.spreads) {
|
// if(book.settings.spreads) {
|
||||||
showDivider();
|
// showDivider();
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
var showDivider = function() {
|
var showDivider = function() {
|
||||||
|
@ -84,8 +84,8 @@ EPUBJS.reader.ReaderController = function(book) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
book.on("book:spreads", function(){
|
book.on("renderer:spreads", function(bool){
|
||||||
if(book.settings.spreads) {
|
if(bool) {
|
||||||
showDivider();
|
showDivider();
|
||||||
} else {
|
} else {
|
||||||
hideDivider();
|
hideDivider();
|
||||||
|
|
|
@ -7,6 +7,8 @@ EPUBJS.plugins = EPUBJS.plugins || {};
|
||||||
|
|
||||||
EPUBJS.filePath = EPUBJS.filePath || "/epubjs/";
|
EPUBJS.filePath = EPUBJS.filePath || "/epubjs/";
|
||||||
|
|
||||||
|
EPUBJS.Render = {};
|
||||||
|
|
||||||
(function(root) {
|
(function(root) {
|
||||||
|
|
||||||
var previousEpub = root.ePub || {};
|
var previousEpub = root.ePub || {};
|
||||||
|
|
279
src/book.js
279
src/book.js
|
@ -13,9 +13,10 @@ EPUBJS.Book = function(options){
|
||||||
contained : false,
|
contained : false,
|
||||||
width : false,
|
width : false,
|
||||||
height: false,
|
height: false,
|
||||||
spreads: true,
|
spread: null,
|
||||||
fixedLayout : false,
|
layout : null,
|
||||||
responsive: true,
|
orientation : null,
|
||||||
|
minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)
|
||||||
version: 1,
|
version: 1,
|
||||||
restore: false,
|
restore: false,
|
||||||
reload : false,
|
reload : false,
|
||||||
|
@ -39,13 +40,9 @@ EPUBJS.Book = function(options){
|
||||||
book:pageChanged
|
book:pageChanged
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-- All hooks to add functions (with a callback) to
|
EPUBJS.Hooks.mixin(this);
|
||||||
this.hooks = {
|
|
||||||
"beforeChapterDisplay" : []
|
|
||||||
};
|
|
||||||
|
|
||||||
//-- Get pre-registered hooks
|
//-- Get pre-registered hooks
|
||||||
this.getHooks();
|
this.getHooks("beforeChapterDisplay");
|
||||||
|
|
||||||
this.online = this.settings.online || navigator.onLine;
|
this.online = this.settings.online || navigator.onLine;
|
||||||
this.networkListeners();
|
this.networkListeners();
|
||||||
|
@ -57,8 +54,6 @@ EPUBJS.Book = function(options){
|
||||||
this.storage = new fileStorage.storage(this.settings.storage);
|
this.storage = new fileStorage.storage(this.settings.storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.ready = {
|
this.ready = {
|
||||||
manifest: new RSVP.defer(),
|
manifest: new RSVP.defer(),
|
||||||
spine: new RSVP.defer(),
|
spine: new RSVP.defer(),
|
||||||
|
@ -83,6 +78,10 @@ EPUBJS.Book = function(options){
|
||||||
this.isRendered = false;
|
this.isRendered = false;
|
||||||
this._rendering = false;
|
this._rendering = false;
|
||||||
this._displayQ = [];
|
this._displayQ = [];
|
||||||
|
|
||||||
|
this.renderer = new EPUBJS.Renderer(this.settings.renderer, this.beforeDisplay.bind(this));
|
||||||
|
this.renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
|
||||||
|
this.listenToRenderer(this.renderer);
|
||||||
|
|
||||||
this.defer_opened = new RSVP.defer();
|
this.defer_opened = new RSVP.defer();
|
||||||
this.opened = this.defer_opened.promise;
|
this.opened = this.defer_opened.promise;
|
||||||
|
@ -154,6 +153,8 @@ EPUBJS.Book.prototype.open = function(bookPath, forceReload){
|
||||||
if(!this.settings.stored) opened.then(book.storeOffline());
|
if(!this.settings.stored) opened.then(book.storeOffline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._registerReplacements();
|
||||||
|
|
||||||
return opened.promise;
|
return opened.promise;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -201,7 +202,10 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
book.spineIndexByURL = book.contents.spineIndexByURL;
|
book.spineIndexByURL = book.contents.spineIndexByURL;
|
||||||
book.metadata = book.contents.metadata;
|
book.metadata = book.contents.metadata;
|
||||||
book.setBookKey(book.metadata.identifier);
|
book.setBookKey(book.metadata.identifier);
|
||||||
|
|
||||||
|
//-- Set Globbal Layout setting based on metadata
|
||||||
|
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
||||||
|
|
||||||
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
||||||
|
|
||||||
book.spineNodeIndex = book.contents.spineNodeIndex;
|
book.spineNodeIndex = book.contents.spineNodeIndex;
|
||||||
|
@ -211,7 +215,6 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
book.ready.metadata.resolve(book.contents.metadata);
|
book.ready.metadata.resolve(book.contents.metadata);
|
||||||
book.ready.cover.resolve(book.contents.cover);
|
book.ready.cover.resolve(book.contents.cover);
|
||||||
|
|
||||||
//-- TODO: Adjust setting based on metadata
|
|
||||||
|
|
||||||
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
||||||
if(book.contents.navPath) {
|
if(book.contents.navPath) {
|
||||||
|
@ -271,6 +274,21 @@ EPUBJS.Book.prototype.networkListeners = function(){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Book.prototype.listenToRenderer = function(renderer){
|
||||||
|
var book = this;
|
||||||
|
renderer.Events.forEach(function(eventName){
|
||||||
|
renderer.on(eventName, function(e){
|
||||||
|
book.trigger(eventName, e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Book.prototype.unlistenToRenderer = function(renderer){
|
||||||
|
renderer.Events.forEach(function(eventName){
|
||||||
|
renderer.off(eventName);
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
//-- Choose between a request from store or a request from network
|
//-- Choose between a request from store or a request from network
|
||||||
EPUBJS.Book.prototype.loadXml = function(url){
|
EPUBJS.Book.prototype.loadXml = function(url){
|
||||||
if(this.settings.fromStorage) {
|
if(this.settings.fromStorage) {
|
||||||
|
@ -335,11 +353,9 @@ EPUBJS.Book.prototype.unarchive = function(bookPath){
|
||||||
|
|
||||||
//-- Checks if url has a .epub or .zip extension
|
//-- Checks if url has a .epub or .zip extension
|
||||||
EPUBJS.Book.prototype.isContained = function(bookUrl){
|
EPUBJS.Book.prototype.isContained = function(bookUrl){
|
||||||
var uri = EPUBJS.core.uri(bookUrl),
|
var uri = EPUBJS.core.uri(bookUrl);
|
||||||
dot = uri.filename.lastIndexOf('.'),
|
|
||||||
ext = uri.filename.slice(dot+1);
|
|
||||||
|
|
||||||
if(ext && (ext == "epub" || ext == "zip")){
|
if(uri.extension && (uri.extension == "epub" || uri.extension == "zip")){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,10 +395,6 @@ EPUBJS.Book.prototype.removeSavedContents = function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// EPUBJS.Book.prototype.chapterTitle = function(){
|
|
||||||
// return this.spine[this.spinePos].id; //-- TODO: clarify that this is returning title
|
|
||||||
// }
|
|
||||||
|
|
||||||
//-- Takes a string or a element
|
//-- Takes a string or a element
|
||||||
EPUBJS.Book.prototype.renderTo = function(elem){
|
EPUBJS.Book.prototype.renderTo = function(elem){
|
||||||
var book = this,
|
var book = this,
|
||||||
|
@ -399,12 +411,13 @@ EPUBJS.Book.prototype.renderTo = function(elem){
|
||||||
|
|
||||||
rendered = this.opened.
|
rendered = this.opened.
|
||||||
then(function(){
|
then(function(){
|
||||||
book.render = new EPUBJS.Renderer(book);
|
// book.render = new EPUBJS.Renderer[this.settings.renderer](book);
|
||||||
|
book.renderer.initialize(book.element, book.settings.width, book.settings.height);
|
||||||
book._rendered();
|
book._rendered();
|
||||||
return book.startDisplay();
|
return book.startDisplay();
|
||||||
}, function(error) { console.error(error); });
|
});
|
||||||
|
|
||||||
rendered.then(null, function(error) { console.error(error); });
|
// rendered.then(null, function(error) { console.error(error); });
|
||||||
|
|
||||||
return rendered;
|
return rendered;
|
||||||
};
|
};
|
||||||
|
@ -413,17 +426,11 @@ EPUBJS.Book.prototype.startDisplay = function(){
|
||||||
var display;
|
var display;
|
||||||
|
|
||||||
if(this.settings.goto) {
|
if(this.settings.goto) {
|
||||||
|
|
||||||
display = this.goto(this.settings.goto);
|
display = this.goto(this.settings.goto);
|
||||||
|
|
||||||
}else if(this.settings.previousLocationCfi) {
|
}else if(this.settings.previousLocationCfi) {
|
||||||
|
display = this.gotoCfi(this.settings.previousLocationCfi);
|
||||||
display = this.displayChapter(this.settings.previousLocationCfi);
|
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
display = this.displayChapter(this.spinePos);
|
display = this.displayChapter(this.spinePos);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return display;
|
return display;
|
||||||
|
@ -469,12 +476,22 @@ EPUBJS.Book.prototype.restore = function(identifier){
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
EPUBJS.Book.prototype.determineStore = function(){
|
||||||
|
var store;
|
||||||
|
if(this.settings.stored){
|
||||||
|
store = this.storage;
|
||||||
|
} else if(this.settings.contained){
|
||||||
|
store = this.zip;
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
EPUBJS.Book.prototype.displayChapter = function(chap, end){
|
EPUBJS.Book.prototype.displayChapter = function(chap, end){
|
||||||
var book = this,
|
var book = this,
|
||||||
render,
|
render,
|
||||||
cfi,
|
cfi,
|
||||||
pos;
|
pos,
|
||||||
|
store;
|
||||||
|
|
||||||
if(!this.isRendered) return this._enqueue("displayChapter", arguments);
|
if(!this.isRendered) return this._enqueue("displayChapter", arguments);
|
||||||
|
|
||||||
|
@ -501,16 +518,16 @@ EPUBJS.Book.prototype.displayChapter = function(chap, end){
|
||||||
this.spinePos = pos;
|
this.spinePos = pos;
|
||||||
|
|
||||||
//-- Create a new chapter
|
//-- Create a new chapter
|
||||||
this.chapter = new EPUBJS.Chapter(this.spine[pos]);
|
this.currentChapter = new EPUBJS.Chapter(this.spine[pos], this.determineStore());
|
||||||
|
|
||||||
this._rendering = true;
|
this._rendering = true;
|
||||||
|
|
||||||
render = book.render.chapter(this.chapter);
|
render = book.renderer.displayChapter(this.currentChapter, this.globalLayoutProperties);
|
||||||
|
|
||||||
if(cfi) {
|
if(cfi) {
|
||||||
render.then(function(chapter){
|
render.then(function(chapter){
|
||||||
chapter.currentLocationCfi = chap;
|
// chapter.currentLocationCfi = chap;
|
||||||
chapter.gotoCfiFragment(cfi);
|
chapter.gotoCfi(cfi);
|
||||||
});
|
});
|
||||||
} else if(end) {
|
} else if(end) {
|
||||||
render.then(function(chapter){
|
render.then(function(chapter){
|
||||||
|
@ -532,7 +549,7 @@ EPUBJS.Book.prototype.displayChapter = function(chap, end){
|
||||||
|
|
||||||
book._rendering = false;
|
book._rendering = false;
|
||||||
if(book._displayQ.length) {
|
if(book._displayQ.length) {
|
||||||
inwait = book._displayQ.unshift();
|
inwait = book._displayQ.shift();
|
||||||
book.displayChapter.apply(book, inwait);
|
book.displayChapter.apply(book, inwait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,7 +562,7 @@ EPUBJS.Book.prototype.nextPage = function(){
|
||||||
|
|
||||||
if(!this.isRendered) return this._enqueue("nextPage", arguments);
|
if(!this.isRendered) return this._enqueue("nextPage", arguments);
|
||||||
|
|
||||||
next = this.render.nextPage();
|
next = this.renderer.nextPage();
|
||||||
|
|
||||||
if(!next){
|
if(!next){
|
||||||
return this.nextChapter();
|
return this.nextChapter();
|
||||||
|
@ -557,7 +574,7 @@ EPUBJS.Book.prototype.prevPage = function() {
|
||||||
|
|
||||||
if(!this.isRendered) return this._enqueue("prevPage", arguments);
|
if(!this.isRendered) return this._enqueue("prevPage", arguments);
|
||||||
|
|
||||||
prev = this.render.prevPage();
|
prev = this.renderer.prevPage();
|
||||||
|
|
||||||
if(!prev){
|
if(!prev){
|
||||||
return this.prevChapter();
|
return this.prevChapter();
|
||||||
|
@ -565,30 +582,60 @@ EPUBJS.Book.prototype.prevPage = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.nextChapter = function() {
|
EPUBJS.Book.prototype.nextChapter = function() {
|
||||||
if(this.spinePos > this.spine.length) return;
|
if(this.spinePos < this.spine.length - 1){
|
||||||
this.spinePos++;
|
this.spinePos += 1;
|
||||||
return this.displayChapter(this.spinePos);
|
return this.displayChapter(this.spinePos);
|
||||||
|
} else {
|
||||||
|
this.trigger("book:atEnd");
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.prevChapter = function() {
|
EPUBJS.Book.prototype.prevChapter = function() {
|
||||||
if(this.spinePos < 1) return;
|
if(this.spinePos > 0){
|
||||||
this.spinePos--;
|
this.spinePos -= 1;
|
||||||
return this.displayChapter(this.spinePos, true);
|
return this.displayChapter(this.spinePos, true);
|
||||||
|
} else {
|
||||||
|
this.trigger("book:atStart");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.getCurrentLocationCfi = function() {
|
EPUBJS.Book.prototype.getCurrentLocationCfi = function() {
|
||||||
if(!this.isRendered) return false;
|
if(!this.isRendered) return false;
|
||||||
return this.render.currentLocationCfi;
|
return this.renderer.currentLocationCfi;
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.gotoCfi = function(cfi){
|
EPUBJS.Book.prototype.gotoCfi = function(cfiString){
|
||||||
//if(!this.isRendered) return this._enqueue("gotoCfi", arguments);
|
var cfi = new EPUBJS.EpubCFI(cfiString);
|
||||||
|
var spinePos = cfi.spinePos;
|
||||||
|
var rendered;
|
||||||
|
var deferred = new RSVP.defer();
|
||||||
|
//if(!this.isRendered) return this._enqueue("gotoCfi", arguments);
|
||||||
if(!this.isRendered) {
|
if(!this.isRendered) {
|
||||||
this.settings.previousLocationCfi = cfi;
|
this.settings.previousLocationCfi = cfiString;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.displayChapter(cfi);
|
//-- If same chapter only stay on current chapter
|
||||||
|
if(this.currentChapter && this.spinePos === spinePos){
|
||||||
|
this.renderer.gotoCfi(cfi);
|
||||||
|
deferred.resolve(this.currentChapter);
|
||||||
|
return deferred.promise;
|
||||||
|
} else {
|
||||||
|
this.currentChapter = new EPUBJS.Chapter(this.spine[spinePos], this.determineStore());
|
||||||
|
|
||||||
|
if(this.currentChapter) {
|
||||||
|
this.spinePos = spinePos;
|
||||||
|
render = this.renderer.displayChapter(this.currentChapter, this.globalLayoutProperties);
|
||||||
|
|
||||||
|
render.then(function(rendered){
|
||||||
|
rendered.gotoCfi(cfi);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return render;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.goto = function(url){
|
EPUBJS.Book.prototype.goto = function(url){
|
||||||
|
@ -608,13 +655,13 @@ EPUBJS.Book.prototype.goto = function(url){
|
||||||
|
|
||||||
//-- If link fragment only stay on current chapter
|
//-- If link fragment only stay on current chapter
|
||||||
if(!chapter){
|
if(!chapter){
|
||||||
spinePos = this.chapter ? this.chapter.spinePos : 0;
|
spinePos = this.currentChapter ? this.currentChapter.spinePos : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-- Check that URL is present in the index, or stop
|
//-- Check that URL is present in the index, or stop
|
||||||
if(typeof(spinePos) != "number") return false;
|
if(typeof(spinePos) != "number") return false;
|
||||||
|
|
||||||
if(!this.chapter || spinePos != this.chapter.spinePos){
|
if(!this.currentChapter || spinePos != this.currentChapter.spinePos){
|
||||||
//-- Load new chapter if different than current
|
//-- Load new chapter if different than current
|
||||||
return this.displayChapter(spinePos).then(function(){
|
return this.displayChapter(spinePos).then(function(){
|
||||||
if(section) this.render.section(section);
|
if(section) this.render.section(section);
|
||||||
|
@ -688,14 +735,14 @@ EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
||||||
|
|
||||||
this.settings.styles[style] = val;
|
this.settings.styles[style] = val;
|
||||||
|
|
||||||
this.render.setStyle(style, val, prefixed);
|
this.renderer.setStyle(style, val, prefixed);
|
||||||
this.render.reformat();
|
this.renderer.reformat();
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.removeStyle = function(style) {
|
EPUBJS.Book.prototype.removeStyle = function(style) {
|
||||||
if(!this.isRendered) return this._enqueue("removeStyle", arguments);
|
if(!this.isRendered) return this._enqueue("removeStyle", arguments);
|
||||||
this.render.removeStyle(style);
|
this.renderer.removeStyle(style);
|
||||||
this.render.reformat();
|
this.renderer.reformat();
|
||||||
delete this.settings.styles[style];
|
delete this.settings.styles[style];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -705,11 +752,19 @@ EPUBJS.Book.prototype.addHeadTag = function(tag, attrs) {
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.useSpreads = function(use) {
|
EPUBJS.Book.prototype.useSpreads = function(use) {
|
||||||
if(!this.isRendered) return this._enqueue("useSpreads", arguments);
|
if(use) {
|
||||||
this.settings.spreads = use;
|
this.renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
|
||||||
this.render.reformat();
|
this.settings.spreads = true;
|
||||||
this.trigger("book:spreads", use);
|
} else {
|
||||||
};
|
this.renderer.setMinSpreadWidth(0);
|
||||||
|
this.settings.spreads = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.isRendered) {
|
||||||
|
this.renderer.reformat();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.unload = function(){
|
EPUBJS.Book.prototype.unload = function(){
|
||||||
|
|
||||||
|
@ -717,6 +772,8 @@ EPUBJS.Book.prototype.unload = function(){
|
||||||
this.saveContents();
|
this.saveContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.unlistenToRenderer(this.renderer);
|
||||||
|
|
||||||
this.trigger("book:unload");
|
this.trigger("book:unload");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -759,66 +816,64 @@ EPUBJS.Book.prototype._rendered = function(err) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-- Get pre-registered hooks
|
|
||||||
EPUBJS.Book.prototype.getHooks = function(){
|
|
||||||
var book = this,
|
|
||||||
plugs;
|
|
||||||
|
|
||||||
var plugTypes = _.values(this.hooks); //-- unused
|
|
||||||
|
|
||||||
for (var plugType in this.hooks) {
|
EPUBJS.Book.prototype.applyStyles = function(callback){
|
||||||
plugs = _.values(EPUBJS.Hooks[plugType]);
|
if(!this.isRendered) return this._enqueue("applyStyles", arguments);
|
||||||
|
this.renderer.applyStyles(this.settings.styles);
|
||||||
plugs.forEach(function(hook){
|
callback();
|
||||||
book.registerHook(plugType, hook);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-- Hooks allow for injecting async functions that must all complete before continuing
|
EPUBJS.Book.prototype._registerReplacements = function(){
|
||||||
// Functions must have a callback as their first argument.
|
this.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true);
|
||||||
EPUBJS.Book.prototype.registerHook = function(type, toAdd, toFront){
|
this.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs, true);
|
||||||
var book = this;
|
|
||||||
|
if(this._needsAssetReplacement()) {
|
||||||
if(typeof(this.hooks[type]) != "undefined"){
|
|
||||||
|
this.registerHook("beforeChapterDisplay", [
|
||||||
if(typeof(toAdd) === "function"){
|
EPUBJS.replace.head,
|
||||||
if(toFront) {
|
EPUBJS.replace.resources,
|
||||||
this.hooks[type].unshift(toAdd);
|
EPUBJS.replace.svg
|
||||||
}else{
|
], true);
|
||||||
this.hooks[type].push(toAdd);
|
|
||||||
}
|
}
|
||||||
}else if(Array.isArray(toAdd)){
|
|
||||||
toAdd.forEach(function(hook){
|
};
|
||||||
if(toFront) {
|
|
||||||
book.hooks[type].unshift(hook);
|
EPUBJS.Book.prototype._needsAssetReplacement = function(){
|
||||||
}else{
|
if(this.settings.fromStorage) {
|
||||||
book.hooks[type].push(hook);
|
|
||||||
}
|
//-- Filesystem api links are relative, so no need to replace them
|
||||||
});
|
if(this.storage.getStorageType() == "filesystem") {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
//-- Allows for undefined hooks, but maybe this should error?
|
return true;
|
||||||
this.hooks[type] = [func];
|
|
||||||
|
} else if(this.settings.contained) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Book.prototype.triggerHooks = function(type, callback, passed){
|
EPUBJS.Book.prototype.beforeDisplay = function(callback, renderer){
|
||||||
var hooks, count;
|
this.triggerHooks("beforeChapterDisplay", callback.bind(this), this.renderer);
|
||||||
|
};
|
||||||
|
|
||||||
if(typeof(this.hooks[type]) == "undefined") return false;
|
//-- http://www.idpf.org/epub/fxl/
|
||||||
|
EPUBJS.Book.prototype.parseLayoutProperties = function(metadata){
|
||||||
hooks = this.hooks[type];
|
var layout = this.settings.layout || metadata.layout || "reflowable";
|
||||||
|
var spread = this.settings.spread || metadata.spread || "auto";
|
||||||
count = hooks.length;
|
var orientation = this.settings.orientations || metadata.orientation || "auto";
|
||||||
function countdown(){
|
return {
|
||||||
count--;
|
layout : layout,
|
||||||
if(count <= 0 && callback) callback();
|
spread : spread,
|
||||||
|
orientation : orientation
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks.forEach(function(hook){
|
|
||||||
hook(countdown, passed);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-- Enable binding events to book
|
//-- Enable binding events to book
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
EPUBJS.Chapter = function(spineObject){
|
EPUBJS.Chapter = function(spineObject, store){
|
||||||
this.href = spineObject.href;
|
this.href = spineObject.href;
|
||||||
this.absolute = spineObject.url;
|
this.absolute = spineObject.url;
|
||||||
this.id = spineObject.id;
|
this.id = spineObject.id;
|
||||||
this.spinePos = spineObject.index;
|
this.spinePos = spineObject.index;
|
||||||
|
this.cfiBase = spineObject.cfiBase;
|
||||||
this.properties = spineObject.properties;
|
this.properties = spineObject.properties;
|
||||||
this.linear = spineObject.linear;
|
this.linear = spineObject.linear;
|
||||||
this.pages = 1;
|
this.pages = 1;
|
||||||
|
this.store = store;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Chapter.prototype.contents = function(store){
|
EPUBJS.Chapter.prototype.contents = function(_store){
|
||||||
|
var store = _store || this.store;
|
||||||
// if(this.store && (!this.book.online || this.book.contained))
|
// if(this.store && (!this.book.online || this.book.contained))
|
||||||
if(store){
|
if(store){
|
||||||
return store.get(href);
|
return store.get(href);
|
||||||
|
@ -19,9 +22,10 @@ EPUBJS.Chapter.prototype.contents = function(store){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Chapter.prototype.url = function(store){
|
EPUBJS.Chapter.prototype.url = function(_store){
|
||||||
var deferred = new RSVP.defer();
|
var deferred = new RSVP.defer();
|
||||||
|
var store = _store || this.store;
|
||||||
|
|
||||||
if(store){
|
if(store){
|
||||||
if(!this.tempUrl) {
|
if(!this.tempUrl) {
|
||||||
this.tempUrl = store.getUrl(this.absolute);
|
this.tempUrl = store.getUrl(this.absolute);
|
||||||
|
|
127
src/content.js
127
src/content.js
|
@ -1,127 +0,0 @@
|
||||||
EPUBJS.Renderer.prototype.replace = function(query, func, finished, progress){
|
|
||||||
var items = this.doc.querySelectorAll(query),
|
|
||||||
resources = Array.prototype.slice.call(items),
|
|
||||||
count = resources.length,
|
|
||||||
after = function(result, full){
|
|
||||||
count--;
|
|
||||||
if(progress) progress(result, full, count);
|
|
||||||
if(count <= 0 && finished) finished(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
if(count === 0) {
|
|
||||||
finished(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resources.forEach(function(item){
|
|
||||||
|
|
||||||
func(item, after);
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.replaceWithStored = function(query, attr, func, callback) {
|
|
||||||
var _oldUrls,
|
|
||||||
_newUrls = {},
|
|
||||||
_store = this.determineStore(),
|
|
||||||
_cache = this.caches[query],
|
|
||||||
_uri = EPUBJS.core.uri(this.book.chapter.absolute),
|
|
||||||
_chapterBase = _uri.base,
|
|
||||||
_attr = attr,
|
|
||||||
_wait = 2000,
|
|
||||||
progress = function(url, full, count) {
|
|
||||||
_newUrls[full] = url;
|
|
||||||
},
|
|
||||||
finished = function(notempty) {
|
|
||||||
if(callback) callback();
|
|
||||||
|
|
||||||
_.each(_oldUrls, function(url){
|
|
||||||
_store.revokeUrl(url);
|
|
||||||
});
|
|
||||||
|
|
||||||
_cache = _newUrls;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!_store) return;
|
|
||||||
|
|
||||||
if(!_cache) _cache = {};
|
|
||||||
_oldUrls = _.clone(_cache);
|
|
||||||
|
|
||||||
this.replace(query, function(link, done){
|
|
||||||
var src = link.getAttribute(_attr),
|
|
||||||
full = EPUBJS.core.resolveUrl(_chapterBase, src);
|
|
||||||
|
|
||||||
var replaceUrl = function(url) {
|
|
||||||
var timeout;
|
|
||||||
|
|
||||||
link.onload = function(){
|
|
||||||
clearTimeout(timeout);
|
|
||||||
done(url, full);
|
|
||||||
};
|
|
||||||
|
|
||||||
link.onerror = function(e){
|
|
||||||
clearTimeout(timeout);
|
|
||||||
done(url, full);
|
|
||||||
console.error(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
if(query == "image") {
|
|
||||||
//-- SVG needs this to trigger a load event
|
|
||||||
link.setAttribute("externalResourcesRequired", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(query == "link[href]") {
|
|
||||||
//-- Only Stylesheet links seem to have a load events, just continue others
|
|
||||||
done(url, full);
|
|
||||||
}
|
|
||||||
|
|
||||||
link.setAttribute(_attr, url);
|
|
||||||
|
|
||||||
//-- If elements never fire Load Event, should continue anyways
|
|
||||||
timeout = setTimeout(function(){
|
|
||||||
done(url, full);
|
|
||||||
}, _wait);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
if(full in _oldUrls){
|
|
||||||
replaceUrl(_oldUrls[full]);
|
|
||||||
_newUrls[full] = _oldUrls[full];
|
|
||||||
delete _oldUrls[full];
|
|
||||||
}else{
|
|
||||||
func(_store, full, replaceUrl, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, finished, progress);
|
|
||||||
};
|
|
||||||
|
|
||||||
//-- Replaces the relative links within the book to use our internal page changer
|
|
||||||
EPUBJS.Renderer.prototype.replaceLinks = function(callback){
|
|
||||||
|
|
||||||
var renderer = this;
|
|
||||||
|
|
||||||
this.replace("a[href]", function(link, done){
|
|
||||||
|
|
||||||
var href = link.getAttribute("href"),
|
|
||||||
relative = href.search("://"),
|
|
||||||
fragment = href[0] == "#";
|
|
||||||
|
|
||||||
if(relative != -1){
|
|
||||||
|
|
||||||
link.setAttribute("target", "_blank");
|
|
||||||
|
|
||||||
}else{
|
|
||||||
|
|
||||||
link.onclick = function(){
|
|
||||||
renderer.book.goto(href);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
done();
|
|
||||||
|
|
||||||
}, callback);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
15
src/core.js
15
src/core.js
|
@ -111,13 +111,21 @@ EPUBJS.core.uri = function(url){
|
||||||
directory : '',
|
directory : '',
|
||||||
base : '',
|
base : '',
|
||||||
filename : '',
|
filename : '',
|
||||||
|
extension : '',
|
||||||
href : url
|
href : url
|
||||||
},
|
},
|
||||||
doubleSlash = url.indexOf('://'),
|
doubleSlash = url.indexOf('://'),
|
||||||
search = url.indexOf('?'),
|
search = url.indexOf('?'),
|
||||||
|
fragment = url.indexOf("#"),
|
||||||
withoutProtocol,
|
withoutProtocol,
|
||||||
|
dot,
|
||||||
firstSlash;
|
firstSlash;
|
||||||
|
|
||||||
|
if(fragment != -1) {
|
||||||
|
uri.fragment = url.slice(fragment + 1);
|
||||||
|
url = url.slice(0, fragment);
|
||||||
|
}
|
||||||
|
|
||||||
if(search != -1) {
|
if(search != -1) {
|
||||||
uri.search = url.slice(search + 1);
|
uri.search = url.slice(search + 1);
|
||||||
url = url.slice(0, search);
|
url = url.slice(0, search);
|
||||||
|
@ -151,7 +159,10 @@ EPUBJS.core.uri = function(url){
|
||||||
|
|
||||||
//-- Filename
|
//-- Filename
|
||||||
uri.filename = url.replace(uri.base, '');
|
uri.filename = url.replace(uri.base, '');
|
||||||
|
dot = uri.filename.lastIndexOf('.');
|
||||||
|
if(dot != -1) {
|
||||||
|
uri.extension = uri.filename.slice(dot+1);
|
||||||
|
}
|
||||||
return uri;
|
return uri;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!element) console.error("No Element For", part);
|
if(!element) console.error("No Element For", part, cfi);
|
||||||
children = Array.prototype.slice.call(element.children);
|
children = Array.prototype.slice.call(element.children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
87
src/hooks.js
87
src/hooks.js
|
@ -1,11 +1,80 @@
|
||||||
|
EPUBJS.hooks = {};
|
||||||
EPUBJS.Hooks = (function(){
|
EPUBJS.Hooks = (function(){
|
||||||
|
function hooks(){};
|
||||||
"use strict";
|
|
||||||
return {
|
//-- Get pre-registered hooks
|
||||||
register: function(name) {
|
hooks.prototype.getHooks = function(){
|
||||||
if(this[name] === undefined) { this[name] = {}; }
|
var plugs;
|
||||||
if(typeof this[name] !== 'object') { throw "Already registered: "+name; }
|
this.hooks = {};
|
||||||
return this[name];
|
Array.prototype.slice.call(arguments).forEach(function(arg){
|
||||||
}
|
this.hooks[arg] = [];
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
for (var plugType in this.hooks) {
|
||||||
|
plugs = _.values(EPUBJS.hooks[plugType]);
|
||||||
|
|
||||||
|
plugs.forEach(function(hook){
|
||||||
|
this.registerHook(plugType, hook);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})();
|
|
||||||
|
//-- Hooks allow for injecting async functions that must all complete before continuing
|
||||||
|
// Functions must have a callback as their first argument.
|
||||||
|
hooks.prototype.registerHook = function(type, toAdd, toFront){
|
||||||
|
|
||||||
|
if(typeof(this.hooks[type]) != "undefined"){
|
||||||
|
|
||||||
|
if(typeof(toAdd) === "function"){
|
||||||
|
if(toFront) {
|
||||||
|
this.hooks[type].unshift(toAdd);
|
||||||
|
}else{
|
||||||
|
this.hooks[type].push(toAdd);
|
||||||
|
}
|
||||||
|
}else if(Array.isArray(toAdd)){
|
||||||
|
toAdd.forEach(function(hook){
|
||||||
|
if(toFront) {
|
||||||
|
this.hooks[type].unshift(hook);
|
||||||
|
}else{
|
||||||
|
this.hooks[type].push(hook);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//-- Allows for undefined hooks, but maybe this should error?
|
||||||
|
this.hooks[type] = [func];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
hooks.prototype.triggerHooks = function(type, callback, passed){
|
||||||
|
var hooks, count;
|
||||||
|
|
||||||
|
if(typeof(this.hooks[type]) == "undefined") return false;
|
||||||
|
|
||||||
|
hooks = this.hooks[type];
|
||||||
|
|
||||||
|
count = hooks.length;
|
||||||
|
function countdown(){
|
||||||
|
count--;
|
||||||
|
if(count <= 0 && callback) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks.forEach(function(hook){
|
||||||
|
hook(countdown, passed);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
register: function(name) {
|
||||||
|
if(EPUBJS.hooks[name] === undefined) { EPUBJS.hooks[name] = {}; }
|
||||||
|
if(typeof EPUBJS.hooks[name] !== 'object') { throw "Already registered: "+name; }
|
||||||
|
return EPUBJS.hooks[name];
|
||||||
|
},
|
||||||
|
mixin: function(object) {
|
||||||
|
for (var prop in hooks.prototype) {
|
||||||
|
object[prop] = hooks.prototype[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
135
src/layout.js
135
src/layout.js
|
@ -1,72 +1,115 @@
|
||||||
EPUBJS.Renderer.prototype.formatSpread = function(){
|
EPUBJS.Layout = EPUBJS.Layout || {};
|
||||||
|
|
||||||
var divisor = 2,
|
|
||||||
cutoff = 800;
|
|
||||||
|
|
||||||
|
EPUBJS.Layout.Reflowable = function(documentElement, _width, _height){
|
||||||
|
var columnAxis = EPUBJS.core.prefixed('columnAxis');
|
||||||
|
var columnGap = EPUBJS.core.prefixed('columnGap');
|
||||||
|
var columnWidth = EPUBJS.core.prefixed('columnWidth');
|
||||||
|
|
||||||
//-- Check the width and decied on columns
|
//-- Check the width and decied on columns
|
||||||
//-- Todo: a better place for this?
|
var width = (_width % 2 == 0) ? _width : Math.floor(_width) - 1;
|
||||||
this.elWidth = this.iframe.clientWidth;
|
var section = Math.ceil(width / 8);
|
||||||
if(this.elWidth % 2 !== 0){
|
var gap = (section % 2 == 0) ? section : section - 1;
|
||||||
this.elWidth -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this.gap = this.gap || Math.ceil(this.elWidth / 8);
|
//-- Single Page
|
||||||
this.gap = Math.ceil(this.elWidth / 8);
|
var spreadWidth = (width + gap);
|
||||||
|
var totalWidth, displayedPages;
|
||||||
|
|
||||||
if(this.gap % 2 !== 0){
|
documentElement.style.width = "auto"; //-- reset width for calculations
|
||||||
this.gap += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.elWidth < cutoff || !this.book.settings.spreads) {
|
|
||||||
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);
|
documentElement.style.overflow = "hidden";
|
||||||
}
|
|
||||||
|
|
||||||
this.spreadWidth = (this.colWidth + this.gap) * divisor;
|
documentElement.style.width = width + "px";
|
||||||
// if(this.bodyEl) this.bodyEl.style.margin = 0;
|
|
||||||
// this.bodyEl.style.fontSize = localStorage.getItem("fontSize") || "medium";
|
|
||||||
|
|
||||||
//-- Clear Margins
|
|
||||||
if(this.bodyEl) this.bodyEl.style.margin = "0";
|
|
||||||
|
|
||||||
this.docEl.style.overflow = "hidden";
|
|
||||||
|
|
||||||
this.docEl.style.width = this.elWidth + "px";
|
|
||||||
|
|
||||||
//-- Adjust height
|
//-- Adjust height
|
||||||
this.docEl.style.height = this.iframe.clientHeight + "px";
|
documentElement.style.height = _height + "px";
|
||||||
|
|
||||||
//-- Add columns
|
//-- Add columns
|
||||||
this.docEl.style[EPUBJS.Renderer.columnAxis] = "horizontal";
|
documentElement.style[columnAxis] = "horizontal";
|
||||||
this.docEl.style[EPUBJS.Renderer.columnGap] = this.gap+"px";
|
documentElement.style[columnGap] = gap+"px";
|
||||||
this.docEl.style[EPUBJS.Renderer.columnWidth] = this.colWidth+"px";
|
documentElement.style[columnWidth] = width+"px";
|
||||||
|
|
||||||
|
totalWidth = documentElement.scrollWidth;
|
||||||
|
displayedPages = Math.ceil(totalWidth / spreadWidth);
|
||||||
|
|
||||||
|
// documentElement.style.width = totalWidth + spreadWidth + "px";
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageWidth : spreadWidth,
|
||||||
|
pageHeight : _height,
|
||||||
|
displayedPages : displayedPages
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.fixedLayout = function(){
|
EPUBJS.Layout.ReflowableSpreads = function(documentElement, _width, _height){
|
||||||
this.paginated = false;
|
var columnAxis = EPUBJS.core.prefixed('columnAxis');
|
||||||
|
var columnGap = EPUBJS.core.prefixed('columnGap');
|
||||||
|
var columnWidth = EPUBJS.core.prefixed('columnWidth');
|
||||||
|
|
||||||
|
var divisor = 2,
|
||||||
|
cutoff = 800;
|
||||||
|
|
||||||
this.elWidth = this.iframe.width;
|
//-- Check the width and decied on columns
|
||||||
this.docEl.style.width = this.elWidth;
|
var width = (_width % 2 == 0) ? _width : Math.floor(_width) - 1;
|
||||||
// this.setLeft(0);
|
var section = Math.ceil(width / 8);
|
||||||
|
var gap = (section % 2 == 0) ? section : section - 1;
|
||||||
|
|
||||||
this.docEl.style.width = this.elWidth;
|
//-- Double Page
|
||||||
|
var colWidth = Math.floor((width - gap) / divisor);
|
||||||
|
var spreadWidth = (colWidth + gap) * divisor;
|
||||||
|
|
||||||
|
var totalWidth, displayedPages;
|
||||||
|
|
||||||
|
documentElement.style.width = "auto"; //-- reset width for calculations
|
||||||
|
|
||||||
|
documentElement.style.overflow = "hidden";
|
||||||
|
|
||||||
|
documentElement.style.width = width + "px";
|
||||||
|
|
||||||
//-- Adjust height
|
//-- Adjust height
|
||||||
this.docEl.style.height = "auto";
|
documentElement.style.height = _height + "px";
|
||||||
|
|
||||||
|
//-- Add columns
|
||||||
|
documentElement.style[columnAxis] = "horizontal";
|
||||||
|
documentElement.style[columnGap] = gap+"px";
|
||||||
|
documentElement.style[columnWidth] = colWidth+"px";
|
||||||
|
|
||||||
|
totalWidth = documentElement.scrollWidth;
|
||||||
|
displayedPages = Math.ceil(totalWidth / spreadWidth);
|
||||||
|
|
||||||
|
documentElement.style.width = totalWidth + spreadWidth + "px";
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageWidth : spreadWidth,
|
||||||
|
pageHeight : _height,
|
||||||
|
displayedPages : displayedPages
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Layout.Fixed = function(documentElement, _width, _height){
|
||||||
|
var columnWidth = EPUBJS.core.prefixed('columnWidth');
|
||||||
|
|
||||||
|
var totalWidth = documentElement.scrollWidth;
|
||||||
|
var totalHeight = documentElement.scrollHeight;
|
||||||
|
|
||||||
|
documentElement.style.width = _width;
|
||||||
|
|
||||||
|
//-- Adjust height
|
||||||
|
documentElement.style.height = "auto";
|
||||||
|
|
||||||
//-- Remove columns
|
//-- Remove columns
|
||||||
// this.docEl.style[EPUBJS.core.columnWidth] = "auto";
|
documentElement.style[columnWidth] = "auto";
|
||||||
|
|
||||||
//-- Scroll
|
//-- Scroll
|
||||||
this.docEl.style.overflow = "auto";
|
documentElement.style.overflow = "auto";
|
||||||
this.iframe.scrolling = "yes";
|
// this.iframe.scrolling = "yes";
|
||||||
|
|
||||||
// this.displayedPages = 1;
|
// this.displayedPages = 1;
|
||||||
|
return {
|
||||||
|
pageWidth : totalWidth,
|
||||||
|
pageHeight : totalHeight,
|
||||||
|
displayedPages : 1
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
|
@ -1,196 +0,0 @@
|
||||||
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);
|
|
||||||
|
|
||||||
this.currentLocationCfi = this.getPageCfi();
|
|
||||||
|
|
||||||
this.book.trigger("renderer:pageChanged", this.currentLocationCfi);
|
|
||||||
|
|
||||||
// localStorage.setItem("chapterPos", pg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//-- Return false if page is greater than the total
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
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.book.trigger("renderer: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.book.trigger("renderer:pageChanged", this.currentLocationCfi);
|
|
||||||
|
|
||||||
return this.chapterPos;
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.gotoChapterEnd = function(){
|
|
||||||
this.chapterEnd();
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.chapterEnd = function(){
|
|
||||||
this.page(this.displayedPages);
|
|
||||||
};
|
|
||||||
|
|
||||||
//-- 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.walk = function(node) {
|
|
||||||
var r, 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;
|
|
||||||
if (children && children.length) {
|
|
||||||
leng = children.length ? children.length : 0;
|
|
||||||
} else {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 rect;
|
|
||||||
|
|
||||||
if(el && typeof el.getBoundingClientRect === 'function'){
|
|
||||||
rect = el.getBoundingClientRect();
|
|
||||||
|
|
||||||
if( rect.width != 0 &&
|
|
||||||
rect.height != 0 &&
|
|
||||||
rect.left >= 0 &&
|
|
||||||
rect.left < this.spreadWidth ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
|
@ -143,7 +143,7 @@ EPUBJS.Parser.prototype.metadata = function(xml){
|
||||||
metadata.rights = p.getElementText(xml, "rights");
|
metadata.rights = p.getElementText(xml, "rights");
|
||||||
|
|
||||||
metadata.modified_date = p.querySelectorText(xml, "meta[property='dcterms:modified']");
|
metadata.modified_date = p.querySelectorText(xml, "meta[property='dcterms:modified']");
|
||||||
metadata.layout = p.querySelectorText(xml, "meta[property='rendition:orientation']");
|
metadata.layout = p.querySelectorText(xml, "meta[property='rendition:layout']");
|
||||||
metadata.orientation = p.querySelectorText(xml, "meta[property='rendition:orientation']");
|
metadata.orientation = p.querySelectorText(xml, "meta[property='rendition:orientation']");
|
||||||
metadata.spread = p.querySelectorText(xml, "meta[property='rendition:spread']");
|
metadata.spread = p.querySelectorText(xml, "meta[property='rendition:spread']");
|
||||||
// metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
|
// metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
|
||||||
|
@ -210,18 +210,25 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
|
||||||
|
|
||||||
var selected = spineXml.getElementsByTagName("itemref"),
|
var selected = spineXml.getElementsByTagName("itemref"),
|
||||||
items = Array.prototype.slice.call(selected);
|
items = Array.prototype.slice.call(selected);
|
||||||
|
|
||||||
|
var spineNodeIndex = Array.prototype.indexOf.call(spineXml.parentNode.childNodes, spineXml);
|
||||||
|
|
||||||
|
var epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
//-- Add to array to mantain ordering and cross reference with manifest
|
//-- Add to array to mantain ordering and cross reference with manifest
|
||||||
items.forEach(function(item, index){
|
items.forEach(function(item, index){
|
||||||
var Id = item.getAttribute('idref');
|
var Id = item.getAttribute('idref');
|
||||||
|
var cfiBase = epubcfi.generateChapter(spineNodeIndex, index, Id);
|
||||||
var vert = {
|
var vert = {
|
||||||
'id' : Id,
|
'id' : Id,
|
||||||
'linear' : item.getAttribute('linear') || '',
|
'linear' : item.getAttribute('linear') || '',
|
||||||
'properties' : manifest[Id].properties || '',
|
'properties' : item.getAttribute('properties') || '',
|
||||||
|
'manifestProperties' : manifest[Id].properties || '',
|
||||||
'href' : manifest[Id].href,
|
'href' : manifest[Id].href,
|
||||||
'url' : manifest[Id].url,
|
'url' : manifest[Id].url,
|
||||||
'index' : index
|
'index' : index,
|
||||||
};
|
'cfiBase' : cfiBase
|
||||||
|
};
|
||||||
|
|
||||||
spine.push(vert);
|
spine.push(vert);
|
||||||
});
|
});
|
||||||
|
|
171
src/render_iframe.js
Normal file
171
src/render_iframe.js
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
EPUBJS.Render.Iframe = function() {
|
||||||
|
this.iframe;
|
||||||
|
this.document;
|
||||||
|
this.window;
|
||||||
|
this.docEl;
|
||||||
|
this.bodyEl;
|
||||||
|
|
||||||
|
this.leftPos = 0;
|
||||||
|
this.pageWidth = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-- Build up any html needed
|
||||||
|
EPUBJS.Render.Iframe.prototype.create = function(){
|
||||||
|
this.iframe = document.createElement('iframe');
|
||||||
|
this.iframe.id = "epubjs-iframe";
|
||||||
|
this.iframe.scrolling = "no";
|
||||||
|
|
||||||
|
return this.iframe;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.load = function(url){
|
||||||
|
var render = this,
|
||||||
|
deferred = new RSVP.defer();
|
||||||
|
|
||||||
|
this.leftPos = 0;
|
||||||
|
this.iframe.src = url;
|
||||||
|
|
||||||
|
if(this.window) {
|
||||||
|
this.unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iframe.onload = function() {
|
||||||
|
render.document = render.iframe.contentDocument;
|
||||||
|
|
||||||
|
render.docEl = render.document.documentElement;
|
||||||
|
render.bodyEl = render.document.body;
|
||||||
|
render.window = render.iframe.contentWindow;
|
||||||
|
|
||||||
|
render.window.addEventListener("resize", render.resized.bind(render), false);
|
||||||
|
|
||||||
|
//-- Clear Margins
|
||||||
|
if(render.bodyEl) render.bodyEl.style.margin = "0";
|
||||||
|
|
||||||
|
deferred.resolve(render.docEl);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.iframe.onerror = function(e) {
|
||||||
|
console.error("Error Loading Contents", e);
|
||||||
|
}
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.resize = function(width, height){
|
||||||
|
var iframeBox;
|
||||||
|
|
||||||
|
if(!this.iframe) return;
|
||||||
|
|
||||||
|
this.iframe.height = height;
|
||||||
|
|
||||||
|
if(!isNaN(width) && width % 2 !== 0){
|
||||||
|
width += 1; //-- Prevent cutting off edges of text in columns
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iframe.width = width;
|
||||||
|
|
||||||
|
this.width = this.iframe.getBoundingClientRect().width;
|
||||||
|
this.height = this.iframe.getBoundingClientRect().height;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.resized = function(e){
|
||||||
|
this.width = this.iframe.getBoundingClientRect().width;
|
||||||
|
this.height = this.iframe.getBoundingClientRect().height;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.totalWidth = function(){
|
||||||
|
return this.docEl.scrollWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.totalHeight = function(){
|
||||||
|
return this.docEl.scrollHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.setPageDimensions = function(pageWidth, pageHeight){
|
||||||
|
this.pageWidth = pageWidth;
|
||||||
|
this.pageHeight = pageHeight;
|
||||||
|
//-- Add a page to the width of the document to account an for odd number of pages
|
||||||
|
// this.docEl.style.width = this.docEl.scrollWidth + pageWidth + "px";
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.setLeft = function(leftPos){
|
||||||
|
// this.bodyEl.style.marginLeft = -leftPos + "px";
|
||||||
|
// this.docEl.style.marginLeft = -leftPos + "px";
|
||||||
|
// this.docEl.style[EPUBJS.Render.Iframe.transform] = 'translate('+ (-leftPos) + 'px, 0)';
|
||||||
|
this.document.defaultView.scrollTo(leftPos, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
// EPUBJS.Render.Iframe.prototype.nextPage = function(){
|
||||||
|
// this.leftPos += this.pageWidth;
|
||||||
|
// this.setLeft(this.leftPos);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// EPUBJS.Render.Iframe.prototype.prevPage = function(){
|
||||||
|
// this.leftPos -= this.pageWidth;
|
||||||
|
// this.setLeft(this.leftPos);
|
||||||
|
// };
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.setStyle = function(style, val, prefixed){
|
||||||
|
if(prefixed) {
|
||||||
|
style = EPUBJS.core.prefixed(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.bodyEl) this.bodyEl.style[style] = val;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.removeStyle = function(style){
|
||||||
|
|
||||||
|
if(this.bodyEl) this.bodyEl.style[style] = '';
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.page = function(pg){
|
||||||
|
this.leftPos = this.pageWidth * (pg-1); //-- pages start at 1
|
||||||
|
this.setLeft(this.leftPos);
|
||||||
|
};
|
||||||
|
|
||||||
|
//-- Show the page containing an Element
|
||||||
|
EPUBJS.Render.Iframe.prototype.getPageNumberByElement = 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.pageWidth) + 1; //-- pages start at 1
|
||||||
|
|
||||||
|
return pg;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--
|
||||||
|
EPUBJS.Render.Iframe.prototype.getBaseElement = function(){
|
||||||
|
return this.bodyEl;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.isElementVisible = function(el){
|
||||||
|
var rect;
|
||||||
|
|
||||||
|
if(el && typeof el.getBoundingClientRect === 'function'){
|
||||||
|
rect = el.getBoundingClientRect();
|
||||||
|
if( rect.width != 0 &&
|
||||||
|
rect.height != 0 &&
|
||||||
|
rect.left >= 0 &&
|
||||||
|
rect.left < this.pageWidth ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.scroll = function(bool){
|
||||||
|
if(bool) {
|
||||||
|
this.iframe.scrolling = "yes";
|
||||||
|
} else {
|
||||||
|
this.iframe.scrolling = "no";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Render.Iframe.prototype.unload = function(){
|
||||||
|
this.window.removeEventListener("resize", this.resized);
|
||||||
|
};
|
851
src/renderer.js
851
src/renderer.js
|
@ -1,94 +1,420 @@
|
||||||
EPUBJS.Renderer = function(book) {
|
EPUBJS.Renderer = function(type, beforeDisplay) {
|
||||||
this.el = book.element;
|
this.beforeDisplay = beforeDisplay;
|
||||||
this.book = book;
|
|
||||||
|
|
||||||
// this.settings = book.settings;
|
|
||||||
this.caches = {};
|
|
||||||
|
|
||||||
this.crossBrowserColumnCss();
|
|
||||||
|
|
||||||
this.epubcfi = new EPUBJS.EpubCFI();
|
|
||||||
|
|
||||||
this.initialize();
|
|
||||||
|
|
||||||
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
|
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
|
||||||
this.listeners();
|
|
||||||
|
if(type && typeof(EPUBJS.Render[type]) != "undefined"){
|
||||||
|
this.render = new EPUBJS.Render[type];
|
||||||
|
} else {
|
||||||
|
console.error("Not a Valid Rendering Method");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.caches = {};
|
||||||
|
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this.spreads = true;
|
||||||
|
this.resized = _.throttle(this.onResized.bind(this), 10);
|
||||||
|
};
|
||||||
|
|
||||||
//-- Renderer events for listening
|
//-- Renderer events for listening
|
||||||
/*
|
EPUBJS.Renderer.prototype.Events = [
|
||||||
renderer:resized
|
"renderer:keydown",
|
||||||
renderer:chapterDisplayed
|
"renderer:keyup",
|
||||||
renderer:chapterUnloaded
|
"renderer:keypressed",
|
||||||
*/
|
"renderer:mouseup",
|
||||||
};
|
"renderer:mousedown",
|
||||||
|
"renderer:click",
|
||||||
|
"renderer:selected",
|
||||||
|
"renderer:chapterUnloaded",
|
||||||
|
"renderer:chapterDisplayed",
|
||||||
|
"renderer:pageChanged",
|
||||||
|
"renderer:resized",
|
||||||
|
"renderer:spreads"
|
||||||
|
];
|
||||||
|
|
||||||
//-- Build up any html needed
|
EPUBJS.Renderer.prototype.initialize = function(element, width, height){
|
||||||
EPUBJS.Renderer.prototype.initialize = function(){
|
this.container = element;
|
||||||
this.iframe = document.createElement('iframe');
|
this.element = this.render.create();
|
||||||
//this.iframe.id = "epubjs-iframe";
|
|
||||||
this.iframe.scrolling = "no";
|
|
||||||
|
|
||||||
if(this.book.settings.width || this.book.settings.height){
|
this.initWidth = width;
|
||||||
this.resizeIframe(this.book.settings.width || this.el.clientWidth, this.book.settings.height || this.el.clientHeight);
|
this.initHeight = height;
|
||||||
|
|
||||||
|
this.width = width || this.container.clientWidth;
|
||||||
|
this.height = height || this.container.clientHeight;
|
||||||
|
|
||||||
|
this.container.appendChild(this.element);
|
||||||
|
|
||||||
|
if(width && height){
|
||||||
|
this.render.resize(this.width, this.height);
|
||||||
} else {
|
} else {
|
||||||
// this.resizeIframe(false, this.el.clientWidth, this.el.clientHeight);
|
this.render.resize('100%', '100%');
|
||||||
this.resizeIframe('100%', '100%');
|
|
||||||
|
|
||||||
// this.on("renderer:resized", this.resizeIframe, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.el.appendChild(this.iframe);
|
|
||||||
};
|
|
||||||
|
|
||||||
//-- Listeners for browser events
|
|
||||||
EPUBJS.Renderer.prototype.listeners = function(){
|
|
||||||
|
|
||||||
this.resized = _.throttle(this.onResized.bind(this), 10);
|
|
||||||
|
|
||||||
// window.addEventListener("hashchange", book.route.bind(this), false);
|
|
||||||
|
|
||||||
this.book.registerHook("beforeChapterDisplay", this.replaceLinks.bind(this), true);
|
|
||||||
|
|
||||||
if(this.determineStore()) {
|
|
||||||
|
|
||||||
this.book.registerHook("beforeChapterDisplay", [
|
|
||||||
EPUBJS.replace.head,
|
|
||||||
EPUBJS.replace.resources,
|
|
||||||
EPUBJS.replace.svg
|
|
||||||
], true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.chapter = function(chapter){
|
|
||||||
|
EPUBJS.Renderer.prototype.displayChapter = function(chapter, globalLayout){
|
||||||
var renderer = this,
|
var renderer = this,
|
||||||
store = false;
|
store = false;
|
||||||
|
|
||||||
if(this.book.settings.contained) store = this.book.zip;
|
|
||||||
// if(this.settings.stored) store = this.storage;
|
|
||||||
|
|
||||||
if(this.currentChapter) {
|
if(this.currentChapter) {
|
||||||
this.currentChapter.unload();
|
this.currentChapter.unload();
|
||||||
|
this.render.window.removeEventListener("resize", this.resized);
|
||||||
|
this.removeEventListeners();
|
||||||
|
this.removeSelectionListeners();
|
||||||
this.trigger("renderer:chapterUnloaded");
|
this.trigger("renderer:chapterUnloaded");
|
||||||
this.book.trigger("renderer:chapterUnloaded");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentChapter = chapter;
|
this.currentChapter = chapter;
|
||||||
this.chapterPos = 1;
|
this.chapterPos = 1;
|
||||||
this.pageIds = {};
|
|
||||||
this.leftPos = 0;
|
this.currentChapterCfiBase = chapter.cfiBase;
|
||||||
|
|
||||||
|
this.settings = this.reconcileLayoutSettings(globalLayout, chapter.properties);
|
||||||
|
|
||||||
this.currentChapterCfi = this.epubcfi.generateChapter(this.book.spineNodeIndex, chapter.spinePos, chapter.id);
|
|
||||||
this.visibileEl = false;
|
|
||||||
|
|
||||||
return chapter.url(store).
|
|
||||||
|
return chapter.url().
|
||||||
then(function(url) {
|
then(function(url) {
|
||||||
return renderer.setIframeSrc(url);
|
return renderer.load(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.reconcileLayoutSettings = function(global, chapter){
|
||||||
|
var layoutMethod = "ReflowableSpreads";
|
||||||
|
var properties = chapter.split(' ');
|
||||||
|
var settings = {};
|
||||||
|
var spreads = true;
|
||||||
|
|
||||||
|
//-- Get the global defaults
|
||||||
|
for (var attr in global) {
|
||||||
|
if (global.hasOwnProperty(attr)){
|
||||||
|
settings[attr] = global[attr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-- Get the chapter's display type
|
||||||
|
properties.forEach(function(prop){
|
||||||
|
var rendition = prop.replace("rendition:", '');
|
||||||
|
var split = rendition.indexOf("-");
|
||||||
|
var property, value;
|
||||||
|
|
||||||
|
if(split != -1){
|
||||||
|
property = rendition.slice(0, split);
|
||||||
|
value = rendition.slice(split+1);
|
||||||
|
|
||||||
|
settings[property] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.determineLayout = function(settings){
|
||||||
|
var layoutMethod = "ReflowableSpreads";
|
||||||
|
|
||||||
|
if(settings.layout === "pre-paginated") {
|
||||||
|
layoutMethod = "Fixed";
|
||||||
|
this.render.scroll(true);
|
||||||
|
return EPUBJS.Layout[layoutMethod];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settings.layout === "reflowable" && settings.spread === "none") {
|
||||||
|
layoutMethod = "Reflowable";
|
||||||
|
this.render.scroll(false);
|
||||||
|
this.trigger("renderer:spreads", false);
|
||||||
|
return EPUBJS.Layout[layoutMethod];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settings.layout === "reflowable" && settings.spread === "both") {
|
||||||
|
layoutMethod = "ReflowableSpreads";
|
||||||
|
this.render.scroll(false);
|
||||||
|
this.trigger("renderer:spreads", true);
|
||||||
|
return EPUBJS.Layout[layoutMethod];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflowable Auto adjustments for width
|
||||||
|
if(settings.layout === "reflowable" && settings.spread === "auto"){
|
||||||
|
spreads = this.determineSpreads(this.minSpreadWidth);
|
||||||
|
if(spreads){
|
||||||
|
layoutMethod = "ReflowableSpreads";
|
||||||
|
this.trigger("renderer:spreads", true);
|
||||||
|
} else {
|
||||||
|
layoutMethod = "Reflowable";
|
||||||
|
this.trigger("renderer:spreads", false);
|
||||||
|
}
|
||||||
|
this.render.scroll(false);
|
||||||
|
return EPUBJS.Layout[layoutMethod];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.load = function(url){
|
||||||
|
var deferred = new RSVP.defer();
|
||||||
|
var loaded;
|
||||||
|
|
||||||
|
this.layoutMethod = this.determineLayout(this.settings);
|
||||||
|
|
||||||
|
this.visible(false);
|
||||||
|
|
||||||
|
loaded = this.render.load(url);
|
||||||
|
|
||||||
|
loaded.then(function(contents) {
|
||||||
|
this.contents = contents;
|
||||||
|
this.doc = this.render.document;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(!this.initWidth && !this.initHeight){
|
||||||
|
this.render.window.addEventListener("resize", this.resized, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addEventListeners();
|
||||||
|
this.addSelectionListeners();
|
||||||
|
|
||||||
|
//-- Trigger registered hooks before displaying
|
||||||
|
this.beforeDisplay(function(){
|
||||||
|
var msg = this.currentChapter;
|
||||||
|
|
||||||
|
msg.cfi = this.currentLocationCfi = this.getPageCfi();
|
||||||
|
|
||||||
|
this.trigger("renderer:chapterDisplayed", msg);
|
||||||
|
this.trigger("renderer:pageChanged", this.currentLocationCfi);
|
||||||
|
|
||||||
|
this.layout = this.layoutMethod(contents, this.render.width, this.render.height);
|
||||||
|
this.updatePages(this.layout);
|
||||||
|
|
||||||
|
this.visible(true);
|
||||||
|
|
||||||
|
deferred.resolve(this); //-- why does this return the renderer?
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.updatePages = function(layout){
|
||||||
|
this.displayedPages = layout.displayedPages;
|
||||||
|
this.currentChapter.pages = layout.displayedPages;
|
||||||
|
this.render.setPageDimensions(layout.pageWidth, layout.pageHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.reformat = function(){
|
||||||
|
var renderer = this;
|
||||||
|
if(!this.contents) return;
|
||||||
|
|
||||||
|
this.layout = this.layoutMethod(this.contents, this.render.width, this.render.height);
|
||||||
|
this.updatePages(this.layout);
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
|
||||||
|
//-- Go to current page after formating
|
||||||
|
if(renderer.currentLocationCfi){
|
||||||
|
renderer.gotoCfi(renderer.currentLocationCfi);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.visible = function(bool){
|
||||||
|
if(typeof(bool) === "undefined") {
|
||||||
|
return this.container.style.visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bool === true){
|
||||||
|
this.container.style.visibility = "visible";
|
||||||
|
}else if(bool === false){
|
||||||
|
this.container.style.visibility = "hidden";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.remove = function() {
|
||||||
|
if(this.renderer.window) {
|
||||||
|
this.render.unload();
|
||||||
|
this.render.window.removeEventListener("resize", this.resized);
|
||||||
|
this.removeEventListeners();
|
||||||
|
this.removeSelectionListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.container.removeChild(this.element);
|
||||||
|
};
|
||||||
|
|
||||||
|
//-- STYLES
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.applyStyles = function(styles) {
|
||||||
|
for (var style in styles) {
|
||||||
|
this.render.setStyle(style, styles[style]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.setStyle = function(style, val, prefixed){
|
||||||
|
this.render.setStyle(style, val, prefixed);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.removeStyle = function(style){
|
||||||
|
this.render.removeStyle(style);
|
||||||
|
};
|
||||||
|
|
||||||
|
//-- NAVIGATION
|
||||||
|
|
||||||
|
//-- Show the page containing an Element
|
||||||
|
EPUBJS.Renderer.prototype.pageByElement = function(el){
|
||||||
|
var pg;
|
||||||
|
if(!el) return;
|
||||||
|
|
||||||
|
pg = this.render.getPageNumberByElement(el);
|
||||||
|
this.page(pg);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.page = function(pg){
|
||||||
|
if(pg >= 1 && pg <= this.displayedPages){
|
||||||
|
this.chapterPos = pg;
|
||||||
|
|
||||||
|
this.render.page(pg);
|
||||||
|
|
||||||
|
this.currentLocationCfi = this.getPageCfi();
|
||||||
|
this.trigger("renderer:pageChanged", this.currentLocationCfi);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//-- Return false if page is greater than the total
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.nextPage = function(){
|
||||||
|
var pg = this.chapterPos + 1;
|
||||||
|
if(pg <= this.displayedPages){
|
||||||
|
this.chapterPos = pg;
|
||||||
|
|
||||||
|
this.render.page(pg);
|
||||||
|
|
||||||
|
this.currentLocationCfi = this.getNextPageCfi();
|
||||||
|
this.trigger("renderer:pageChanged", this.currentLocationCfi);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//-- Return false if page is greater than the total
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.prevPage = function(){
|
||||||
|
return this.page(this.chapterPos - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.gotoChapterEnd = function(){
|
||||||
|
this.chapterEnd();
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.chapterEnd = function(){
|
||||||
|
this.page(this.displayedPages);
|
||||||
|
};
|
||||||
|
|
||||||
|
//-- 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.walk = function(node) {
|
||||||
|
var r, children, leng,
|
||||||
|
startNode = node,
|
||||||
|
prevNode,
|
||||||
|
stack = [startNode];
|
||||||
|
|
||||||
|
var STOP = 10000, ITER=0;
|
||||||
|
|
||||||
|
while(!r && stack.length) {
|
||||||
|
|
||||||
|
node = stack.shift();
|
||||||
|
if( this.render.isElementVisible(node) ) {
|
||||||
|
r = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!r && node && node.childElementCount > 0){
|
||||||
|
children = node.children;
|
||||||
|
if (children && children.length) {
|
||||||
|
leng = children.length ? children.length : 0;
|
||||||
|
} else {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
|
||||||
|
// 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.currentChapter.cfiBase);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.getNextPageCfi = function(){
|
||||||
|
var prevEl = this.visibileEl;
|
||||||
|
this.visibileEl = this.findFirstVisible(prevEl);
|
||||||
|
|
||||||
|
return this.epubcfi.generateFragment(this.visibileEl, this.currentChapter.cfiBase);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.gotoCfi = 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.render.getBaseElement();
|
||||||
|
var found;
|
||||||
|
found = this.walk(el);
|
||||||
|
|
||||||
|
if(found) {
|
||||||
|
return found;
|
||||||
|
}else{
|
||||||
|
return startEl;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -110,34 +436,58 @@ EPUBJS.Renderer.prototype.hideHashChanges = function(){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-- Listeners for events in the frame
|
//-- Listeners for events in the frame
|
||||||
EPUBJS.Renderer.prototype.addIframeListeners = function(){
|
|
||||||
|
EPUBJS.Renderer.prototype.onResized = function(e){
|
||||||
|
var spreads;
|
||||||
|
|
||||||
|
this.width = this.container.clientWidth;
|
||||||
|
this.height = this.container.clientHeight;
|
||||||
|
|
||||||
|
spreads = this.determineSpreads(this.minSpreadWidth);
|
||||||
|
if(spreads != this.spreads){
|
||||||
|
this.spreads = spreads;
|
||||||
|
this.layoutMethod = this.determineLayout(this.settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.contents){
|
||||||
|
this.reformat();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("renderer:resized", {
|
||||||
|
width: this.width,
|
||||||
|
height: this.height
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.addEventListeners = function(){
|
||||||
|
|
||||||
this.listenedEvents.forEach(function(eventName){
|
this.listenedEvents.forEach(function(eventName){
|
||||||
this.doc.addEventListener(eventName, this.triggerEvent.bind(this), false);
|
this.render.document.addEventListener(eventName, this.triggerEvent.bind(this), false);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.removeIframeListeners = function(){
|
EPUBJS.Renderer.prototype.removeEventListeners = function(){
|
||||||
|
|
||||||
this.listenedEvents.forEach(function(eventName){
|
this.listenedEvents.forEach(function(eventName){
|
||||||
this.doc.removeEventListener(eventName, this.triggerEvent, false);
|
this.render.document.removeEventListener(eventName, this.triggerEvent, false);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.triggerEvent = function(e){
|
EPUBJS.Renderer.prototype.triggerEvent = function(e){
|
||||||
this.book.trigger("renderer:"+e.type, e);
|
this.trigger("renderer:"+e.type, e);
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.addSelectionListeners = function(){
|
EPUBJS.Renderer.prototype.addSelectionListeners = function(){
|
||||||
this.doc.addEventListener("selectionchange", this.onSelectionChange.bind(this), false);
|
this.render.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false);
|
||||||
this.contentWindow.addEventListener("mouseup", this.onMouseUp.bind(this), false);
|
this.render.window.addEventListener("mouseup", this.onMouseUp.bind(this), false);
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.removeSelectionListeners = function(){
|
EPUBJS.Renderer.prototype.removeSelectionListeners = function(){
|
||||||
this.doc.removeEventListener("selectionchange", this.onSelectionChange, false);
|
this.doc.removeEventListener("selectionchange", this.onSelectionChange, false);
|
||||||
this.contentWindow.removeEventListener("mouseup", this.onMouseUp, false);
|
this.render.window.removeEventListener("mouseup", this.onMouseUp, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.onSelectionChange = function(e){
|
EPUBJS.Renderer.prototype.onSelectionChange = function(e){
|
||||||
|
@ -147,246 +497,133 @@ EPUBJS.Renderer.prototype.onSelectionChange = function(e){
|
||||||
EPUBJS.Renderer.prototype.onMouseUp = function(e){
|
EPUBJS.Renderer.prototype.onMouseUp = function(e){
|
||||||
var selection;
|
var selection;
|
||||||
if(this.highlighted) {
|
if(this.highlighted) {
|
||||||
selection = this.contentWindow.getSelection();
|
selection = this.render.window.getSelection();
|
||||||
this.book.trigger("renderer:selected", selection);
|
this.trigger("renderer:selected", selection);
|
||||||
this.highlighted = false;
|
this.highlighted = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.onResized = function(e){
|
|
||||||
|
|
||||||
var msg = {
|
|
||||||
width: this.iframe.clientWidth,
|
|
||||||
height: this.iframe.clientHeight
|
|
||||||
};
|
|
||||||
|
|
||||||
if(this.doc){
|
|
||||||
this.reformat();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.trigger("renderer:resized", msg);
|
//-- Spreads
|
||||||
this.book.trigger("book:resized", msg);
|
// EPUBJS.Renderer.prototype.useSpreads = function(spreads){
|
||||||
|
// var prevSpreads = this.spreads;
|
||||||
|
// this.spreads = spreads;
|
||||||
|
//
|
||||||
|
// if(this.contents && (this.spreads != prevSpreads)) {
|
||||||
|
// this.layoutMethod = this.determineLayout(this.currentChapter.properties);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.setMinSpreadWidth = function(width){
|
||||||
|
this.minSpreadWidth = width;
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.reformat = function(){
|
EPUBJS.Renderer.prototype.determineSpreads = function(cutoff){
|
||||||
var renderer = this;
|
if(this.width < cutoff || !cutoff) {
|
||||||
|
return false; //-- Single Page
|
||||||
//-- reformat
|
}else{
|
||||||
if(renderer.book.settings.fixedLayout) {
|
return true; //-- Double Page
|
||||||
renderer.fixedLayout();
|
|
||||||
} else {
|
|
||||||
renderer.formatSpread();
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
setTimeout(function(){
|
|
||||||
|
//-- Content Replacements
|
||||||
//-- re-calc number of pages
|
|
||||||
renderer.calcPages();
|
EPUBJS.Renderer.prototype.replace = function(query, func, finished, progress){
|
||||||
|
var items = this.contents.querySelectorAll(query),
|
||||||
|
resources = Array.prototype.slice.call(items),
|
||||||
//-- Go to current page after resize
|
count = resources.length,
|
||||||
if(renderer.currentLocationCfi){
|
after = function(result, full){
|
||||||
renderer.gotoCfiFragment(renderer.currentLocationCfi);
|
count--;
|
||||||
|
if(progress) progress(result, full, count);
|
||||||
|
if(count <= 0 && finished) finished(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
if(count === 0) {
|
||||||
|
finished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resources.forEach(function(item){
|
||||||
|
|
||||||
|
func(item, after);
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Renderer.prototype.replaceWithStored = function(query, attr, func, callback) {
|
||||||
|
var _oldUrls,
|
||||||
|
_newUrls = {},
|
||||||
|
_store = this.currentChapter.store,
|
||||||
|
_cache = this.caches[query],
|
||||||
|
_uri = EPUBJS.core.uri(this.currentChapter.absolute),
|
||||||
|
_chapterBase = _uri.base,
|
||||||
|
_attr = attr,
|
||||||
|
_wait = 2000,
|
||||||
|
progress = function(url, full, count) {
|
||||||
|
_newUrls[full] = url;
|
||||||
|
},
|
||||||
|
finished = function(notempty) {
|
||||||
|
if(callback) callback();
|
||||||
|
|
||||||
|
_.each(_oldUrls, function(url){
|
||||||
|
_store.revokeUrl(url);
|
||||||
|
});
|
||||||
|
|
||||||
|
_cache = _newUrls;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!_store) return;
|
||||||
|
|
||||||
|
if(!_cache) _cache = {};
|
||||||
|
_oldUrls = _.clone(_cache);
|
||||||
|
|
||||||
|
this.replace(query, function(link, done){
|
||||||
|
var src = link.getAttribute(_attr),
|
||||||
|
full = EPUBJS.core.resolveUrl(_chapterBase, src);
|
||||||
|
|
||||||
|
var replaceUrl = function(url) {
|
||||||
|
var timeout;
|
||||||
|
|
||||||
|
link.onload = function(){
|
||||||
|
clearTimeout(timeout);
|
||||||
|
done(url, full);
|
||||||
|
};
|
||||||
|
|
||||||
|
link.onerror = function(e){
|
||||||
|
clearTimeout(timeout);
|
||||||
|
done(url, full);
|
||||||
|
console.error(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
if(query == "image") {
|
||||||
|
//-- SVG needs this to trigger a load event
|
||||||
|
link.setAttribute("externalResourcesRequired", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(query == "link[href]") {
|
||||||
|
//-- Only Stylesheet links seem to have a load events, just continue others
|
||||||
|
done(url, full);
|
||||||
|
}
|
||||||
|
|
||||||
|
link.setAttribute(_attr, url);
|
||||||
|
|
||||||
|
//-- If elements never fire Load Event, should continue anyways
|
||||||
|
timeout = setTimeout(function(){
|
||||||
|
done(url, full);
|
||||||
|
}, _wait);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if(full in _oldUrls){
|
||||||
|
replaceUrl(_oldUrls[full]);
|
||||||
|
_newUrls[full] = _oldUrls[full];
|
||||||
|
delete _oldUrls[full];
|
||||||
|
}else{
|
||||||
|
func(_store, full, replaceUrl, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, 10);
|
}, finished, progress);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.resizeIframe = function(width, height){
|
|
||||||
|
|
||||||
this.iframe.height = height;
|
|
||||||
|
|
||||||
if(!isNaN(width) && width % 2 !== 0){
|
|
||||||
width += 1; //-- Prevent cutting off edges of text in columns
|
|
||||||
}
|
|
||||||
|
|
||||||
this.iframe.width = width;
|
|
||||||
|
|
||||||
this.onResized();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.crossBrowserColumnCss = function(){
|
|
||||||
|
|
||||||
EPUBJS.Renderer.columnAxis = EPUBJS.core.prefixed('columnAxis');
|
|
||||||
EPUBJS.Renderer.columnGap = EPUBJS.core.prefixed('columnGap');
|
|
||||||
EPUBJS.Renderer.columnWidth = EPUBJS.core.prefixed('columnWidth');
|
|
||||||
EPUBJS.Renderer.transform = EPUBJS.core.prefixed('transform');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.setIframeSrc = function(url){
|
|
||||||
var renderer = this,
|
|
||||||
deferred = new RSVP.defer();
|
|
||||||
|
|
||||||
this.visible(false);
|
|
||||||
|
|
||||||
this.iframe.src = url;
|
|
||||||
|
|
||||||
this.iframe.onload = function() {
|
|
||||||
renderer.doc = renderer.iframe.contentDocument;
|
|
||||||
renderer.docEl = renderer.doc.documentElement;
|
|
||||||
renderer.headEl = renderer.doc.head;
|
|
||||||
renderer.bodyEl = renderer.doc.body;
|
|
||||||
renderer.contentWindow = renderer.iframe.contentWindow;
|
|
||||||
|
|
||||||
renderer.applyStyles();
|
|
||||||
renderer.applyHeadTags();
|
|
||||||
|
|
||||||
if(renderer.book.settings.fixedLayout) {
|
|
||||||
renderer.fixedLayout();
|
|
||||||
} else {
|
|
||||||
renderer.formatSpread();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-- Trigger registered hooks before displaying
|
|
||||||
renderer.beforeDisplay(function(){
|
|
||||||
var msg = renderer.currentChapter;
|
|
||||||
|
|
||||||
renderer.calcPages();
|
|
||||||
|
|
||||||
deferred.resolve(renderer);
|
|
||||||
|
|
||||||
msg.cfi = renderer.currentLocationCfi = renderer.getPageCfi();
|
|
||||||
|
|
||||||
renderer.trigger("renderer:chapterDisplayed", msg);
|
|
||||||
renderer.book.trigger("renderer:chapterDisplayed", msg);
|
|
||||||
renderer.book.trigger("renderer:pageChanged", renderer.currentLocationCfi);
|
|
||||||
|
|
||||||
renderer.visible(true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
renderer.contentWindow.addEventListener("resize", renderer.onResized.bind(renderer), false);
|
|
||||||
renderer.addIframeListeners();
|
|
||||||
renderer.addSelectionListeners();
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.setStyle = function(style, val, prefixed){
|
|
||||||
if(prefixed) {
|
|
||||||
style = EPUBJS.core.prefixed(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.bodyEl) this.bodyEl.style[style] = val;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.removeStyle = function(style){
|
|
||||||
|
|
||||||
if(this.bodyEl) this.bodyEl.style[style] = '';
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.applyStyles = function() {
|
|
||||||
var styles = this.book.settings.styles;
|
|
||||||
|
|
||||||
for (var style in styles) {
|
|
||||||
this.setStyle(style, styles[style]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.addHeadTag = function(tag, attrs) {
|
|
||||||
var s = document.createElement(tag);
|
|
||||||
|
|
||||||
for(attr in attrs) {
|
|
||||||
s[attr] = attrs[attr];
|
|
||||||
}
|
|
||||||
this.headEl.appendChild(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.applyHeadTags = function() {
|
|
||||||
|
|
||||||
var headTags = this.book.settings.headTags;
|
|
||||||
|
|
||||||
for ( var headTag in headTags ) {
|
|
||||||
this.addHeadTag(headTag, headTags[headTag])
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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() {
|
|
||||||
|
|
||||||
if(this.docEl) this.totalWidth = this.docEl.scrollWidth;
|
|
||||||
|
|
||||||
this.displayedPages = Math.ceil(this.totalWidth / this.spreadWidth);
|
|
||||||
|
|
||||||
this.currentChapter.pages = this.displayedPages;
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.setLeft = function(leftPos){
|
|
||||||
// this.bodyEl.style.marginLeft = -leftPos + "px";
|
|
||||||
// this.docEl.style.marginLeft = -leftPos + "px";
|
|
||||||
// this.docEl.style[EPUBJS.Renderer.transform] = 'translate('+ (-leftPos) + 'px, 0)';
|
|
||||||
this.doc.defaultView.scrollTo(leftPos, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.determineStore = function(callback){
|
|
||||||
if(this.book.fromStorage) {
|
|
||||||
|
|
||||||
//-- Filesystem api links are relative, so no need to replace them
|
|
||||||
if(this.book.storage.getStorageType() == "filesystem") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.book.store;
|
|
||||||
|
|
||||||
} else if(this.book.contained) {
|
|
||||||
|
|
||||||
return this.book.zip;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.beforeDisplay = function(callback){
|
|
||||||
this.book.triggerHooks("beforeChapterDisplay", callback.bind(this), this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.height = function(el){
|
|
||||||
return this.docEl.offsetHeight;
|
|
||||||
};
|
|
||||||
|
|
||||||
EPUBJS.Renderer.prototype.remove = function() {
|
|
||||||
this.contentWindow.removeEventListener("resize", this.resize);
|
|
||||||
this.removeIframeListeners();
|
|
||||||
this.removeSelectionListeners();
|
|
||||||
this.el.removeChild(this.iframe);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-- Enable binding events to Renderer
|
//-- Enable binding events to Renderer
|
||||||
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
|
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
|
||||||
|
|
|
@ -1,6 +1,33 @@
|
||||||
var EPUBJS = EPUBJS || {};
|
var EPUBJS = EPUBJS || {};
|
||||||
EPUBJS.replace = {};
|
EPUBJS.replace = {};
|
||||||
|
|
||||||
|
//-- Replaces the relative links within the book to use our internal page changer
|
||||||
|
EPUBJS.replace.hrefs = function(callback, renderer){
|
||||||
|
var replacments = function(link, done){
|
||||||
|
var href = link.getAttribute("href"),
|
||||||
|
relative = href.search("://"),
|
||||||
|
fragment = href[0] == "#";
|
||||||
|
|
||||||
|
if(relative != -1){
|
||||||
|
|
||||||
|
link.setAttribute("target", "_blank");
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
link.onclick = function(){
|
||||||
|
renderer.book.goto(href);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer.replace("a[href]", replacments, callback);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
EPUBJS.replace.head = function(callback, renderer) {
|
EPUBJS.replace.head = function(callback, renderer) {
|
||||||
|
|
||||||
renderer.replaceWithStored("link[href]", "href", EPUBJS.replace.links, callback);
|
renderer.replaceWithStored("link[href]", "href", EPUBJS.replace.links, callback);
|
||||||
|
@ -73,7 +100,7 @@ EPUBJS.replace.stylesheets = function(_store, full) {
|
||||||
EPUBJS.replace.cssUrls = function(_store, base, text){
|
EPUBJS.replace.cssUrls = function(_store, base, text){
|
||||||
var deferred = new RSVP.defer(),
|
var deferred = new RSVP.defer(),
|
||||||
promises = [],
|
promises = [],
|
||||||
matches = text.match(/url\(\'?\"?([^\'|^\"]*)\'?\"?\)/g);
|
matches = text.match(/url\(\'?\"?([^\'|^\"|^\)]*)\'?\"?\)/g);
|
||||||
|
|
||||||
if(!_store) return;
|
if(!_store) return;
|
||||||
|
|
||||||
|
@ -86,8 +113,6 @@ EPUBJS.replace.cssUrls = function(_store, base, text){
|
||||||
var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]/g, ''));
|
var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]/g, ''));
|
||||||
var replaced = _store.getUrl(full).then(function(url){
|
var replaced = _store.getUrl(full).then(function(url){
|
||||||
text = text.replace(str, 'url("'+url+'")');
|
text = text.replace(str, 'url("'+url+'")');
|
||||||
}, function(e) {
|
|
||||||
console.error(e);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
promises.push(replaced);
|
promises.push(replaced);
|
||||||
|
|
|
@ -55,8 +55,11 @@ EPUBJS.Unarchiver.prototype.getUrl = function(url, mime){
|
||||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||||
|
|
||||||
if(!entry) {
|
if(!entry) {
|
||||||
console.error("File not found in the epub:", url);
|
deferred.reject({
|
||||||
return;
|
message : "File not found in the epub: " + url,
|
||||||
|
stack : new Error().stack
|
||||||
|
});
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(url in this.urlCache) {
|
if(url in this.urlCache) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue