mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
Added render functions to rendition and views
This commit is contained in:
parent
948c356597
commit
ddb127cac5
17 changed files with 1402 additions and 679 deletions
1264
dist/epub.js
vendored
1264
dist/epub.js
vendored
File diff suppressed because it is too large
Load diff
2
dist/epub.js.map
vendored
2
dist/epub.js.map
vendored
File diff suppressed because one or more lines are too long
|
@ -62,7 +62,7 @@
|
||||||
var currentSectionIndex = 8;
|
var currentSectionIndex = 8;
|
||||||
// Load the opf
|
// Load the opf
|
||||||
var book = ePub("../books/alice/OPS/package.opf");
|
var book = ePub("../books/alice/OPS/package.opf");
|
||||||
var rendition = book.renderTo("viewer");
|
var rendition = book.renderTo("viewer", { view: "inline" });
|
||||||
|
|
||||||
rendition.display("chapter_008.xhtml");
|
rendition.display("chapter_008.xhtml");
|
||||||
|
|
||||||
|
|
22
src/book.js
22
src/book.js
|
@ -68,6 +68,7 @@ Book.prototype.open = function(_url){
|
||||||
var book = this;
|
var book = this;
|
||||||
var containerPath = "META-INF/container.xml";
|
var containerPath = "META-INF/container.xml";
|
||||||
var location;
|
var location;
|
||||||
|
var absoluteUri;
|
||||||
|
|
||||||
if(!_url) {
|
if(!_url) {
|
||||||
this.opening.resolve(this);
|
this.opening.resolve(this);
|
||||||
|
@ -81,7 +82,13 @@ Book.prototype.open = function(_url){
|
||||||
// uri = core.uri(_url);
|
// uri = core.uri(_url);
|
||||||
// }
|
// }
|
||||||
uri = URI(_url);
|
uri = URI(_url);
|
||||||
this.url = _url;
|
|
||||||
|
if (window) {
|
||||||
|
absoluteUri = uri.absoluteTo(window.location.href);
|
||||||
|
this.url = absoluteUri.toString();
|
||||||
|
} else {
|
||||||
|
this.url = _url;
|
||||||
|
}
|
||||||
|
|
||||||
// Find path to the Container
|
// Find path to the Container
|
||||||
if(uri.suffix() === "opf") {
|
if(uri.suffix() === "opf") {
|
||||||
|
@ -91,8 +98,9 @@ Book.prototype.open = function(_url){
|
||||||
|
|
||||||
if(uri.origin()) {
|
if(uri.origin()) {
|
||||||
this.baseUrl = uri.origin() + "/" + uri.directory() + "/";
|
this.baseUrl = uri.origin() + "/" + uri.directory() + "/";
|
||||||
} else if(window){
|
} else if(absoluteUri){
|
||||||
this.baseUrl = uri.absoluteTo(window.location.href).directory() + "/";
|
this.baseUrl = absoluteUri.origin();
|
||||||
|
this.baseUrl += absoluteUri.directory() + "/";
|
||||||
} else {
|
} else {
|
||||||
this.baseUrl = uri.directory() + "/";
|
this.baseUrl = uri.directory() + "/";
|
||||||
}
|
}
|
||||||
|
@ -130,14 +138,14 @@ Book.prototype.open = function(_url){
|
||||||
then(function(paths){
|
then(function(paths){
|
||||||
var packageUri = URI(paths.packagePath);
|
var packageUri = URI(paths.packagePath);
|
||||||
var absPackageUri = packageUri.absoluteTo(book.url);
|
var absPackageUri = packageUri.absoluteTo(book.url);
|
||||||
|
var absWindowUri;
|
||||||
|
|
||||||
book.packageUrl = absPackageUri.toString();
|
book.packageUrl = absPackageUri.toString();
|
||||||
book.encoding = paths.encoding;
|
book.encoding = paths.encoding;
|
||||||
|
|
||||||
// Set Url relative to the content
|
// Set Url relative to the content
|
||||||
if(packageUri.origin()) {
|
if(absPackageUri.origin()) {
|
||||||
book.baseUrl = packageUri.origin() + "/" + packageUri.directory() + "/";
|
book.baseUrl = absPackageUri.origin() + absPackageUri.directory() + "/";
|
||||||
} else if(window && !book.isArchivedUrl(uri)){
|
|
||||||
book.baseUrl = absPackageUri.absoluteTo(window.location.href).directory() + "/";
|
|
||||||
} else {
|
} else {
|
||||||
book.baseUrl = "/" + packageUri.directory() + "/";
|
book.baseUrl = "/" + packageUri.directory() + "/";
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,16 +69,14 @@ Contents.prototype.textHeight = function() {
|
||||||
return height;
|
return height;
|
||||||
};
|
};
|
||||||
|
|
||||||
Contents.prototype.scrollWidth = function(min) {
|
Contents.prototype.scrollWidth = function() {
|
||||||
var prev;
|
var width = this.documentElement.scrollWidth;
|
||||||
var width = this.document.body.scrollWidth;
|
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
};
|
};
|
||||||
|
|
||||||
Contents.prototype.scrollHeight = function(min) {
|
Contents.prototype.scrollHeight = function() {
|
||||||
var prev;
|
var height = this.documentElement.scrollHeight;
|
||||||
var height = this.document.body.scrollHeight;
|
|
||||||
|
|
||||||
return height;
|
return height;
|
||||||
};
|
};
|
||||||
|
@ -149,6 +147,10 @@ Contents.prototype.viewport = function() {
|
||||||
// // stub
|
// // stub
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
Contents.prototype.expand = function() {
|
||||||
|
//TODO: this should just report resize
|
||||||
|
};
|
||||||
|
|
||||||
Contents.prototype.listeners = function() {
|
Contents.prototype.listeners = function() {
|
||||||
|
|
||||||
this.imageLoadListeners();
|
this.imageLoadListeners();
|
||||||
|
@ -197,6 +199,28 @@ Contents.prototype.mediaQueryListeners = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Contents.prototype.observe = function(target) {
|
||||||
|
var renderer = this;
|
||||||
|
|
||||||
|
// create an observer instance
|
||||||
|
var observer = new MutationObserver(function(mutations) {
|
||||||
|
if(renderer._expanding) {
|
||||||
|
renderer.expand();
|
||||||
|
}
|
||||||
|
// mutations.forEach(function(mutation) {
|
||||||
|
// console.log(mutation);
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
|
||||||
|
// configuration of the observer:
|
||||||
|
var config = { attributes: true, childList: true, characterData: true, subtree: true };
|
||||||
|
|
||||||
|
// pass in the target node, as well as the observer options
|
||||||
|
observer.observe(target, config);
|
||||||
|
|
||||||
|
return observer;
|
||||||
|
};
|
||||||
|
|
||||||
Contents.prototype.imageLoadListeners = function(target) {
|
Contents.prototype.imageLoadListeners = function(target) {
|
||||||
var images = this.contentDocument.querySelectorAll("img");
|
var images = this.contentDocument.querySelectorAll("img");
|
||||||
var img;
|
var img;
|
||||||
|
@ -403,6 +427,16 @@ Contents.prototype.map = function(layout){
|
||||||
return map.section();
|
return map.section();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Contents.prototype.destroy = function() {
|
||||||
|
// Stop observing
|
||||||
|
if(this.observer) {
|
||||||
|
this.observer.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeListeners();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
RSVP.EventTarget.mixin(Contents.prototype);
|
RSVP.EventTarget.mixin(Contents.prototype);
|
||||||
|
|
||||||
module.exports = Contents;
|
module.exports = Contents;
|
||||||
|
|
|
@ -28,6 +28,7 @@ ePub.register = {
|
||||||
|
|
||||||
// Default Views
|
// Default Views
|
||||||
ePub.register.view("iframe", require('./views/iframe'));
|
ePub.register.view("iframe", require('./views/iframe'));
|
||||||
|
ePub.register.view("inline", require('./views/inline'));
|
||||||
|
|
||||||
// Default View Managers
|
// Default View Managers
|
||||||
ePub.register.manager("single", require('./managers/single'));
|
ePub.register.manager("single", require('./managers/single'));
|
||||||
|
|
|
@ -14,6 +14,8 @@ function Reflowable(){
|
||||||
this.column = 0;
|
this.column = 0;
|
||||||
this.gap = 0;
|
this.gap = 0;
|
||||||
this.divisor = 0;
|
this.divisor = 0;
|
||||||
|
|
||||||
|
this.name = "reflowable";
|
||||||
};
|
};
|
||||||
|
|
||||||
Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){
|
Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){
|
||||||
|
@ -107,6 +109,9 @@ Reflowable.prototype.count = function(totalWidth) {
|
||||||
function Fixed(_width, _height){
|
function Fixed(_width, _height){
|
||||||
this.width = 0;
|
this.width = 0;
|
||||||
this.height = 0;
|
this.height = 0;
|
||||||
|
|
||||||
|
this.name = "pre-paginated";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Fixed.prototype.calculate = function(_width, _height){
|
Fixed.prototype.calculate = function(_width, _height){
|
||||||
|
@ -166,6 +171,7 @@ function Scroll(){
|
||||||
this.spread = 0;
|
this.spread = 0;
|
||||||
this.column = 0;
|
this.column = 0;
|
||||||
this.gap = 0;
|
this.gap = 0;
|
||||||
|
this.name = "scrolled";
|
||||||
};
|
};
|
||||||
|
|
||||||
Scroll.prototype.calculate = function(_width, _height){
|
Scroll.prototype.calculate = function(_width, _height){
|
||||||
|
@ -180,7 +186,7 @@ Scroll.prototype.format = function(contents){
|
||||||
|
|
||||||
// $doc.style.width = "auto";
|
// $doc.style.width = "auto";
|
||||||
// $doc.style.height = "auto";
|
// $doc.style.height = "auto";
|
||||||
contents.width("auto");
|
// contents.width("auto");
|
||||||
contents.height("auto");
|
contents.height("auto");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,7 @@ ContinuousViewManager.prototype.moveTo = function(offset){
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
ContinuousViewManager.prototype.afterDisplayed = function(currView){
|
ContinuousViewManager.prototype.afterDisplayed = function(currView){
|
||||||
var next = currView.section.next();
|
var next = currView.section.next();
|
||||||
var prev = currView.section.prev();
|
var prev = currView.section.prev();
|
||||||
|
@ -61,7 +61,10 @@ ContinuousViewManager.prototype.afterDisplayed = function(currView){
|
||||||
this.trigger("added", currView.section);
|
this.trigger("added", currView.section);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
ContinuousViewManager.prototype.afterResized = function(view){
|
||||||
|
this.trigger("resize", view.section);
|
||||||
|
};
|
||||||
|
|
||||||
// Remove Previous Listeners if present
|
// Remove Previous Listeners if present
|
||||||
ContinuousViewManager.prototype.removeShownListeners = function(view){
|
ContinuousViewManager.prototype.removeShownListeners = function(view){
|
||||||
|
@ -72,27 +75,31 @@ ContinuousViewManager.prototype.removeShownListeners = function(view){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.append = function(view){
|
ContinuousViewManager.prototype.append = function(section){
|
||||||
|
var view = this.createView(section);
|
||||||
|
|
||||||
// view.on("shown", this.afterDisplayed.bind(this));
|
return this.q.enqueue(function() {
|
||||||
view.onDisplayed = this.afterDisplayed.bind(this);
|
|
||||||
|
|
||||||
this.views.append(view);
|
this.views.append(view);
|
||||||
|
|
||||||
//this.q.enqueue(this.check);
|
return this.update();
|
||||||
return this.check();
|
|
||||||
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.prepend = function(view){
|
ContinuousViewManager.prototype.prepend = function(section){
|
||||||
// view.on("shown", this.afterDisplayedAbove.bind(this));
|
var view = this.createView(section);
|
||||||
view.onDisplayed = this.afterDisplayed.bind(this);
|
|
||||||
|
|
||||||
view.on("resized", this.counter.bind(this));
|
view.on("resized", this.counter.bind(this));
|
||||||
|
|
||||||
this.views.prepend(view);
|
return this.q.enqueue(function() {
|
||||||
|
|
||||||
|
this.views.prepend(view);
|
||||||
|
|
||||||
|
return this.update();
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
// this.q.enqueue(this.check);
|
|
||||||
return this.check();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.counter = function(bounds){
|
ContinuousViewManager.prototype.counter = function(bounds){
|
||||||
|
@ -104,7 +111,7 @@ ContinuousViewManager.prototype.counter = function(bounds){
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
ContinuousViewManager.prototype.check = function(_offset){
|
ContinuousViewManager.prototype.check = function(_offset){
|
||||||
var checking = new RSVP.defer();
|
var checking = new RSVP.defer();
|
||||||
var container = this.stage.bounds();
|
var container = this.stage.bounds();
|
||||||
|
@ -154,6 +161,98 @@ ContinuousViewManager.prototype.check = function(_offset){
|
||||||
return checking.promise;
|
return checking.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype.update = function(_offset){
|
||||||
|
var container = this.stage.bounds();
|
||||||
|
var views = this.views;
|
||||||
|
var viewsLength = views.length;
|
||||||
|
var visible = [];
|
||||||
|
var isVisible;
|
||||||
|
var view;
|
||||||
|
|
||||||
|
var updating = new RSVP.defer();
|
||||||
|
var promises = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < viewsLength; i++) {
|
||||||
|
view = views[i];
|
||||||
|
isVisible = this.isVisible(view, 0, 0, container);
|
||||||
|
|
||||||
|
if(isVisible === true) {
|
||||||
|
promises.push(view.display());
|
||||||
|
visible.push(view);
|
||||||
|
} else {
|
||||||
|
this.q.enqueue(view.destroy.bind(view));
|
||||||
|
|
||||||
|
clearTimeout(this.trimTimeout);
|
||||||
|
this.trimTimeout = setTimeout(function(){
|
||||||
|
this.q.enqueue(this.trim.bind(this));
|
||||||
|
}.bind(this), 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(promises.length){
|
||||||
|
return RSVP.all(promises);
|
||||||
|
} else {
|
||||||
|
updating.resolve();
|
||||||
|
return updating.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){
|
||||||
|
var next, prev;
|
||||||
|
var horizontal = (this.settings.axis === "horizontal");
|
||||||
|
var delta = this.settings.offset || 0;
|
||||||
|
|
||||||
|
if (_offsetLeft && horizontal) {
|
||||||
|
delta = _offsetLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_offsetTop && !horizontal) {
|
||||||
|
delta = _offsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bounds = this.stage.bounds(); // TODO: save this until resize
|
||||||
|
|
||||||
|
var offset = horizontal ? this.container.scrollLeft : this.container.scrollTop;
|
||||||
|
var visibleLength = horizontal ? bounds.width : bounds.height;
|
||||||
|
var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
|
||||||
|
|
||||||
|
var checking = new RSVP.defer();
|
||||||
|
var promises = [];
|
||||||
|
|
||||||
|
if (offset + visibleLength + delta >= contentLength) {
|
||||||
|
next = this.views.last().section.next();
|
||||||
|
if(next) {
|
||||||
|
promises.push(this.append(next));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset - delta < 0 ) {
|
||||||
|
prev = this.views.first().section.prev();
|
||||||
|
if(prev) {
|
||||||
|
promises.push(this.prepend(prev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(promises.length){
|
||||||
|
|
||||||
|
return RSVP.all(promises)
|
||||||
|
.then(function(posts) {
|
||||||
|
// Check to see if anything new is on screen after rendering
|
||||||
|
this.q.enqueue(this.update.bind(this));
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
checking.resolve();
|
||||||
|
|
||||||
|
return checking.promise;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.trim = function(){
|
ContinuousViewManager.prototype.trim = function(){
|
||||||
|
@ -309,15 +408,15 @@ ContinuousViewManager.prototype.onScroll = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ContinuousViewManager.prototype.resizeView = function(view) {
|
// ContinuousViewManager.prototype.resizeView = function(view) {
|
||||||
|
//
|
||||||
if(this.settings.axis === "horizontal") {
|
// if(this.settings.axis === "horizontal") {
|
||||||
view.lock("height", this.stage.width, this.stage.height);
|
// view.lock("height", this.stage.width, this.stage.height);
|
||||||
} else {
|
// } else {
|
||||||
view.lock("width", this.stage.width, this.stage.height);
|
// view.lock("width", this.stage.width, this.stage.height);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
};
|
// };
|
||||||
|
|
||||||
ContinuousViewManager.prototype.currentLocation = function(){
|
ContinuousViewManager.prototype.currentLocation = function(){
|
||||||
var visible = this.visible();
|
var visible = this.visible();
|
||||||
|
|
|
@ -2,7 +2,7 @@ var RSVP = require('rsvp');
|
||||||
var core = require('../core');
|
var core = require('../core');
|
||||||
var ContinuousViewManager = require('./continuous');
|
var ContinuousViewManager = require('./continuous');
|
||||||
var Map = require('../map');
|
var Map = require('../map');
|
||||||
// var Layout = require('./layout');
|
var Layout = require('../layout');
|
||||||
|
|
||||||
function PaginatedViewManager(book, options) {
|
function PaginatedViewManager(book, options) {
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ PaginatedViewManager.prototype.applyLayoutMethod = function() {
|
||||||
|
|
||||||
// Set the look ahead offset for what is visible
|
// Set the look ahead offset for what is visible
|
||||||
|
|
||||||
this.map = new Map(this.layout);
|
// this.map = new Map(this.layout);
|
||||||
|
|
||||||
// this.hooks.layout.register(this.layout.format.bind(this));
|
// this.hooks.layout.register(this.layout.format.bind(this));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('../core');
|
var core = require('../core');
|
||||||
|
var Stage = require('../stage');
|
||||||
var Views = require('../views');
|
var Views = require('../views');
|
||||||
var EpubCFI = require('../epubcfi');
|
var EpubCFI = require('../epubcfi');
|
||||||
|
var Layout = require('../layout');
|
||||||
|
|
||||||
function SingleViewManager(options) {
|
function SingleViewManager(options) {
|
||||||
|
|
||||||
|
@ -15,23 +17,35 @@ function SingleViewManager(options) {
|
||||||
width: false,
|
width: false,
|
||||||
height: null,
|
height: null,
|
||||||
globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'},
|
globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'},
|
||||||
layout: null,
|
// layout: null,
|
||||||
axis: "vertical",
|
axis: "vertical",
|
||||||
ignoreClass: ''
|
ignoreClass: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options.settings);
|
core.extend(this.settings, options.settings);
|
||||||
|
|
||||||
|
|
||||||
this.viewSettings = {
|
this.viewSettings = {
|
||||||
ignoreClass: this.settings.ignoreClass
|
ignoreClass: this.settings.ignoreClass,
|
||||||
|
globalLayoutProperties: this.settings.globalLayoutProperties,
|
||||||
|
axis: this.settings.axis,
|
||||||
|
layout: this.layout,
|
||||||
|
width: 0,
|
||||||
|
height: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleViewManager.prototype.start = function(stage){
|
SingleViewManager.prototype.render = function(element, size){
|
||||||
|
|
||||||
// Save the stage
|
// Save the stage
|
||||||
this.stage = stage;
|
this.stage = new Stage({
|
||||||
|
width: size.width,
|
||||||
|
height: size.height,
|
||||||
|
hidden: this.settings.hidden
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stage.attachTo(element);
|
||||||
|
|
||||||
// Get this stage container div
|
// Get this stage container div
|
||||||
this.container = this.stage.getContainer();
|
this.container = this.stage.getContainer();
|
||||||
|
@ -42,6 +56,10 @@ SingleViewManager.prototype.start = function(stage){
|
||||||
// Calculate Stage Size
|
// Calculate Stage Size
|
||||||
this.bounds = this.stage.bounds();
|
this.bounds = this.stage.bounds();
|
||||||
|
|
||||||
|
// Set the dimensions for views
|
||||||
|
this.viewSettings.width = this.bounds.width;
|
||||||
|
this.viewSettings.height = this.bounds.height;
|
||||||
|
|
||||||
// Function to handle a resize event.
|
// Function to handle a resize event.
|
||||||
// Will only attach if width and height are both fixed.
|
// Will only attach if width and height are both fixed.
|
||||||
this.stage.onResize(this.onResized.bind(this));
|
this.stage.onResize(this.onResized.bind(this));
|
||||||
|
@ -50,7 +68,7 @@ SingleViewManager.prototype.start = function(stage){
|
||||||
this.addEventListeners();
|
this.addEventListeners();
|
||||||
|
|
||||||
// Add Layout method
|
// Add Layout method
|
||||||
// this.applyLayoutMethod();
|
this.applyLayoutMethod();
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.addEventListeners = function(){
|
SingleViewManager.prototype.addEventListeners = function(){
|
||||||
|
@ -65,7 +83,14 @@ SingleViewManager.prototype.resize = function(width, height){
|
||||||
|
|
||||||
this.bounds = this.stage.bounds(width, height);
|
this.bounds = this.stage.bounds(width, height);
|
||||||
|
|
||||||
this.views.each(this.resizeView.bind(this));
|
// Update for new views
|
||||||
|
this.viewSettings.width = this.bounds.width;
|
||||||
|
this.viewSettings.height = this.bounds.height;
|
||||||
|
|
||||||
|
// Update for existing views
|
||||||
|
this.views.each(function(view) {
|
||||||
|
view.size(this.bounds.width, this.bounds.height);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
this.trigger("resized", {
|
this.trigger("resized", {
|
||||||
width: this.stage.width,
|
width: this.stage.width,
|
||||||
|
@ -74,10 +99,12 @@ SingleViewManager.prototype.resize = function(width, height){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.layout = function(layoutFunc){
|
SingleViewManager.prototype.setLayout = function(layout){
|
||||||
|
|
||||||
|
this.viewSettings.layout = layout;
|
||||||
|
|
||||||
this.views.each(function(view){
|
this.views.each(function(view){
|
||||||
layoutFunc(view);
|
view.setLayout(layout);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -106,10 +133,12 @@ SingleViewManager.prototype.display = function(section, target){
|
||||||
// Hide all current views
|
// Hide all current views
|
||||||
this.views.hide();
|
this.views.hide();
|
||||||
|
|
||||||
|
this.views.clear();
|
||||||
|
|
||||||
// Create a new view
|
// Create a new view
|
||||||
view = this.createView(section);
|
view = this.createView(section);
|
||||||
|
|
||||||
return this.fill(view)
|
return this.add(view)
|
||||||
.then(function(){
|
.then(function(){
|
||||||
|
|
||||||
// Move to correct place within the section, if needed
|
// Move to correct place within the section, if needed
|
||||||
|
@ -129,34 +158,38 @@ SingleViewManager.prototype.display = function(section, target){
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.afterDisplayed = function(view){
|
SingleViewManager.prototype.afterDisplayed = function(view){
|
||||||
this.trigger("added", view.section);
|
this.trigger("added", view);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.afterResized = function(view){
|
||||||
|
this.trigger("resize", view.section);
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.moveTo = function(offset){
|
SingleViewManager.prototype.moveTo = function(offset){
|
||||||
this.scrollTo(offset.left, offset.top);
|
this.scrollTo(offset.left, offset.top);
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.fill = function(view){
|
SingleViewManager.prototype.add = function(view){
|
||||||
|
|
||||||
this.views.clear();
|
|
||||||
|
|
||||||
this.views.append(view);
|
this.views.append(view);
|
||||||
|
|
||||||
// view.on("shown", this.afterDisplayed.bind(this));
|
// view.on("shown", this.afterDisplayed.bind(this));
|
||||||
view.onDisplayed = this.afterDisplayed.bind(this);
|
view.onDisplayed = this.afterDisplayed.bind(this);
|
||||||
|
view.onResize = this.afterResized.bind(this);
|
||||||
|
|
||||||
return this.renderer(view, this.views.hidden);
|
return view.display();
|
||||||
|
// return this.renderer(view, this.views.hidden);
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.resizeView = function(view) {
|
// SingleViewManager.prototype.resizeView = function(view) {
|
||||||
|
//
|
||||||
if(this.settings.globalLayoutProperties.layout === "pre-paginated") {
|
// if(this.settings.globalLayoutProperties.layout === "pre-paginated") {
|
||||||
view.lock("both", this.bounds.width, this.bounds.height);
|
// view.lock("both", this.bounds.width, this.bounds.height);
|
||||||
} else {
|
// } else {
|
||||||
view.lock("width", this.bounds.width, this.bounds.height);
|
// view.lock("width", this.bounds.width, this.bounds.height);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
};
|
// };
|
||||||
|
|
||||||
SingleViewManager.prototype.next = function(){
|
SingleViewManager.prototype.next = function(){
|
||||||
var next;
|
var next;
|
||||||
|
@ -167,8 +200,10 @@ SingleViewManager.prototype.next = function(){
|
||||||
next = this.views.last().section.next();
|
next = this.views.last().section.next();
|
||||||
|
|
||||||
if(next) {
|
if(next) {
|
||||||
|
this.views.clear();
|
||||||
|
|
||||||
view = this.createView(next);
|
view = this.createView(next);
|
||||||
return this.fill(view)
|
return this.add(view)
|
||||||
.then(function(){
|
.then(function(){
|
||||||
this.views.show();
|
this.views.show();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@ -183,8 +218,10 @@ SingleViewManager.prototype.prev = function(){
|
||||||
|
|
||||||
prev = this.views.first().section.prev();
|
prev = this.views.first().section.prev();
|
||||||
if(prev) {
|
if(prev) {
|
||||||
|
this.views.clear();
|
||||||
|
|
||||||
view = this.createView(prev);
|
view = this.createView(prev);
|
||||||
return this.fill(view)
|
return this.add(view)
|
||||||
.then(function(){
|
.then(function(){
|
||||||
this.views.show();
|
this.views.show();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@ -236,14 +273,17 @@ SingleViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.visible = function(){
|
SingleViewManager.prototype.visible = function(){
|
||||||
|
return this.views.displayed();
|
||||||
|
/*
|
||||||
var container = this.stage.bounds();
|
var container = this.stage.bounds();
|
||||||
var displayedViews = this.views.displayed();
|
var views = this.views;
|
||||||
|
var viewsLength = views.length;
|
||||||
var visible = [];
|
var visible = [];
|
||||||
var isVisible;
|
var isVisible;
|
||||||
var view;
|
var view;
|
||||||
|
|
||||||
for (var i = 0; i < displayedViews.length; i++) {
|
for (var i = 0; i < viewsLength; i++) {
|
||||||
view = displayedViews[i];
|
view = views[i];
|
||||||
isVisible = this.isVisible(view, 0, 0, container);
|
isVisible = this.isVisible(view, 0, 0, container);
|
||||||
|
|
||||||
if(isVisible === true) {
|
if(isVisible === true) {
|
||||||
|
@ -252,7 +292,7 @@ SingleViewManager.prototype.visible = function(){
|
||||||
|
|
||||||
}
|
}
|
||||||
return visible;
|
return visible;
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.scrollBy = function(x, y, silent){
|
SingleViewManager.prototype.scrollBy = function(x, y, silent){
|
||||||
|
@ -293,6 +333,40 @@ SingleViewManager.prototype.scrollTo = function(x, y, silent){
|
||||||
// };
|
// };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.bounds = function() {
|
||||||
|
var bounds;
|
||||||
|
|
||||||
|
if(!this.settings.height || !this.container) {
|
||||||
|
bounds = core.windowBounds();
|
||||||
|
} else {
|
||||||
|
bounds = this.container.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.applyLayoutMethod = function() {
|
||||||
|
|
||||||
|
this.layout = new Layout.Scroll();
|
||||||
|
this.calculateLayout();
|
||||||
|
|
||||||
|
this.setLayout(this.layout);
|
||||||
|
|
||||||
|
// this.map = new Map(this.layout);
|
||||||
|
// this.manager.layout(this.layout.format);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.calculateLayout = function() {
|
||||||
|
var bounds = this.stage.bounds();
|
||||||
|
this.layout.calculate(bounds.width, bounds.height);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.updateLayout = function() {
|
||||||
|
this.calculateLayout();
|
||||||
|
|
||||||
|
this.setLayout(this.layout);
|
||||||
|
};
|
||||||
|
|
||||||
//-- Enable binding events to Manager
|
//-- Enable binding events to Manager
|
||||||
RSVP.EventTarget.mixin(SingleViewManager.prototype);
|
RSVP.EventTarget.mixin(SingleViewManager.prototype);
|
||||||
|
|
||||||
|
|
|
@ -154,9 +154,11 @@ Parser.prototype.metadata = function(xml){
|
||||||
metadata.rights = p.getElementText(xml, "rights");
|
metadata.rights = p.getElementText(xml, "rights");
|
||||||
|
|
||||||
metadata.modified_date = p.getPropertyText(xml, 'dcterms:modified');
|
metadata.modified_date = p.getPropertyText(xml, 'dcterms:modified');
|
||||||
|
|
||||||
metadata.layout = p.getPropertyText(xml, "rendition:layout");
|
metadata.layout = p.getPropertyText(xml, "rendition:layout");
|
||||||
metadata.orientation = p.getPropertyText(xml, 'rendition:orientation');
|
metadata.orientation = p.getPropertyText(xml, 'rendition:orientation');
|
||||||
metadata.spread = p.getPropertyText(xml, 'rendition:spread');
|
metadata.flow = p.getPropertyText(xml, 'rendition:flow');
|
||||||
|
metadata.viewport = p.getPropertyText(xml, 'rendition:viewport');
|
||||||
// metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
|
// metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
|
||||||
|
|
||||||
return metadata;
|
return metadata;
|
||||||
|
|
106
src/rendition.js
106
src/rendition.js
|
@ -9,16 +9,15 @@ var View = require('./view');
|
||||||
var Views = require('./views');
|
var Views = require('./views');
|
||||||
var Layout = require('./layout');
|
var Layout = require('./layout');
|
||||||
var Map = require('./map');
|
var Map = require('./map');
|
||||||
var Stage = require('./stage');
|
|
||||||
|
|
||||||
function Rendition(book, options) {
|
function Rendition(book, options) {
|
||||||
|
|
||||||
this.settings = core.extend(this.settings || {}, {
|
this.settings = core.extend(this.settings || {}, {
|
||||||
infinite: true,
|
infinite: true,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
width: false,
|
width: null,
|
||||||
height: null,
|
height: null,
|
||||||
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto', flow: 'auto', viewport: ''},
|
||||||
axis: "vertical",
|
axis: "vertical",
|
||||||
ignoreClass: '',
|
ignoreClass: '',
|
||||||
manager: "single",
|
manager: "single",
|
||||||
|
@ -67,6 +66,15 @@ function Rendition(book, options) {
|
||||||
this.replacements();
|
this.replacements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.ViewManager = this.requireManager(this.settings.manager);
|
||||||
|
this.View = this.requireView(this.settings.view);
|
||||||
|
|
||||||
|
this.manager = new this.ViewManager({
|
||||||
|
view: this.View,
|
||||||
|
queue: this.q,
|
||||||
|
settings: this.settings
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.setManager = function(manager) {
|
Rendition.prototype.setManager = function(manager) {
|
||||||
|
@ -104,30 +112,13 @@ Rendition.prototype.requireView = function(view) {
|
||||||
return View;
|
return View;
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.start = function(stage){
|
Rendition.prototype.start = function(){
|
||||||
var ViewManager, View;
|
|
||||||
|
|
||||||
// Add view manager
|
|
||||||
if (!this.manager) {
|
|
||||||
ViewManager = this.requireManager(this.settings.manager);
|
|
||||||
View = this.requireView(this.settings.view);
|
|
||||||
|
|
||||||
this.manager = new ViewManager({
|
|
||||||
view: View,
|
|
||||||
renderer: this.render.bind(this),
|
|
||||||
queue: this.q,
|
|
||||||
settings: this.settings
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen for displayed views
|
// Listen for displayed views
|
||||||
this.manager.on("added", this.afterDisplayed.bind(this))
|
this.manager.on("added", this.afterDisplayed.bind(this))
|
||||||
|
|
||||||
// Start rendering
|
|
||||||
this.manager.start(stage);
|
|
||||||
|
|
||||||
// Add Layout method
|
// Add Layout method
|
||||||
this.applyLayoutMethod();
|
// this.applyLayoutMethod();
|
||||||
|
|
||||||
this.on('displayed', this.reportLocation.bind(this));
|
this.on('displayed', this.reportLocation.bind(this));
|
||||||
|
|
||||||
|
@ -142,12 +133,13 @@ Rendition.prototype.start = function(stage){
|
||||||
// Container must be attached before rendering can begin
|
// Container must be attached before rendering can begin
|
||||||
Rendition.prototype.attachTo = function(element){
|
Rendition.prototype.attachTo = function(element){
|
||||||
|
|
||||||
this.container = new Stage(element, {
|
// Start rendering
|
||||||
|
this.manager.render(element, {
|
||||||
"width" : this.settings.width,
|
"width" : this.settings.width,
|
||||||
"height" : this.settings.height
|
"height" : this.settings.height
|
||||||
});
|
});
|
||||||
|
|
||||||
this.start(this.container);
|
this.start();
|
||||||
|
|
||||||
// Trigger Attached
|
// Trigger Attached
|
||||||
this.trigger("attached");
|
this.trigger("attached");
|
||||||
|
@ -197,6 +189,7 @@ Rendition.prototype._display = function(target){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
Rendition.prototype.render = function(view, show) {
|
Rendition.prototype.render = function(view, show) {
|
||||||
|
|
||||||
// view.onLayout = this.layout.format.bind(this.layout);
|
// view.onLayout = this.layout.format.bind(this.layout);
|
||||||
|
@ -239,36 +232,17 @@ Rendition.prototype.render = function(view, show) {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
Rendition.prototype.afterDisplayed = function(section){
|
Rendition.prototype.afterDisplayed = function(view){
|
||||||
this.trigger("added", section);
|
this.hooks.content.trigger(view, this);
|
||||||
|
this.trigger("rendered", view.section);
|
||||||
this.reportLocation();
|
this.reportLocation();
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.applyLayoutMethod = function() {
|
|
||||||
|
|
||||||
this.layout = new Layout.Scroll();
|
|
||||||
this.calculateLayout();
|
|
||||||
|
|
||||||
// this.map = new Map(this.layout);
|
|
||||||
// this.manager.layout(this.layout.format);
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.calculateLayout = function() {
|
|
||||||
// TODO: should this be a function to get the live bounds? It is cached and updated on resize for now.
|
|
||||||
var bounds = this.manager.bounds;
|
|
||||||
this.layout.calculate(bounds.width, bounds.height);
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.updateLayout = function() {
|
|
||||||
this.calculateLayout();
|
|
||||||
|
|
||||||
this.manager.layout(this.layout.format);
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.onResized = function(size){
|
Rendition.prototype.onResized = function(size){
|
||||||
|
|
||||||
this.updateLayout();
|
this.manager.updateLayout();
|
||||||
|
|
||||||
if(this.location) {
|
if(this.location) {
|
||||||
this.display(this.location.start);
|
this.display(this.location.start);
|
||||||
|
@ -293,29 +267,21 @@ Rendition.prototype.prev = function(){
|
||||||
return this.q.enqueue(this.manager.prev.bind(this.manager));
|
return this.q.enqueue(this.manager.prev.bind(this.manager));
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.bounds = function() {
|
|
||||||
var bounds;
|
|
||||||
|
|
||||||
if(!this.settings.height || !this.container) {
|
|
||||||
bounds = core.windowBounds();
|
|
||||||
} else {
|
|
||||||
bounds = this.container.getBoundingClientRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return bounds;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-- http://www.idpf.org/epub/fxl/
|
//-- http://www.idpf.org/epub/fxl/
|
||||||
Rendition.prototype.parseLayoutProperties = function(_metadata){
|
Rendition.prototype.parseLayoutProperties = function(_metadata){
|
||||||
var metadata = _metadata || this.book.package.metadata;
|
var metadata = _metadata || this.book.package.metadata;
|
||||||
var layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || "reflowable";
|
var layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || "reflowable";
|
||||||
var spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || "auto";
|
var spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || "auto";
|
||||||
var orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || "auto";
|
var orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || "auto";
|
||||||
|
var flow = (this.layoutOveride && this.layoutOveride.flow) || metadata.flow || "auto";
|
||||||
|
var viewport = (this.layoutOveride && this.layoutOveride.viewport) || metadata.viewport || "";
|
||||||
|
|
||||||
this.settings.globalLayoutProperties = {
|
this.settings.globalLayoutProperties = {
|
||||||
layout : layout,
|
layout : layout,
|
||||||
spread : spread,
|
spread : spread,
|
||||||
orientation : orientation
|
orientation : orientation,
|
||||||
|
flow : flow,
|
||||||
|
viewport : viewport
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.settings.globalLayoutProperties;
|
return this.settings.globalLayoutProperties;
|
||||||
|
@ -323,33 +289,23 @@ Rendition.prototype.parseLayoutProperties = function(_metadata){
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the settings to determine which Layout Method is needed
|
* 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
|
|
||||||
*/
|
*/
|
||||||
// Paginate.prototype.determineLayout = function(settings){
|
// Rendition.prototype.determineLayout = function(settings){
|
||||||
// // Default is layout: reflowable & spread: auto
|
// // Default is layout: reflowable & spread: auto
|
||||||
// var spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
// var spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
||||||
// console.log("spreads", spreads, this.settings.minSpreadWidth)
|
|
||||||
// var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
|
// var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable";
|
||||||
// var scroll = false;
|
// var scroll = false;
|
||||||
//
|
//
|
||||||
// if(settings.layout === "pre-paginated") {
|
// if(settings.layout === "pre-paginated") {
|
||||||
// layoutMethod = "Fixed";
|
//
|
||||||
// scroll = true;
|
|
||||||
// spreads = false;
|
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// if(settings.layout === "reflowable" && settings.spread === "none") {
|
// if(settings.layout === "reflowable" && settings.spread === "none") {
|
||||||
// layoutMethod = "Reflowable";
|
//
|
||||||
// scroll = false;
|
|
||||||
// spreads = false;
|
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// if(settings.layout === "reflowable" && settings.spread === "both") {
|
// if(settings.layout === "reflowable" && settings.spread === "both") {
|
||||||
// layoutMethod = "ReflowableSpreads";
|
//
|
||||||
// scroll = false;
|
|
||||||
// spreads = true;
|
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// this.spreads = spreads;
|
// this.spreads = spreads;
|
||||||
|
|
|
@ -16,11 +16,10 @@ function base(doc, section){
|
||||||
|
|
||||||
if(!base) {
|
if(!base) {
|
||||||
base = doc.createElement("base");
|
base = doc.createElement("base");
|
||||||
|
head.insertBefore(base, head.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
base.setAttribute("href", section.url);
|
base.setAttribute("href", section.url);
|
||||||
head.insertBefore(base, head.firstChild);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function links(view, renderer) {
|
function links(view, renderer) {
|
||||||
|
|
|
@ -60,8 +60,9 @@ Section.prototype.base = function(_document){
|
||||||
var task = new RSVP.defer();
|
var task = new RSVP.defer();
|
||||||
var base = _document.createElement("base"); // TODO: check if exists
|
var base = _document.createElement("base"); // TODO: check if exists
|
||||||
var head;
|
var head;
|
||||||
|
console.log(window.location.origin + "/" +this.url);
|
||||||
|
|
||||||
base.setAttribute("href", this.url);
|
base.setAttribute("href", window.location.origin + "/" +this.url);
|
||||||
|
|
||||||
if(_document) {
|
if(_document) {
|
||||||
head = _document.querySelector("head");
|
head = _document.querySelector("head");
|
||||||
|
|
27
src/stage.js
27
src/stage.js
|
@ -1,16 +1,12 @@
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
|
||||||
function Stage(element, _options) {
|
function Stage(_options) {
|
||||||
this.settings = _options || {};
|
this.settings = _options || {};
|
||||||
|
|
||||||
this.element = this.getElement(element);
|
|
||||||
this.container = this.create(this.settings);
|
this.container = this.create(this.settings);
|
||||||
|
|
||||||
if(this.settings.hidden) {
|
if(this.settings.hidden) {
|
||||||
this.wrapper = this.wrap(this.container);
|
this.wrapper = this.wrap(this.container);
|
||||||
this.attachTo(this.wrapper, this.element);
|
|
||||||
} else {
|
|
||||||
this.attachTo(this.container, this.element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,7 +35,7 @@ Stage.prototype.create = function(options){
|
||||||
container.classList.add("epub-container");
|
container.classList.add("epub-container");
|
||||||
|
|
||||||
// Style Element
|
// Style Element
|
||||||
container.style.fontSize = "0";
|
// container.style.fontSize = "0";
|
||||||
container.style.wordSpacing = "0";
|
container.style.wordSpacing = "0";
|
||||||
container.style.lineHeight = "0";
|
container.style.lineHeight = "0";
|
||||||
container.style.verticalAlign = "top";
|
container.style.verticalAlign = "top";
|
||||||
|
@ -93,13 +89,24 @@ Stage.prototype.getElement = function(_element){
|
||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
|
|
||||||
Stage.prototype.attachTo = function(what, element){
|
Stage.prototype.attachTo = function(what){
|
||||||
|
|
||||||
|
var element = this.getElement(what);
|
||||||
|
var base;
|
||||||
|
|
||||||
if(!element){
|
if(!element){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
element.appendChild(what);
|
if(this.settings.hidden) {
|
||||||
|
base = this.wrapper;
|
||||||
|
} else {
|
||||||
|
base = this.container;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.appendChild(base);
|
||||||
|
|
||||||
|
this.element = element;
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
|
||||||
|
@ -125,7 +132,7 @@ Stage.prototype.bounds = function(_width, _height){
|
||||||
var height = _height || this.settings.height;
|
var height = _height || this.settings.height;
|
||||||
|
|
||||||
// If width or height are set to false, inherit them from containing element
|
// If width or height are set to false, inherit them from containing element
|
||||||
if(width === false) {
|
if(width === null) {
|
||||||
bounds = this.element.getBoundingClientRect();
|
bounds = this.element.getBoundingClientRect();
|
||||||
|
|
||||||
if(bounds.width) {
|
if(bounds.width) {
|
||||||
|
@ -134,7 +141,7 @@ Stage.prototype.bounds = function(_width, _height){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(height === false) {
|
if(height === null) {
|
||||||
bounds = bounds || this.element.getBoundingClientRect();
|
bounds = bounds || this.element.getBoundingClientRect();
|
||||||
|
|
||||||
if(bounds.height) {
|
if(bounds.height) {
|
||||||
|
|
|
@ -13,10 +13,6 @@ Views.prototype.last = function() {
|
||||||
return this._views[this._views.length-1];
|
return this._views[this._views.length-1];
|
||||||
};
|
};
|
||||||
|
|
||||||
Views.prototype.each = function() {
|
|
||||||
return this._views.forEach.apply(this._views, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
Views.prototype.indexOf = function(view) {
|
Views.prototype.indexOf = function(view) {
|
||||||
return this._views.indexOf(view);
|
return this._views.indexOf(view);
|
||||||
};
|
};
|
||||||
|
@ -89,6 +85,10 @@ Views.prototype.destroy = function(view) {
|
||||||
|
|
||||||
// Iterators
|
// Iterators
|
||||||
|
|
||||||
|
Views.prototype.each = function() {
|
||||||
|
return this._views.forEach.apply(this._views, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
Views.prototype.clear = function(){
|
Views.prototype.clear = function(){
|
||||||
// Remove all views
|
// Remove all views
|
||||||
var view;
|
var view;
|
||||||
|
|
|
@ -5,42 +5,50 @@ var Contents = require('../contents');
|
||||||
|
|
||||||
function IframeView(section, options) {
|
function IframeView(section, options) {
|
||||||
this.settings = core.extend({
|
this.settings = core.extend({
|
||||||
ignoreClass : ''
|
ignoreClass : '',
|
||||||
|
axis: 'vertical',
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
layout: undefined,
|
||||||
|
globalLayoutProperties: {},
|
||||||
}, options || {});
|
}, options || {});
|
||||||
|
|
||||||
this.id = "epubjs-view:" + core.uuid();
|
this.id = "epubjs-view:" + core.uuid();
|
||||||
this.section = section;
|
this.section = section;
|
||||||
this.index = section.index;
|
this.index = section.index;
|
||||||
|
|
||||||
this.element = this.createContainer();
|
this.element = this.container(this.settings.axis);
|
||||||
|
|
||||||
this.added = false;
|
this.added = false;
|
||||||
this.displayed = false;
|
this.displayed = false;
|
||||||
this.rendered = false;
|
this.rendered = false;
|
||||||
|
|
||||||
//this.width = 0;
|
this.width = this.settings.width;
|
||||||
//this.height = 0;
|
this.height = this.settings.height;
|
||||||
|
|
||||||
|
this.fixedWidth = 0;
|
||||||
|
this.fixedHeight = 0;
|
||||||
|
|
||||||
// Blank Cfi for Parsing
|
// Blank Cfi for Parsing
|
||||||
this.epubcfi = new EpubCFI();
|
this.epubcfi = new EpubCFI();
|
||||||
|
|
||||||
|
this.layout = this.settings.layout;
|
||||||
// Dom events to listen for
|
// Dom events to listen for
|
||||||
// this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
|
// this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IframeView.prototype.createContainer = function() {
|
IframeView.prototype.container = function(axis) {
|
||||||
var element = document.createElement('div');
|
var element = document.createElement('div');
|
||||||
|
|
||||||
element.classList.add("epub-view");
|
element.classList.add("epub-view");
|
||||||
|
|
||||||
|
|
||||||
// this.element.style.minHeight = "100px";
|
// this.element.style.minHeight = "100px";
|
||||||
element.style.height = "0px";
|
element.style.height = "0px";
|
||||||
element.style.width = "0px";
|
element.style.width = "0px";
|
||||||
element.style.overflow = "hidden";
|
element.style.overflow = "hidden";
|
||||||
|
|
||||||
if(this.settings.axis && this.settings.axis == "horizontal"){
|
if(axis && axis == "horizontal"){
|
||||||
element.style.display = "inline-block";
|
element.style.display = "inline-block";
|
||||||
} else {
|
} else {
|
||||||
element.style.display = "block";
|
element.style.display = "block";
|
||||||
|
@ -92,20 +100,87 @@ IframeView.prototype.create = function() {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Firefox has trouble with baseURI and srcdoc
|
// Firefox has trouble with baseURI and srcdoc
|
||||||
// Disabled for now
|
// TODO: Disable for now in firefox
|
||||||
/*
|
|
||||||
if(!!("srcdoc" in this.iframe)) {
|
if(!!("srcdoc" in this.iframe)) {
|
||||||
this.supportsSrcdoc = true;
|
this.supportsSrcdoc = true;
|
||||||
} else {
|
} else {
|
||||||
this.supportsSrcdoc = false;
|
this.supportsSrcdoc = false;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
this.supportsSrcdoc = false;
|
|
||||||
|
|
||||||
return this.iframe;
|
return this.iframe;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.render = function(request, show) {
|
||||||
|
|
||||||
|
// view.onLayout = this.layout.format.bind(this.layout);
|
||||||
|
this.create();
|
||||||
|
|
||||||
|
// Fit to size of the container, apply padding
|
||||||
|
this.size();
|
||||||
|
|
||||||
|
// Render Chain
|
||||||
|
return this.section.render(request)
|
||||||
|
.then(function(contents){
|
||||||
|
return this.load(contents);
|
||||||
|
}.bind(this))
|
||||||
|
// .then(function(doc){
|
||||||
|
// return this.hooks.content.trigger(view, this);
|
||||||
|
// }.bind(this))
|
||||||
|
.then(function(){
|
||||||
|
// this.settings.layout.format(view.contents);
|
||||||
|
// return this.hooks.layout.trigger(view, this);
|
||||||
|
}.bind(this))
|
||||||
|
// .then(function(){
|
||||||
|
// return this.display();
|
||||||
|
// }.bind(this))
|
||||||
|
// .then(function(){
|
||||||
|
// return this.hooks.render.trigger(view, this);
|
||||||
|
// }.bind(this))
|
||||||
|
.then(function(){
|
||||||
|
|
||||||
|
// apply the layout function to the contents
|
||||||
|
this.settings.layout.format(this.contents);
|
||||||
|
|
||||||
|
// Expand the iframe to the full size of the content
|
||||||
|
this.expand();
|
||||||
|
|
||||||
|
// Listen for events that require an expansion of the iframe
|
||||||
|
this.addListeners();
|
||||||
|
|
||||||
|
if(show !== false) {
|
||||||
|
//this.q.enqueue(function(view){
|
||||||
|
this.show();
|
||||||
|
//}, view);
|
||||||
|
}
|
||||||
|
// this.map = new Map(view, this.layout);
|
||||||
|
//this.hooks.show.trigger(view, this);
|
||||||
|
this.trigger("rendered", this.section);
|
||||||
|
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function(e){
|
||||||
|
this.trigger("loaderror", e);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine locks base on settings
|
||||||
|
IframeView.prototype.size = function(_width, _height) {
|
||||||
|
var width = _width || this.settings.width;
|
||||||
|
var height = _height || this.settings.height;
|
||||||
|
|
||||||
|
if(this.layout.name === "pre-paginated") {
|
||||||
|
// TODO: check if these are different than the size set in chapter
|
||||||
|
this.lock("both", width, height);
|
||||||
|
} else if(this.settings.axis === "horizontal") {
|
||||||
|
this.lock("height", width, height);
|
||||||
|
} else {
|
||||||
|
this.lock("width", width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lock an axis to element dimensions, taking borders into account
|
||||||
IframeView.prototype.lock = function(what, width, height) {
|
IframeView.prototype.lock = function(what, width, height) {
|
||||||
var elBorders = core.borders(this.element);
|
var elBorders = core.borders(this.element);
|
||||||
var iframeBorders;
|
var iframeBorders;
|
||||||
|
@ -147,18 +222,20 @@ IframeView.prototype.lock = function(what, width, height) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Resize a single axis based on content dimensions
|
||||||
IframeView.prototype.expand = function(force) {
|
IframeView.prototype.expand = function(force) {
|
||||||
var width = this.lockedWidth;
|
var width = this.lockedWidth;
|
||||||
var height = this.lockedHeight;
|
var height = this.lockedHeight;
|
||||||
|
|
||||||
var textWidth, textHeight;
|
var textWidth, textHeight;
|
||||||
// console.log("expanding a")
|
|
||||||
if(!this.iframe || this._expanding) return;
|
if(!this.iframe || this._expanding) return;
|
||||||
|
|
||||||
this._expanding = true;
|
this._expanding = true;
|
||||||
|
|
||||||
// Expand Horizontally
|
// Expand Horizontally
|
||||||
if(height && !width) {
|
// if(height && !width) {
|
||||||
|
if(this.settings.axis === "horizontal") {
|
||||||
// Get the width of the text
|
// Get the width of the text
|
||||||
textWidth = this.contents.textWidth();
|
textWidth = this.contents.textWidth();
|
||||||
// Check if the textWidth has changed
|
// Check if the textWidth has changed
|
||||||
|
@ -174,10 +251,8 @@ IframeView.prototype.expand = function(force) {
|
||||||
// Otherwise assume content height hasn't changed
|
// Otherwise assume content height hasn't changed
|
||||||
width = this._contentWidth;
|
width = this._contentWidth;
|
||||||
}
|
}
|
||||||
}
|
} // Expand Vertically
|
||||||
|
else if(this.settings.axis === "vertical") {
|
||||||
// Expand Vertically
|
|
||||||
if(width && !height) {
|
|
||||||
textHeight = this.contents.textHeight();
|
textHeight = this.contents.textHeight();
|
||||||
if(textHeight != this._textHeight){
|
if(textHeight != this._textHeight){
|
||||||
height = this.contentHeight(textHeight);
|
height = this.contentHeight(textHeight);
|
||||||
|
@ -248,12 +323,12 @@ IframeView.prototype.resize = function(width, height) {
|
||||||
};
|
};
|
||||||
|
|
||||||
IframeView.prototype.reframe = function(width, height) {
|
IframeView.prototype.reframe = function(width, height) {
|
||||||
//var prevBounds;
|
var size;
|
||||||
|
|
||||||
if(!this.displayed) {
|
// if(!this.displayed) {
|
||||||
this._needsReframe = true;
|
// this._needsReframe = true;
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if(core.isNumber(width)){
|
if(core.isNumber(width)){
|
||||||
this.element.style.width = width + "px";
|
this.element.style.width = width + "px";
|
||||||
|
@ -267,43 +342,19 @@ IframeView.prototype.reframe = function(width, height) {
|
||||||
|
|
||||||
this.elementBounds = core.bounds(this.element);
|
this.elementBounds = core.bounds(this.element);
|
||||||
|
|
||||||
this.trigger("resized", {
|
size = {
|
||||||
width: this.elementBounds.width,
|
width: this.elementBounds.width,
|
||||||
height: this.elementBounds.height,
|
height: this.elementBounds.height,
|
||||||
widthDelta: this.elementBounds.width - this.prevBounds.width,
|
widthDelta: this.elementBounds.width - this.prevBounds.width,
|
||||||
heightDelta: this.elementBounds.height - this.prevBounds.height,
|
heightDelta: this.elementBounds.height - this.prevBounds.height,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
this.onResize(this, size);
|
||||||
|
|
||||||
|
this.trigger("resized", size);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// View.prototype.resized = function(e) {
|
|
||||||
// /*
|
|
||||||
// if (!this.resizing) {
|
|
||||||
// if(this.iframe) {
|
|
||||||
// // this.expand();
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// this.resizing = false;
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
// };
|
|
||||||
/*
|
|
||||||
View.prototype.render = function(_request) {
|
|
||||||
|
|
||||||
// if(this.rendering){
|
|
||||||
// return this.displayed;
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.rendering = true;
|
|
||||||
// this.displayingDefer = new RSVP.defer();
|
|
||||||
// this.displayedPromise = this.displaying.promise;
|
|
||||||
|
|
||||||
return this.section.render(_request)
|
|
||||||
.then(function(contents){
|
|
||||||
return this.load(contents);
|
|
||||||
}.bind(this));
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
IframeView.prototype.load = function(contents) {
|
IframeView.prototype.load = function(contents) {
|
||||||
var loading = new RSVP.defer();
|
var loading = new RSVP.defer();
|
||||||
|
@ -375,50 +426,10 @@ IframeView.prototype.onLoad = function(event, promise) {
|
||||||
// // stub
|
// // stub
|
||||||
// };
|
// };
|
||||||
|
|
||||||
IframeView.prototype.setLayout = function(layoutFunc) {
|
IframeView.prototype.setLayout = function(layout) {
|
||||||
this.layoutFunc = layoutFunc;
|
this.layout = layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
IframeView.prototype.listeners = function() {
|
|
||||||
/*
|
|
||||||
setTimeout(function(){
|
|
||||||
this.window.addEventListener("resize", this.resized.bind(this), false);
|
|
||||||
}.bind(this), 10); // Wait to listen for resize events
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Wait for fonts to load to finish
|
|
||||||
// http://dev.w3.org/csswg/css-font-loading/
|
|
||||||
// Not implemented fully except in chrome
|
|
||||||
|
|
||||||
if(this.document.fonts && this.document.fonts.status === "loading") {
|
|
||||||
// console.log("fonts unloaded");
|
|
||||||
this.document.fonts.onloadingdone = function(){
|
|
||||||
// console.log("loaded fonts");
|
|
||||||
this.expand();
|
|
||||||
}.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.section.properties.indexOf("scripted") > -1){
|
|
||||||
this.observer = this.observe(this.document.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.imageLoadListeners();
|
|
||||||
|
|
||||||
this.mediaQueryListeners();
|
|
||||||
|
|
||||||
// this.resizeListenters();
|
|
||||||
|
|
||||||
// this.addEventListeners();
|
|
||||||
|
|
||||||
// this.addSelectionListeners();
|
|
||||||
};
|
|
||||||
|
|
||||||
IframeView.prototype.removeListeners = function() {
|
|
||||||
|
|
||||||
// this.removeEventListeners();
|
|
||||||
|
|
||||||
// this.removeSelectionListeners();
|
|
||||||
};
|
|
||||||
|
|
||||||
IframeView.prototype.resizeListenters = function() {
|
IframeView.prototype.resizeListenters = function() {
|
||||||
// Test size again
|
// Test size again
|
||||||
|
@ -426,93 +437,34 @@ IframeView.prototype.resizeListenters = function() {
|
||||||
this.expanding = setTimeout(this.expand.bind(this), 350);
|
this.expanding = setTimeout(this.expand.bind(this), 350);
|
||||||
};
|
};
|
||||||
|
|
||||||
//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js
|
IframeView.prototype.addListeners = function() {
|
||||||
IframeView.prototype.mediaQueryListeners = function() {
|
//TODO: Add content listeners for expanding
|
||||||
var sheets = this.document.styleSheets;
|
|
||||||
var mediaChangeHandler = function(m){
|
|
||||||
if(m.matches && !this._expanding) {
|
|
||||||
setTimeout(this.expand.bind(this), 1);
|
|
||||||
// this.expand();
|
|
||||||
}
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
for (var i = 0; i < sheets.length; i += 1) {
|
|
||||||
var rules = sheets[i].cssRules;
|
|
||||||
if(!rules) return; // Stylesheets changed
|
|
||||||
for (var j = 0; j < rules.length; j += 1) {
|
|
||||||
//if (rules[j].constructor === CSSMediaRule) {
|
|
||||||
if(rules[j].media){
|
|
||||||
var mql = this.window.matchMedia(rules[j].media.mediaText);
|
|
||||||
mql.addListener(mediaChangeHandler);
|
|
||||||
//mql.onchange = mediaChangeHandler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IframeView.prototype.observe = function(target) {
|
IframeView.prototype.removeListeners = function(layoutFunc) {
|
||||||
var renderer = this;
|
//TODO: remove content listeners for expanding
|
||||||
|
|
||||||
// create an observer instance
|
|
||||||
var observer = new MutationObserver(function(mutations) {
|
|
||||||
if(renderer._expanding) {
|
|
||||||
renderer.expand();
|
|
||||||
}
|
|
||||||
// mutations.forEach(function(mutation) {
|
|
||||||
// console.log(mutation);
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
// configuration of the observer:
|
|
||||||
var config = { attributes: true, childList: true, characterData: true, subtree: true };
|
|
||||||
|
|
||||||
// pass in the target node, as well as the observer options
|
|
||||||
observer.observe(target, config);
|
|
||||||
|
|
||||||
return observer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// View.prototype.appendTo = function(element) {
|
IframeView.prototype.display = function(request) {
|
||||||
// this.element = element;
|
|
||||||
// this.element.appendChild(this.iframe);
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// View.prototype.prependTo = function(element) {
|
|
||||||
// this.element = element;
|
|
||||||
// element.insertBefore(this.iframe, element.firstChild);
|
|
||||||
// };
|
|
||||||
|
|
||||||
IframeView.prototype.imageLoadListeners = function(target) {
|
|
||||||
var images = this.document.body.querySelectorAll("img");
|
|
||||||
var img;
|
|
||||||
for (var i = 0; i < images.length; i++) {
|
|
||||||
img = images[i];
|
|
||||||
|
|
||||||
if (typeof img.naturalWidth !== "undefined" &&
|
|
||||||
img.naturalWidth === 0) {
|
|
||||||
img.onload = this.expand.bind(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IframeView.prototype.display = function() {
|
|
||||||
var displayed = new RSVP.defer();
|
var displayed = new RSVP.defer();
|
||||||
|
|
||||||
this.displayed = true;
|
if (!this.displayed) {
|
||||||
|
|
||||||
// apply the layout function to the contents
|
this.render(request).then(function () {
|
||||||
// this.layout(layoutFunc);
|
|
||||||
|
|
||||||
// Expand the iframe to the full size of the content
|
this.trigger("displayed", this);
|
||||||
this.expand();
|
this.onDisplayed(this);
|
||||||
|
|
||||||
// Listen for event that require an expansion of the iframe
|
this.displayed = true;
|
||||||
this.listeners();
|
|
||||||
|
|
||||||
this.trigger("displayed", this);
|
displayed.resolve(this);
|
||||||
this.onDisplayed(this);
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
displayed.resolve(this);
|
||||||
|
}
|
||||||
|
|
||||||
displayed.resolve(this);
|
|
||||||
|
|
||||||
return displayed.promise;
|
return displayed.promise;
|
||||||
};
|
};
|
||||||
|
@ -555,6 +507,10 @@ IframeView.prototype.onDisplayed = function(view) {
|
||||||
// Stub, override with a custom functions
|
// Stub, override with a custom functions
|
||||||
};
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.onResize = function(view, e) {
|
||||||
|
// Stub, override with a custom functions
|
||||||
|
};
|
||||||
|
|
||||||
IframeView.prototype.bounds = function() {
|
IframeView.prototype.bounds = function() {
|
||||||
if(!this.elementBounds) {
|
if(!this.elementBounds) {
|
||||||
this.elementBounds = core.bounds(this.element);
|
this.elementBounds = core.bounds(this.element);
|
||||||
|
@ -563,12 +519,10 @@ IframeView.prototype.bounds = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
IframeView.prototype.destroy = function() {
|
IframeView.prototype.destroy = function() {
|
||||||
// Stop observing
|
|
||||||
if(this.observer) {
|
|
||||||
this.observer.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.displayed){
|
if(this.displayed){
|
||||||
|
this.displayed = false;
|
||||||
|
|
||||||
this.removeListeners();
|
this.removeListeners();
|
||||||
|
|
||||||
this.stopExpanding = true;
|
this.stopExpanding = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue