1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-04 15:09:16 +02:00

Added basic pagination

This commit is contained in:
Fred Chasen 2014-08-28 17:05:13 -04:00
parent 1a89a9c3ff
commit 816880d328
12 changed files with 1289 additions and 373 deletions

13
API.js
View file

@ -116,4 +116,15 @@ section.find("query");
epub.on("noAuth", function(){ epub.on("noAuth", function(){
}); });
rendition = epub.renderTo("elementID", {});
pagination = rendition.paginate({});
pagination = new EPUBJS.Paginate(rendition, {spreads: true, minwidth: 800, layout: {} });
layout = new EPUBJS.Layout(global);
pagination.next();
pagination.prev();
pagination.page();
pagination.map();

744
dist/epub.js vendored
View file

@ -4401,9 +4401,9 @@ EPUBJS.Book.prototype.section = function(target) {
// Sugar to render a book // Sugar to render a book
EPUBJS.Book.prototype.renderTo = function(element, options) { EPUBJS.Book.prototype.renderTo = function(element, options) {
var rendition = new EPUBJS.Renderer(this, options); this.rendition = new EPUBJS.Renderer(this, options);
rendition.attachTo(element); this.rendition.attachTo(element);
return rendition; return this.rendition;
}; };
EPUBJS.Book.prototype.requestMethod = function(_url) { EPUBJS.Book.prototype.requestMethod = function(_url) {
@ -4744,7 +4744,37 @@ EPUBJS.core.documentHeight = function() {
EPUBJS.core.isNumber = function(n) { EPUBJS.core.isNumber = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n); return !isNaN(parseFloat(n)) && isFinite(n);
} };
EPUBJS.core.prefixed = function(unprefixed) {
var vendors = ["Webkit", "Moz", "O", "ms" ],
prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],
upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),
length = vendors.length;
if (typeof(document.body.style[unprefixed]) != 'undefined') {
return unprefixed;
}
for ( var i=0; i < length; i++ ) {
if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {
return vendors[i] + upper;
}
}
return unprefixed;
};
EPUBJS.core.defaults = function(obj) {
for (var i = 1, length = arguments.length; i < length; i++) {
var source = arguments[i];
for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
}
return obj;
};
EPUBJS.EpubCFI = function(cfiStr){ EPUBJS.EpubCFI = function(cfiStr){
if(cfiStr) return this.parse(cfiStr); if(cfiStr) return this.parse(cfiStr);
}; };
@ -5291,16 +5321,17 @@ EPUBJS.Hook.prototype.trigger = function(){
return executing; return executing;
}; };
EPUBJS.Infinite = function(container, renderer){ EPUBJS.Infinite = function(container, axis){
this.container = container; this.container = container;
this.windowHeight = window.innerHeight; this.windowHeight = window.innerHeight;
this.tick = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; this.tick = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
this.scrolled = false; this.scrolled = false;
this.ignore = false; this.ignore = false;
this.displaying = false; this.displaying = false;
this.offset = 350; this.offset = 900;
this.views = []; this.views = [];
this.renderer = renderer; this.axis = axis;
// this.renderer = renderer;
this.prevScrollTop = 0; this.prevScrollTop = 0;
}; };
@ -5342,12 +5373,25 @@ EPUBJS.Infinite.prototype.check = function(){
if(this.scrolled && !this.displaying) { if(this.scrolled && !this.displaying) {
if(this.axis === "vertical") {
this.checkTop();
} else {
this.checkLeft();
}
this.scrolled = false;
} else {
this.displaying = false;
this.scrolled = false;
}
this.tick.call(window, this.check.bind(this));
}
EPUBJS.Infinite.prototype.checkTop = function(){
var scrollTop = this.container.scrollTop; var scrollTop = this.container.scrollTop;
var scrollLeft = this.container.scrollLeft;
var scrollHeight = this.container.scrollHeight; var scrollHeight = this.container.scrollHeight;
var scrollWidth = this.container.scrollWidth;
var direction = scrollTop - this.prevScrollTop; var direction = scrollTop - this.prevScrollTop;
var height = this.container.getBoundingClientRect().height; var height = this.container.getBoundingClientRect().height;
@ -5366,14 +5410,36 @@ EPUBJS.Infinite.prototype.check = function(){
// console.log(scrollTop) // console.log(scrollTop)
this.prevScrollTop = scrollTop; this.prevScrollTop = scrollTop;
this.scrolled = false; return scrollTop;
} else { };
this.displaying = false;
this.scrolled = false;
}
this.tick.call(window, this.check.bind(this)); EPUBJS.Infinite.prototype.checkLeft = function(){
}
var scrollLeft = this.container.scrollLeft;
var scrollWidth = this.container.scrollWidth;
var direction = scrollLeft - this.prevscrollLeft;
var width = this.container.getBoundingClientRect().width;
var right = scrollLeft + this.offset > scrollWidth-width;
var left = scrollLeft < this.offset;
// Add to bottom
if(right && direction > 0) {
this.forwards();
}
// Add to top
else if(left && direction < 0) {
this.backwards();
}
// console.log(scrollTop)
this.prevscrollLeft = scrollLeft;
return scrollLeft;
};
EPUBJS.Infinite.prototype.scrollBy = function(x, y, silent){ EPUBJS.Infinite.prototype.scrollBy = function(x, y, silent){
if(silent) { if(silent) {
@ -5381,6 +5447,9 @@ EPUBJS.Infinite.prototype.scrollBy = function(x, y, silent){
} }
this.container.scrollLeft += x; this.container.scrollLeft += x;
this.container.scrollTop += y; this.container.scrollTop += y;
this.scrolled = true;
this.check();
}; };
EPUBJS.Infinite.prototype.scroll = function(x, y, silent){ EPUBJS.Infinite.prototype.scroll = function(x, y, silent){
@ -5389,106 +5458,189 @@ EPUBJS.Infinite.prototype.scroll = function(x, y, silent){
} }
this.container.scrollLeft = x; this.container.scrollLeft = x;
this.container.scrollTop = y; this.container.scrollTop = y;
this.scrolled = true;
this.check();
}; };
RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype); RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype);
EPUBJS.Layout = function(){}; EPUBJS.Layout = EPUBJS.Layout || {};
/** EPUBJS.Layout.Reflowable = function(){
* Reconciles the current chapters layout properies with this.documentElement = null;
* the global layout properities. this.spreadWidth = null;
* Takes: global layout settings object, chapter properties string };
* Returns: Object with layout properties
*/
EPUBJS.Layout.prototype.reconcileLayoutSettings = function(global, chapter){
var settings = {};
//-- Get the global defaults EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _height, _gap){
for (var attr in global) { // Get the prefixed CSS commands
if (global.hasOwnProperty(attr)){ var columnAxis = EPUBJS.core.prefixed('columnAxis');
settings[attr] = global[attr]; var columnGap = EPUBJS.core.prefixed('columnGap');
var columnWidth = EPUBJS.core.prefixed('columnWidth');
var columnFill = EPUBJS.core.prefixed('columnFill');
//-- Check the width and create even width columns
var width = Math.floor(_width);
// var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 0; // Not needed for single
var section = Math.floor(width / 8);
var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);
this.documentElement = documentElement;
//-- Single Page
this.spreadWidth = (width + gap);
documentElement.style.overflow = "hidden";
// Must be set to the new calculated width or the columns will be off
documentElement.style.width = width + "px";
//-- Adjust height
documentElement.style.height = _height + "px";
//-- Add columns
documentElement.style[columnAxis] = "horizontal";
documentElement.style[columnFill] = "auto";
documentElement.style[columnWidth] = width+"px";
documentElement.style[columnGap] = gap+"px";
this.colWidth = width;
this.gap = gap;
return {
pageWidth : this.spreadWidth,
pageHeight : _height
};
};
EPUBJS.Layout.Reflowable.prototype.calculatePages = function() {
var totalWidth, displayedPages;
this.documentElement.style.width = "auto"; //-- reset width for calculations
totalWidth = this.documentElement.scrollWidth;
displayedPages = Math.ceil(totalWidth / this.spreadWidth);
return {
displayedPages : displayedPages,
pageCount : displayedPages
};
};
EPUBJS.Layout.ReflowableSpreads = function(){
this.documentElement = null;
this.spreadWidth = null;
};
EPUBJS.Layout.ReflowableSpreads.prototype.format = function(view, _width, _height, _gap){
var columnAxis = EPUBJS.core.prefixed('columnAxis');
var columnGap = EPUBJS.core.prefixed('columnGap');
var columnWidth = EPUBJS.core.prefixed('columnWidth');
var columnFill = EPUBJS.core.prefixed('columnFill');
var divisor = 2,
cutoff = 800;
//-- Check the width and create even width columns
var fullWidth = Math.floor(_width);
var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;
var section = Math.floor(width / 8);
var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);
//-- Double Page
var colWidth = Math.floor((width - gap) / divisor);
this.spreadWidth = (colWidth + gap) * divisor;
view.document.documentElement.style.overflow = "hidden";
// Must be set to the new calculated width or the columns will be off
view.document.body.style.width = width + "px";
//-- Adjust height
view.document.body.style.height = _height + "px";
//-- Add columns
view.document.body.style[columnAxis] = "horizontal";
view.document.body.style[columnFill] = "auto";
view.document.body.style[columnGap] = gap+"px";
view.document.body.style[columnWidth] = colWidth+"px";
this.colWidth = colWidth;
this.gap = gap;
view.iframe.style.width = colWidth+"px";
view.iframe.style.paddingRight = gap+"px";
return {
pageWidth : this.spreadWidth,
pageHeight : _height
};
};
EPUBJS.Layout.ReflowableSpreads.prototype.calculatePages = function() {
var totalWidth = this.documentElement.scrollWidth;
var displayedPages = Math.ceil(totalWidth / this.spreadWidth);
//-- Add a page to the width of the document to account an for odd number of pages
this.documentElement.style.width = totalWidth + this.spreadWidth + "px";
return {
displayedPages : displayedPages,
pageCount : displayedPages * 2
};
};
EPUBJS.Layout.Fixed = function(){
this.documentElement = null;
};
EPUBJS.Layout.Fixed = function(documentElement, _width, _height, _gap){
var columnWidth = EPUBJS.core.prefixed('columnWidth');
var viewport = documentElement.querySelector("[name=viewport");
var content;
var contents;
var width, height;
this.documentElement = documentElement;
/**
* 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=", '');
} }
} }
//-- Get the chapter's display type
chapter.forEach(function(prop){
var rendition = prop.replace("rendition:", '');
var split = rendition.indexOf("-");
var property, value;
if(split != -1){ //-- Adjust width and height
property = rendition.slice(0, split); documentElement.style.width = width + "px" || "auto";
value = rendition.slice(split+1); documentElement.style.height = height + "px" || "auto";
//-- Remove columns
documentElement.style[columnWidth] = "auto";
//-- Scroll
documentElement.style.overflow = "auto";
this.colWidth = width;
this.gap = 0;
return {
pageWidth : width,
pageHeight : height
};
settings[property] = value;
}
});
return settings;
}; };
/** EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
* Uses the settings to determine which Layout Method is needed return {
* Triggers events based on the method choosen displayedPages : 1,
* Takes: Layout settings object pageCount : 1
* Returns: String of appropriate for EPUBJS.Layout function };
*/
EPUBJS.Layout.prototype.determineLayout = function(settings){
// Default is layout: reflowable & spread: auto
var spreads = this.determineSpreads(this.minSpreadWidth);
var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
var scroll = false;
if(settings.layout === "pre-paginated") {
layoutMethod = "Fixed";
scroll = true;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "none") {
layoutMethod = "Reflowable";
scroll = false;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "both") {
layoutMethod = "ReflowableSpreads";
scroll = false;
spreads = true;
}
this.spreads = spreads;
this.render.scroll(scroll);
this.trigger("renderer:spreads", spreads);
return layoutMethod;
}; };
//-- STYLES
EPUBJS.Layout.prototype.applyStyles = function(styles) {
for (var style in styles) {
for (var view in this.views) {
view.setStyle(style, styles[style]);
}
}
};
EPUBJS.Layout.prototype.setStyle = function(style, val, prefixed){
for (var view in this.views) {
view.setStyle(style, val, prefixed);
}
};
EPUBJS.Layout.prototype.removeStyle = function(style){
for (var view in this.views) {
view.removeStyle(style);
}
};
//-- HEAD TAGS
EPUBJS.Layout.prototype.applyHeadTags = function(headTags) {
for ( var headTag in headTags ) {
this.render.addHeadTag(headTag, headTags[headTag]);
}
};
/* /*
EPUBJS.Renderer.prototype.listeners = function(){ EPUBJS.Renderer.prototype.listeners = function(){
// Dom events to listen for // Dom events to listen for
@ -5656,6 +5808,146 @@ EPUBJS.Navigation.prototype.get = function(target) {
return this.toc[index]; return this.toc[index];
}; };
EPUBJS.Paginate = function(renderer, _options) {
var options = _options || {};
var defaults = {
width: 600,
height: 400,
forceSingle: false,
minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)
gap: "auto", //-- "auto" or int
layoutOveride : null // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'}
};
this.settings = EPUBJS.core.defaults(options, defaults);
this.renderer = renderer;
this.isForcedSingle = false;
this.initialize();
};
EPUBJS.Paginate.prototype.determineSpreads = function(cutoff){
if(this.isForcedSingle || !cutoff || this.width < cutoff) {
return false; //-- Single Page
}else{
return true; //-- Double Page
}
};
EPUBJS.Paginate.prototype.forceSingle = function(bool){
if(bool) {
this.isForcedSingle = true;
// this.spreads = false;
} else {
this.isForcedSingle = false;
// this.spreads = this.determineSpreads(this.minSpreadWidth);
}
};
/**
* Uses the settings to determine which Layout Method is needed
* Triggers events based on the method choosen
* Takes: Layout settings object
* Returns: String of appropriate for EPUBJS.Layout function
*/
EPUBJS.Paginate.prototype.determineLayout = function(settings){
// Default is layout: reflowable & spread: auto
var spreads = this.determineSpreads(this.settings.minSpreadWidth);
var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
var scroll = false;
if(settings.layout === "pre-paginated") {
layoutMethod = "Fixed";
scroll = true;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "none") {
layoutMethod = "Reflowable";
scroll = false;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "both") {
layoutMethod = "ReflowableSpreads";
scroll = false;
spreads = true;
}
this.spreads = spreads;
// this.render.scroll(scroll);
return layoutMethod;
};
/**
* 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.Paginate.prototype.reconcileLayoutSettings = function(global, chapter){
var settings = {};
//-- Get the global defaults
for (var attr in global) {
if (global.hasOwnProperty(attr)){
settings[attr] = global[attr];
}
}
//-- Get the chapter's display type
chapter.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.Paginate.prototype.initialize = function(){
// On display
// this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);
// this.layoutMethod = this.determineLayout(this.layoutSettings);
// this.layout = new EPUBJS.Layout[this.layoutMethod]();
this.renderer.hooks.display.register(this.registerLayoutMethod.bind(this));
};
EPUBJS.Paginate.prototype.registerLayoutMethod = function(view) {
var task = new RSVP.defer();
this.layoutMethod = this.determineLayout({});
this.layout = new EPUBJS.Layout[this.layoutMethod]();
this.formated = this.layout.format(view, this.settings.width, this.settings.height, this.settings.gap);
task.resolve();
return task.promise;
};
EPUBJS.Paginate.prototype.page = function(pg){
//-- Return false if page is greater than the total
return false;
};
EPUBJS.Paginate.prototype.next = function(){
// return this.page(this.chapterPos + 1);
console.log("next", this.formated.pageWidth)
this.renderer.infinite.scrollBy(this.formated.pageWidth, 0);
};
EPUBJS.Paginate.prototype.prev = function(){
console.log("prev", this.formated.pageWidth)
this.renderer.infinite.scrollBy(-this.formated.pageWidth, 0);
};
EPUBJS.Parser = function(){}; EPUBJS.Parser = function(){};
EPUBJS.Parser.prototype.container = function(containerXml){ EPUBJS.Parser.prototype.container = function(containerXml){
@ -6025,10 +6317,12 @@ EPUBJS.Parser.prototype.ncx = function(tocXml){
EPUBJS.Renderer = function(book, _options) { EPUBJS.Renderer = function(book, _options) {
var options = _options || {}; var options = _options || {};
this.settings = { this.settings = {
hidden: options.hidden || false, infinite: typeof(options.infinite) === "undefined" ? true : options.infinite,
viewsLimit: 6, hidden: typeof(options.hidden) === "undefined" ? false : options.hidden,
width: options.width || false, axis: options.axis || "vertical",
height: options.height || false, viewsLimit: options.viewsLimit || 5,
width: typeof(options.width) === "undefined" ? false : options.width,
height: typeof(options.height) === "undefined" ? false : options.height,
}; };
this.book = book; this.book = book;
@ -6057,6 +6351,11 @@ EPUBJS.Renderer = function(book, _options) {
this.hooks.display = new EPUBJS.Hook(this); this.hooks.display = new EPUBJS.Hook(this);
this.hooks.replacements = new EPUBJS.Hook(this); this.hooks.replacements = new EPUBJS.Hook(this);
if(!this.settings.infinite) {
this.settings.viewsLimit = 1;
}
}; };
/** /**
@ -6065,12 +6364,29 @@ EPUBJS.Renderer = function(book, _options) {
*/ */
EPUBJS.Renderer.prototype.initialize = function(_options){ EPUBJS.Renderer.prototype.initialize = function(_options){
var options = _options || {}; var options = _options || {};
var height = options.height ? options.height + "px" : "100%"; var height = options.height !== false ? options.height : "100%";
var width = options.width ? options.width + "px" : "100%"; var width = options.width !== false ? options.width : "100%";
var hidden = options.hidden || false; var hidden = options.hidden || false;
if(options.height && EPUBJS.core.isNumber(options.height)) {
height = options.height + "px";
}
if(options.width && EPUBJS.core.isNumber(options.width)) {
width = options.width + "px";
}
this.container = document.createElement("div"); this.container = document.createElement("div");
this.infinite = new EPUBJS.Infinite(this.container, this);
if(this.settings.infinite) {
this.infinite = new EPUBJS.Infinite(this.container, this.settings.axis);
}
if(this.settings.axis === "horizontal") {
// this.container.style.display = "flex";
// this.container.style.flexWrap = "nowrap";
this.container.style.whiteSpace = "nowrap";
}
this.container.style.width = width; this.container.style.width = width;
this.container.style.height = height; this.container.style.height = height;
@ -6140,26 +6456,29 @@ EPUBJS.Renderer.prototype.attachTo = function(_element){
this.resize(bounds.width, bounds.height); this.resize(bounds.width, bounds.height);
} }
this.infinite.start(); if(this.settings.infinite) {
this.infinite.on("forwards", function(){ this.infinite.start();
var next = this.last().section.index + 1;
if(!this.rendering && next < this.book.spine.length){
this.forwards();
}
}.bind(this));
this.infinite.on("backwards", function(){ this.infinite.on("forwards", function(){
var prev = this.first().section.index - 1; var next = this.last().section.index + 1;
if(!this.rendering && prev > 0){ if(!this.rendering && next < this.book.spine.length){
this.backwards(); this.forwards();
} }
}.bind(this)); }.bind(this));
this.infinite.on("backwards", function(){
var prev = this.first().section.index - 1;
if(!this.rendering && prev > 0){
this.backwards();
}
}.bind(this));
}
window.addEventListener("resize", this.onResized.bind(this), false); window.addEventListener("resize", this.onResized.bind(this), false);
this.hooks.replacements.register(this.replacements.bind(this)); this.hooks.replacements.register(this.replacements.bind(this));
@ -6188,11 +6507,14 @@ EPUBJS.Renderer.prototype.display = function(what){
if(section){ if(section){
rendered = this.render(section); rendered = this.render(section);
rendered if(this.settings.infinite) {
.then(this.fill.bind(this)) rendered.then(this.fill.bind(this))
.then(function(){ }
displaying.resolve(this);
}.bind(this)); rendered.then(function(){
displaying.resolve(this);
}.bind(this));
} else { } else {
displaying.reject(new Error("No Section Found")); displaying.reject(new Error("No Section Found"));
} }
@ -6226,6 +6548,9 @@ EPUBJS.Renderer.prototype.render = function(section){
.then(function(){ .then(function(){
return this.hooks.replacements.trigger(view, this); return this.hooks.replacements.trigger(view, this);
}.bind(this)) }.bind(this))
.then(function(){
return view.expand();
}.bind(this))
.then(function(){ .then(function(){
this.rendering = false; this.rendering = false;
view.show(); view.show();
@ -6259,16 +6584,24 @@ EPUBJS.Renderer.prototype.forwards = function(){
rendered.then(function(){ rendered.then(function(){
var first = this.first(); var first = this.first();
var bounds = first.bounds(); var bounds = first.bounds();
var prev = this.container.scrollTop; var prevTop = this.container.scrollTop;
var prevLeft = this.container.scrollLeft;
if(this.views.length > this.settings.viewsLimit) { if(this.views.length > this.settings.viewsLimit) {
// Remove the item // Remove the item
this.remove(first); this.remove(first);
// Reset Position if(this.settings.infinite) {
this.infinite.scroll(0, prev - bounds.height, true) // Reset Position
if(this.settings.axis === "vertical") {
this.infinite.scroll(0, prevTop - bounds.height, true)
} else {
this.infinite.scroll(prevLeft - bounds.width, true);
}
}
} }
}.bind(this)); }.bind(this));
@ -6296,11 +6629,23 @@ EPUBJS.Renderer.prototype.backwards = function(view){
rendered = this.render(section); rendered = this.render(section);
rendered.then(function(){ rendered.then(function(){
// this.container.scrollTop += this.first().height; var last;
this.infinite.scrollBy(0, this.first().height, true); if(this.settings.infinite) {
// this.container.scrollTop += this.first().height;
if(this.settings.axis === "vertical") {
this.infinite.scrollBy(0, this.first().bounds().height, true);
} else {
this.infinite.scrollBy(this.first().bounds().width, 0, true);
}
}
if(this.views.length > this.settings.viewsLimit) { if(this.views.length > this.settings.viewsLimit) {
last = this.last(); last = this.last();
this.remove(last); this.remove(last);
} }
@ -6314,21 +6659,15 @@ EPUBJS.Renderer.prototype.backwards = function(view){
// -- this might want to be in infinite // -- this might want to be in infinite
EPUBJS.Renderer.prototype.fill = function() { EPUBJS.Renderer.prototype.fill = function() {
var height = this.container.getBoundingClientRect().height;
var next = function(){
var bottom = this.last().bounds().bottom;
var defer = new RSVP.defer();
if (height && bottom && (bottom < height)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(next);
} else {
this.rendering = false;
defer.resolve();
return defer.promise;
}
}.bind(this);
var prev = this.first().section.index - 1; var prev = this.first().section.index - 1;
var filling = next(); var filling = this.forwards();
if(this.settings.axis === "vertical") {
filling.then(this.fillVertical.bind(this));
} else {
filling.then(this.fillHorizontal.bind(this));
}
if(prev > 0){ if(prev > 0){
filling.then(this.backwards.bind(this)); filling.then(this.backwards.bind(this));
@ -6343,6 +6682,34 @@ EPUBJS.Renderer.prototype.fill = function() {
}; };
EPUBJS.Renderer.prototype.fillVertical = function() {
var height = this.container.getBoundingClientRect().height;
var bottom = this.last().bounds().bottom;
var defer = new RSVP.defer();
if (height && bottom && (bottom < height)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(this.fillVertical.bind(this));
} else {
this.rendering = false;
defer.resolve();
return defer.promise;
}
};
EPUBJS.Renderer.prototype.fillHorizontal = function() {
var width = this.container.getBoundingClientRect().width;
var right = this.last().bounds().right;
var defer = new RSVP.defer();
if (width && right && (right <= width)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(this.fillHorizontal.bind(this));
} else {
this.rendering = false;
defer.resolve();
return defer.promise;
}
};
EPUBJS.Renderer.prototype.append = function(view){ EPUBJS.Renderer.prototype.append = function(view){
var first, prevTop, prevHeight, offset; var first, prevTop, prevHeight, offset;
@ -6422,6 +6789,14 @@ EPUBJS.Renderer.prototype.replacements = function(view, renderer) {
return task.promise; return task.promise;
}; };
EPUBJS.Renderer.prototype.paginate = function(options) {
this.pagination = new EPUBJS.Paginate(this, {
width: this.settings.width,
height: this.settings.height
});
return this.pagination;
};
//-- Enable binding events to Renderer //-- Enable binding events to Renderer
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype); RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
EPUBJS.Section = function(item){ EPUBJS.Section = function(item){
@ -6615,20 +6990,18 @@ EPUBJS.View.prototype.create = function() {
this.iframe.style.border = "none"; this.iframe.style.border = "none";
this.resizing = true; this.resizing = true;
this.iframe.width = "100%"; this.iframe.style.width = "100%";
this.iframe.style.height = "100%"; this.iframe.style.height = "100%";
this.iframe.style.display = "none"; this.iframe.style.display = "none";
this.iframe.style.visibility = "hidden"; this.iframe.style.visibility = "hidden";
return this.iframe; return this.iframe;
}; };
EPUBJS.View.prototype.resized = function(e) { EPUBJS.View.prototype.resized = function(e) {
if (!this.resizing) { if (!this.resizing) {
this.layout(); this.expand();
} else { } else {
this.resizing = false; this.resizing = false;
} }
@ -6653,7 +7026,6 @@ EPUBJS.View.prototype.load = function(contents) {
this.document = this.iframe.contentDocument; this.document = this.iframe.contentDocument;
this.iframe.addEventListener("load", function(event) { this.iframe.addEventListener("load", function(event) {
var layout;
this.window = this.iframe.contentWindow; this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument; this.document = this.iframe.contentDocument;
@ -6675,56 +7047,62 @@ EPUBJS.View.prototype.display = function(contents) {
var displaying = new RSVP.defer(); var displaying = new RSVP.defer();
var displayed = displaying.promise; var displayed = displaying.promise;
this.iframe.style.display = "block"; // this.iframe.style.display = "block";
this.iframe.style.display = "inline-block";
// Reset Body Styles // Reset Body Styles
this.document.body.style.margin = "0"; this.document.body.style.margin = "0";
this.document.body.style.display = "inline-block"; // this.document.body.style.display = "inline-block";
this.document.documentElement.style.width = "auto";
// Set Padding -> TODO: apply these from a function
this.document.body.style.padding = "0 20px 20px 20px";
setTimeout(function(){ setTimeout(function(){
this.window.addEventListener("resize", this.resized.bind(this), false); this.window.addEventListener("resize", this.resized.bind(this), false);
}.bind(this), 10); // Wait to listen for resize events }.bind(this), 10); // Wait to listen for resize events
if(this.document.fonts.status !== "loading") { if(!this.document.fonts || this.document.fonts.status !== "loading") {
this.layout(); this.expand();
displaying.resolve(this); displaying.resolve(this);
} else { } else {
this.document.fonts.onloading = function(){ this.document.fonts.onloading = function(){
this.layout(); this.expand();
displaying.resolve(this); displaying.resolve(this);
}.bind(this); }.bind(this);
} }
// this.observer = this.observe(this.document); // this.observer = this.observe(this.document.body);
return displayed return displayed
}; };
EPUBJS.View.prototype.layout = function() { EPUBJS.View.prototype.expand = function() {
var bounds; var bounds;
var width, height;
// Check bounds // Check bounds
bounds = this.document.body.getBoundingClientRect(); bounds = this.document.body.getBoundingClientRect();
if(!bounds || (bounds.height === 0 && bounds.width === 0)) {
if(!bounds || (bounds.height == 0 && bounds.width == 0)) {
console.error("View not shown"); console.error("View not shown");
} }
// Apply Changes // Apply Changes
this.resizing = true; this.resizing = true;
this.iframe.style.height = bounds.height + "px";
// this.iframe.style.width = bounds.width + "px";
this.width = bounds.width; height = bounds.height; //this.document.documentElement.scrollHeight;
this.height = bounds.height; this.iframe.style.height = height + "px";
width = this.document.documentElement.scrollWidth;
this.iframe.style.width = width + "px";
// this.width = width;
// this.height = height;
return bounds;
}; };
EPUBJS.View.prototype.observe = function(target) { EPUBJS.View.prototype.observe = function(target) {
@ -6732,9 +7110,10 @@ EPUBJS.View.prototype.observe = function(target) {
// create an observer instance // create an observer instance
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) { renderer.expand();
renderer.layout(); // mutations.forEach(function(mutation) {
}); // console.log(mutation)
// });
}); });
// configuration of the observer: // configuration of the observer:
@ -6756,12 +7135,9 @@ EPUBJS.View.prototype.prependTo = function(element) {
element.insertBefore(this.iframe, element.firstChild); element.insertBefore(this.iframe, element.firstChild);
}; };
EPUBJS.View.prototype.bounds = function() {
return this.iframe.getBoundingClientRect();
};
EPUBJS.View.prototype.show = function() { EPUBJS.View.prototype.show = function() {
this.iframe.style.display = "block"; // this.iframe.style.display = "block";
this.iframe.style.display = "inline-block";
this.iframe.style.visibility = "visible"; this.iframe.style.visibility = "visible";
}; };
@ -6770,6 +7146,10 @@ EPUBJS.View.prototype.hide = function() {
this.iframe.style.visibility = "hidden"; this.iframe.style.visibility = "hidden";
}; };
EPUBJS.View.prototype.bounds = function() {
return this.iframe.getBoundingClientRect();
};
EPUBJS.View.prototype.destroy = function() { EPUBJS.View.prototype.destroy = function() {
// Stop observing // Stop observing
// this.observer.disconnect(); // this.observer.disconnect();

6
dist/epub.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -17,15 +17,17 @@
#viewer { #viewer {
display: block; display: block;
margin: 0; margin: 0;
width: 100%; width: 60%;
height: 100%; height: 100%;
margin: 0 auto;
} }
#viewer iframe { #viewer iframe {
background: white; background: white;
box-shadow: 0 0 4px #ccc; box-shadow: 0 0 4px #ccc;
width: 590px; margin: 10px;
margin: 10px auto; width: calc(100% - 60px) !important;
padding: 20px;
} }
@ -72,7 +74,7 @@
<script> <script>
var currentSectionIndex = 10; var currentSectionIndex = 10;
// Load the opf // Load the opf
var book = ePub("../books/accessible_epub_3-20121024.epub/package.opf"); var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
var rendition = book.renderTo("viewer"); var rendition = book.renderTo("viewer");
var displayed = rendition.display(currentSectionIndex); var displayed = rendition.display(currentSectionIndex);

145
examples/pages.html Normal file
View file

@ -0,0 +1,145 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>EPUB.js Basic Example</title>
<script src="../dist/epub.js"></script>
<style type="text/css">
body {
margin: 0;
background: #fafafa;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #333;
/* Center Content */
position: absolute;
height: 100%;
width: 100%;
display: flex;
-webkit-align-items: center;
-webkit-justify-content: center;
}
#viewer {
width: 900px;
height: 400px;
background: white;
box-shadow: 0 0 4px #ccc;
border-radius: 5px;
padding: 20px 40px;
/*width: 100%;*/
/* height: 400px;*/
position: relative;
}
#viewer:after {
position: absolute;
width: 1px;
border-right: 1px #000 solid;
height: 90%;
z-index: 1;
left: 50%;
margin-left: -1px;
top: 5%;
opacity: .15;
box-shadow: -2px 0 15px rgba(0, 0, 0, 1);
content: "";
}
/*
#viewer > iframe {
overflow: scroll;
height: 400px;
-webkit-column-axis: horizontal;
-webkit-column-fill: auto;
-webkit-column-width: 400px;
-webkit-column-gap: 10px;
} */
#viewer iframe {
background: white;
/*box-shadow: 0 0 4px #ccc;*/
/*width: 590px;
margin: 10px auto;*/
}
#prev {
left: 40px;
}
#next {
right: 40px;
}
.arrow {
position: fixed;
top: 50%;
margin-top: -32px;
font-size: 64px;
color: #E2E2E2;
font-family: arial, sans-serif;
font-weight: bold;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.arrow:hover {
color: #777;
}
.arrow:active {
color: #000;
}
#toc {
display: block;
margin: 10px auto;
}
</style>
</head>
<body>
<div id="viewer"></div>
<div id="prev" class="arrow"></div>
<div id="next" class="arrow"></div>
<script>
var currentSectionIndex = 10;
// Load the opf
var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
var rendition = book.renderTo("viewer", {axis: "horizontal", width: 900, height: 400});
var pagination = rendition.paginate();
var displayed = rendition.display(currentSectionIndex);
displayed.then(function(renderer){
// -- do stuff
});
// Navigation loaded
book.loaded.navigation.then(function(toc){
// console.log(toc);
});
var next = document.getElementById("next");
next.addEventListener("click", function(){
pagination.next();
}, false);
var prev = document.getElementById("prev");
prev.addEventListener("click", function(){
pagination.prev();
}, false);
</script>
</body>
</html>

View file

@ -162,9 +162,9 @@ EPUBJS.Book.prototype.section = function(target) {
// Sugar to render a book // Sugar to render a book
EPUBJS.Book.prototype.renderTo = function(element, options) { EPUBJS.Book.prototype.renderTo = function(element, options) {
var rendition = new EPUBJS.Renderer(this, options); this.rendition = new EPUBJS.Renderer(this, options);
rendition.attachTo(element); this.rendition.attachTo(element);
return rendition; return this.rendition;
}; };
EPUBJS.Book.prototype.requestMethod = function(_url) { EPUBJS.Book.prototype.requestMethod = function(_url) {

View file

@ -304,4 +304,33 @@ EPUBJS.core.documentHeight = function() {
EPUBJS.core.isNumber = function(n) { EPUBJS.core.isNumber = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n); return !isNaN(parseFloat(n)) && isFinite(n);
} };
EPUBJS.core.prefixed = function(unprefixed) {
var vendors = ["Webkit", "Moz", "O", "ms" ],
prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],
upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),
length = vendors.length;
if (typeof(document.body.style[unprefixed]) != 'undefined') {
return unprefixed;
}
for ( var i=0; i < length; i++ ) {
if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {
return vendors[i] + upper;
}
}
return unprefixed;
};
EPUBJS.core.defaults = function(obj) {
for (var i = 1, length = arguments.length; i < length; i++) {
var source = arguments[i];
for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
}
return obj;
};

View file

@ -1,13 +1,14 @@
EPUBJS.Infinite = function(container, renderer){ EPUBJS.Infinite = function(container, axis){
this.container = container; this.container = container;
this.windowHeight = window.innerHeight; this.windowHeight = window.innerHeight;
this.tick = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; this.tick = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
this.scrolled = false; this.scrolled = false;
this.ignore = false; this.ignore = false;
this.displaying = false; this.displaying = false;
this.offset = 350; this.offset = 900;
this.views = []; this.views = [];
this.renderer = renderer; this.axis = axis;
// this.renderer = renderer;
this.prevScrollTop = 0; this.prevScrollTop = 0;
}; };
@ -49,12 +50,25 @@ EPUBJS.Infinite.prototype.check = function(){
if(this.scrolled && !this.displaying) { if(this.scrolled && !this.displaying) {
if(this.axis === "vertical") {
this.checkTop();
} else {
this.checkLeft();
}
this.scrolled = false;
} else {
this.displaying = false;
this.scrolled = false;
}
this.tick.call(window, this.check.bind(this));
}
EPUBJS.Infinite.prototype.checkTop = function(){
var scrollTop = this.container.scrollTop; var scrollTop = this.container.scrollTop;
var scrollLeft = this.container.scrollLeft;
var scrollHeight = this.container.scrollHeight; var scrollHeight = this.container.scrollHeight;
var scrollWidth = this.container.scrollWidth;
var direction = scrollTop - this.prevScrollTop; var direction = scrollTop - this.prevScrollTop;
var height = this.container.getBoundingClientRect().height; var height = this.container.getBoundingClientRect().height;
@ -73,14 +87,36 @@ EPUBJS.Infinite.prototype.check = function(){
// console.log(scrollTop) // console.log(scrollTop)
this.prevScrollTop = scrollTop; this.prevScrollTop = scrollTop;
this.scrolled = false; return scrollTop;
} else { };
this.displaying = false;
this.scrolled = false;
}
this.tick.call(window, this.check.bind(this)); EPUBJS.Infinite.prototype.checkLeft = function(){
}
var scrollLeft = this.container.scrollLeft;
var scrollWidth = this.container.scrollWidth;
var direction = scrollLeft - this.prevscrollLeft;
var width = this.container.getBoundingClientRect().width;
var right = scrollLeft + this.offset > scrollWidth-width;
var left = scrollLeft < this.offset;
// Add to bottom
if(right && direction > 0) {
this.forwards();
}
// Add to top
else if(left && direction < 0) {
this.backwards();
}
// console.log(scrollTop)
this.prevscrollLeft = scrollLeft;
return scrollLeft;
};
EPUBJS.Infinite.prototype.scrollBy = function(x, y, silent){ EPUBJS.Infinite.prototype.scrollBy = function(x, y, silent){
if(silent) { if(silent) {
@ -88,6 +124,9 @@ EPUBJS.Infinite.prototype.scrollBy = function(x, y, silent){
} }
this.container.scrollLeft += x; this.container.scrollLeft += x;
this.container.scrollTop += y; this.container.scrollTop += y;
this.scrolled = true;
this.check();
}; };
EPUBJS.Infinite.prototype.scroll = function(x, y, silent){ EPUBJS.Infinite.prototype.scroll = function(x, y, silent){
@ -96,6 +135,9 @@ EPUBJS.Infinite.prototype.scroll = function(x, y, silent){
} }
this.container.scrollLeft = x; this.container.scrollLeft = x;
this.container.scrollTop = y; this.container.scrollTop = y;
this.scrolled = true;
this.check();
}; };
RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype); RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype);

View file

@ -1,97 +1,176 @@
EPUBJS.Layout = function(){}; EPUBJS.Layout = EPUBJS.Layout || {};
/** EPUBJS.Layout.Reflowable = function(){
* Reconciles the current chapters layout properies with this.documentElement = null;
* the global layout properities. this.spreadWidth = null;
* Takes: global layout settings object, chapter properties string };
* Returns: Object with layout properties
*/
EPUBJS.Layout.prototype.reconcileLayoutSettings = function(global, chapter){
var settings = {};
//-- Get the global defaults EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _height, _gap){
for (var attr in global) { // Get the prefixed CSS commands
if (global.hasOwnProperty(attr)){ var columnAxis = EPUBJS.core.prefixed('columnAxis');
settings[attr] = global[attr]; var columnGap = EPUBJS.core.prefixed('columnGap');
var columnWidth = EPUBJS.core.prefixed('columnWidth');
var columnFill = EPUBJS.core.prefixed('columnFill');
//-- Check the width and create even width columns
var width = Math.floor(_width);
// var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 0; // Not needed for single
var section = Math.floor(width / 8);
var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);
this.documentElement = documentElement;
//-- Single Page
this.spreadWidth = (width + gap);
documentElement.style.overflow = "hidden";
// Must be set to the new calculated width or the columns will be off
documentElement.style.width = width + "px";
//-- Adjust height
documentElement.style.height = _height + "px";
//-- Add columns
documentElement.style[columnAxis] = "horizontal";
documentElement.style[columnFill] = "auto";
documentElement.style[columnWidth] = width+"px";
documentElement.style[columnGap] = gap+"px";
this.colWidth = width;
this.gap = gap;
return {
pageWidth : this.spreadWidth,
pageHeight : _height
};
};
EPUBJS.Layout.Reflowable.prototype.calculatePages = function() {
var totalWidth, displayedPages;
this.documentElement.style.width = "auto"; //-- reset width for calculations
totalWidth = this.documentElement.scrollWidth;
displayedPages = Math.ceil(totalWidth / this.spreadWidth);
return {
displayedPages : displayedPages,
pageCount : displayedPages
};
};
EPUBJS.Layout.ReflowableSpreads = function(){
this.documentElement = null;
this.spreadWidth = null;
};
EPUBJS.Layout.ReflowableSpreads.prototype.format = function(view, _width, _height, _gap){
var columnAxis = EPUBJS.core.prefixed('columnAxis');
var columnGap = EPUBJS.core.prefixed('columnGap');
var columnWidth = EPUBJS.core.prefixed('columnWidth');
var columnFill = EPUBJS.core.prefixed('columnFill');
var divisor = 2,
cutoff = 800;
//-- Check the width and create even width columns
var fullWidth = Math.floor(_width);
var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;
var section = Math.floor(width / 8);
var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);
//-- Double Page
var colWidth = Math.floor((width - gap) / divisor);
this.spreadWidth = (colWidth + gap) * divisor;
view.document.documentElement.style.overflow = "hidden";
// Must be set to the new calculated width or the columns will be off
view.document.body.style.width = width + "px";
//-- Adjust height
view.document.body.style.height = _height + "px";
//-- Add columns
view.document.body.style[columnAxis] = "horizontal";
view.document.body.style[columnFill] = "auto";
view.document.body.style[columnGap] = gap+"px";
view.document.body.style[columnWidth] = colWidth+"px";
this.colWidth = colWidth;
this.gap = gap;
view.iframe.style.width = colWidth+"px";
view.iframe.style.paddingRight = gap+"px";
return {
pageWidth : this.spreadWidth,
pageHeight : _height
};
};
EPUBJS.Layout.ReflowableSpreads.prototype.calculatePages = function() {
var totalWidth = this.documentElement.scrollWidth;
var displayedPages = Math.ceil(totalWidth / this.spreadWidth);
//-- Add a page to the width of the document to account an for odd number of pages
this.documentElement.style.width = totalWidth + this.spreadWidth + "px";
return {
displayedPages : displayedPages,
pageCount : displayedPages * 2
};
};
EPUBJS.Layout.Fixed = function(){
this.documentElement = null;
};
EPUBJS.Layout.Fixed = function(documentElement, _width, _height, _gap){
var columnWidth = EPUBJS.core.prefixed('columnWidth');
var viewport = documentElement.querySelector("[name=viewport");
var content;
var contents;
var width, height;
this.documentElement = documentElement;
/**
* 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=", '');
} }
} }
//-- Get the chapter's display type
chapter.forEach(function(prop){
var rendition = prop.replace("rendition:", '');
var split = rendition.indexOf("-");
var property, value;
if(split != -1){ //-- Adjust width and height
property = rendition.slice(0, split); documentElement.style.width = width + "px" || "auto";
value = rendition.slice(split+1); documentElement.style.height = height + "px" || "auto";
//-- Remove columns
documentElement.style[columnWidth] = "auto";
//-- Scroll
documentElement.style.overflow = "auto";
this.colWidth = width;
this.gap = 0;
return {
pageWidth : width,
pageHeight : height
};
settings[property] = value;
}
});
return settings;
}; };
/** EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
* Uses the settings to determine which Layout Method is needed return {
* Triggers events based on the method choosen displayedPages : 1,
* Takes: Layout settings object pageCount : 1
* Returns: String of appropriate for EPUBJS.Layout function };
*/
EPUBJS.Layout.prototype.determineLayout = function(settings){
// Default is layout: reflowable & spread: auto
var spreads = this.determineSpreads(this.minSpreadWidth);
var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
var scroll = false;
if(settings.layout === "pre-paginated") {
layoutMethod = "Fixed";
scroll = true;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "none") {
layoutMethod = "Reflowable";
scroll = false;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "both") {
layoutMethod = "ReflowableSpreads";
scroll = false;
spreads = true;
}
this.spreads = spreads;
this.render.scroll(scroll);
this.trigger("renderer:spreads", spreads);
return layoutMethod;
}; };
//-- STYLES
EPUBJS.Layout.prototype.applyStyles = function(styles) {
for (var style in styles) {
for (var view in this.views) {
view.setStyle(style, styles[style]);
}
}
};
EPUBJS.Layout.prototype.setStyle = function(style, val, prefixed){
for (var view in this.views) {
view.setStyle(style, val, prefixed);
}
};
EPUBJS.Layout.prototype.removeStyle = function(style){
for (var view in this.views) {
view.removeStyle(style);
}
};
//-- HEAD TAGS
EPUBJS.Layout.prototype.applyHeadTags = function(headTags) {
for ( var headTag in headTags ) {
this.render.addHeadTag(headTag, headTags[headTag]);
}
};

140
lib/epubjs/pagination.js Normal file
View file

@ -0,0 +1,140 @@
EPUBJS.Paginate = function(renderer, _options) {
var options = _options || {};
var defaults = {
width: 600,
height: 400,
forceSingle: false,
minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)
gap: "auto", //-- "auto" or int
layoutOveride : null // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'}
};
this.settings = EPUBJS.core.defaults(options, defaults);
this.renderer = renderer;
this.isForcedSingle = false;
this.initialize();
};
EPUBJS.Paginate.prototype.determineSpreads = function(cutoff){
if(this.isForcedSingle || !cutoff || this.width < cutoff) {
return false; //-- Single Page
}else{
return true; //-- Double Page
}
};
EPUBJS.Paginate.prototype.forceSingle = function(bool){
if(bool) {
this.isForcedSingle = true;
// this.spreads = false;
} else {
this.isForcedSingle = false;
// this.spreads = this.determineSpreads(this.minSpreadWidth);
}
};
/**
* Uses the settings to determine which Layout Method is needed
* Triggers events based on the method choosen
* Takes: Layout settings object
* Returns: String of appropriate for EPUBJS.Layout function
*/
EPUBJS.Paginate.prototype.determineLayout = function(settings){
// Default is layout: reflowable & spread: auto
var spreads = this.determineSpreads(this.settings.minSpreadWidth);
var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
var scroll = false;
if(settings.layout === "pre-paginated") {
layoutMethod = "Fixed";
scroll = true;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "none") {
layoutMethod = "Reflowable";
scroll = false;
spreads = false;
}
if(settings.layout === "reflowable" && settings.spread === "both") {
layoutMethod = "ReflowableSpreads";
scroll = false;
spreads = true;
}
this.spreads = spreads;
// this.render.scroll(scroll);
return layoutMethod;
};
/**
* 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.Paginate.prototype.reconcileLayoutSettings = function(global, chapter){
var settings = {};
//-- Get the global defaults
for (var attr in global) {
if (global.hasOwnProperty(attr)){
settings[attr] = global[attr];
}
}
//-- Get the chapter's display type
chapter.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.Paginate.prototype.initialize = function(){
// On display
// this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);
// this.layoutMethod = this.determineLayout(this.layoutSettings);
// this.layout = new EPUBJS.Layout[this.layoutMethod]();
this.renderer.hooks.display.register(this.registerLayoutMethod.bind(this));
};
EPUBJS.Paginate.prototype.registerLayoutMethod = function(view) {
var task = new RSVP.defer();
this.layoutMethod = this.determineLayout({});
this.layout = new EPUBJS.Layout[this.layoutMethod]();
this.formated = this.layout.format(view, this.settings.width, this.settings.height, this.settings.gap);
task.resolve();
return task.promise;
};
EPUBJS.Paginate.prototype.page = function(pg){
//-- Return false if page is greater than the total
return false;
};
EPUBJS.Paginate.prototype.next = function(){
// return this.page(this.chapterPos + 1);
console.log("next", this.formated.pageWidth)
this.renderer.infinite.scrollBy(this.formated.pageWidth, 0);
};
EPUBJS.Paginate.prototype.prev = function(){
console.log("prev", this.formated.pageWidth)
this.renderer.infinite.scrollBy(-this.formated.pageWidth, 0);
};

View file

@ -1,10 +1,12 @@
EPUBJS.Renderer = function(book, _options) { EPUBJS.Renderer = function(book, _options) {
var options = _options || {}; var options = _options || {};
this.settings = { this.settings = {
hidden: options.hidden || false, infinite: typeof(options.infinite) === "undefined" ? true : options.infinite,
viewsLimit: 6, hidden: typeof(options.hidden) === "undefined" ? false : options.hidden,
width: options.width || false, axis: options.axis || "vertical",
height: options.height || false, viewsLimit: options.viewsLimit || 5,
width: typeof(options.width) === "undefined" ? false : options.width,
height: typeof(options.height) === "undefined" ? false : options.height,
}; };
this.book = book; this.book = book;
@ -33,6 +35,11 @@ EPUBJS.Renderer = function(book, _options) {
this.hooks.display = new EPUBJS.Hook(this); this.hooks.display = new EPUBJS.Hook(this);
this.hooks.replacements = new EPUBJS.Hook(this); this.hooks.replacements = new EPUBJS.Hook(this);
if(!this.settings.infinite) {
this.settings.viewsLimit = 1;
}
}; };
/** /**
@ -41,12 +48,29 @@ EPUBJS.Renderer = function(book, _options) {
*/ */
EPUBJS.Renderer.prototype.initialize = function(_options){ EPUBJS.Renderer.prototype.initialize = function(_options){
var options = _options || {}; var options = _options || {};
var height = options.height ? options.height + "px" : "100%"; var height = options.height !== false ? options.height : "100%";
var width = options.width ? options.width + "px" : "100%"; var width = options.width !== false ? options.width : "100%";
var hidden = options.hidden || false; var hidden = options.hidden || false;
if(options.height && EPUBJS.core.isNumber(options.height)) {
height = options.height + "px";
}
if(options.width && EPUBJS.core.isNumber(options.width)) {
width = options.width + "px";
}
this.container = document.createElement("div"); this.container = document.createElement("div");
this.infinite = new EPUBJS.Infinite(this.container, this);
if(this.settings.infinite) {
this.infinite = new EPUBJS.Infinite(this.container, this.settings.axis);
}
if(this.settings.axis === "horizontal") {
// this.container.style.display = "flex";
// this.container.style.flexWrap = "nowrap";
this.container.style.whiteSpace = "nowrap";
}
this.container.style.width = width; this.container.style.width = width;
this.container.style.height = height; this.container.style.height = height;
@ -116,26 +140,29 @@ EPUBJS.Renderer.prototype.attachTo = function(_element){
this.resize(bounds.width, bounds.height); this.resize(bounds.width, bounds.height);
} }
this.infinite.start(); if(this.settings.infinite) {
this.infinite.on("forwards", function(){ this.infinite.start();
var next = this.last().section.index + 1;
if(!this.rendering && next < this.book.spine.length){
this.forwards();
}
}.bind(this));
this.infinite.on("backwards", function(){ this.infinite.on("forwards", function(){
var prev = this.first().section.index - 1; var next = this.last().section.index + 1;
if(!this.rendering && prev > 0){ if(!this.rendering && next < this.book.spine.length){
this.backwards(); this.forwards();
} }
}.bind(this)); }.bind(this));
this.infinite.on("backwards", function(){
var prev = this.first().section.index - 1;
if(!this.rendering && prev > 0){
this.backwards();
}
}.bind(this));
}
window.addEventListener("resize", this.onResized.bind(this), false); window.addEventListener("resize", this.onResized.bind(this), false);
this.hooks.replacements.register(this.replacements.bind(this)); this.hooks.replacements.register(this.replacements.bind(this));
@ -164,11 +191,14 @@ EPUBJS.Renderer.prototype.display = function(what){
if(section){ if(section){
rendered = this.render(section); rendered = this.render(section);
rendered if(this.settings.infinite) {
.then(this.fill.bind(this)) rendered.then(this.fill.bind(this))
.then(function(){ }
displaying.resolve(this);
}.bind(this)); rendered.then(function(){
displaying.resolve(this);
}.bind(this));
} else { } else {
displaying.reject(new Error("No Section Found")); displaying.reject(new Error("No Section Found"));
} }
@ -202,6 +232,9 @@ EPUBJS.Renderer.prototype.render = function(section){
.then(function(){ .then(function(){
return this.hooks.replacements.trigger(view, this); return this.hooks.replacements.trigger(view, this);
}.bind(this)) }.bind(this))
.then(function(){
return view.expand();
}.bind(this))
.then(function(){ .then(function(){
this.rendering = false; this.rendering = false;
view.show(); view.show();
@ -235,16 +268,24 @@ EPUBJS.Renderer.prototype.forwards = function(){
rendered.then(function(){ rendered.then(function(){
var first = this.first(); var first = this.first();
var bounds = first.bounds(); var bounds = first.bounds();
var prev = this.container.scrollTop; var prevTop = this.container.scrollTop;
var prevLeft = this.container.scrollLeft;
if(this.views.length > this.settings.viewsLimit) { if(this.views.length > this.settings.viewsLimit) {
// Remove the item // Remove the item
this.remove(first); this.remove(first);
// Reset Position if(this.settings.infinite) {
this.infinite.scroll(0, prev - bounds.height, true) // Reset Position
if(this.settings.axis === "vertical") {
this.infinite.scroll(0, prevTop - bounds.height, true)
} else {
this.infinite.scroll(prevLeft - bounds.width, true);
}
}
} }
}.bind(this)); }.bind(this));
@ -272,11 +313,23 @@ EPUBJS.Renderer.prototype.backwards = function(view){
rendered = this.render(section); rendered = this.render(section);
rendered.then(function(){ rendered.then(function(){
// this.container.scrollTop += this.first().height; var last;
this.infinite.scrollBy(0, this.first().height, true); if(this.settings.infinite) {
// this.container.scrollTop += this.first().height;
if(this.settings.axis === "vertical") {
this.infinite.scrollBy(0, this.first().bounds().height, true);
} else {
this.infinite.scrollBy(this.first().bounds().width, 0, true);
}
}
if(this.views.length > this.settings.viewsLimit) { if(this.views.length > this.settings.viewsLimit) {
last = this.last(); last = this.last();
this.remove(last); this.remove(last);
} }
@ -290,21 +343,15 @@ EPUBJS.Renderer.prototype.backwards = function(view){
// -- this might want to be in infinite // -- this might want to be in infinite
EPUBJS.Renderer.prototype.fill = function() { EPUBJS.Renderer.prototype.fill = function() {
var height = this.container.getBoundingClientRect().height;
var next = function(){
var bottom = this.last().bounds().bottom;
var defer = new RSVP.defer();
if (height && bottom && (bottom < height)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(next);
} else {
this.rendering = false;
defer.resolve();
return defer.promise;
}
}.bind(this);
var prev = this.first().section.index - 1; var prev = this.first().section.index - 1;
var filling = next(); var filling = this.forwards();
if(this.settings.axis === "vertical") {
filling.then(this.fillVertical.bind(this));
} else {
filling.then(this.fillHorizontal.bind(this));
}
if(prev > 0){ if(prev > 0){
filling.then(this.backwards.bind(this)); filling.then(this.backwards.bind(this));
@ -319,6 +366,34 @@ EPUBJS.Renderer.prototype.fill = function() {
}; };
EPUBJS.Renderer.prototype.fillVertical = function() {
var height = this.container.getBoundingClientRect().height;
var bottom = this.last().bounds().bottom;
var defer = new RSVP.defer();
if (height && bottom && (bottom < height)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(this.fillVertical.bind(this));
} else {
this.rendering = false;
defer.resolve();
return defer.promise;
}
};
EPUBJS.Renderer.prototype.fillHorizontal = function() {
var width = this.container.getBoundingClientRect().width;
var right = this.last().bounds().right;
var defer = new RSVP.defer();
if (width && right && (right <= width)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(this.fillHorizontal.bind(this));
} else {
this.rendering = false;
defer.resolve();
return defer.promise;
}
};
EPUBJS.Renderer.prototype.append = function(view){ EPUBJS.Renderer.prototype.append = function(view){
var first, prevTop, prevHeight, offset; var first, prevTop, prevHeight, offset;
@ -398,5 +473,13 @@ EPUBJS.Renderer.prototype.replacements = function(view, renderer) {
return task.promise; return task.promise;
}; };
EPUBJS.Renderer.prototype.paginate = function(options) {
this.pagination = new EPUBJS.Paginate(this, {
width: this.settings.width,
height: this.settings.height
});
return this.pagination;
};
//-- Enable binding events to Renderer //-- Enable binding events to Renderer
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype); RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);

View file

@ -15,20 +15,18 @@ EPUBJS.View.prototype.create = function() {
this.iframe.style.border = "none"; this.iframe.style.border = "none";
this.resizing = true; this.resizing = true;
this.iframe.width = "100%"; this.iframe.style.width = "100%";
this.iframe.style.height = "100%"; this.iframe.style.height = "100%";
this.iframe.style.display = "none"; this.iframe.style.display = "none";
this.iframe.style.visibility = "hidden"; this.iframe.style.visibility = "hidden";
return this.iframe; return this.iframe;
}; };
EPUBJS.View.prototype.resized = function(e) { EPUBJS.View.prototype.resized = function(e) {
if (!this.resizing) { if (!this.resizing) {
this.layout(); this.expand();
} else { } else {
this.resizing = false; this.resizing = false;
} }
@ -53,7 +51,6 @@ EPUBJS.View.prototype.load = function(contents) {
this.document = this.iframe.contentDocument; this.document = this.iframe.contentDocument;
this.iframe.addEventListener("load", function(event) { this.iframe.addEventListener("load", function(event) {
var layout;
this.window = this.iframe.contentWindow; this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument; this.document = this.iframe.contentDocument;
@ -75,56 +72,62 @@ EPUBJS.View.prototype.display = function(contents) {
var displaying = new RSVP.defer(); var displaying = new RSVP.defer();
var displayed = displaying.promise; var displayed = displaying.promise;
this.iframe.style.display = "block"; // this.iframe.style.display = "block";
this.iframe.style.display = "inline-block";
// Reset Body Styles // Reset Body Styles
this.document.body.style.margin = "0"; this.document.body.style.margin = "0";
this.document.body.style.display = "inline-block"; // this.document.body.style.display = "inline-block";
this.document.documentElement.style.width = "auto";
// Set Padding -> TODO: apply these from a function
this.document.body.style.padding = "0 20px 20px 20px";
setTimeout(function(){ setTimeout(function(){
this.window.addEventListener("resize", this.resized.bind(this), false); this.window.addEventListener("resize", this.resized.bind(this), false);
}.bind(this), 10); // Wait to listen for resize events }.bind(this), 10); // Wait to listen for resize events
if(this.document.fonts.status !== "loading") { if(!this.document.fonts || this.document.fonts.status !== "loading") {
this.layout(); this.expand();
displaying.resolve(this); displaying.resolve(this);
} else { } else {
this.document.fonts.onloading = function(){ this.document.fonts.onloading = function(){
this.layout(); this.expand();
displaying.resolve(this); displaying.resolve(this);
}.bind(this); }.bind(this);
} }
// this.observer = this.observe(this.document); // this.observer = this.observe(this.document.body);
return displayed return displayed
}; };
EPUBJS.View.prototype.layout = function() { EPUBJS.View.prototype.expand = function() {
var bounds; var bounds;
var width, height;
// Check bounds // Check bounds
bounds = this.document.body.getBoundingClientRect(); bounds = this.document.body.getBoundingClientRect();
if(!bounds || (bounds.height === 0 && bounds.width === 0)) {
if(!bounds || (bounds.height == 0 && bounds.width == 0)) {
console.error("View not shown"); console.error("View not shown");
} }
// Apply Changes // Apply Changes
this.resizing = true; this.resizing = true;
this.iframe.style.height = bounds.height + "px";
// this.iframe.style.width = bounds.width + "px";
this.width = bounds.width; height = bounds.height; //this.document.documentElement.scrollHeight;
this.height = bounds.height; this.iframe.style.height = height + "px";
width = this.document.documentElement.scrollWidth;
this.iframe.style.width = width + "px";
// this.width = width;
// this.height = height;
return bounds;
}; };
EPUBJS.View.prototype.observe = function(target) { EPUBJS.View.prototype.observe = function(target) {
@ -132,9 +135,10 @@ EPUBJS.View.prototype.observe = function(target) {
// create an observer instance // create an observer instance
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) { renderer.expand();
renderer.layout(); // mutations.forEach(function(mutation) {
}); // console.log(mutation)
// });
}); });
// configuration of the observer: // configuration of the observer:
@ -156,12 +160,9 @@ EPUBJS.View.prototype.prependTo = function(element) {
element.insertBefore(this.iframe, element.firstChild); element.insertBefore(this.iframe, element.firstChild);
}; };
EPUBJS.View.prototype.bounds = function() {
return this.iframe.getBoundingClientRect();
};
EPUBJS.View.prototype.show = function() { EPUBJS.View.prototype.show = function() {
this.iframe.style.display = "block"; // this.iframe.style.display = "block";
this.iframe.style.display = "inline-block";
this.iframe.style.visibility = "visible"; this.iframe.style.visibility = "visible";
}; };
@ -170,6 +171,10 @@ EPUBJS.View.prototype.hide = function() {
this.iframe.style.visibility = "hidden"; this.iframe.style.visibility = "hidden";
}; };
EPUBJS.View.prototype.bounds = function() {
return this.iframe.getBoundingClientRect();
};
EPUBJS.View.prototype.destroy = function() { EPUBJS.View.prototype.destroy = function() {
// Stop observing // Stop observing
// this.observer.disconnect(); // this.observer.disconnect();