mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
split rendition into view managers
This commit is contained in:
parent
d9a19e5a28
commit
48216cc7ec
20 changed files with 4683 additions and 2188 deletions
4240
dist/epub.js
vendored
4240
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
|
@ -78,7 +78,7 @@
|
||||||
var currentSectionIndex = 8;
|
var currentSectionIndex = 8;
|
||||||
// Load the opf
|
// Load the opf
|
||||||
var book = ePub("../books/moby-dick/OPS/package.opf");
|
var book = ePub("../books/moby-dick/OPS/package.opf");
|
||||||
var rendition = book.renderTo(document.body, { method: "continuous", width: "60%" });
|
var rendition = book.renderTo(document.body, { manager: "continuous", width: "60%" });
|
||||||
var displayed = rendition.display("epubcfi(/6/14[xchapter_001]!4/2/24/2[c001p0011]/1:799)");
|
var displayed = rendition.display("epubcfi(/6/14[xchapter_001]!4/2/24/2[c001p0011]/1:799)");
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,14 +55,13 @@ gulp.task('watch', function(cb) {
|
||||||
bundle('epub.js', cb);
|
bundle('epub.js', cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('serve', function() {
|
gulp.task('serve', function(cb) {
|
||||||
server();
|
server();
|
||||||
bundle('epub.js', cb);
|
bundle('epub.js', cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('serve:no-watch', function() {
|
gulp.task('serve:no-watch', function(cb) {
|
||||||
server();
|
server();
|
||||||
bundle('epub.js', cb);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test', function(cb) {
|
gulp.task('test', function(cb) {
|
||||||
|
|
16
package.json
16
package.json
|
@ -14,26 +14,26 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"brfs": "^1.4.1",
|
"brfs": "^1.4.1",
|
||||||
"browserify": "^12.0.1",
|
"browserify": "^13.0.0",
|
||||||
"colors": "^0.6.2",
|
"colors": "^1.1.2",
|
||||||
"connect": "^3.0.1",
|
"connect": "^3.0.1",
|
||||||
"express": "^4.5.1",
|
"express": "^4.5.1",
|
||||||
"gulp": "^3.9.0",
|
"gulp": "^3.9.0",
|
||||||
"gulp-concat": "^2.3.4",
|
"gulp-concat": "^2.3.4",
|
||||||
"gulp-connect": "~2.0.6",
|
"gulp-connect": "~3.1.1",
|
||||||
"gulp-jshint": "^1.8.4",
|
"gulp-jshint": "^2.0.0",
|
||||||
"gulp-plumber": "^0.6.4",
|
"gulp-plumber": "^1.1.0",
|
||||||
"gulp-rename": "^1.2.0",
|
"gulp-rename": "^1.2.0",
|
||||||
"gulp-size": "^2.0.0",
|
"gulp-size": "^2.0.0",
|
||||||
"gulp-sourcemaps": "^1.6.0",
|
"gulp-sourcemaps": "^1.6.0",
|
||||||
"gulp-uglify": "^0.3.1",
|
"gulp-uglify": "^1.5.3",
|
||||||
"gulp-util": "^3.0.0",
|
"gulp-util": "^3.0.0",
|
||||||
"jquery": "^2.1.4",
|
"jquery": "^2.1.4",
|
||||||
"mochify": "^2.14.3",
|
"mochify": "^2.14.3",
|
||||||
"morgan": "^1.1.1",
|
"morgan": "^1.1.1",
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"phantomjs": "^1.9.19",
|
"phantomjs": "^2.1.3",
|
||||||
"portfinder": "^0.2.1",
|
"portfinder": "^1.0.2",
|
||||||
"qunitjs": "^1.14.0",
|
"qunitjs": "^1.14.0",
|
||||||
"serve-static": "^1.3.1",
|
"serve-static": "^1.3.1",
|
||||||
"sinon": "^1.17.2",
|
"sinon": "^1.17.2",
|
||||||
|
|
21
src/book.js
21
src/book.js
|
@ -6,13 +6,19 @@ var Locations = require('./locations');
|
||||||
var Parser = require('./parser');
|
var Parser = require('./parser');
|
||||||
var Navigation = require('./navigation');
|
var Navigation = require('./navigation');
|
||||||
var Rendition = require('./rendition');
|
var Rendition = require('./rendition');
|
||||||
var Continuous = require('./continuous');
|
|
||||||
var Paginate = require('./paginate');
|
|
||||||
var Unarchive = require('./unarchive');
|
var Unarchive = require('./unarchive');
|
||||||
var request = require('./request');
|
var request = require('./request');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
|
|
||||||
function Book(_url, options){
|
function Book(_url, options){
|
||||||
|
|
||||||
|
this.settings = core.extend(this.settings || {}, {
|
||||||
|
requestMethod: this.requestMethod
|
||||||
|
});
|
||||||
|
|
||||||
|
core.extend(this.settings, options);
|
||||||
|
|
||||||
|
|
||||||
// Promises
|
// Promises
|
||||||
this.opening = new RSVP.defer();
|
this.opening = new RSVP.defer();
|
||||||
this.opened = this.opening.promise;
|
this.opened = this.opening.promise;
|
||||||
|
@ -44,7 +50,7 @@ function Book(_url, options){
|
||||||
this.isRendered = false;
|
this.isRendered = false;
|
||||||
// this._q = core.queue(this);
|
// this._q = core.queue(this);
|
||||||
|
|
||||||
this.request = this.requestMethod.bind(this);
|
this.request = this.settings.requestMethod.bind(this);
|
||||||
|
|
||||||
this.spine = new Spine(this.request);
|
this.spine = new Spine(this.request);
|
||||||
this.locations = new Locations(this.spine, this.request);
|
this.locations = new Locations(this.spine, this.request);
|
||||||
|
@ -204,12 +210,11 @@ Book.prototype.section = function(target) {
|
||||||
|
|
||||||
// Sugar to render a book
|
// Sugar to render a book
|
||||||
Book.prototype.renderTo = function(element, options) {
|
Book.prototype.renderTo = function(element, options) {
|
||||||
var renderMethod = (options && options.method) ?
|
// var renderMethod = (options && options.method) ?
|
||||||
options.method :
|
// options.method :
|
||||||
"rendition";
|
// "single";
|
||||||
var Renderer = require('./'+renderMethod);
|
|
||||||
|
|
||||||
this.rendition = new Renderer(this, options);
|
this.rendition = new Rendition(this, options);
|
||||||
this.rendition.attachTo(element);
|
this.rendition.attachTo(element);
|
||||||
|
|
||||||
return this.rendition;
|
return this.rendition;
|
||||||
|
|
408
src/contents.js
Normal file
408
src/contents.js
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
var RSVP = require('rsvp');
|
||||||
|
var core = require('./core');
|
||||||
|
var EpubCFI = require('./epubcfi');
|
||||||
|
|
||||||
|
function Contents(doc, content) {
|
||||||
|
// Blank Cfi for Parsing
|
||||||
|
this.epubcfi = new EpubCFI();
|
||||||
|
|
||||||
|
this.document = doc;
|
||||||
|
this.documentElement = this.document.documentElement;
|
||||||
|
this.content = content || this.document.body;
|
||||||
|
this.window = this.document.defaultView;
|
||||||
|
// Dom events to listen for
|
||||||
|
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.width = function(w) {
|
||||||
|
|
||||||
|
if (w && core.isNumber(w)) {
|
||||||
|
w = w + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w) {
|
||||||
|
this.documentElement.style.width = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.window.getComputedStyle(this.documentElement)['width'];
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.height = function(h) {
|
||||||
|
|
||||||
|
if (h && core.isNumber(h)) {
|
||||||
|
h = h + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h) {
|
||||||
|
this.documentElement.style.height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.window.getComputedStyle(this.documentElement)['height'];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.textWidth = function(w) {
|
||||||
|
var width;
|
||||||
|
var range = this.document.createRange();
|
||||||
|
|
||||||
|
// Select the contents of frame
|
||||||
|
range.selectNodeContents(this.content);
|
||||||
|
|
||||||
|
// get the width of the text content
|
||||||
|
width = range.getBoundingClientRect().width;
|
||||||
|
return width;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.textHeight = function(h) {
|
||||||
|
var height;
|
||||||
|
var range = this.document.createRange();
|
||||||
|
|
||||||
|
|
||||||
|
range.selectNodeContents(this.content);
|
||||||
|
|
||||||
|
height = range.getBoundingClientRect().height;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.scrollWidth = function(min) {
|
||||||
|
var prev;
|
||||||
|
var width = this.document.body.scrollWidth;
|
||||||
|
|
||||||
|
return width;
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.scrollHeight = function(min) {
|
||||||
|
var prev;
|
||||||
|
var height = this.document.body.scrollHeight;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.overflow = function(overflow) {
|
||||||
|
|
||||||
|
if (h) {
|
||||||
|
this.documentElement.style.overflow = overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.window.getComputedStyle(this.documentElement)['overflow'];
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.css = function(property, value) {
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
this.content.style[property] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.window.getComputedStyle(this.content)[property];
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.viewport = function() {
|
||||||
|
var width, height;
|
||||||
|
var $doc = this.document.documentElement;
|
||||||
|
var $viewport = $doc.querySelector("[name=viewport");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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=", '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Contents.prototype.layout = function(layoutFunc) {
|
||||||
|
//
|
||||||
|
// this.iframe.style.display = "inline-block";
|
||||||
|
//
|
||||||
|
// // Reset Body Styles
|
||||||
|
// this.content.style.margin = "0";
|
||||||
|
// //this.document.body.style.display = "inline-block";
|
||||||
|
// //this.document.documentElement.style.width = "auto";
|
||||||
|
//
|
||||||
|
// if(layoutFunc){
|
||||||
|
// layoutFunc(this);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// this.onLayout(this);
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// Contents.prototype.onLayout = function(view) {
|
||||||
|
// // stub
|
||||||
|
// };
|
||||||
|
|
||||||
|
Contents.prototype.listeners = function() {
|
||||||
|
|
||||||
|
this.imageLoadListeners();
|
||||||
|
|
||||||
|
this.mediaQueryListeners();
|
||||||
|
|
||||||
|
this.addEventListeners();
|
||||||
|
|
||||||
|
this.addSelectionListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.removeListeners = function() {
|
||||||
|
|
||||||
|
this.removeEventListeners();
|
||||||
|
|
||||||
|
this.removeSelectionListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.resizeListenters = function() {
|
||||||
|
// Test size again
|
||||||
|
clearTimeout(this.expanding);
|
||||||
|
this.expanding = setTimeout(this.expand.bind(this), 350);
|
||||||
|
};
|
||||||
|
|
||||||
|
//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js
|
||||||
|
Contents.prototype.mediaQueryListeners = function() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.imageLoadListeners = function(target) {
|
||||||
|
var images = this.contentDocument.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.root = function() {
|
||||||
|
if(!this.document) return null;
|
||||||
|
return this.document.documentElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.locationOf = function(target, ignoreClass) {
|
||||||
|
var targetPos = {"left": 0, "top": 0};
|
||||||
|
|
||||||
|
if(!this.document) return;
|
||||||
|
|
||||||
|
if(this.epubcfi.isCfiString(target)) {
|
||||||
|
range = new EpubCFI(cfi).toRange(this.document, ignoreClass);
|
||||||
|
if(range) {
|
||||||
|
targetPos = range.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(typeof target === "string" &&
|
||||||
|
target.indexOf("#") > -1) {
|
||||||
|
|
||||||
|
id = target.substring(target.indexOf("#")+1);
|
||||||
|
el = this.document.getElementById(id);
|
||||||
|
|
||||||
|
if(el) {
|
||||||
|
targetPos = el.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetPos;
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.addStylesheet = function(src) {
|
||||||
|
return new RSVP.Promise(function(resolve, reject){
|
||||||
|
var $stylesheet;
|
||||||
|
var ready = false;
|
||||||
|
|
||||||
|
if(!this.document) {
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stylesheet = this.document.createElement('link');
|
||||||
|
$stylesheet.type = 'text/css';
|
||||||
|
$stylesheet.rel = "stylesheet";
|
||||||
|
$stylesheet.href = src;
|
||||||
|
$stylesheet.onload = $stylesheet.onreadystatechange = function() {
|
||||||
|
if ( !ready && (!this.readyState || this.readyState == 'complete') ) {
|
||||||
|
ready = true;
|
||||||
|
// Let apply
|
||||||
|
setTimeout(function(){
|
||||||
|
resolve(true);
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.document.head.appendChild($stylesheet);
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule
|
||||||
|
Contents.prototype.addStylesheetRules = function(rules) {
|
||||||
|
var styleEl;
|
||||||
|
var styleSheet;
|
||||||
|
|
||||||
|
if(!this.document) return;
|
||||||
|
|
||||||
|
styleEl = this.document.createElement('style');
|
||||||
|
|
||||||
|
// Append style element to head
|
||||||
|
this.document.head.appendChild(styleEl);
|
||||||
|
|
||||||
|
// Grab style sheet
|
||||||
|
styleSheet = styleEl.sheet;
|
||||||
|
|
||||||
|
for (var i = 0, rl = rules.length; i < rl; i++) {
|
||||||
|
var j = 1, rule = rules[i], selector = rules[i][0], propStr = '';
|
||||||
|
// If the second argument of a rule is an array of arrays, correct our variables.
|
||||||
|
if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {
|
||||||
|
rule = rule[1];
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var pl = rule.length; j < pl; j++) {
|
||||||
|
var prop = rule[j];
|
||||||
|
propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert CSS Rule
|
||||||
|
styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.addScript = function(src) {
|
||||||
|
|
||||||
|
return new RSVP.Promise(function(resolve, reject){
|
||||||
|
var $script;
|
||||||
|
var ready = false;
|
||||||
|
|
||||||
|
if(!this.document) {
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$script = this.document.createElement('script');
|
||||||
|
$script.type = 'text/javascript';
|
||||||
|
$script.async = true;
|
||||||
|
$script.src = src;
|
||||||
|
$script.onload = $script.onreadystatechange = function() {
|
||||||
|
if ( !ready && (!this.readyState || this.readyState == 'complete') ) {
|
||||||
|
ready = true;
|
||||||
|
setTimeout(function(){
|
||||||
|
resolve(true);
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.document.head.appendChild($script);
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.addEventListeners = function(){
|
||||||
|
if(!this.document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.listenedEvents.forEach(function(eventName){
|
||||||
|
this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.removeEventListeners = function(){
|
||||||
|
if(!this.document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.listenedEvents.forEach(function(eventName){
|
||||||
|
this.document.removeEventListener(eventName, this.triggerEvent, false);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pass browser events
|
||||||
|
Contents.prototype.triggerEvent = function(e){
|
||||||
|
this.trigger(e.type, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.addSelectionListeners = function(){
|
||||||
|
if(!this.document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false);
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.removeSelectionListeners = function(){
|
||||||
|
if(!this.document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.document.removeEventListener("selectionchange", this.onSelectionChange, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.onSelectionChange = function(e){
|
||||||
|
if (this.selectionEndTimeout) {
|
||||||
|
clearTimeout(this.selectionEndTimeout);
|
||||||
|
}
|
||||||
|
this.selectionEndTimeout = setTimeout(function() {
|
||||||
|
var selection = this.window.getSelection();
|
||||||
|
this.triggerSelectedEvent(selection);
|
||||||
|
}.bind(this), 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.triggerSelectedEvent = function(selection){
|
||||||
|
var range, cfirange;
|
||||||
|
|
||||||
|
if (selection && selection.rangeCount > 0) {
|
||||||
|
range = selection.getRangeAt(0);
|
||||||
|
if(!range.collapsed) {
|
||||||
|
cfirange = this.section.cfiFromRange(range);
|
||||||
|
this.trigger("selected", cfirange);
|
||||||
|
this.trigger("selectedRange", range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.range = function(_cfi, ignoreClass){
|
||||||
|
var cfi = new EpubCFI(_cfi);
|
||||||
|
return cfi.toRange(this.document, ignoreClass);
|
||||||
|
};
|
||||||
|
|
||||||
|
Contents.prototype.map = function(layout){
|
||||||
|
var map = new Map(layout);
|
||||||
|
return map.section();
|
||||||
|
};
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(Contents.prototype);
|
||||||
|
|
||||||
|
module.exports = Contents;
|
19
src/epub.js
19
src/epub.js
|
@ -9,4 +9,23 @@ ePub.VERSION = "0.3.0";
|
||||||
|
|
||||||
ePub.CFI = EpubCFI;
|
ePub.CFI = EpubCFI;
|
||||||
|
|
||||||
|
ePub.ViewManagers = {};
|
||||||
|
ePub.Views = {};
|
||||||
|
ePub.register = {
|
||||||
|
manager : function(name, manager){
|
||||||
|
return ePub.ViewManagers[name] = manager;
|
||||||
|
},
|
||||||
|
view : function(name, view){
|
||||||
|
return ePub.Views[name] = view;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default Views
|
||||||
|
ePub.register.view("iframe", require('./views/iframe'));
|
||||||
|
|
||||||
|
// Default View Managers
|
||||||
|
ePub.register.manager("single", require('./managers/single'));
|
||||||
|
ePub.register.manager("continuous", require('./managers/continuous'));
|
||||||
|
ePub.register.manager("paginate", require('./managers/paginate'));
|
||||||
|
|
||||||
module.exports = ePub;
|
module.exports = ePub;
|
||||||
|
|
|
@ -52,4 +52,8 @@ Hook.prototype.list = function(){
|
||||||
return this.hooks;
|
return this.hooks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Hook.prototype.clear = function(){
|
||||||
|
return this.hooks = [];
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = Hook;
|
module.exports = Hook;
|
||||||
|
|
119
src/layout.js
119
src/layout.js
|
@ -1,7 +1,19 @@
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
|
||||||
function Reflowable(){
|
function Reflowable(){
|
||||||
|
this.columnAxis = core.prefixed('columnAxis');
|
||||||
|
this.columnGap = core.prefixed('columnGap');
|
||||||
|
this.columnWidth = core.prefixed('columnWidth');
|
||||||
|
this.columnFill = core.prefixed('columnFill');
|
||||||
|
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 0;
|
||||||
|
this.spread = 0;
|
||||||
|
this.delta = 0;
|
||||||
|
|
||||||
|
this.column = 0;
|
||||||
|
this.gap = 0;
|
||||||
|
this.divisor = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){
|
Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){
|
||||||
|
@ -48,32 +60,39 @@ Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Reflowable.prototype.format = function(view){
|
Reflowable.prototype.format = function(contents){
|
||||||
|
|
||||||
var $doc = view.document.documentElement;
|
// var $doc = doc.documentElement;
|
||||||
var $body = view.document.body;//view.document.querySelector("body");
|
// var $body = doc.body;//view.document.querySelector("body");
|
||||||
|
|
||||||
$doc.style.overflow = "hidden";
|
// $doc.style.overflow = "hidden";
|
||||||
|
contents.overflow("hidden");
|
||||||
|
|
||||||
// Must be set to the new calculated width or the columns will be off
|
// Must be set to the new calculated width or the columns will be off
|
||||||
// $body.style.width = this.width + "px";
|
// $body.style.width = this.width + "px";
|
||||||
$doc.style.width = this.width + "px";
|
// $doc.style.width = this.width + "px";
|
||||||
|
contents.width(this.width);
|
||||||
|
|
||||||
//-- Adjust height
|
//-- Adjust height
|
||||||
$body.style.height = this.height + "px";
|
// $body.style.height = this.height + "px";
|
||||||
|
contents.height(this.height);
|
||||||
|
|
||||||
//-- Add columns
|
//-- Add columns
|
||||||
$body.style[this.columnAxis] = "horizontal";
|
// $body.style[this.columnAxis] = "horizontal";
|
||||||
$body.style[this.columnFill] = "auto";
|
contents.css(this.columnAxis, "horizontal");
|
||||||
$body.style[this.columnGap] = this.gap+"px";
|
// $body.style[this.columnFill] = "auto";
|
||||||
$body.style[this.columnWidth] = this.column+"px";
|
contents.css(this.columnFill, "auto");
|
||||||
|
// $body.style[this.columnGap] = this.gap+"px";
|
||||||
|
contents.css(this.columnGap, this.gap+"px");
|
||||||
|
// $body.style[this.columnWidth] = this.column +"px";
|
||||||
|
contents.css(this.columnWidth, this.column+"px");
|
||||||
|
|
||||||
// Add extra padding for the gap between this and the next view
|
// Add extra padding for the gap between this and the next view
|
||||||
view.iframe.style.marginRight = this.gap+"px";
|
// view.iframe.style.marginRight = this.gap+"px";
|
||||||
};
|
};
|
||||||
|
|
||||||
Reflowable.prototype.count = function(view) {
|
Reflowable.prototype.count = function(totalWidth) {
|
||||||
var totalWidth = view.root().scrollWidth;
|
// var totalWidth = view.root().scrollWidth;
|
||||||
var spreads = Math.ceil(totalWidth / this.spread);
|
var spreads = Math.ceil(totalWidth / this.spread);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -83,41 +102,51 @@ Reflowable.prototype.count = function(view) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function Fixed(_width, _height){
|
function Fixed(_width, _height){
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Fixed.prototype.calculate = function(_width, _height){
|
Fixed.prototype.calculate = function(_width, _height){
|
||||||
|
this.width = _width;
|
||||||
|
this.height = _height;
|
||||||
};
|
};
|
||||||
|
|
||||||
Fixed.prototype.format = function(view){
|
Fixed.prototype.format = function(contents){
|
||||||
var width, height;
|
var viewport = contents.viewport();
|
||||||
|
// var width, height;
|
||||||
var $doc = view.document.documentElement;
|
//
|
||||||
var $viewport = documentElement.querySelector("[name=viewport");
|
// var $doc = doc.documentElement;
|
||||||
|
// var $viewport = $doc.querySelector("[name=viewport");
|
||||||
/**
|
//
|
||||||
* check for the viewport size
|
// /**
|
||||||
* <meta name="viewport" content="width=1024,height=697" />
|
// * check for the viewport size
|
||||||
*/
|
// * <meta name="viewport" content="width=1024,height=697" />
|
||||||
if($viewport && $viewport.hasAttribute("content")) {
|
// */
|
||||||
content = $viewport.getAttribute("content");
|
// if($viewport && $viewport.hasAttribute("content")) {
|
||||||
contents = content.split(',');
|
// content = $viewport.getAttribute("content");
|
||||||
if(contents[0]){
|
// contents = content.split(',');
|
||||||
width = contents[0].replace("width=", '');
|
// if(contents[0]){
|
||||||
}
|
// width = contents[0].replace("width=", '');
|
||||||
if(contents[1]){
|
// }
|
||||||
height = contents[1].replace("height=", '');
|
// if(contents[1]){
|
||||||
}
|
// height = contents[1].replace("height=", '');
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
//-- Adjust width and height
|
//-- Adjust width and height
|
||||||
// $doc.style.width = width + "px" || "auto";
|
// $doc.style.width = width + "px" || "auto";
|
||||||
// $doc.style.height = height + "px" || "auto";
|
// $doc.style.height = height + "px" || "auto";
|
||||||
view.resize(width, height);
|
if (viewport.width) {
|
||||||
|
contents.width(viewport.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (viewport.height) {
|
||||||
|
contents.height(viewport.height);
|
||||||
|
}
|
||||||
|
|
||||||
//-- Scroll
|
//-- Scroll
|
||||||
$doc.style.overflow = "auto";
|
// $doc.style.overflow = "auto";
|
||||||
|
contents.overflow("auto");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,7 +158,11 @@ Fixed.prototype.count = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
function Scroll(){
|
function Scroll(){
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 0;
|
||||||
|
this.spread = 0;
|
||||||
|
this.column = 0;
|
||||||
|
this.gap = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Scroll.prototype.calculate = function(_width, _height){
|
Scroll.prototype.calculate = function(_width, _height){
|
||||||
|
@ -138,12 +171,14 @@ Scroll.prototype.calculate = function(_width, _height){
|
||||||
this.gap = 0;
|
this.gap = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Scroll.prototype.format = function(view){
|
Scroll.prototype.format = function(contents){
|
||||||
|
|
||||||
var $doc = view.document.documentElement;
|
// var $doc = doc.documentElement;
|
||||||
|
|
||||||
$doc.style.width = "auto";
|
// $doc.style.width = "auto";
|
||||||
$doc.style.height = "auto";
|
// $doc.style.height = "auto";
|
||||||
|
contents.width("auto");
|
||||||
|
contents.height("auto");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('../core');
|
||||||
var Rendition = require('./rendition');
|
var SingleViewManager = require('./single');
|
||||||
var View = require('./view');
|
|
||||||
|
|
||||||
function Continuous(book, options) {
|
function ContinuousViewManager(options) {
|
||||||
|
|
||||||
Rendition.apply(this, arguments); // call super constructor.
|
SingleViewManager.apply(this, arguments); // call super constructor.
|
||||||
|
|
||||||
this.settings = core.extend(this.settings || {}, {
|
this.settings = core.extend(this.settings || {}, {
|
||||||
infinite: true,
|
infinite: true,
|
||||||
|
@ -15,47 +14,17 @@ function Continuous(book, options) {
|
||||||
offsetDelta: 250
|
offsetDelta: 250
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options);
|
core.extend(this.settings, options.settings);
|
||||||
|
|
||||||
if(this.settings.hidden) {
|
|
||||||
this.wrapper = this.wrap(this.container);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// subclass extends superclass
|
// subclass extends superclass
|
||||||
Continuous.prototype = Object.create(Rendition.prototype);
|
ContinuousViewManager.prototype = Object.create(SingleViewManager.prototype);
|
||||||
Continuous.prototype.constructor = Continuous;
|
ContinuousViewManager.prototype.constructor = ContinuousViewManager;
|
||||||
|
|
||||||
Continuous.prototype.attachListeners = function(){
|
|
||||||
|
|
||||||
// Listen to window for resize event if width or height is set to a percent
|
|
||||||
if(!core.isNumber(this.settings.width) ||
|
|
||||||
!core.isNumber(this.settings.height) ) {
|
|
||||||
window.addEventListener("resize", this.onResized.bind(this), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(this.settings.infinite) {
|
ContinuousViewManager.prototype.moveTo = function(offset){
|
||||||
this.start();
|
// var bounds = this.stage.bounds();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Continuous.prototype.parseTarget = function(target){
|
|
||||||
if(this.epubcfi.isCfiString(target)) {
|
|
||||||
cfi = new EpubCFI(target);
|
|
||||||
spinePos = cfi.spinePos;
|
|
||||||
section = this.book.spine.get(spinePos);
|
|
||||||
} else {
|
|
||||||
section = this.book.spine.get(target);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Continuous.prototype.moveTo = function(offset){
|
|
||||||
// var bounds = this.bounds();
|
|
||||||
// var dist = Math.floor(offset.top / bounds.height) * bounds.height;
|
// var dist = Math.floor(offset.top / bounds.height) * bounds.height;
|
||||||
return this.check(
|
return this.check(
|
||||||
offset.left+this.settings.offset,
|
offset.left+this.settings.offset,
|
||||||
|
@ -71,7 +40,7 @@ Continuous.prototype.moveTo = function(offset){
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.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();
|
||||||
var index = this.views.indexOf(currView);
|
var index = this.views.indexOf(currView);
|
||||||
|
@ -79,12 +48,12 @@ Continuous.prototype.afterDisplayed = function(currView){
|
||||||
|
|
||||||
if(index + 1 === this.views.length && next) {
|
if(index + 1 === this.views.length && next) {
|
||||||
nextView = this.createView(next);
|
nextView = this.createView(next);
|
||||||
this.q.enqueue(this.append, nextView);
|
this.q.enqueue(this.append.bind(this), nextView);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index === 0 && prev) {
|
if(index === 0 && prev) {
|
||||||
prevView = this.createView(prev, this.viewSettings);
|
prevView = this.createView(prev, this.viewSettings);
|
||||||
this.q.enqueue(this.prepend, prevView);
|
this.q.enqueue(this.prepend.bind(this), prevView);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.removeShownListeners(currView);
|
// this.removeShownListeners(currView);
|
||||||
|
@ -95,7 +64,7 @@ Continuous.prototype.afterDisplayed = function(currView){
|
||||||
|
|
||||||
|
|
||||||
// Remove Previous Listeners if present
|
// Remove Previous Listeners if present
|
||||||
Continuous.prototype.removeShownListeners = function(view){
|
ContinuousViewManager.prototype.removeShownListeners = function(view){
|
||||||
|
|
||||||
// view.off("shown", this.afterDisplayed);
|
// view.off("shown", this.afterDisplayed);
|
||||||
// view.off("shown", this.afterDisplayedAbove);
|
// view.off("shown", this.afterDisplayedAbove);
|
||||||
|
@ -103,18 +72,18 @@ Continuous.prototype.removeShownListeners = function(view){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.append = function(view){
|
ContinuousViewManager.prototype.append = function(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);
|
||||||
|
console.log(this);
|
||||||
this.views.append(view);
|
this.views.append(view);
|
||||||
|
|
||||||
//this.q.enqueue(this.check);
|
//this.q.enqueue(this.check);
|
||||||
return this.check();
|
return this.check();
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.prepend = function(view){
|
ContinuousViewManager.prototype.prepend = function(view){
|
||||||
// view.on("shown", this.afterDisplayedAbove.bind(this));
|
// view.on("shown", this.afterDisplayedAbove.bind(this));
|
||||||
view.onDisplayed = this.afterDisplayed.bind(this);
|
view.onDisplayed = this.afterDisplayed.bind(this);
|
||||||
|
|
||||||
|
@ -126,7 +95,7 @@ Continuous.prototype.prepend = function(view){
|
||||||
return this.check();
|
return this.check();
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.counter = function(bounds){
|
ContinuousViewManager.prototype.counter = function(bounds){
|
||||||
|
|
||||||
if(this.settings.axis === "vertical") {
|
if(this.settings.axis === "vertical") {
|
||||||
this.scrollBy(0, bounds.heightDelta, true);
|
this.scrollBy(0, bounds.heightDelta, true);
|
||||||
|
@ -136,9 +105,9 @@ Continuous.prototype.counter = function(bounds){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.check = function(_offset){
|
ContinuousViewManager.prototype.check = function(_offset){
|
||||||
var checking = new RSVP.defer();
|
var checking = new RSVP.defer();
|
||||||
var container = this.bounds();
|
var container = this.stage.bounds();
|
||||||
var promises = [];
|
var promises = [];
|
||||||
var offset = _offset || this.settings.offset;
|
var offset = _offset || this.settings.offset;
|
||||||
|
|
||||||
|
@ -161,7 +130,7 @@ Continuous.prototype.check = function(_offset){
|
||||||
// this.q.enqueue(this.trim);
|
// this.q.enqueue(this.trim);
|
||||||
clearTimeout(this.trimTimeout);
|
clearTimeout(this.trimTimeout);
|
||||||
this.trimTimeout = setTimeout(function(){
|
this.trimTimeout = setTimeout(function(){
|
||||||
this.q.enqueue(this.trim);
|
this.q.enqueue(this.trim.bind(this));
|
||||||
}.bind(this), 250);
|
}.bind(this), 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +144,7 @@ Continuous.prototype.check = function(_offset){
|
||||||
return RSVP.all(promises)
|
return RSVP.all(promises)
|
||||||
.then(function(posts) {
|
.then(function(posts) {
|
||||||
// Check to see if anything new is on screen after rendering
|
// Check to see if anything new is on screen after rendering
|
||||||
this.q.enqueue(this.check);
|
this.q.enqueue(this.check.bind(this));
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
@ -187,7 +156,7 @@ Continuous.prototype.check = function(_offset){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.trim = function(){
|
ContinuousViewManager.prototype.trim = function(){
|
||||||
var task = new RSVP.defer();
|
var task = new RSVP.defer();
|
||||||
var displayed = this.views.displayed();
|
var displayed = this.views.displayed();
|
||||||
var first = displayed[0];
|
var first = displayed[0];
|
||||||
|
@ -211,7 +180,7 @@ Continuous.prototype.trim = function(){
|
||||||
return task.promise;
|
return task.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.erase = function(view, above){ //Trim
|
ContinuousViewManager.prototype.erase = function(view, above){ //Trim
|
||||||
|
|
||||||
var prevTop;
|
var prevTop;
|
||||||
var prevLeft;
|
var prevLeft;
|
||||||
|
@ -239,7 +208,11 @@ Continuous.prototype.erase = function(view, above){ //Trim
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.start = function() {
|
ContinuousViewManager.prototype.addEventListeners = function(stage){
|
||||||
|
this.addScrollListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype.addScrollListeners = function() {
|
||||||
var scroller;
|
var scroller;
|
||||||
|
|
||||||
this.tick = core.requestAnimationFrame;
|
this.tick = core.requestAnimationFrame;
|
||||||
|
@ -261,7 +234,7 @@ Continuous.prototype.start = function() {
|
||||||
scroller = window;
|
scroller = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("scroll", function(e){
|
scroller.addEventListener("scroll", function(e){
|
||||||
if(!this.ignore) {
|
if(!this.ignore) {
|
||||||
this.scrolled = true;
|
this.scrolled = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -280,7 +253,7 @@ Continuous.prototype.start = function() {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.onScroll = function(){
|
ContinuousViewManager.prototype.onScroll = function(){
|
||||||
|
|
||||||
if(this.scrolled) {
|
if(this.scrolled) {
|
||||||
|
|
||||||
|
@ -299,7 +272,7 @@ Continuous.prototype.onScroll = function(){
|
||||||
this.scrollDeltaVert > this.settings.offsetDelta ||
|
this.scrollDeltaVert > this.settings.offsetDelta ||
|
||||||
this.scrollDeltaHorz > this.settings.offsetDelta) {
|
this.scrollDeltaHorz > this.settings.offsetDelta) {
|
||||||
|
|
||||||
this.q.enqueue(this.check);
|
this.q.enqueue(this.check.bind(this));
|
||||||
|
|
||||||
this.scrollDeltaVert = 0;
|
this.scrollDeltaVert = 0;
|
||||||
this.scrollDeltaHorz = 0;
|
this.scrollDeltaHorz = 0;
|
||||||
|
@ -336,7 +309,7 @@ Continuous.prototype.onScroll = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Continuous.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);
|
||||||
|
@ -346,7 +319,7 @@ Continuous.prototype.onScroll = function(){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Continuous.prototype.currentLocation = function(){
|
ContinuousViewManager.prototype.currentLocation = function(){
|
||||||
var visible = this.visible();
|
var visible = this.visible();
|
||||||
var startPage, endPage;
|
var startPage, endPage;
|
||||||
|
|
||||||
|
@ -415,4 +388,4 @@ Continuous.prototype.current = function(what){
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = Continuous;
|
module.exports = ContinuousViewManager;
|
|
@ -1,12 +1,12 @@
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('../core');
|
||||||
var Continuous = require('./continuous');
|
var ContinuousViewManager = require('./continuous');
|
||||||
var Map = require('./map');
|
var Map = require('../map');
|
||||||
var Layout = require('./layout');
|
// var Layout = require('./layout');
|
||||||
|
|
||||||
function Paginate(book, options) {
|
function PaginatedViewManager(book, options) {
|
||||||
|
|
||||||
Continuous.apply(this, arguments);
|
ContinuousViewManager.apply(arguments);
|
||||||
|
|
||||||
this.settings = core.extend(this.settings || {}, {
|
this.settings = core.extend(this.settings || {}, {
|
||||||
width: 600,
|
width: 600,
|
||||||
|
@ -19,28 +19,28 @@ function Paginate(book, options) {
|
||||||
infinite: false
|
infinite: false
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options);
|
core.extend(this.settings, options.settings);
|
||||||
|
|
||||||
this.isForcedSingle = this.settings.forceSingle;
|
this.isForcedSingle = this.settings.forceSingle;
|
||||||
|
|
||||||
this.viewSettings.axis = this.settings.axis;
|
this.viewSettings.axis = this.settings.axis;
|
||||||
|
|
||||||
this.start();
|
// this.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype = Object.create(Continuous.prototype);
|
PaginatedViewManager.prototype = Object.create(ContinuousViewManager.prototype);
|
||||||
Paginate.prototype.constructor = Paginate;
|
PaginatedViewManager.prototype.constructor = PaginatedViewManager;
|
||||||
|
|
||||||
|
|
||||||
Paginate.prototype.determineSpreads = function(cutoff){
|
PaginatedViewManager.prototype.determineSpreads = function(cutoff){
|
||||||
if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) {
|
if(this.isForcedSingle || !cutoff || this.stage.bounds().width < cutoff) {
|
||||||
return 1; //-- Single Page
|
return 1; //-- Single Page
|
||||||
}else{
|
}else{
|
||||||
return 2; //-- Double Page
|
return 2; //-- Double Page
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.forceSingle = function(bool){
|
PaginatedViewManager.prototype.forceSingle = function(bool){
|
||||||
if(bool === false) {
|
if(bool === false) {
|
||||||
this.isForcedSingle = false;
|
this.isForcedSingle = false;
|
||||||
// this.spreads = false;
|
// this.spreads = false;
|
||||||
|
@ -51,50 +51,15 @@ Paginate.prototype.forceSingle = function(bool){
|
||||||
this.applyLayoutMethod();
|
this.applyLayoutMethod();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 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){
|
|
||||||
// // Default is layout: reflowable & spread: auto
|
|
||||||
// var spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
|
||||||
// console.log("spreads", spreads, 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;
|
|
||||||
//
|
|
||||||
// return layoutMethod;
|
|
||||||
// };
|
|
||||||
|
|
||||||
Paginate.prototype.start = function(){
|
PaginatedViewManager.prototype.addEventListeners = function(){
|
||||||
// On display
|
// On display
|
||||||
// this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);
|
// this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);
|
||||||
// this.layoutMethod = this.determineLayout(this.layoutSettings);
|
// this.layoutMethod = this.determineLayout(this.layoutSettings);
|
||||||
// this.layout = new EPUBJS.Layout[this.layoutMethod]();
|
// this.layout = new EPUBJS.Layout[this.layoutMethod]();
|
||||||
//this.hooks.display.register(this.registerLayoutMethod.bind(this));
|
//this.hooks.display.register(this.registerLayoutMethod.bind(this));
|
||||||
// this.hooks.display.register(this.reportLocation);
|
// this.hooks.display.register(this.reportLocation);
|
||||||
this.on('displayed', this.reportLocation.bind(this));
|
// this.on('displayed', this.reportLocation.bind(this));
|
||||||
|
|
||||||
// this.hooks.content.register(this.adjustImages.bind(this));
|
// this.hooks.content.register(this.adjustImages.bind(this));
|
||||||
|
|
||||||
|
@ -107,14 +72,8 @@ Paginate.prototype.start = function(){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// EPUBJS.Rendition.prototype.createView = function(section) {
|
|
||||||
// var view = new EPUBJS.View(section, this.viewSettings);
|
|
||||||
|
|
||||||
|
PaginatedViewManager.prototype.applyLayoutMethod = function() {
|
||||||
// return view;
|
|
||||||
// };
|
|
||||||
|
|
||||||
Paginate.prototype.applyLayoutMethod = function() {
|
|
||||||
//var task = new RSVP.defer();
|
//var task = new RSVP.defer();
|
||||||
|
|
||||||
// this.spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
// this.spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
||||||
|
@ -134,7 +93,7 @@ Paginate.prototype.applyLayoutMethod = function() {
|
||||||
// return layout;
|
// return layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.updateLayout = function() {
|
PaginatedViewManager.prototype.updateLayout = function() {
|
||||||
|
|
||||||
this.spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
this.spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
||||||
|
|
||||||
|
@ -149,14 +108,14 @@ Paginate.prototype.updateLayout = function() {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.moveTo = function(offset){
|
PaginatedViewManager.prototype.moveTo = function(offset){
|
||||||
var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
|
var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
|
||||||
return this.check(0, dist+this.settings.offset).then(function(){
|
return this.check(0, dist+this.settings.offset).then(function(){
|
||||||
this.scrollBy(dist, 0);
|
this.scrollBy(dist, 0);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.page = function(pg){
|
PaginatedViewManager.prototype.page = function(pg){
|
||||||
|
|
||||||
// this.currentPage = pg;
|
// this.currentPage = pg;
|
||||||
// this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0);
|
// this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0);
|
||||||
|
@ -164,9 +123,8 @@ Paginate.prototype.page = function(pg){
|
||||||
// return false;
|
// return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.next = function(){
|
PaginatedViewManager.prototype.next = function(){
|
||||||
|
|
||||||
return this.q.enqueue(function(){
|
|
||||||
// console.log(this.container.scrollWidth, this.container.scrollLeft + this.container.offsetWidth + this.layout.delta)
|
// console.log(this.container.scrollWidth, this.container.scrollLeft + this.container.offsetWidth + this.layout.delta)
|
||||||
if(this.container.scrollLeft +
|
if(this.container.scrollLeft +
|
||||||
this.container.offsetWidth +
|
this.container.offsetWidth +
|
||||||
|
@ -177,19 +135,15 @@ Paginate.prototype.next = function(){
|
||||||
}
|
}
|
||||||
this.reportLocation();
|
this.reportLocation();
|
||||||
return this.check();
|
return this.check();
|
||||||
});
|
|
||||||
|
|
||||||
// return this.page(this.currentPage + 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.prev = function(){
|
PaginatedViewManager.prototype.prev = function(){
|
||||||
|
|
||||||
return this.q.enqueue(function(){
|
|
||||||
this.scrollBy(-this.layout.delta, 0);
|
this.scrollBy(-this.layout.delta, 0);
|
||||||
this.reportLocation();
|
this.reportLocation();
|
||||||
return this.check();
|
return this.check();
|
||||||
});
|
|
||||||
// return this.page(this.currentPage - 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Paginate.prototype.reportLocation = function(){
|
// Paginate.prototype.reportLocation = function(){
|
||||||
|
@ -199,7 +153,7 @@ Paginate.prototype.prev = function(){
|
||||||
// }.bind(this));
|
// }.bind(this));
|
||||||
// };
|
// };
|
||||||
|
|
||||||
Paginate.prototype.currentLocation = function(){
|
PaginatedViewManager.prototype.currentLocation = function(){
|
||||||
var visible = this.visible();
|
var visible = this.visible();
|
||||||
var startA, startB, endA, endB;
|
var startA, startB, endA, endB;
|
||||||
var pageLeft, pageRight;
|
var pageLeft, pageRight;
|
||||||
|
@ -232,17 +186,17 @@ Paginate.prototype.currentLocation = function(){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.resize = function(width, height){
|
PaginatedViewManager.prototype.resize = function(width, height){
|
||||||
// Clear the queue
|
// Clear the queue
|
||||||
this.q.clear();
|
this.q.clear();
|
||||||
|
|
||||||
this.stageSize(width, height);
|
this.bounds = this.stage.bounds(width, height);
|
||||||
|
|
||||||
this.updateLayout();
|
// this.updateLayout();
|
||||||
|
|
||||||
if(this.location) {
|
// if(this.location) {
|
||||||
this.display(this.location.start);
|
// this.display(this.location.start);
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.trigger("resized", {
|
this.trigger("resized", {
|
||||||
width: this.stage.width,
|
width: this.stage.width,
|
||||||
|
@ -251,7 +205,7 @@ Paginate.prototype.resize = function(width, height){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.onResized = function(e) {
|
PaginatedViewManager.prototype.onResized = function(e) {
|
||||||
|
|
||||||
this.views.clear();
|
this.views.clear();
|
||||||
|
|
||||||
|
@ -261,24 +215,9 @@ Paginate.prototype.onResized = function(e) {
|
||||||
}.bind(this), 150);
|
}.bind(this), 150);
|
||||||
};
|
};
|
||||||
|
|
||||||
Paginate.prototype.adjustImages = function(view) {
|
|
||||||
|
|
||||||
view.addStylesheetRules([
|
|
||||||
["img",
|
|
||||||
["max-width", (this.layout.spread) + "px"],
|
|
||||||
["max-height", (this.layout.height) + "px"]
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
return new RSVP.Promise(function(resolve, reject){
|
|
||||||
// Wait to apply
|
|
||||||
setTimeout(function() {
|
|
||||||
resolve();
|
|
||||||
}, 1);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Paginate.prototype.display = function(what){
|
// Paginate.prototype.display = function(what){
|
||||||
// return this.display(what);
|
// return this.display(what);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
module.exports = Paginate;
|
module.exports = PaginatedViewManager;
|
299
src/managers/single.js
Normal file
299
src/managers/single.js
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
var RSVP = require('rsvp');
|
||||||
|
var core = require('../core');
|
||||||
|
var Views = require('../views');
|
||||||
|
var EpubCFI = require('../epubcfi');
|
||||||
|
|
||||||
|
function SingleViewManager(options) {
|
||||||
|
|
||||||
|
this.View = options.view;
|
||||||
|
this.renderer = options.renderer;
|
||||||
|
this.q = options.queue;
|
||||||
|
|
||||||
|
this.settings = core.extend(this.settings || {}, {
|
||||||
|
infinite: true,
|
||||||
|
hidden: false,
|
||||||
|
width: false,
|
||||||
|
height: null,
|
||||||
|
globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'},
|
||||||
|
layout: null,
|
||||||
|
axis: "vertical",
|
||||||
|
ignoreClass: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
core.extend(this.settings, options.settings);
|
||||||
|
|
||||||
|
this.viewSettings = {
|
||||||
|
ignoreClass: this.settings.ignoreClass
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleViewManager.prototype.start = function(stage){
|
||||||
|
|
||||||
|
// Save the stage
|
||||||
|
this.stage = stage;
|
||||||
|
|
||||||
|
// Get this stage container div
|
||||||
|
this.container = this.stage.getContainer();
|
||||||
|
|
||||||
|
// Views array methods
|
||||||
|
this.views = new Views(this.container);
|
||||||
|
|
||||||
|
// Calculate Stage Size
|
||||||
|
this.bounds = this.stage.bounds();
|
||||||
|
|
||||||
|
// Function to handle a resize event.
|
||||||
|
// Will only attach if width and height are both fixed.
|
||||||
|
this.stage.onResize(this.onResized.bind(this));
|
||||||
|
|
||||||
|
// Add Event Listeners
|
||||||
|
this.addEventListeners();
|
||||||
|
|
||||||
|
// Add Layout method
|
||||||
|
// this.applyLayoutMethod();
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.addEventListeners = function(){
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.onResized = function(e) {
|
||||||
|
this.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.resize = function(width, height){
|
||||||
|
|
||||||
|
this.bounds = this.stage.bounds(width, height);
|
||||||
|
|
||||||
|
this.views.each(this.resizeView.bind(this));
|
||||||
|
|
||||||
|
this.trigger("resized", {
|
||||||
|
width: this.stage.width,
|
||||||
|
height: this.stage.height
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.layout = function(layoutFunc){
|
||||||
|
|
||||||
|
this.views.each(function(view){
|
||||||
|
layoutFunc(view);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.createView = function(section) {
|
||||||
|
return new this.View(section, this.viewSettings);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.display = function(section, target){
|
||||||
|
|
||||||
|
var displaying = new RSVP.defer();
|
||||||
|
var displayed = displaying.promise;
|
||||||
|
|
||||||
|
var isCfi = EpubCFI().isCfiString(target);
|
||||||
|
|
||||||
|
// Check to make sure the section we want isn't already shown
|
||||||
|
var visible = this.views.find(section);
|
||||||
|
|
||||||
|
// View is already shown, just move to correct location
|
||||||
|
if(visible && target) {
|
||||||
|
offset = visible.locationOf(target);
|
||||||
|
this.moveTo(offset);
|
||||||
|
return displaying.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide all current views
|
||||||
|
this.views.hide();
|
||||||
|
|
||||||
|
// Create a new view
|
||||||
|
view = this.createView(section);
|
||||||
|
|
||||||
|
return this.fill(view)
|
||||||
|
.then(function(){
|
||||||
|
|
||||||
|
// Move to correct place within the section, if needed
|
||||||
|
if(target) {
|
||||||
|
offset = view.locationOf(target);
|
||||||
|
return this.moveTo(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this))
|
||||||
|
// .then(function(){
|
||||||
|
// return this.hooks.display.trigger(view);
|
||||||
|
// }.bind(this))
|
||||||
|
.then(function(){
|
||||||
|
this.views.show();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.afterDisplayed = function(view){
|
||||||
|
this.trigger("added", view.section);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.moveTo = function(offset){
|
||||||
|
this.scrollTo(offset.left, offset.top);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.fill = function(view){
|
||||||
|
|
||||||
|
this.views.clear();
|
||||||
|
|
||||||
|
this.views.append(view);
|
||||||
|
|
||||||
|
// view.on("shown", this.afterDisplayed.bind(this));
|
||||||
|
view.onDisplayed = this.afterDisplayed.bind(this);
|
||||||
|
|
||||||
|
return this.renderer(view, this.views.hidden);
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.resizeView = function(view) {
|
||||||
|
|
||||||
|
if(this.settings.globalLayoutProperties.layout === "pre-paginated") {
|
||||||
|
view.lock("both", this.bounds.width, this.bounds.height);
|
||||||
|
} else {
|
||||||
|
view.lock("width", this.bounds.width, this.bounds.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.next = function(){
|
||||||
|
var next;
|
||||||
|
var view;
|
||||||
|
|
||||||
|
if(!this.views.length) return;
|
||||||
|
|
||||||
|
next = this.views.last().section.next();
|
||||||
|
|
||||||
|
if(next) {
|
||||||
|
view = this.createView(next);
|
||||||
|
return this.fill(view)
|
||||||
|
.then(function(){
|
||||||
|
this.views.show();
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.prev = function(){
|
||||||
|
var prev;
|
||||||
|
var view;
|
||||||
|
|
||||||
|
if(!this.views.length) return;
|
||||||
|
|
||||||
|
prev = this.views.first().section.prev();
|
||||||
|
if(prev) {
|
||||||
|
view = this.createView(prev);
|
||||||
|
return this.fill(view)
|
||||||
|
.then(function(){
|
||||||
|
this.views.show();
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.current = function(){
|
||||||
|
var visible = this.visible();
|
||||||
|
if(visible.length){
|
||||||
|
// Current is the last visible view
|
||||||
|
return visible[visible.length-1];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.currentLocation = function(){
|
||||||
|
var view;
|
||||||
|
var start, end;
|
||||||
|
|
||||||
|
if(this.views.length) {
|
||||||
|
view = this.views.first();
|
||||||
|
// start = container.left - view.position().left;
|
||||||
|
// end = start + this.layout.spread;
|
||||||
|
console.log("visibile currentLocation", view);
|
||||||
|
// return this.map.page(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){
|
||||||
|
var position = view.position();
|
||||||
|
var container = _container || this.container.getBoundingClientRect();
|
||||||
|
|
||||||
|
if(this.settings.axis === "horizontal" &&
|
||||||
|
position.right > container.left - offsetPrev &&
|
||||||
|
position.left < container.right + offsetNext) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if(this.settings.axis === "vertical" &&
|
||||||
|
position.bottom > container.top - offsetPrev &&
|
||||||
|
position.top < container.bottom + offsetNext) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.visible = function(){
|
||||||
|
var container = this.stage.bounds();
|
||||||
|
var displayedViews = this.views.displayed();
|
||||||
|
var visible = [];
|
||||||
|
var isVisible;
|
||||||
|
var view;
|
||||||
|
|
||||||
|
for (var i = 0; i < displayedViews.length; i++) {
|
||||||
|
view = displayedViews[i];
|
||||||
|
isVisible = this.isVisible(view, 0, 0, container);
|
||||||
|
|
||||||
|
if(isVisible === true) {
|
||||||
|
visible.push(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return visible;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.scrollBy = function(x, y, silent){
|
||||||
|
if(silent) {
|
||||||
|
this.ignore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.settings.height) {
|
||||||
|
|
||||||
|
if(x) this.container.scrollLeft += x;
|
||||||
|
if(y) this.container.scrollTop += y;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
window.scrollBy(x,y);
|
||||||
|
}
|
||||||
|
// console.log("scrollBy", x, y);
|
||||||
|
this.scrolled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.scrollTo = function(x, y, silent){
|
||||||
|
if(silent) {
|
||||||
|
this.ignore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.settings.height) {
|
||||||
|
this.container.scrollLeft = x;
|
||||||
|
this.container.scrollTop = y;
|
||||||
|
} else {
|
||||||
|
window.scrollTo(x,y);
|
||||||
|
}
|
||||||
|
// console.log("scrollTo", x, y);
|
||||||
|
this.scrolled = true;
|
||||||
|
// if(this.container.scrollLeft != x){
|
||||||
|
// setTimeout(function() {
|
||||||
|
// this.scrollTo(x, y, silent);
|
||||||
|
// }.bind(this), 10);
|
||||||
|
// return;
|
||||||
|
// };
|
||||||
|
};
|
||||||
|
|
||||||
|
//-- Enable binding events to Manager
|
||||||
|
RSVP.EventTarget.mixin(SingleViewManager.prototype);
|
||||||
|
|
||||||
|
module.exports = SingleViewManager;
|
602
src/rendition.js
602
src/rendition.js
|
@ -9,6 +9,7 @@ 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) {
|
||||||
|
|
||||||
|
@ -19,7 +20,9 @@ function Rendition(book, options) {
|
||||||
height: null,
|
height: null,
|
||||||
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},
|
||||||
axis: "vertical",
|
axis: "vertical",
|
||||||
ignoreClass: ''
|
ignoreClass: '',
|
||||||
|
manager: "single",
|
||||||
|
view: "iframe"
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options);
|
core.extend(this.settings, options);
|
||||||
|
@ -54,151 +57,111 @@ function Rendition(book, options) {
|
||||||
|
|
||||||
this.q.enqueue(this.parseLayoutProperties);
|
this.q.enqueue(this.parseLayoutProperties);
|
||||||
|
|
||||||
|
// Block the queue until rendering is started
|
||||||
|
this.starting = new RSVP.defer();
|
||||||
|
this.started = this.starting.promise;
|
||||||
|
this.q.enqueue(this.started);
|
||||||
|
|
||||||
|
// TODO: move this somewhere else
|
||||||
if(this.book.archive) {
|
if(this.book.archive) {
|
||||||
this.replacements();
|
this.replacements();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
Rendition.prototype.requireManager = function(manager) {
|
||||||
* Creates an element to render to.
|
var viewManager;
|
||||||
* Resizes to passed width and height or to the elements size
|
|
||||||
*/
|
|
||||||
Rendition.prototype.initialize = function(_options){
|
|
||||||
var options = _options || {};
|
|
||||||
var height = options.height;// !== false ? options.height : "100%";
|
|
||||||
var width = options.width;// !== false ? options.width : "100%";
|
|
||||||
var hidden = options.hidden || false;
|
|
||||||
var container;
|
|
||||||
var wrapper;
|
|
||||||
|
|
||||||
if(options.height && core.isNumber(options.height)) {
|
// If manager is a string, try to load from register managers,
|
||||||
height = options.height + "px";
|
// or require included managers directly
|
||||||
|
if (typeof manager == "string") {
|
||||||
|
viewManager = ePub.ViewManagers[manager] || require('./managers/'+manager);
|
||||||
|
} else {
|
||||||
|
// otherwise, assume we were passed a function
|
||||||
|
viewManager = manager
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options.width && core.isNumber(options.width)) {
|
return viewManager;
|
||||||
width = options.width + "px";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new container element
|
|
||||||
container = document.createElement("div");
|
|
||||||
|
|
||||||
container.id = "epubjs-container:" + core.uuid();
|
|
||||||
container.classList.add("epub-container");
|
|
||||||
|
|
||||||
// Style Element
|
|
||||||
container.style.fontSize = "0";
|
|
||||||
container.style.wordSpacing = "0";
|
|
||||||
container.style.lineHeight = "0";
|
|
||||||
container.style.verticalAlign = "top";
|
|
||||||
|
|
||||||
if(this.settings.axis === "horizontal") {
|
|
||||||
container.style.whiteSpace = "nowrap";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(width){
|
|
||||||
container.style.width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(height){
|
|
||||||
container.style.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
container.style.overflow = this.settings.overflow;
|
|
||||||
|
|
||||||
return container;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.wrap = function(container) {
|
Rendition.prototype.requireView = function(view) {
|
||||||
var wrapper = document.createElement("div");
|
var View;
|
||||||
|
|
||||||
wrapper.style.visibility = "hidden";
|
// If view is a string, try to load from register managers,
|
||||||
wrapper.style.overflow = "hidden";
|
// or require included managers directly
|
||||||
wrapper.style.width = "0";
|
if (typeof view == "string") {
|
||||||
wrapper.style.height = "0";
|
View = ePub.Views[view] || require('./views/'+view);
|
||||||
|
} else {
|
||||||
|
// otherwise, assume we were passed a function
|
||||||
|
View = view
|
||||||
|
}
|
||||||
|
|
||||||
wrapper.appendChild(container);
|
return View;
|
||||||
return wrapper;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call to attach the container to an element in the dom
|
Rendition.prototype.start = function(stage){
|
||||||
// Container must be attached before rendering can begin
|
var ViewManager = this.requireManager(this.settings.manager);
|
||||||
Rendition.prototype.attachTo = function(_element){
|
var View = this.requireView(this.settings.view);
|
||||||
var bounds;
|
|
||||||
|
|
||||||
this.container = this.initialize({
|
// Add view manager
|
||||||
"width" : this.settings.width,
|
this.manager = new ViewManager({
|
||||||
"height" : this.settings.height
|
view: View,
|
||||||
|
renderer: this.render.bind(this),
|
||||||
|
queue: this.q,
|
||||||
|
settings: this.settings
|
||||||
});
|
});
|
||||||
|
|
||||||
if(core.isElement(_element)) {
|
// Listen for displayed views
|
||||||
this.element = _element;
|
this.manager.on("added", this.afterDisplayed.bind(this))
|
||||||
} else if (typeof _element === "string") {
|
|
||||||
this.element = document.getElementById(_element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!this.element){
|
// Start rendering
|
||||||
console.error("Not an Element");
|
this.manager.start(stage);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.settings.hidden) {
|
|
||||||
this.wrapper = this.wrap(this.container);
|
|
||||||
this.element.appendChild(this.wrapper);
|
|
||||||
} else {
|
|
||||||
this.element.appendChild(this.container);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.views = new Views(this.container);
|
|
||||||
|
|
||||||
// Attach Listeners
|
|
||||||
this.attachListeners();
|
|
||||||
|
|
||||||
// Calculate Stage Size
|
|
||||||
this.stageSize();
|
|
||||||
|
|
||||||
// Add Layout method
|
// Add Layout method
|
||||||
this.applyLayoutMethod();
|
this.applyLayoutMethod();
|
||||||
|
|
||||||
|
this.on('displayed', this.reportLocation.bind(this));
|
||||||
|
|
||||||
|
// Trigger that rendering has started
|
||||||
|
this.trigger("started");
|
||||||
|
|
||||||
|
// Start processing queue
|
||||||
|
this.starting.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call to attach the container to an element in the dom
|
||||||
|
// Container must be attached before rendering can begin
|
||||||
|
Rendition.prototype.attachTo = function(element){
|
||||||
|
|
||||||
|
this.container = new Stage(element, {
|
||||||
|
"width" : this.settings.width,
|
||||||
|
"height" : this.settings.height
|
||||||
|
});
|
||||||
|
|
||||||
|
this.start(this.container);
|
||||||
|
|
||||||
// Trigger Attached
|
// Trigger Attached
|
||||||
this.trigger("attached");
|
this.trigger("attached");
|
||||||
|
|
||||||
// Start processing queue
|
|
||||||
// this.q.run();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.attachListeners = function(){
|
|
||||||
|
|
||||||
// Listen to window for resize event if width or height is set to 100%
|
|
||||||
if(!core.isNumber(this.settings.width) ||
|
|
||||||
!core.isNumber(this.settings.height) ) {
|
|
||||||
window.addEventListener("resize", this.onResized.bind(this), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.bounds = function() {
|
|
||||||
return this.container.getBoundingClientRect();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.display = function(target){
|
Rendition.prototype.display = function(target){
|
||||||
|
|
||||||
|
// if (!this.book.spine.spineItems.length > 0) {
|
||||||
|
// Book isn't open yet
|
||||||
|
// return this.q.enqueue(this.display, target);
|
||||||
|
// }
|
||||||
|
|
||||||
return this.q.enqueue(this._display, target);
|
return this.q.enqueue(this._display, target);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype._display = function(target){
|
Rendition.prototype._display = function(target){
|
||||||
|
var isCfiString = this.epubcfi.isCfiString(target);
|
||||||
var displaying = new RSVP.defer();
|
var displaying = new RSVP.defer();
|
||||||
var displayed = displaying.promise;
|
var displayed = displaying.promise;
|
||||||
|
|
||||||
var section;
|
var section;
|
||||||
var view;
|
var moveTo;
|
||||||
var offset;
|
|
||||||
var fragment;
|
|
||||||
var cfi = this.epubcfi.isCfiString(target);
|
|
||||||
|
|
||||||
var visible;
|
|
||||||
|
|
||||||
section = this.book.spine.get(target);
|
section = this.book.spine.get(target);
|
||||||
|
|
||||||
|
@ -207,81 +170,42 @@ Rendition.prototype._display = function(target){
|
||||||
return displayed;
|
return displayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure the section we want isn't already shown
|
// Trim the target fragment
|
||||||
visible = this.views.find(section);
|
// removing the chapter
|
||||||
|
if(!isCfiString && typeof target === "string" &&
|
||||||
if(visible) {
|
|
||||||
offset = visible.locationOf(target);
|
|
||||||
this.moveTo(offset);
|
|
||||||
displaying.resolve();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Hide all current views
|
|
||||||
this.views.hide();
|
|
||||||
|
|
||||||
// Create a new view
|
|
||||||
// view = new View(section, this.viewSettings);
|
|
||||||
view = this.createView(section);
|
|
||||||
|
|
||||||
// This will clear all previous views
|
|
||||||
displayed = this.fill(view)
|
|
||||||
.then(function(){
|
|
||||||
|
|
||||||
// Parse the target fragment
|
|
||||||
if(typeof target === "string" &&
|
|
||||||
target.indexOf("#") > -1) {
|
target.indexOf("#") > -1) {
|
||||||
fragment = target.substring(target.indexOf("#")+1);
|
moveTo = target.substring(target.indexOf("#")+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to correct place within the section, if needed
|
if (isCfiString) {
|
||||||
if(cfi || fragment) {
|
moveTo = target;
|
||||||
offset = view.locationOf(target);
|
|
||||||
return this.moveTo(offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(typeof this.check === 'function') {
|
return this.manager.display(section, moveTo)
|
||||||
return this.check();
|
|
||||||
}
|
|
||||||
}.bind(this))
|
|
||||||
.then(function(){
|
.then(function(){
|
||||||
return this.hooks.display.trigger(view);
|
|
||||||
}.bind(this))
|
|
||||||
.then(function(){
|
|
||||||
this.views.show();
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
displayed.then(function(){
|
|
||||||
|
|
||||||
this.trigger("displayed", section);
|
this.trigger("displayed", section);
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
|
||||||
return displayed;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Takes a cfi, fragment or page?
|
|
||||||
Rendition.prototype.moveTo = function(offset){
|
|
||||||
this.scrollTo(offset.left, offset.top);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.render = function(view, show) {
|
Rendition.prototype.render = function(view, show) {
|
||||||
|
|
||||||
|
// view.onLayout = this.layout.format.bind(this.layout);
|
||||||
view.create();
|
view.create();
|
||||||
|
|
||||||
view.onLayout = this.layout.format.bind(this.layout);
|
|
||||||
|
|
||||||
// Fit to size of the container, apply padding
|
// Fit to size of the container, apply padding
|
||||||
this.resizeView(view);
|
this.manager.resizeView(view);
|
||||||
|
|
||||||
// Render Chain
|
// Render Chain
|
||||||
return view.render(this.book.request)
|
return view.section.render(this.book.request)
|
||||||
.then(function(){
|
.then(function(contents){
|
||||||
|
return view.load(contents);
|
||||||
|
}.bind(this))
|
||||||
|
.then(function(doc){
|
||||||
return this.hooks.content.trigger(view, this);
|
return this.hooks.content.trigger(view, this);
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.then(function(){
|
.then(function(){
|
||||||
|
this.layout.format(view.contents);
|
||||||
return this.hooks.layout.trigger(view, this);
|
return this.hooks.layout.trigger(view, this);
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.then(function(){
|
.then(function(){
|
||||||
|
@ -291,13 +215,11 @@ Rendition.prototype.render = function(view, show) {
|
||||||
return this.hooks.render.trigger(view, this);
|
return this.hooks.render.trigger(view, this);
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.then(function(){
|
.then(function(){
|
||||||
if(show !== false && this.views.hidden === false) {
|
if(show !== false) {
|
||||||
this.q.enqueue(function(view){
|
this.q.enqueue(function(view){
|
||||||
view.show();
|
view.show();
|
||||||
}, view);
|
}, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// this.map = new Map(view, this.layout);
|
// this.map = new Map(view, this.layout);
|
||||||
this.hooks.show.trigger(view, this);
|
this.hooks.show.trigger(view, this);
|
||||||
this.trigger("rendered", view.section);
|
this.trigger("rendered", view.section);
|
||||||
|
@ -309,170 +231,69 @@ Rendition.prototype.render = function(view, show) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Rendition.prototype.afterDisplayed = function(section){
|
||||||
Rendition.prototype.afterDisplayed = function(view){
|
this.trigger("added", section);
|
||||||
this.trigger("added", view.section);
|
|
||||||
this.reportLocation();
|
this.reportLocation();
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.fill = function(view){
|
|
||||||
|
|
||||||
this.views.clear();
|
|
||||||
|
|
||||||
this.views.append(view);
|
|
||||||
|
|
||||||
// view.on("shown", this.afterDisplayed.bind(this));
|
|
||||||
view.onDisplayed = this.afterDisplayed.bind(this);
|
|
||||||
|
|
||||||
return this.render(view);
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.resizeView = function(view) {
|
|
||||||
|
|
||||||
if(this.globalLayoutProperties.layout === "pre-paginated") {
|
|
||||||
view.lock("both", this.stage.width, this.stage.height);
|
|
||||||
} else {
|
|
||||||
view.lock("width", this.stage.width, this.stage.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.stageSize = function(_width, _height){
|
|
||||||
var bounds;
|
|
||||||
var width = _width || this.settings.width;
|
|
||||||
var height = _height || this.settings.height;
|
|
||||||
|
|
||||||
// If width or height are set to false, inherit them from containing element
|
|
||||||
if(width === false) {
|
|
||||||
bounds = this.element.getBoundingClientRect();
|
|
||||||
|
|
||||||
if(bounds.width) {
|
|
||||||
width = bounds.width;
|
|
||||||
this.container.style.width = bounds.width + "px";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(height === false) {
|
|
||||||
bounds = bounds || this.element.getBoundingClientRect();
|
|
||||||
|
|
||||||
if(bounds.height) {
|
|
||||||
height = bounds.height;
|
|
||||||
this.container.style.height = bounds.height + "px";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(width && !core.isNumber(width)) {
|
|
||||||
bounds = this.container.getBoundingClientRect();
|
|
||||||
width = bounds.width;
|
|
||||||
//height = bounds.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(height && !core.isNumber(height)) {
|
|
||||||
bounds = bounds || this.container.getBoundingClientRect();
|
|
||||||
//width = bounds.width;
|
|
||||||
height = bounds.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.containerStyles = window.getComputedStyle(this.container);
|
|
||||||
this.containerPadding = {
|
|
||||||
left: parseFloat(this.containerStyles["padding-left"]) || 0,
|
|
||||||
right: parseFloat(this.containerStyles["padding-right"]) || 0,
|
|
||||||
top: parseFloat(this.containerStyles["padding-top"]) || 0,
|
|
||||||
bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0
|
|
||||||
};
|
|
||||||
|
|
||||||
this.stage = {
|
|
||||||
width: width -
|
|
||||||
this.containerPadding.left -
|
|
||||||
this.containerPadding.right,
|
|
||||||
height: height -
|
|
||||||
this.containerPadding.top -
|
|
||||||
this.containerPadding.bottom
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.stage;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.applyLayoutMethod = function() {
|
Rendition.prototype.applyLayoutMethod = function() {
|
||||||
|
|
||||||
this.layout = new Layout.Scroll();
|
this.layout = new Layout.Scroll();
|
||||||
this.updateLayout();
|
this.calculateLayout();
|
||||||
|
|
||||||
this.map = new Map(this.layout);
|
// this.map = new Map(this.layout);
|
||||||
|
// this.manager.layout(this.layout.format);
|
||||||
|
};
|
||||||
|
|
||||||
|
Rendition.prototype.calculateLayout = function() {
|
||||||
|
var bounds = this.manager.stage.bounds();
|
||||||
|
|
||||||
|
this.layout.calculate(bounds.width, bounds.height);
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.updateLayout = function() {
|
Rendition.prototype.updateLayout = function() {
|
||||||
|
this.calculateLayout();
|
||||||
|
|
||||||
this.layout.calculate(this.stage.width, this.stage.height);
|
this.manager.layout(this.layout.format);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.resize = function(width, height){
|
Rendition.prototype.onResized = function(size){
|
||||||
|
|
||||||
this.stageSize(width, height);
|
|
||||||
|
|
||||||
this.updateLayout();
|
this.updateLayout();
|
||||||
|
|
||||||
this.views.each(this.resizeView.bind(this));
|
if(this.location) {
|
||||||
|
this.display(this.location.start);
|
||||||
|
}
|
||||||
|
|
||||||
this.trigger("resized", {
|
this.trigger("resized", {
|
||||||
width: this.stage.width,
|
width: size.width,
|
||||||
height: this.stage.height
|
height: size.height
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.onResized = function(e) {
|
Rendition.prototype.moveTo = function(offset){
|
||||||
this.resize();
|
this.manager.moveTo(offset);
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.createView = function(section) {
|
|
||||||
// Transfer the existing hooks
|
|
||||||
section.hooks.serialize.register(this.hooks.serialize.list());
|
|
||||||
|
|
||||||
return new View(section, this.viewSettings);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.next = function(){
|
Rendition.prototype.next = function(){
|
||||||
|
return this.q.enqueue(this.manager.next.bind(this.manager));
|
||||||
return this.q.enqueue(function(){
|
|
||||||
|
|
||||||
var next;
|
|
||||||
var view;
|
|
||||||
|
|
||||||
if(!this.views.length) return;
|
|
||||||
|
|
||||||
next = this.views.last().section.next();
|
|
||||||
|
|
||||||
if(next) {
|
|
||||||
view = this.createView(next);
|
|
||||||
return this.fill(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.prev = function(){
|
Rendition.prototype.prev = function(){
|
||||||
|
return this.q.enqueue(this.manager.prev.bind(this.manager));
|
||||||
|
};
|
||||||
|
|
||||||
return this.q.enqueue(function(){
|
Rendition.prototype.bounds = function() {
|
||||||
|
var bounds;
|
||||||
|
|
||||||
var prev;
|
if(!this.settings.height || !this.container) {
|
||||||
var view;
|
bounds = core.windowBounds();
|
||||||
|
} else {
|
||||||
if(!this.views.length) return;
|
bounds = this.container.getBoundingClientRect();
|
||||||
|
|
||||||
prev = this.views.first().section.prev();
|
|
||||||
if(prev) {
|
|
||||||
view = this.createView(prev);
|
|
||||||
return this.fill(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
return bounds;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-- http://www.idpf.org/epub/fxl/
|
//-- http://www.idpf.org/epub/fxl/
|
||||||
|
@ -481,76 +302,60 @@ Rendition.prototype.parseLayoutProperties = function(_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";
|
||||||
this.globalLayoutProperties = {
|
|
||||||
|
this.settings.globalLayoutProperties = {
|
||||||
layout : layout,
|
layout : layout,
|
||||||
spread : spread,
|
spread : spread,
|
||||||
orientation : orientation
|
orientation : orientation
|
||||||
};
|
};
|
||||||
return this.globalLayoutProperties;
|
|
||||||
|
return this.settings.globalLayoutProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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){
|
||||||
|
// // Default is layout: reflowable & spread: auto
|
||||||
|
// var spreads = this.determineSpreads(this.settings.minSpreadWidth);
|
||||||
|
// console.log("spreads", spreads, 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;
|
||||||
|
//
|
||||||
|
// return layoutMethod;
|
||||||
|
// };
|
||||||
|
|
||||||
Rendition.prototype.current = function(){
|
|
||||||
var visible = this.visible();
|
Rendition.prototype.reportLocation = function(){
|
||||||
if(visible.length){
|
return this.q.enqueue(function(){
|
||||||
// Current is the last visible view
|
this.location = this.manager.currentLocation();
|
||||||
return visible[visible.length-1];
|
this.trigger("locationChanged", this.location);
|
||||||
}
|
}.bind(this));
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){
|
|
||||||
var position = view.position();
|
|
||||||
var container = _container || this.container.getBoundingClientRect();
|
|
||||||
|
|
||||||
if(this.settings.axis === "horizontal" &&
|
|
||||||
position.right > container.left - offsetPrev &&
|
|
||||||
position.left < container.right + offsetNext) {
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if(this.settings.axis === "vertical" &&
|
|
||||||
position.bottom > container.top - offsetPrev &&
|
|
||||||
position.top < container.bottom + offsetNext) {
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.visible = function(){
|
|
||||||
var container = this.bounds();
|
|
||||||
var displayedViews = this.views.displayed();
|
|
||||||
var visible = [];
|
|
||||||
var isVisible;
|
|
||||||
var view;
|
|
||||||
|
|
||||||
for (var i = 0; i < displayedViews.length; i++) {
|
|
||||||
view = displayedViews[i];
|
|
||||||
isVisible = this.isVisible(view, 0, 0, container);
|
|
||||||
|
|
||||||
if(isVisible === true) {
|
|
||||||
visible.push(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return visible;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.bounds = function(func) {
|
|
||||||
var bounds;
|
|
||||||
|
|
||||||
if(!this.settings.height) {
|
|
||||||
bounds = core.windowBounds();
|
|
||||||
} else {
|
|
||||||
bounds = this.container.getBoundingClientRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return bounds;
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.destroy = function(){
|
Rendition.prototype.destroy = function(){
|
||||||
// Clear the queue
|
// Clear the queue
|
||||||
|
@ -567,67 +372,8 @@ Rendition.prototype.destroy = function(){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.reportLocation = function(){
|
|
||||||
return this.q.enqueue(function(){
|
|
||||||
this.location = this.currentLocation();
|
|
||||||
this.trigger("locationChanged", this.location);
|
|
||||||
}.bind(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.currentLocation = function(){
|
|
||||||
var view;
|
|
||||||
var start, end;
|
|
||||||
|
|
||||||
if(this.views.length) {
|
|
||||||
view = this.views.first();
|
|
||||||
// start = container.left - view.position().left;
|
|
||||||
// end = start + this.layout.spread;
|
|
||||||
|
|
||||||
return this.map.page(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.scrollBy = function(x, y, silent){
|
|
||||||
if(silent) {
|
|
||||||
this.ignore = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.settings.height) {
|
|
||||||
|
|
||||||
if(x) this.container.scrollLeft += x;
|
|
||||||
if(y) this.container.scrollTop += y;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
window.scrollBy(x,y);
|
|
||||||
}
|
|
||||||
// console.log("scrollBy", x, y);
|
|
||||||
this.scrolled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.scrollTo = function(x, y, silent){
|
|
||||||
if(silent) {
|
|
||||||
this.ignore = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.settings.height) {
|
|
||||||
this.container.scrollLeft = x;
|
|
||||||
this.container.scrollTop = y;
|
|
||||||
} else {
|
|
||||||
window.scrollTo(x,y);
|
|
||||||
}
|
|
||||||
// console.log("scrollTo", x, y);
|
|
||||||
this.scrolled = true;
|
|
||||||
// if(this.container.scrollLeft != x){
|
|
||||||
// setTimeout(function() {
|
|
||||||
// this.scrollTo(x, y, silent);
|
|
||||||
// }.bind(this), 10);
|
|
||||||
// return;
|
|
||||||
// };
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.passViewEvents = function(view){
|
Rendition.prototype.passViewEvents = function(view){
|
||||||
view.listenedEvents.forEach(function(e){
|
view.contents.listenedEvents.forEach(function(e){
|
||||||
view.on(e, this.triggerViewEvent.bind(this));
|
view.on(e, this.triggerViewEvent.bind(this));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
@ -699,7 +445,7 @@ Rendition.prototype.replacements = function(){
|
||||||
|
|
||||||
// Replace Asset Urls in chapters
|
// Replace Asset Urls in chapters
|
||||||
// by registering a hook after the sections contents has been serialized
|
// by registering a hook after the sections contents has been serialized
|
||||||
this.hooks.serialize.register(function(output, section) {
|
this.book.spine.hooks.serialize.register(function(output, section) {
|
||||||
this.replaceAssets(section, urls, replacementUrls);
|
this.replaceAssets(section, urls, replacementUrls);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
@ -765,6 +511,22 @@ Rendition.prototype.range = function(_cfi, ignoreClass){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Rendition.prototype.adjustImages = function(view) {
|
||||||
|
|
||||||
|
view.addStylesheetRules([
|
||||||
|
["img",
|
||||||
|
["max-width", (this.layout.spread) + "px"],
|
||||||
|
["max-height", (this.layout.height) + "px"]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
return new RSVP.Promise(function(resolve, reject){
|
||||||
|
// Wait to apply
|
||||||
|
setTimeout(function() {
|
||||||
|
resolve();
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//-- Enable binding events to Renderer
|
//-- Enable binding events to Renderer
|
||||||
RSVP.EventTarget.mixin(Rendition.prototype);
|
RSVP.EventTarget.mixin(Rendition.prototype);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ var URI = require('urijs');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
var Hook = require('./hook');
|
var Hook = require('./hook');
|
||||||
var replacements = require('./replacements');
|
|
||||||
|
|
||||||
function Section(item, hooks){
|
function Section(item, hooks){
|
||||||
this.idref = item.idref;
|
this.idref = item.idref;
|
||||||
|
@ -17,12 +16,14 @@ function Section(item, hooks){
|
||||||
|
|
||||||
this.cfiBase = item.cfiBase;
|
this.cfiBase = item.cfiBase;
|
||||||
|
|
||||||
|
if (hooks) {
|
||||||
|
this.hooks = hooks;
|
||||||
|
} else {
|
||||||
this.hooks = {};
|
this.hooks = {};
|
||||||
this.hooks.serialize = new Hook(this);
|
this.hooks.serialize = new Hook(this);
|
||||||
this.hooks.content = new Hook(this);
|
this.hooks.content = new Hook(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Register replacements
|
|
||||||
this.hooks.content.register(replacements.base);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
17
src/spine.js
17
src/spine.js
|
@ -1,7 +1,9 @@
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
|
var Hook = require('./hook');
|
||||||
var Section = require('./section');
|
var Section = require('./section');
|
||||||
|
var replacements = require('./replacements');
|
||||||
|
|
||||||
function Spine(_request){
|
function Spine(_request){
|
||||||
this.request = _request;
|
this.request = _request;
|
||||||
|
@ -9,6 +11,16 @@ function Spine(_request){
|
||||||
this.spineByHref = {};
|
this.spineByHref = {};
|
||||||
this.spineById = {};
|
this.spineById = {};
|
||||||
|
|
||||||
|
this.hooks = {};
|
||||||
|
this.hooks.serialize = new Hook();
|
||||||
|
this.hooks.content = new Hook();
|
||||||
|
|
||||||
|
// Register replacements
|
||||||
|
this.hooks.content.register(replacements.base);
|
||||||
|
|
||||||
|
this.epubcfi = new EpubCFI();
|
||||||
|
|
||||||
|
this.loaded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Spine.prototype.load = function(_package) {
|
Spine.prototype.load = function(_package) {
|
||||||
|
@ -18,7 +30,6 @@ Spine.prototype.load = function(_package) {
|
||||||
this.spineNodeIndex = _package.spineNodeIndex;
|
this.spineNodeIndex = _package.spineNodeIndex;
|
||||||
this.baseUrl = _package.baseUrl || '';
|
this.baseUrl = _package.baseUrl || '';
|
||||||
this.length = this.items.length;
|
this.length = this.items.length;
|
||||||
this.epubcfi = new EpubCFI();
|
|
||||||
|
|
||||||
this.items.forEach(function(item, index){
|
this.items.forEach(function(item, index){
|
||||||
var href, url;
|
var href, url;
|
||||||
|
@ -44,12 +55,14 @@ Spine.prototype.load = function(_package) {
|
||||||
item.next = function(){ return this.get(index+1); }.bind(this);
|
item.next = function(){ return this.get(index+1); }.bind(this);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
spineItem = new Section(item);
|
spineItem = new Section(item, this.hooks);
|
||||||
|
|
||||||
this.append(spineItem);
|
this.append(spineItem);
|
||||||
|
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// book.spine.get();
|
// book.spine.get();
|
||||||
|
|
179
src/stage.js
Normal file
179
src/stage.js
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
var core = require('./core');
|
||||||
|
|
||||||
|
function Stage(element, _options) {
|
||||||
|
this.settings = _options || {};
|
||||||
|
|
||||||
|
this.element = this.getElement(element);
|
||||||
|
this.container = this.create(this.settings);
|
||||||
|
|
||||||
|
if(this.settings.hidden) {
|
||||||
|
this.wrapper = this.wrap(this.container);
|
||||||
|
this.attachTo(this.wrapper, this.element);
|
||||||
|
} else {
|
||||||
|
this.attachTo(this.container, this.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an element to render to.
|
||||||
|
* Resizes to passed width and height or to the elements size
|
||||||
|
*/
|
||||||
|
Stage.prototype.create = function(options){
|
||||||
|
var height = options.height;// !== false ? options.height : "100%";
|
||||||
|
var width = options.width;// !== false ? options.width : "100%";
|
||||||
|
var overflow = options.overflow || false;
|
||||||
|
|
||||||
|
if(options.height && core.isNumber(options.height)) {
|
||||||
|
height = options.height + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.width && core.isNumber(options.width)) {
|
||||||
|
width = options.width + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new container element
|
||||||
|
container = document.createElement("div");
|
||||||
|
|
||||||
|
container.id = "epubjs-container:" + core.uuid();
|
||||||
|
container.classList.add("epub-container");
|
||||||
|
|
||||||
|
// Style Element
|
||||||
|
container.style.fontSize = "0";
|
||||||
|
container.style.wordSpacing = "0";
|
||||||
|
container.style.lineHeight = "0";
|
||||||
|
container.style.verticalAlign = "top";
|
||||||
|
|
||||||
|
if(this.settings.axis === "horizontal") {
|
||||||
|
container.style.whiteSpace = "nowrap";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(width){
|
||||||
|
container.style.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height){
|
||||||
|
container.style.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overflow) {
|
||||||
|
container.style.overflow = overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stage.wrap = function(container) {
|
||||||
|
var wrapper = document.createElement("div");
|
||||||
|
|
||||||
|
wrapper.style.visibility = "hidden";
|
||||||
|
wrapper.style.overflow = "hidden";
|
||||||
|
wrapper.style.width = "0";
|
||||||
|
wrapper.style.height = "0";
|
||||||
|
|
||||||
|
wrapper.appendChild(container);
|
||||||
|
return wrapper;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Stage.prototype.getElement = function(_element){
|
||||||
|
var element;
|
||||||
|
|
||||||
|
if(core.isElement(_element)) {
|
||||||
|
element = _element;
|
||||||
|
} else if (typeof _element === "string") {
|
||||||
|
element = document.getElementById(_element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!element){
|
||||||
|
console.error("Not an Element");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stage.prototype.attachTo = function(what, element){
|
||||||
|
|
||||||
|
if(!element){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.appendChild(what);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Stage.prototype.getContainer = function() {
|
||||||
|
return this.container;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stage.prototype.onResize = function(func){
|
||||||
|
// Only listen to window for resize event if width and height are not fixed.
|
||||||
|
// This applies if it is set to a percent or auto.
|
||||||
|
if(!core.isNumber(this.settings.width) ||
|
||||||
|
!core.isNumber(this.settings.height) ) {
|
||||||
|
window.addEventListener("resize", func, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Stage.prototype.bounds = function(_width, _height){
|
||||||
|
var bounds;
|
||||||
|
var width = _width || this.settings.width;
|
||||||
|
var height = _height || this.settings.height;
|
||||||
|
|
||||||
|
// If width or height are set to false, inherit them from containing element
|
||||||
|
if(width === false) {
|
||||||
|
bounds = this.element.getBoundingClientRect();
|
||||||
|
|
||||||
|
if(bounds.width) {
|
||||||
|
width = bounds.width;
|
||||||
|
this.container.style.width = bounds.width + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height === false) {
|
||||||
|
bounds = bounds || this.element.getBoundingClientRect();
|
||||||
|
|
||||||
|
if(bounds.height) {
|
||||||
|
height = bounds.height;
|
||||||
|
this.container.style.height = bounds.height + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(width && !core.isNumber(width)) {
|
||||||
|
bounds = this.container.getBoundingClientRect();
|
||||||
|
width = bounds.width;
|
||||||
|
//height = bounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height && !core.isNumber(height)) {
|
||||||
|
bounds = bounds || this.container.getBoundingClientRect();
|
||||||
|
//width = bounds.width;
|
||||||
|
height = bounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.containerStyles = window.getComputedStyle(this.container);
|
||||||
|
this.containerPadding = {
|
||||||
|
left: parseFloat(this.containerStyles["padding-left"]) || 0,
|
||||||
|
right: parseFloat(this.containerStyles["padding-right"]) || 0,
|
||||||
|
top: parseFloat(this.containerStyles["padding-top"]) || 0,
|
||||||
|
bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: width -
|
||||||
|
this.containerPadding.left -
|
||||||
|
this.containerPadding.right,
|
||||||
|
height: height -
|
||||||
|
this.containerPadding.top -
|
||||||
|
this.containerPadding.bottom
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Stage;
|
10
src/views.js
10
src/views.js
|
@ -31,14 +31,18 @@ Views.prototype.get = function(i) {
|
||||||
|
|
||||||
Views.prototype.append = function(view){
|
Views.prototype.append = function(view){
|
||||||
this._views.push(view);
|
this._views.push(view);
|
||||||
|
if(this.container){
|
||||||
this.container.appendChild(view.element);
|
this.container.appendChild(view.element);
|
||||||
|
}
|
||||||
this.length++;
|
this.length++;
|
||||||
return view;
|
return view;
|
||||||
};
|
};
|
||||||
|
|
||||||
Views.prototype.prepend = function(view){
|
Views.prototype.prepend = function(view){
|
||||||
this._views.unshift(view);
|
this._views.unshift(view);
|
||||||
|
if(this.container){
|
||||||
this.container.insertBefore(view.element, this.container.firstChild);
|
this.container.insertBefore(view.element, this.container.firstChild);
|
||||||
|
}
|
||||||
this.length++;
|
this.length++;
|
||||||
return view;
|
return view;
|
||||||
};
|
};
|
||||||
|
@ -46,11 +50,14 @@ Views.prototype.prepend = function(view){
|
||||||
Views.prototype.insert = function(view, index) {
|
Views.prototype.insert = function(view, index) {
|
||||||
this._views.splice(index, 0, view);
|
this._views.splice(index, 0, view);
|
||||||
|
|
||||||
|
if(this.container){
|
||||||
if(index < this.container.children.length){
|
if(index < this.container.children.length){
|
||||||
this.container.insertBefore(view.element, this.container.children[index]);
|
this.container.insertBefore(view.element, this.container.children[index]);
|
||||||
} else {
|
} else {
|
||||||
this.container.appendChild(view.element);
|
this.container.appendChild(view.element);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.length++;
|
this.length++;
|
||||||
return view;
|
return view;
|
||||||
};
|
};
|
||||||
|
@ -74,8 +81,9 @@ Views.prototype.destroy = function(view) {
|
||||||
if(view.displayed){
|
if(view.displayed){
|
||||||
view.destroy();
|
view.destroy();
|
||||||
}
|
}
|
||||||
|
if(this.container){
|
||||||
this.container.removeChild(view.element);
|
this.container.removeChild(view.element);
|
||||||
|
}
|
||||||
view = null;
|
view = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
590
src/views/iframe.js
Normal file
590
src/views/iframe.js
Normal file
|
@ -0,0 +1,590 @@
|
||||||
|
var RSVP = require('rsvp');
|
||||||
|
var core = require('../core');
|
||||||
|
var EpubCFI = require('../epubcfi');
|
||||||
|
var Contents = require('../contents');
|
||||||
|
|
||||||
|
function IframeView(section, options) {
|
||||||
|
this.settings = core.extend({
|
||||||
|
ignoreClass : ''
|
||||||
|
}, options || {});
|
||||||
|
|
||||||
|
this.id = "epubjs-view:" + core.uuid();
|
||||||
|
this.section = section;
|
||||||
|
this.index = section.index;
|
||||||
|
|
||||||
|
this.element = this.createContainer();
|
||||||
|
|
||||||
|
this.added = false;
|
||||||
|
this.displayed = false;
|
||||||
|
this.rendered = false;
|
||||||
|
|
||||||
|
//this.width = 0;
|
||||||
|
//this.height = 0;
|
||||||
|
|
||||||
|
// Blank Cfi for Parsing
|
||||||
|
this.epubcfi = new EpubCFI();
|
||||||
|
|
||||||
|
// Dom events to listen for
|
||||||
|
// this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.createContainer = function() {
|
||||||
|
var element = document.createElement('div');
|
||||||
|
|
||||||
|
element.classList.add("epub-view");
|
||||||
|
|
||||||
|
|
||||||
|
// this.element.style.minHeight = "100px";
|
||||||
|
element.style.height = "0px";
|
||||||
|
element.style.width = "0px";
|
||||||
|
element.style.overflow = "hidden";
|
||||||
|
|
||||||
|
if(this.settings.axis && this.settings.axis == "horizontal"){
|
||||||
|
element.style.display = "inline-block";
|
||||||
|
} else {
|
||||||
|
element.style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.create = function() {
|
||||||
|
|
||||||
|
if(this.iframe) {
|
||||||
|
return this.iframe;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.element) {
|
||||||
|
this.element = this.createContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iframe = document.createElement('iframe');
|
||||||
|
this.iframe.id = this.id;
|
||||||
|
this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations
|
||||||
|
this.iframe.style.overflow = "hidden";
|
||||||
|
this.iframe.seamless = "seamless";
|
||||||
|
// Back up if seamless isn't supported
|
||||||
|
this.iframe.style.border = "none";
|
||||||
|
|
||||||
|
this.resizing = true;
|
||||||
|
|
||||||
|
// this.iframe.style.display = "none";
|
||||||
|
this.element.style.visibility = "hidden";
|
||||||
|
this.iframe.style.visibility = "hidden";
|
||||||
|
|
||||||
|
this.iframe.style.width = "0";
|
||||||
|
this.iframe.style.height = "0";
|
||||||
|
this._width = 0;
|
||||||
|
this._height = 0;
|
||||||
|
|
||||||
|
this.element.appendChild(this.iframe);
|
||||||
|
this.added = true;
|
||||||
|
|
||||||
|
this.elementBounds = core.bounds(this.element);
|
||||||
|
|
||||||
|
// if(width || height){
|
||||||
|
// this.resize(width, height);
|
||||||
|
// } else if(this.width && this.height){
|
||||||
|
// this.resize(this.width, this.height);
|
||||||
|
// } else {
|
||||||
|
// this.iframeBounds = core.bounds(this.iframe);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Firefox has trouble with baseURI and srcdoc
|
||||||
|
// Disabled for now
|
||||||
|
/*
|
||||||
|
if(!!("srcdoc" in this.iframe)) {
|
||||||
|
this.supportsSrcdoc = true;
|
||||||
|
} else {
|
||||||
|
this.supportsSrcdoc = false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
this.supportsSrcdoc = false;
|
||||||
|
|
||||||
|
return this.iframe;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
IframeView.prototype.lock = function(what, width, height) {
|
||||||
|
var elBorders = core.borders(this.element);
|
||||||
|
var iframeBorders;
|
||||||
|
|
||||||
|
if(this.iframe) {
|
||||||
|
iframeBorders = core.borders(this.iframe);
|
||||||
|
} else {
|
||||||
|
iframeBorders = {width: 0, height: 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(what == "width" && core.isNumber(width)){
|
||||||
|
this.lockedWidth = width - elBorders.width - iframeBorders.width;
|
||||||
|
this.resize(this.lockedWidth, width); // width keeps ratio correct
|
||||||
|
}
|
||||||
|
|
||||||
|
if(what == "height" && core.isNumber(height)){
|
||||||
|
this.lockedHeight = height - elBorders.height - iframeBorders.height;
|
||||||
|
this.resize(width, this.lockedHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(what === "both" &&
|
||||||
|
core.isNumber(width) &&
|
||||||
|
core.isNumber(height)){
|
||||||
|
|
||||||
|
this.lockedWidth = width - elBorders.width - iframeBorders.width;
|
||||||
|
this.lockedHeight = height - elBorders.height - iframeBorders.height;
|
||||||
|
|
||||||
|
this.resize(this.lockedWidth, this.lockedHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.displayed && this.iframe) {
|
||||||
|
|
||||||
|
// this.contents.layout();
|
||||||
|
this.expand();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.expand = function(force) {
|
||||||
|
var width = this.lockedWidth;
|
||||||
|
var height = this.lockedHeight;
|
||||||
|
|
||||||
|
var textWidth, textHeight;
|
||||||
|
// console.log("expanding a")
|
||||||
|
if(!this.iframe || this._expanding) return;
|
||||||
|
|
||||||
|
this._expanding = true;
|
||||||
|
|
||||||
|
// Expand Horizontally
|
||||||
|
if(height && !width) {
|
||||||
|
// Get the width of the text
|
||||||
|
textWidth = this.contents.textWidth();
|
||||||
|
// Check if the textWidth has changed
|
||||||
|
if(textWidth != this._textWidth){
|
||||||
|
// Get the contentWidth by resizing the iframe
|
||||||
|
// Check with a min reset of the textWidth
|
||||||
|
width = this.contentWidth(textWidth);
|
||||||
|
// Save the textWdith
|
||||||
|
this._textWidth = textWidth;
|
||||||
|
// Save the contentWidth
|
||||||
|
this._contentWidth = width;
|
||||||
|
} else {
|
||||||
|
// Otherwise assume content height hasn't changed
|
||||||
|
width = this._contentWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand Vertically
|
||||||
|
if(width && !height) {
|
||||||
|
textHeight = this.contents.textHeight();
|
||||||
|
if(textHeight != this._textHeight){
|
||||||
|
height = this.contentHeight(textHeight);
|
||||||
|
this._textHeight = textHeight;
|
||||||
|
this._contentHeight = height;
|
||||||
|
} else {
|
||||||
|
height = this._contentHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Resize if dimensions have changed or
|
||||||
|
// if Frame is still hidden, so needs reframing
|
||||||
|
if(this._needsReframe || width != this._width || height != this._height){
|
||||||
|
this.resize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._expanding = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.contentWidth = function(min) {
|
||||||
|
var prev;
|
||||||
|
var width;
|
||||||
|
|
||||||
|
// Save previous width
|
||||||
|
prev = this.iframe.style.width;
|
||||||
|
// Set the iframe size to min, width will only ever be greater
|
||||||
|
// Will preserve the aspect ratio
|
||||||
|
this.iframe.style.width = (min || 0) + "px";
|
||||||
|
// Get the scroll overflow width
|
||||||
|
width = this.contents.scrollWidth();
|
||||||
|
// Reset iframe size back
|
||||||
|
this.iframe.style.width = prev;
|
||||||
|
return width;
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.contentHeight = function(min) {
|
||||||
|
var prev;
|
||||||
|
var height;
|
||||||
|
|
||||||
|
prev = this.iframe.style.height;
|
||||||
|
this.iframe.style.height = (min || 0) + "px";
|
||||||
|
height = this.contents.scrollHeight();
|
||||||
|
|
||||||
|
this.iframe.style.height = prev;
|
||||||
|
return height;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
IframeView.prototype.resize = function(width, height) {
|
||||||
|
|
||||||
|
if(!this.iframe) return;
|
||||||
|
|
||||||
|
if(core.isNumber(width)){
|
||||||
|
this.iframe.style.width = width + "px";
|
||||||
|
this._width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(core.isNumber(height)){
|
||||||
|
this.iframe.style.height = height + "px";
|
||||||
|
this._height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iframeBounds = core.bounds(this.iframe);
|
||||||
|
|
||||||
|
this.reframe(this.iframeBounds.width, this.iframeBounds.height);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.reframe = function(width, height) {
|
||||||
|
//var prevBounds;
|
||||||
|
|
||||||
|
if(!this.displayed) {
|
||||||
|
this._needsReframe = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(core.isNumber(width)){
|
||||||
|
this.element.style.width = width + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(core.isNumber(height)){
|
||||||
|
this.element.style.height = height + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.prevBounds = this.elementBounds;
|
||||||
|
|
||||||
|
this.elementBounds = core.bounds(this.element);
|
||||||
|
|
||||||
|
this.trigger("resized", {
|
||||||
|
width: this.elementBounds.width,
|
||||||
|
height: this.elementBounds.height,
|
||||||
|
widthDelta: this.elementBounds.width - this.prevBounds.width,
|
||||||
|
heightDelta: this.elementBounds.height - this.prevBounds.height,
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
var loading = new RSVP.defer();
|
||||||
|
var loaded = loading.promise;
|
||||||
|
|
||||||
|
if(!this.iframe) {
|
||||||
|
loading.reject(new Error("No Iframe Available"));
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iframe.onload = function(event) {
|
||||||
|
|
||||||
|
this.onLoad(event, loading);
|
||||||
|
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
if(this.supportsSrcdoc){
|
||||||
|
this.iframe.srcdoc = contents;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.document = this.iframe.contentDocument;
|
||||||
|
|
||||||
|
if(!this.document) {
|
||||||
|
loading.reject(new Error("No Document Available"));
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.document.open();
|
||||||
|
this.document.write(contents);
|
||||||
|
this.document.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return loaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.onLoad = function(event, promise) {
|
||||||
|
|
||||||
|
this.window = this.iframe.contentWindow;
|
||||||
|
this.document = this.iframe.contentDocument;
|
||||||
|
|
||||||
|
this.contents = new Contents(this.document);
|
||||||
|
|
||||||
|
this.rendering = false;
|
||||||
|
|
||||||
|
promise.resolve(this.contents);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// IframeView.prototype.layout = function(layoutFunc) {
|
||||||
|
//
|
||||||
|
// this.iframe.style.display = "inline-block";
|
||||||
|
//
|
||||||
|
// // Reset Body Styles
|
||||||
|
// // this.document.body.style.margin = "0";
|
||||||
|
// //this.document.body.style.display = "inline-block";
|
||||||
|
// //this.document.documentElement.style.width = "auto";
|
||||||
|
//
|
||||||
|
// if(layoutFunc){
|
||||||
|
// this.layoutFunc = layoutFunc;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// this.contents.layout(this.layoutFunc);
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// IframeView.prototype.onLayout = function(view) {
|
||||||
|
// // stub
|
||||||
|
// };
|
||||||
|
|
||||||
|
IframeView.prototype.setLayout = function(layoutFunc) {
|
||||||
|
this.layoutFunc = layoutFunc;
|
||||||
|
};
|
||||||
|
|
||||||
|
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() {
|
||||||
|
// Test size again
|
||||||
|
clearTimeout(this.expanding);
|
||||||
|
this.expanding = setTimeout(this.expand.bind(this), 350);
|
||||||
|
};
|
||||||
|
|
||||||
|
//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js
|
||||||
|
IframeView.prototype.mediaQueryListeners = function() {
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// View.prototype.appendTo = function(element) {
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
this.displayed = true;
|
||||||
|
|
||||||
|
// apply the layout function to the contents
|
||||||
|
// this.layout(layoutFunc);
|
||||||
|
|
||||||
|
// Expand the iframe to the full size of the content
|
||||||
|
this.expand();
|
||||||
|
|
||||||
|
// Listen for event that require an expansion of the iframe
|
||||||
|
this.listeners();
|
||||||
|
|
||||||
|
this.trigger("displayed", this);
|
||||||
|
this.onDisplayed(this);
|
||||||
|
|
||||||
|
displayed.resolve(this);
|
||||||
|
|
||||||
|
return displayed.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.show = function() {
|
||||||
|
|
||||||
|
this.element.style.visibility = "visible";
|
||||||
|
|
||||||
|
if(this.iframe){
|
||||||
|
this.iframe.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("shown", this);
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.hide = function() {
|
||||||
|
// this.iframe.style.display = "none";
|
||||||
|
this.element.style.visibility = "hidden";
|
||||||
|
this.iframe.style.visibility = "hidden";
|
||||||
|
|
||||||
|
this.stopExpanding = true;
|
||||||
|
this.trigger("hidden", this);
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.position = function() {
|
||||||
|
return this.element.getBoundingClientRect();
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.locationOf = function(target) {
|
||||||
|
var parentPos = this.iframe.getBoundingClientRect();
|
||||||
|
var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
|
||||||
|
|
||||||
|
return {
|
||||||
|
"left": window.scrollX + parentPos.left + targetPos.left,
|
||||||
|
"top": window.scrollY + parentPos.top + targetPos.top
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.onDisplayed = function(view) {
|
||||||
|
// Stub, override with a custom functions
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.bounds = function() {
|
||||||
|
if(!this.elementBounds) {
|
||||||
|
this.elementBounds = core.bounds(this.element);
|
||||||
|
}
|
||||||
|
return this.elementBounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
IframeView.prototype.destroy = function() {
|
||||||
|
// Stop observing
|
||||||
|
if(this.observer) {
|
||||||
|
this.observer.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.displayed){
|
||||||
|
this.removeListeners();
|
||||||
|
|
||||||
|
this.stopExpanding = true;
|
||||||
|
this.element.removeChild(this.iframe);
|
||||||
|
this.displayed = false;
|
||||||
|
this.iframe = null;
|
||||||
|
|
||||||
|
this._textWidth = null;
|
||||||
|
this._textHeight = null;
|
||||||
|
this._width = null;
|
||||||
|
this._height = null;
|
||||||
|
}
|
||||||
|
// this.element.style.height = "0px";
|
||||||
|
// this.element.style.width = "0px";
|
||||||
|
};
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(IframeView.prototype);
|
||||||
|
|
||||||
|
module.exports = IframeView;
|
|
@ -5,6 +5,7 @@ var morgan = require('morgan');
|
||||||
var colors = require('colors');
|
var colors = require('colors');
|
||||||
var argv = require('optimist').argv;
|
var argv = require('optimist').argv;
|
||||||
var portfinder = require('portfinder');
|
var portfinder = require('portfinder');
|
||||||
|
var path = require('path');
|
||||||
var logger, port;
|
var logger, port;
|
||||||
var log = console.log;
|
var log = console.log;
|
||||||
|
|
||||||
|
@ -34,9 +35,9 @@ function allowCrossDomain(req, res, next) {
|
||||||
function listen(port) {
|
function listen(port) {
|
||||||
var server = express();
|
var server = express();
|
||||||
server.use(allowCrossDomain);
|
server.use(allowCrossDomain);
|
||||||
server.use(serveStatic(__dirname + "../../"));
|
server.use(serveStatic(path.resolve(__dirname, '../')));
|
||||||
|
|
||||||
if(!logger) server.use(morgan(logger))
|
if(!logger) server.use(morgan('dev'))
|
||||||
|
|
||||||
server.listen(port);
|
server.listen(port);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue