1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-03 14:59:18 +02:00

comments and js linted

This commit is contained in:
Fred Chasen 2014-01-21 20:34:29 -08:00
parent 0398b5eedf
commit 3fb0b5de30
12 changed files with 307 additions and 234 deletions

View file

@ -36,12 +36,43 @@ module.exports = function(grunt) {
'build/libs/screenfull.min.js': ['libs/screenfull.min.js'] 'build/libs/screenfull.min.js': ['libs/screenfull.min.js']
} }
} }
},
jshint: {
all: ['src/**/*.js'],//, 'reader/**/*.js']
options : {
// Environments
"browser": true,
"devel": true,
"worker": true,
// Enforcing
//"maxlen": 80,
//"quotmark": "single",
"trailing": true,
"strict": false,
// Relaxing
"boss": true,
"funcscope": true,
"globalstrict": true,
"loopfunc": true,
"maxerr": 1000,
"nonstandard": true,
"sub": true,
"validthis": true,
"globals": {
"_": false,
"define" : false,
"module" : false
}
}
} }
}); });
grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
// Default task(s). // Default task(s).
grunt.registerTask('default', ['concat', 'uglify']); grunt.registerTask('default', ['concat', 'uglify']);
}; };

View file

@ -67,8 +67,8 @@ EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, rend
//-- Add hide on page change //-- Add hide on page change
// chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", hidePop); // chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", hidePop);
// chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", offPop); // chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", offPop);
chapter.book.on("renderer:pageChanged", hidePop, this); renderer.on("renderer:pageChanged", hidePop, this);
chapter.book.on("renderer:pageChanged", offPop, this); renderer.on("renderer:pageChanged", offPop, this);
// chapter.book.on("renderer:chapterDestroy", hidePop, this); // chapter.book.on("renderer:chapterDestroy", hidePop, this);
} }

View file

@ -40,7 +40,7 @@ EPUBJS.Hooks.register("beforeChapterDisplay").transculsions = function(callback,
//-- resize event //-- resize event
chapter.book.listenUntil("book:resized", "book:chapterDestroy", size); renderer.listenUntil("renderer:resized", "renderer:chapterUnloaded", size);
iframe.src = src; iframe.src = src;

View file

@ -10,6 +10,7 @@
"optimist": "~0.6.0", "optimist": "~0.6.0",
"portfinder": "~0.2.1", "portfinder": "~0.2.1",
"grunt-contrib-concat": "~0.3.0", "grunt-contrib-concat": "~0.3.0",
"grunt-contrib-uglify": "~0.2.2" "grunt-contrib-uglify": "~0.2.2",
"grunt-contrib-jshint": "~0.8.0"
} }
} }

View file

@ -1,7 +1,7 @@
EPUBJS.Book = function(options){ EPUBJS.Book = function(options){
var book = this; var book = this;
this.settings = _.defaults(options || {}, { this.settings = _.defaults(options || {}, {
bookPath : null, bookPath : null,
bookKey : null, bookKey : null,
@ -11,11 +11,11 @@ EPUBJS.Book = function(options){
saved : false, saved : false,
online : true, online : true,
contained : false, contained : false,
width : false, width : null,
height: false, height: null,
spread: null, spread: null,
layout : null, layout : null,
orientation : null, orientation : null,
minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always) minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)
version: 1, version: 1,
restore: false, restore: false,
@ -25,7 +25,7 @@ EPUBJS.Book = function(options){
headTags : {}, headTags : {},
withCredentials: false, withCredentials: false,
}); });
this.settings.EPUBJSVERSION = EPUBJS.VERSION; this.settings.EPUBJSVERSION = EPUBJS.VERSION;
this.spinePos = 0; this.spinePos = 0;
@ -40,13 +40,17 @@ EPUBJS.Book = function(options){
book:pageChanged book:pageChanged
*/ */
EPUBJS.Hooks.mixin(this); //-- Adds Hook methods to the Book prototype
//-- Get pre-registered hooks // Hooks will all return before triggering the callback.
this.getHooks("beforeChapterDisplay"); // EPUBJS.Hooks.mixin(this);
//-- Get pre-registered hooks for events
// this.getHooks("beforeChapterDisplay");
this.online = this.settings.online || navigator.onLine; this.online = this.settings.online || navigator.onLine;
this.networkListeners(); this.networkListeners();
this.store = false; //-- False if not using storage;
//-- Determine storage method //-- Determine storage method
//-- Override options: none | ram | websqldatabase | indexeddb | filesystem //-- Override options: none | ram | websqldatabase | indexeddb | filesystem
@ -79,8 +83,14 @@ EPUBJS.Book = function(options){
this._rendering = false; this._rendering = false;
this._displayQ = []; this._displayQ = [];
this.renderer = new EPUBJS.Renderer(this.settings.renderer, this.beforeDisplay.bind(this)); /**
* Creates a new renderer.
* The renderer will handle displaying the content using the method provided in the settings
*/
this.renderer = new EPUBJS.Renderer(this.settings.renderer);
//-- Set the width at which to switch from spreads to single pages
this.renderer.setMinSpreadWidth(this.settings.minSpreadWidth); this.renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
//-- Pass through the renderer events
this.listenToRenderer(this.renderer); this.listenToRenderer(this.renderer);
this.defer_opened = new RSVP.defer(); this.defer_opened = new RSVP.defer();
@ -89,7 +99,6 @@ EPUBJS.Book = function(options){
if(typeof this.settings.bookPath === 'string') { if(typeof this.settings.bookPath === 'string') {
this.open(this.settings.bookPath, this.settings.reload); this.open(this.settings.bookPath, this.settings.reload);
} }
window.addEventListener("beforeunload", this.unload.bind(this), false); window.addEventListener("beforeunload", this.unload.bind(this), false);
@ -110,21 +119,20 @@ EPUBJS.Book.prototype.open = function(bookPath, forceReload){
this.bookUrl = this.urlFrom(bookPath); this.bookUrl = this.urlFrom(bookPath);
if(this.settings.contained || this.isContained(bookPath)){ if(this.settings.contained || this.isContained(bookPath)){
this.settings.contained = this.contained = true; this.settings.contained = this.contained = true;
this.bookUrl = ''; this.bookUrl = '';
// return; //-- TODO: this need to be fixed and tested before enabling
epubpackage = this.unarchive(bookPath). epubpackage = this.unarchive(bookPath).
then(function(){ then(function(){
return book.loadPackage(); return book.loadPackage();
}); });
} else { } else {
epubpackage = this.loadPackage(); epubpackage = this.loadPackage();
} }
if(this.settings.restore && !forceReload){ if(this.settings.restore && !forceReload){
//-- Will load previous package json, or re-unpack if error //-- Will load previous package json, or re-unpack if error
epubpackage.then(function(packageXml) { epubpackage.then(function(packageXml) {
@ -201,7 +209,9 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
book.spine = book.contents.spine; book.spine = book.contents.spine;
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); if(!book.settings.bookKey) {
book.settings.bookKey = book.generateBookKey(book.metadata.identifier);
}
//-- Set Globbal Layout setting based on metadata //-- Set Globbal Layout setting based on metadata
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata); book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
@ -274,6 +284,7 @@ EPUBJS.Book.prototype.networkListeners = function(){
}; };
// Listen to all events the renderer triggers and pass them as book events
EPUBJS.Book.prototype.listenToRenderer = function(renderer){ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
var book = this; var book = this;
renderer.Events.forEach(function(eventName){ renderer.Events.forEach(function(eventName){
@ -347,7 +358,7 @@ EPUBJS.Book.prototype.unarchive = function(bookPath){
// } // }
this.zip = new EPUBJS.Unarchiver(); this.zip = new EPUBJS.Unarchiver();
this.store = this.zip; // Use zip storaged in ram
return this.zip.openZip(bookPath); return this.zip.openZip(bookPath);
}; };
@ -374,13 +385,7 @@ EPUBJS.Book.prototype.isSaved = function(bookKey) {
} }
}; };
EPUBJS.Book.prototype.setBookKey = function(identifier){ // Generates the Book Key using the identifer in the manifest or other string provided
if(!this.settings.bookKey) {
this.settings.bookKey = this.generateBookKey(identifier);
}
return this.settings.bookKey;
};
EPUBJS.Book.prototype.generateBookKey = function(identifier){ EPUBJS.Book.prototype.generateBookKey = function(identifier){
return "epubjs:" + EPUBJS.VERSION + ":" + window.location.host + ":" + identifier; return "epubjs:" + EPUBJS.VERSION + ":" + window.location.host + ":" + identifier;
}; };
@ -432,28 +437,28 @@ EPUBJS.Book.prototype.startDisplay = function(){
}else{ }else{
display = this.displayChapter(this.spinePos); display = this.displayChapter(this.spinePos);
} }
return display; return display;
}; };
EPUBJS.Book.prototype.restore = function(identifier){ EPUBJS.Book.prototype.restore = function(identifier){
var book = this, var book = this,
fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'], fetch = ['manifest', 'spine', 'metadata', 'cover', 'toc', 'spineNodeIndex', 'spineIndexByURL'],
reject = false, reject = false,
bookKey = this.setBookKey(identifier), bookKey = this.generateBookKey(identifier),
fromStore = localStorage.getItem(bookKey), fromStore = localStorage.getItem(bookKey),
len = fetch.length, len = fetch.length,
i; i;
if(this.settings.clearSaved) reject = true; if(this.settings.clearSaved) reject = true;
if(!reject && fromStore != 'undefined' && fromStore != null){ if(!reject && fromStore != 'undefined' && fromStore !== null){
book.contents = JSON.parse(fromStore); book.contents = JSON.parse(fromStore);
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
var item = fetch[i]; var item = fetch[i];
if(!book.contents[item]) { if(!book.contents[item]) {
reject = true; reject = true;
break; break;
@ -461,10 +466,11 @@ EPUBJS.Book.prototype.restore = function(identifier){
book[item] = book.contents[item]; book[item] = book.contents[item];
} }
} }
if(reject || !fromStore || !this.contents || !this.settings.contentsPath){ if(reject || !fromStore || !this.contents || !this.settings.contentsPath){
return false; return false;
}else{ }else{
this.settings.bookKey = bookKey;
this.ready.manifest.resolve(this.manifest); this.ready.manifest.resolve(this.manifest);
this.ready.spine.resolve(this.spine); this.ready.spine.resolve(this.spine);
this.ready.metadata.resolve(this.metadata); this.ready.metadata.resolve(this.metadata);
@ -475,17 +481,6 @@ 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,
@ -518,7 +513,7 @@ EPUBJS.Book.prototype.displayChapter = function(chap, end){
this.spinePos = pos; this.spinePos = pos;
//-- Create a new chapter //-- Create a new chapter
this.currentChapter = new EPUBJS.Chapter(this.spine[pos], this.determineStore()); this.currentChapter = new EPUBJS.Chapter(this.spine[pos], this.store);
this._rendering = true; this._rendering = true;
@ -531,7 +526,7 @@ EPUBJS.Book.prototype.displayChapter = function(chap, end){
}); });
} else if(end) { } else if(end) {
render.then(function(chapter){ render.then(function(chapter){
chapter.gotoChapterEnd(); chapter.lastPage();
}); });
} }
@ -606,23 +601,35 @@ EPUBJS.Book.prototype.getCurrentLocationCfi = function() {
}; };
EPUBJS.Book.prototype.gotoCfi = function(cfiString){ EPUBJS.Book.prototype.gotoCfi = function(cfiString){
var cfi = new EPUBJS.EpubCFI(cfiString); var cfi,
var spinePos = cfi.spinePos; spinePos,
var rendered; spineItem,
var deferred = new RSVP.defer(); rendered,
//if(!this.isRendered) return this._enqueue("gotoCfi", arguments); deferred;
if(!this.isRendered) { if(!this.isRendered) {
this.settings.previousLocationCfi = cfiString; this.settings.previousLocationCfi = cfiString;
return; return false;
} }
cfi = new EPUBJS.EpubCFI(cfiString);
spinePos = cfi.spinePos;
spineItem = this.spine[spinePos];
deferred = new RSVP.defer();
//-- If same chapter only stay on current chapter //-- If same chapter only stay on current chapter
if(this.currentChapter && this.spinePos === spinePos){ if(this.currentChapter && this.spinePos === spinePos){
this.renderer.gotoCfi(cfi); this.renderer.gotoCfi(cfi);
deferred.resolve(this.currentChapter); deferred.resolve(this.currentChapter);
return deferred.promise; return deferred.promise;
} else { } else {
this.currentChapter = new EPUBJS.Chapter(this.spine[spinePos], this.determineStore());
if(!spineItem || spinePos == -1) {
spinePos = 0;
spineItem = this.spine[spinePos];
}
this.currentChapter = new EPUBJS.Chapter(spineItem, this.store);
if(this.currentChapter) { if(this.currentChapter) {
this.spinePos = spinePos; this.spinePos = spinePos;
@ -762,9 +769,9 @@ EPUBJS.Book.prototype.useSpreads = function(use) {
if(this.isRendered) { if(this.isRendered) {
this.renderer.reformat(); this.renderer.reformat();
} }
}; };
EPUBJS.Book.prototype.unload = function(){ EPUBJS.Book.prototype.unload = function(){
@ -824,12 +831,12 @@ EPUBJS.Book.prototype.applyStyles = function(callback){
}; };
EPUBJS.Book.prototype._registerReplacements = function(){ EPUBJS.Book.prototype._registerReplacements = function(){
this.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true); this.renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true);
this.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs, true); this.renderer.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs, true);
if(this._needsAssetReplacement()) { if(this._needsAssetReplacement()) {
this.registerHook("beforeChapterDisplay", [ this.renderer.registerHook("beforeChapterDisplay", [
EPUBJS.replace.head, EPUBJS.replace.head,
EPUBJS.replace.resources, EPUBJS.replace.resources,
EPUBJS.replace.svg EPUBJS.replace.svg
@ -860,9 +867,6 @@ EPUBJS.Book.prototype._needsAssetReplacement = function(){
} }
}; };
EPUBJS.Book.prototype.beforeDisplay = function(callback, renderer){
this.triggerHooks("beforeChapterDisplay", callback.bind(this), this.renderer);
};
//-- http://www.idpf.org/epub/fxl/ //-- http://www.idpf.org/epub/fxl/
EPUBJS.Book.prototype.parseLayoutProperties = function(metadata){ EPUBJS.Book.prototype.parseLayoutProperties = function(metadata){
@ -873,7 +877,7 @@ EPUBJS.Book.prototype.parseLayoutProperties = function(metadata){
layout : layout, layout : layout,
spread : spread, spread : spread,
orientation : orientation orientation : orientation
} };
}; };
//-- Enable binding events to book //-- Enable binding events to book

View file

@ -101,7 +101,7 @@ EPUBJS.core.toArray = function(obj) {
return arr; return arr;
}; };
//-- Parse out the origin //-- Parse the different parts of a url, returning a object
EPUBJS.core.uri = function(url){ EPUBJS.core.uri = function(url){
var uri = { var uri = {
protocol : '', protocol : '',
@ -112,6 +112,7 @@ EPUBJS.core.uri = function(url){
base : '', base : '',
filename : '', filename : '',
extension : '', extension : '',
fragment : '',
href : url href : url
}, },
doubleSlash = url.indexOf('://'), doubleSlash = url.indexOf('://'),
@ -166,7 +167,8 @@ EPUBJS.core.uri = function(url){
return uri; return uri;
}; };
//-- Parse out the folder //-- Parse out the folder, will return everything before the last slash
EPUBJS.core.folder = function(url){ EPUBJS.core.folder = function(url){
var lastSlash = url.lastIndexOf('/'); var lastSlash = url.lastIndexOf('/');

View file

@ -1,13 +1,13 @@
EPUBJS.hooks = {}; EPUBJS.hooks = {};
EPUBJS.Hooks = (function(){ EPUBJS.Hooks = (function(){
function hooks(){}; function hooks(){}
//-- Get pre-registered hooks //-- Get pre-registered hooks
hooks.prototype.getHooks = function(){ hooks.prototype.getHooks = function(){
var plugs; var plugs;
this.hooks = {}; this.hooks = {};
Array.prototype.slice.call(arguments).forEach(function(arg){ Array.prototype.slice.call(arguments).forEach(function(arg){
this.hooks[arg] = []; this.hooks[arg] = [];
}, this); }, this);
for (var plugType in this.hooks) { for (var plugType in this.hooks) {

View file

@ -1,14 +1,15 @@
EPUBJS.Layout = EPUBJS.Layout || {}; EPUBJS.Layout = EPUBJS.Layout || {};
EPUBJS.Layout.Reflowable = function(documentElement, _width, _height){ EPUBJS.Layout.Reflowable = function(documentElement, _width, _height){
// Get the prefixed CSS commands
var columnAxis = EPUBJS.core.prefixed('columnAxis'); var columnAxis = EPUBJS.core.prefixed('columnAxis');
var columnGap = EPUBJS.core.prefixed('columnGap'); var columnGap = EPUBJS.core.prefixed('columnGap');
var columnWidth = EPUBJS.core.prefixed('columnWidth'); var columnWidth = EPUBJS.core.prefixed('columnWidth');
//-- Check the width and decied on columns //-- Check the width and decied on columns
var width = (_width % 2 == 0) ? _width : Math.floor(_width) - 1; var width = (_width % 2 === 0) ? _width : Math.floor(_width) - 1;
var section = Math.ceil(width / 8); var section = Math.ceil(width / 8);
var gap = (section % 2 == 0) ? section : section - 1; var gap = (section % 2 === 0) ? section : section - 1;
//-- Single Page //-- Single Page
var spreadWidth = (width + gap); var spreadWidth = (width + gap);
@ -16,12 +17,8 @@ EPUBJS.Layout.Reflowable = function(documentElement, _width, _height){
documentElement.style.width = "auto"; //-- reset width for calculations documentElement.style.width = "auto"; //-- reset width for calculations
documentElement.style.overflow = "hidden"; documentElement.style.overflow = "hidden";
documentElement.style.width = width + "px";
//-- Adjust height //-- Adjust height
documentElement.style.height = _height + "px"; documentElement.style.height = _height + "px";
@ -31,9 +28,9 @@ EPUBJS.Layout.Reflowable = function(documentElement, _width, _height){
documentElement.style[columnWidth] = width+"px"; documentElement.style[columnWidth] = width+"px";
totalWidth = documentElement.scrollWidth; totalWidth = documentElement.scrollWidth;
displayedPages = Math.ceil(totalWidth / spreadWidth); displayedPages = Math.ceil(totalWidth / spreadWidth);
// documentElement.style.width = totalWidth + spreadWidth + "px"; documentElement.style.width = width + "px";
return { return {
pageWidth : spreadWidth, pageWidth : spreadWidth,
@ -50,10 +47,10 @@ EPUBJS.Layout.ReflowableSpreads = function(documentElement, _width, _height){
var divisor = 2, var divisor = 2,
cutoff = 800; cutoff = 800;
//-- Check the width and decied on columns //-- Check the width and create even width columns
var width = (_width % 2 == 0) ? _width : Math.floor(_width) - 1; var width = (_width % 2 === 0) ? _width : Math.floor(_width) - 1;
var section = Math.ceil(width / 8); var section = Math.ceil(width / 8);
var gap = (section % 2 == 0) ? section : section - 1; var gap = (section % 2 === 0) ? section : section - 1;
//-- Double Page //-- Double Page
var colWidth = Math.floor((width - gap) / divisor); var colWidth = Math.floor((width - gap) / divisor);
@ -78,6 +75,7 @@ EPUBJS.Layout.ReflowableSpreads = function(documentElement, _width, _height){
totalWidth = documentElement.scrollWidth; totalWidth = documentElement.scrollWidth;
displayedPages = Math.ceil(totalWidth / spreadWidth); displayedPages = Math.ceil(totalWidth / spreadWidth);
//-- Add a page to the width of the document to account an for odd number of pages
documentElement.style.width = totalWidth + spreadWidth + "px"; documentElement.style.width = totalWidth + spreadWidth + "px";
return { return {
@ -89,26 +87,40 @@ EPUBJS.Layout.ReflowableSpreads = function(documentElement, _width, _height){
EPUBJS.Layout.Fixed = function(documentElement, _width, _height){ EPUBJS.Layout.Fixed = function(documentElement, _width, _height){
var columnWidth = EPUBJS.core.prefixed('columnWidth'); var columnWidth = EPUBJS.core.prefixed('columnWidth');
var viewport = documentElement.querySelector("[name=viewport");
var totalWidth = documentElement.scrollWidth; var content;
var totalHeight = documentElement.scrollHeight; var contents;
var width, height;
documentElement.style.width = _width;
//-- Adjust height /**
documentElement.style.height = "auto"; * check for the viewport size
* <meta name="viewport" content="width=1024,height=697" />
*/
if(viewport && viewport.hasAttribute("content")) {
content = viewport.getAttribute("content");
contents = content.split(',');
if(contents[0]){
width = contents[0].replace("width=", '');
}
if(contents[1]){
height = contents[1].replace("height=", '');
}
}
//-- Adjust width and height
documentElement.style.width = width + "px" || "auto";
documentElement.style.height = height + "px" || "auto";
//-- Remove columns //-- Remove columns
documentElement.style[columnWidth] = "auto"; documentElement.style[columnWidth] = "auto";
//-- Scroll //-- Scroll
documentElement.style.overflow = "auto"; documentElement.style.overflow = "auto";
// this.iframe.scrolling = "yes";
// this.displayedPages = 1;
return { return {
pageWidth : totalWidth, pageWidth : width,
pageHeight : totalHeight, pageHeight : height,
displayedPages : 1 displayedPages : 1
}; };

View file

@ -213,8 +213,8 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
var spineNodeIndex = Array.prototype.indexOf.call(spineXml.parentNode.childNodes, spineXml); var spineNodeIndex = Array.prototype.indexOf.call(spineXml.parentNode.childNodes, spineXml);
var epubcfi = new EPUBJS.EpubCFI(); 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');
@ -295,8 +295,8 @@ EPUBJS.Parser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){
if(!id) { if(!id) {
if(spinePos) { if(spinePos) {
spineItem = bookSpine[spinePos]; spineItem = bookSpine[spinePos];
id = spineItem.id id = spineItem.id;
} else { } else {
id = 'epubjs-autogen-toc-id-' + (idCounter++); id = 'epubjs-autogen-toc-id-' + (idCounter++);
} }
@ -325,7 +325,6 @@ EPUBJS.Parser.prototype.toc = function(tocXml, spineIndexByURL, bookSpine){
function getTOC(parent){ function getTOC(parent){
var list = [], var list = [],
items = [],
nodes = parent.querySelectorAll("navPoint"), nodes = parent.querySelectorAll("navPoint"),
items = Array.prototype.slice.call(nodes).reverse(), items = Array.prototype.slice.call(nodes).reverse(),
length = items.length, length = items.length,
@ -349,7 +348,7 @@ EPUBJS.Parser.prototype.toc = function(tocXml, spineIndexByURL, bookSpine){
if(!id) { if(!id) {
if(spinePos) { if(spinePos) {
spineItem = bookSpine[spinePos]; spineItem = bookSpine[spinePos];
id = spineItem.id id = spineItem.id;
} else { } else {
id = 'epubjs-autogen-toc-id-' + (idCounter++); id = 'epubjs-autogen-toc-id-' + (idCounter++);
} }

View file

@ -1,9 +1,9 @@
EPUBJS.Render.Iframe = function() { EPUBJS.Render.Iframe = function() {
this.iframe; this.iframe = null;
this.document; this.document = null;
this.window; this.window = null;
this.docEl; this.docEl = null;
this.bodyEl; this.bodyEl = null;
this.leftPos = 0; this.leftPos = 0;
this.pageWidth = 0; this.pageWidth = 0;
@ -18,6 +18,11 @@ EPUBJS.Render.Iframe.prototype.create = function(){
return this.iframe; return this.iframe;
}; };
/**
* Sets the source of the iframe with the given URL string
* Takes: URL string
* Returns: promise with document element
*/
EPUBJS.Render.Iframe.prototype.load = function(url){ EPUBJS.Render.Iframe.prototype.load = function(url){
var render = this, var render = this,
deferred = new RSVP.defer(); deferred = new RSVP.defer();
@ -41,15 +46,21 @@ EPUBJS.Render.Iframe.prototype.load = function(url){
//-- Clear Margins //-- Clear Margins
if(render.bodyEl) render.bodyEl.style.margin = "0"; if(render.bodyEl) render.bodyEl.style.margin = "0";
deferred.resolve(render.docEl); deferred.resolve(render.docEl);
}; };
this.iframe.onerror = function(e) { this.iframe.onerror = function(e) {
console.error("Error Loading Contents", e); console.error("Error Loading Contents", e);
} deferred.reject({
message : "Error Loading Contents: " + e,
stack : new Error().stack
});
};
return deferred.promise; return deferred.promise;
}; };
// Resize the iframe to the given width and height
EPUBJS.Render.Iframe.prototype.resize = function(width, height){ EPUBJS.Render.Iframe.prototype.resize = function(width, height){
var iframeBox; var iframeBox;
@ -62,13 +73,14 @@ EPUBJS.Render.Iframe.prototype.resize = function(width, height){
} }
this.iframe.width = width; this.iframe.width = width;
// Get the fractional height and width of the iframe
this.width = this.iframe.getBoundingClientRect().width; this.width = this.iframe.getBoundingClientRect().width;
this.height = this.iframe.getBoundingClientRect().height; this.height = this.iframe.getBoundingClientRect().height;
}; };
EPUBJS.Render.Iframe.prototype.resized = function(e){ EPUBJS.Render.Iframe.prototype.resized = function(e){
// Get the fractional height and width of the iframe
this.width = this.iframe.getBoundingClientRect().width; this.width = this.iframe.getBoundingClientRect().width;
this.height = this.iframe.getBoundingClientRect().height; this.height = this.iframe.getBoundingClientRect().height;
}; };
@ -95,16 +107,6 @@ EPUBJS.Render.Iframe.prototype.setLeft = function(leftPos){
this.document.defaultView.scrollTo(leftPos, 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){ EPUBJS.Render.Iframe.prototype.setStyle = function(style, val, prefixed){
if(prefixed) { if(prefixed) {
style = EPUBJS.core.prefixed(style); style = EPUBJS.core.prefixed(style);
@ -136,18 +138,19 @@ EPUBJS.Render.Iframe.prototype.getPageNumberByElement = function(el){
return pg; return pg;
}; };
//-- // Return the root element of the content
EPUBJS.Render.Iframe.prototype.getBaseElement = function(){ EPUBJS.Render.Iframe.prototype.getBaseElement = function(){
return this.bodyEl; return this.bodyEl;
}; };
// Checks if an element is on the screen
EPUBJS.Render.Iframe.prototype.isElementVisible = function(el){ EPUBJS.Render.Iframe.prototype.isElementVisible = function(el){
var rect; var rect;
if(el && typeof el.getBoundingClientRect === 'function'){ if(el && typeof el.getBoundingClientRect === 'function'){
rect = el.getBoundingClientRect(); rect = el.getBoundingClientRect();
if( rect.width != 0 && if( rect.width !== 0 &&
rect.height != 0 && rect.height !== 0 && // Element not visible
rect.left >= 0 && rect.left >= 0 &&
rect.left < this.pageWidth ) { rect.left < this.pageWidth ) {
return true; return true;
@ -166,6 +169,7 @@ EPUBJS.Render.Iframe.prototype.scroll = function(bool){
} }
}; };
// Cleanup event listeners
EPUBJS.Render.Iframe.prototype.unload = function(){ EPUBJS.Render.Iframe.prototype.unload = function(){
this.window.removeEventListener("resize", this.resized); this.window.removeEventListener("resize", this.resized);
}; };

View file

@ -1,38 +1,53 @@
EPUBJS.Renderer = function(type, beforeDisplay) { EPUBJS.Renderer = function(type) {
this.beforeDisplay = beforeDisplay; // Dom events to listen for
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"]; this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
/**
* Setup a render method.
* Options are: Iframe
*/
if(type && typeof(EPUBJS.Render[type]) != "undefined"){ if(type && typeof(EPUBJS.Render[type]) != "undefined"){
this.render = new EPUBJS.Render[type]; this.render = new EPUBJS.Render[type]() ;
} else { } else {
console.error("Not a Valid Rendering Method"); console.error("Not a Valid Rendering Method");
} }
this.caches = {};
// Cached for replacement urls from storage
this.caches = {};
// Blank Cfi for Parsing
this.epubcfi = new EPUBJS.EpubCFI(); this.epubcfi = new EPUBJS.EpubCFI();
this.spreads = true; this.spreads = true;
this.resized = _.throttle(this.onResized.bind(this), 10); this.resized = _.throttle(this.onResized.bind(this), 10);
//-- Adds Hook methods to the Book prototype
// Hooks will all return before triggering the callback.
EPUBJS.Hooks.mixin(this);
//-- Get pre-registered hooks for events
this.getHooks("beforeChapterDisplay");
}; };
//-- Renderer events for listening //-- Renderer events for listening
EPUBJS.Renderer.prototype.Events = [ EPUBJS.Renderer.prototype.Events = [
"renderer:keydown", "renderer:keydown",
"renderer:keyup", "renderer:keyup",
"renderer:keypressed", "renderer:keypressed",
"renderer:mouseup", "renderer:mouseup",
"renderer:mousedown", "renderer:mousedown",
"renderer:click", "renderer:click",
"renderer:selected", "renderer:selected",
"renderer:chapterUnloaded", "renderer:chapterUnloaded",
"renderer:chapterDisplayed", "renderer:chapterDisplayed",
"renderer:pageChanged", "renderer:pageChanged",
"renderer:resized", "renderer:resized",
"renderer:spreads" "renderer:spreads"
]; ];
/**
* Creates an element to render to.
* Resizes to passed width and height or to the elements size
*/
EPUBJS.Renderer.prototype.initialize = function(element, width, height){ EPUBJS.Renderer.prototype.initialize = function(element, width, height){
this.container = element; this.container = element;
this.element = this.render.create(); this.element = this.render.create();
@ -53,14 +68,18 @@ EPUBJS.Renderer.prototype.initialize = function(element, width, height){
}; };
/**
* Display a chapter
* Takes: chapter object, global layout settings
* Returns: Promise with passed Renderer after pages has loaded
*/
EPUBJS.Renderer.prototype.displayChapter = function(chapter, globalLayout){ EPUBJS.Renderer.prototype.displayChapter = function(chapter, globalLayout){
var renderer = this, var renderer = this,
store = false; store = false;
// Unload the previous chapter listener
if(this.currentChapter) { if(this.currentChapter) {
this.currentChapter.unload(); this.currentChapter.unload(); // Remove stored blobs
this.render.window.removeEventListener("resize", this.resized); this.render.window.removeEventListener("resize", this.resized);
this.removeEventListeners(); this.removeEventListeners();
this.removeSelectionListeners(); this.removeSelectionListeners();
@ -73,9 +92,8 @@ EPUBJS.Renderer.prototype.displayChapter = function(chapter, globalLayout){
this.currentChapterCfiBase = chapter.cfiBase; this.currentChapterCfiBase = chapter.cfiBase;
this.settings = this.reconcileLayoutSettings(globalLayout, chapter.properties); this.settings = this.reconcileLayoutSettings(globalLayout, chapter.properties);
// Get the url string from the chapter (may be from storage)
return chapter.url(). return chapter.url().
then(function(url) { then(function(url) {
return renderer.load(url); return renderer.load(url);
@ -83,8 +101,63 @@ EPUBJS.Renderer.prototype.displayChapter = function(chapter, globalLayout){
}; };
/**
* Loads a url (string) and renders it,
* attaching event listeners and triggering hooks.
* Returns: Promise with the rendered contents.
*/
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;
};
/**
* Reconciles the current chapters layout properies with
* the global layout properities.
* Takes: global layout settings object, chapter properties string
* Returns: Object with layout properties
*/
EPUBJS.Renderer.prototype.reconcileLayoutSettings = function(global, chapter){ EPUBJS.Renderer.prototype.reconcileLayoutSettings = function(global, chapter){
var layoutMethod = "ReflowableSpreads"; var layoutMethod = "ReflowableSpreads"; // Default to Spreads
var properties = chapter.split(' '); var properties = chapter.split(' ');
var settings = {}; var settings = {};
var spreads = true; var spreads = true;
@ -112,6 +185,11 @@ EPUBJS.Renderer.prototype.reconcileLayoutSettings = function(global, chapter){
return settings; return settings;
}; };
/**
* Uses the settings to determine which Layout Method is needed
* Takes: Layout settings object
* Returns: EPUBJS.Layout function
*/
EPUBJS.Renderer.prototype.determineLayout = function(settings){ EPUBJS.Renderer.prototype.determineLayout = function(settings){
var layoutMethod = "ReflowableSpreads"; var layoutMethod = "ReflowableSpreads";
@ -152,57 +230,19 @@ EPUBJS.Renderer.prototype.determineLayout = function(settings){
}; };
EPUBJS.Renderer.prototype.load = function(url){ // Shortcut to trigger the hook before displaying the chapter
var deferred = new RSVP.defer(); EPUBJS.Renderer.prototype.beforeDisplay = function(callback, renderer){
var loaded; this.triggerHooks("beforeChapterDisplay", callback, this);
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;
}; };
// Update the renderer with the information passed by the layout
EPUBJS.Renderer.prototype.updatePages = function(layout){ EPUBJS.Renderer.prototype.updatePages = function(layout){
this.displayedPages = layout.displayedPages; this.displayedPages = layout.displayedPages;
this.currentChapter.pages = layout.displayedPages; this.currentChapter.pages = layout.displayedPages;
this.render.setPageDimensions(layout.pageWidth, layout.pageHeight); this.render.setPageDimensions(layout.pageWidth, layout.pageHeight);
}; };
// Apply the layout again and jump back to the previous cfi position
EPUBJS.Renderer.prototype.reformat = function(){ EPUBJS.Renderer.prototype.reformat = function(){
var renderer = this; var renderer = this;
if(!this.contents) return; if(!this.contents) return;
@ -221,6 +261,7 @@ EPUBJS.Renderer.prototype.reformat = function(){
}; };
// Hide and show the render's container element.
EPUBJS.Renderer.prototype.visible = function(bool){ EPUBJS.Renderer.prototype.visible = function(bool){
if(typeof(bool) === "undefined") { if(typeof(bool) === "undefined") {
return this.container.style.visibility; return this.container.style.visibility;
@ -233,6 +274,7 @@ EPUBJS.Renderer.prototype.visible = function(bool){
} }
}; };
// Remove the render element and clean up listeners
EPUBJS.Renderer.prototype.remove = function() { EPUBJS.Renderer.prototype.remove = function() {
if(this.renderer.window) { if(this.renderer.window) {
this.render.unload(); this.render.unload();
@ -262,15 +304,6 @@ EPUBJS.Renderer.prototype.removeStyle = function(style){
//-- NAVIGATION //-- 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){ EPUBJS.Renderer.prototype.page = function(pg){
if(pg >= 1 && pg <= this.displayedPages){ if(pg >= 1 && pg <= this.displayedPages){
this.chapterPos = pg; this.chapterPos = pg;
@ -286,6 +319,7 @@ EPUBJS.Renderer.prototype.page = function(pg){
return false; return false;
}; };
// Short cut to find next page's cfi starting at the last visible element
EPUBJS.Renderer.prototype.nextPage = function(){ EPUBJS.Renderer.prototype.nextPage = function(){
var pg = this.chapterPos + 1; var pg = this.chapterPos + 1;
if(pg <= this.displayedPages){ if(pg <= this.displayedPages){
@ -293,7 +327,7 @@ EPUBJS.Renderer.prototype.nextPage = function(){
this.render.page(pg); this.render.page(pg);
this.currentLocationCfi = this.getNextPageCfi(); this.currentLocationCfi = this.getPageCfi(this.visibileEl);
this.trigger("renderer:pageChanged", this.currentLocationCfi); this.trigger("renderer:pageChanged", this.currentLocationCfi);
return true; return true;
@ -306,11 +340,17 @@ EPUBJS.Renderer.prototype.prevPage = function(){
return this.page(this.chapterPos - 1); return this.page(this.chapterPos - 1);
}; };
EPUBJS.Renderer.prototype.gotoChapterEnd = function(){ //-- Show the page containing an Element
this.chapterEnd(); EPUBJS.Renderer.prototype.pageByElement = function(el){
var pg;
if(!el) return;
pg = this.render.getPageNumberByElement(el);
this.page(pg);
}; };
EPUBJS.Renderer.prototype.chapterEnd = function(){ // Jump to the last page of the chapter
EPUBJS.Renderer.prototype.lastPage = function(){
this.page(this.displayedPages); this.page(this.displayedPages);
}; };
@ -325,7 +365,7 @@ EPUBJS.Renderer.prototype.section = function(fragment){
}; };
// Walk the node tree from an element to the root
EPUBJS.Renderer.prototype.walk = function(node) { EPUBJS.Renderer.prototype.walk = function(node) {
var r, children, leng, var r, children, leng,
startNode = node, startNode = node,
@ -371,28 +411,14 @@ EPUBJS.Renderer.prototype.walk = function(node) {
return r; return r;
}; };
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(){ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
// 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); this.visibileEl = this.findFirstVisible(prevEl);
return this.epubcfi.generateFragment(this.visibileEl, this.currentChapter.cfiBase); return this.epubcfi.generateFragment(this.visibileEl, this.currentChapter.cfiBase);
}; };
// Goto a cfi position in the current chapter
EPUBJS.Renderer.prototype.gotoCfi = function(cfi){ EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
var element; var element;
@ -404,6 +430,7 @@ EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
this.pageByElement(element); this.pageByElement(element);
}; };
// Walk nodes until a visible element is found
EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){ EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
var el = startEl || this.render.getBaseElement(); var el = startEl || this.render.getBaseElement();
var found; var found;
@ -418,7 +445,6 @@ EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
}; };
/* /*
EPUBJS.Renderer.prototype.route = function(hash, callback){ EPUBJS.Renderer.prototype.route = function(hash, callback){
var location = window.location.hash.replace('#/', ''); var location = window.location.hash.replace('#/', '');
if(this.useHash && location.length && location != this.prevLocation){ if(this.useHash && location.length && location != this.prevLocation){
@ -449,7 +475,7 @@ EPUBJS.Renderer.prototype.onResized = function(e){
this.layoutMethod = this.determineLayout(this.settings); this.layoutMethod = this.determineLayout(this.settings);
} }
if(this.contents){ if(this.contents){
this.reformat(); this.reformat();
} }
@ -476,6 +502,7 @@ EPUBJS.Renderer.prototype.removeEventListeners = function(){
}; };
// Pass browser events
EPUBJS.Renderer.prototype.triggerEvent = function(e){ EPUBJS.Renderer.prototype.triggerEvent = function(e){
this.trigger("renderer:"+e.type, e); this.trigger("renderer:"+e.type, e);
}; };
@ -494,6 +521,7 @@ EPUBJS.Renderer.prototype.onSelectionChange = function(e){
this.highlighted = true; this.highlighted = true;
}; };
// only pass selection on mouse up
EPUBJS.Renderer.prototype.onMouseUp = function(e){ EPUBJS.Renderer.prototype.onMouseUp = function(e){
var selection; var selection;
if(this.highlighted) { if(this.highlighted) {
@ -505,14 +533,6 @@ EPUBJS.Renderer.prototype.onMouseUp = function(e){
//-- Spreads //-- Spreads
// 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){ EPUBJS.Renderer.prototype.setMinSpreadWidth = function(width){
this.minSpreadWidth = width; this.minSpreadWidth = width;
@ -520,7 +540,7 @@ EPUBJS.Renderer.prototype.setMinSpreadWidth = function(width){
EPUBJS.Renderer.prototype.determineSpreads = function(cutoff){ EPUBJS.Renderer.prototype.determineSpreads = function(cutoff){
if(this.width < cutoff || !cutoff) { if(this.width < cutoff || !cutoff) {
return false; //-- Single Page return false; //-- Single Page
}else{ }else{
return true; //-- Double Page return true; //-- Double Page
} }

View file

@ -29,7 +29,7 @@ asyncTest("Fit to given width and height", 3, function() {
equal( $iframe.width(), 400, "iframe had correct width" ); equal( $iframe.width(), 400, "iframe had correct width" );
equal( $iframe.height(), 600, "iframe has correct height" ); equal( $iframe.height(), 600, "iframe has correct height" );
start(); start();
}; };