mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
Added fixed layout scaling, manager queue
This commit is contained in:
parent
7c135b2152
commit
0d8deb5991
14 changed files with 436 additions and 1781 deletions
1097
dist/epub.js
vendored
1097
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
|
@ -118,15 +118,14 @@
|
||||||
<div id="next" class="arrow">›</div>
|
<div id="next" class="arrow">›</div>
|
||||||
<script>
|
<script>
|
||||||
// Load the opf
|
// Load the opf
|
||||||
// var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
|
var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
|
||||||
var book = ePub("../books/alice/OPS/package.opf");
|
|
||||||
var rendition = book.renderTo("viewer", {
|
var rendition = book.renderTo("viewer", {
|
||||||
manager: "paginate",
|
manager: "paginate",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 600
|
height: 600
|
||||||
});
|
});
|
||||||
|
|
||||||
var displayed = rendition.display(3);
|
var displayed = rendition.display(6);
|
||||||
|
|
||||||
|
|
||||||
displayed.then(function(renderer){
|
displayed.then(function(renderer){
|
||||||
|
|
|
@ -95,6 +95,7 @@ Contents.prototype.textWidth = function() {
|
||||||
|
|
||||||
// get the width of the text content
|
// get the width of the text content
|
||||||
width = range.getBoundingClientRect().width;
|
width = range.getBoundingClientRect().width;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -155,16 +156,16 @@ Contents.prototype.viewport = function() {
|
||||||
content = $viewport.getAttribute("content");
|
content = $viewport.getAttribute("content");
|
||||||
contents = content.split(',');
|
contents = content.split(',');
|
||||||
if(contents[0]){
|
if(contents[0]){
|
||||||
width = contents[0].replace("width=", '');
|
width = contents[0].replace("width=", '').trim();
|
||||||
}
|
}
|
||||||
if(contents[1]){
|
if(contents[1]){
|
||||||
height = contents[1].replace("height=", '');
|
height = contents[1].replace("height=", '').trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: width,
|
width: parseInt(width),
|
||||||
height: height
|
height: parseInt(height)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
102
src/layout.js
102
src/layout.js
|
@ -46,11 +46,6 @@ Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){
|
||||||
|
|
||||||
delta = (colWidth + gap) * divisor;
|
delta = (colWidth + gap) * divisor;
|
||||||
|
|
||||||
this.columnAxis = core.prefixed('columnAxis');
|
|
||||||
this.columnGap = core.prefixed('columnGap');
|
|
||||||
this.columnWidth = core.prefixed('columnWidth');
|
|
||||||
this.columnFill = core.prefixed('columnFill');
|
|
||||||
|
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = _height;
|
this.height = _height;
|
||||||
this.spread = spreadWidth;
|
this.spread = spreadWidth;
|
||||||
|
@ -109,53 +104,88 @@ Reflowable.prototype.count = function(totalWidth) {
|
||||||
function Fixed(_width, _height){
|
function Fixed(_width, _height){
|
||||||
this.width = 0;
|
this.width = 0;
|
||||||
this.height = 0;
|
this.height = 0;
|
||||||
|
this.spread = 0;
|
||||||
|
this.delta = 0;
|
||||||
|
|
||||||
|
this.column = 0;
|
||||||
|
this.gap = 0;
|
||||||
|
this.divisor = 0;
|
||||||
|
|
||||||
this.name = "pre-paginated";
|
this.name = "pre-paginated";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Fixed.prototype.calculate = function(_width, _height){
|
Fixed.prototype.calculate = function(_width, _height, _gap, _devisor){
|
||||||
this.width = _width;
|
var divisor = _devisor || 1;
|
||||||
|
var section = Math.floor(_width / 8);
|
||||||
|
var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);
|
||||||
|
|
||||||
|
|
||||||
|
var colWidth;
|
||||||
|
var spreadWidth;
|
||||||
|
var delta;
|
||||||
|
|
||||||
|
//-- Double Page
|
||||||
|
if(divisor > 1) {
|
||||||
|
colWidth = Math.floor((_width - gap) / divisor);
|
||||||
|
} else {
|
||||||
|
colWidth = _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
spreadWidth = colWidth * divisor;
|
||||||
|
|
||||||
|
delta = (colWidth + gap) * divisor;
|
||||||
|
|
||||||
|
this.width = colWidth;
|
||||||
this.height = _height;
|
this.height = _height;
|
||||||
|
this.spread = spreadWidth;
|
||||||
|
this.delta = delta;
|
||||||
|
|
||||||
|
this.column = colWidth;
|
||||||
|
this.gap = gap;
|
||||||
|
this.divisor = divisor;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Fixed.prototype.format = function(contents){
|
Fixed.prototype.format = function(contents){
|
||||||
var promises = [];
|
var promises = [];
|
||||||
var viewport = contents.viewport();
|
var viewport = contents.viewport();
|
||||||
// var width, height;
|
|
||||||
//
|
|
||||||
// var $doc = doc.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=", '');
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//-- Adjust width and height
|
var width = viewport.width;
|
||||||
// $doc.style.width = width + "px" || "auto";
|
var height = viewport.height;
|
||||||
// $doc.style.height = height + "px" || "auto";
|
var widthScale = this.column / width;
|
||||||
if (viewport.width) {
|
var heightScale = this.height / height;
|
||||||
promises.push(contents.width(viewport.width));
|
var scale = widthScale < heightScale ? widthScale : heightScale;
|
||||||
}
|
|
||||||
|
|
||||||
if (viewport.height) {
|
var offsetX = (this.width - (width * scale)) / 2;
|
||||||
promises.push(contents.height(viewport.height));
|
var offsetY = (this.height - (height * scale)) / 2;
|
||||||
}
|
|
||||||
|
promises.push(contents.width(this.width));
|
||||||
|
promises.push(contents.height(this.height));
|
||||||
|
|
||||||
|
promises.push(contents.css("position", "absolute"));
|
||||||
|
promises.push(contents.css("transform", "scale(" + scale + ")"));
|
||||||
|
|
||||||
|
promises.push(contents.overflow("hidden"));
|
||||||
|
|
||||||
|
promises.push(contents.css("transformOrigin", "top left"));
|
||||||
|
|
||||||
|
promises.push(contents.css("backgroundColor", "transparent"));
|
||||||
|
|
||||||
|
promises.push(contents.css("marginTop", offsetY + "px"));
|
||||||
|
// promises.push(contents.css("marginLeft", offsetX + "px"));
|
||||||
|
|
||||||
|
|
||||||
|
// page.style.transformOrigin = "top left";
|
||||||
|
// if (!view.offsetRight) {
|
||||||
|
// page.style.transformOrigin = "top right";
|
||||||
|
// page.style.right = 0;
|
||||||
|
// page.style.left = "auto";
|
||||||
|
// }
|
||||||
|
|
||||||
//-- Scroll
|
//-- Scroll
|
||||||
// $doc.style.overflow = "auto";
|
// $doc.style.overflow = "auto";
|
||||||
promises.push(contents.overflow("auto"));
|
// promises.push(contents.overflow("auto"));
|
||||||
|
|
||||||
return RSVP.all(promises);
|
return RSVP.all(promises);
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,35 @@ function ContinuousViewManager(options) {
|
||||||
});
|
});
|
||||||
|
|
||||||
core.defaults(this.settings, options.settings || {});
|
core.defaults(this.settings, options.settings || {});
|
||||||
// core.extend(this.settings, options.settings || {});
|
|
||||||
|
this.scrollTop = 0;
|
||||||
|
this.scrollLeft = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// subclass extends superclass
|
// subclass extends superclass
|
||||||
ContinuousViewManager.prototype = Object.create(SingleViewManager.prototype);
|
ContinuousViewManager.prototype = Object.create(SingleViewManager.prototype);
|
||||||
ContinuousViewManager.prototype.constructor = ContinuousViewManager;
|
ContinuousViewManager.prototype.constructor = ContinuousViewManager;
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype.display = function(section, target){
|
||||||
|
return SingleViewManager.prototype.display.call(this, section, target)
|
||||||
|
.then(function () {
|
||||||
|
return this.fill();
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype.fill = function(_full){
|
||||||
|
var full = _full || new RSVP.defer();
|
||||||
|
|
||||||
|
this.check().then(function(result) {
|
||||||
|
if (result) {
|
||||||
|
this.fill(full);
|
||||||
|
} else {
|
||||||
|
full.resolve();
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return full.promise;
|
||||||
|
}
|
||||||
|
|
||||||
ContinuousViewManager.prototype.moveTo = function(offset){
|
ContinuousViewManager.prototype.moveTo = function(offset){
|
||||||
// var bounds = this.stage.bounds();
|
// var bounds = this.stage.bounds();
|
||||||
|
@ -75,31 +97,38 @@ ContinuousViewManager.prototype.removeShownListeners = function(view){
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.append = function(section){
|
|
||||||
var view = this.createView(section);
|
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype.append = function(section){
|
||||||
return this.q.enqueue(function() {
|
return this.q.enqueue(function() {
|
||||||
|
|
||||||
this.views.append(view);
|
this._append(section);
|
||||||
|
|
||||||
// return this.update();
|
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.prepend = function(section){
|
ContinuousViewManager.prototype.prepend = function(section){
|
||||||
|
return this.q.enqueue(function() {
|
||||||
|
|
||||||
|
this._prepend(section);
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype._append = function(section){
|
||||||
|
var view = this.createView(section);
|
||||||
|
this.views.append(view);
|
||||||
|
return view;
|
||||||
|
};
|
||||||
|
|
||||||
|
ContinuousViewManager.prototype._prepend = function(section){
|
||||||
var view = this.createView(section);
|
var view = this.createView(section);
|
||||||
|
|
||||||
view.on("resized", this.counter.bind(this));
|
view.on("resized", this.counter.bind(this));
|
||||||
|
|
||||||
return this.q.enqueue(function() {
|
|
||||||
|
|
||||||
this.views.prepend(view);
|
this.views.prepend(view);
|
||||||
|
return view;
|
||||||
// return this.update();
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.counter = function(bounds){
|
ContinuousViewManager.prototype.counter = function(bounds){
|
||||||
|
@ -169,7 +198,7 @@ ContinuousViewManager.prototype.update = function(_offset){
|
||||||
var views = this.views.all();
|
var views = this.views.all();
|
||||||
var viewsLength = views.length;
|
var viewsLength = views.length;
|
||||||
var visible = [];
|
var visible = [];
|
||||||
var offset = _offset || this.settings.offset || 0;
|
var offset = typeof _offset != "undefined" ? _offset : (this.settings.offset || 0);
|
||||||
var isVisible;
|
var isVisible;
|
||||||
var view;
|
var view;
|
||||||
|
|
||||||
|
@ -182,7 +211,9 @@ ContinuousViewManager.prototype.update = function(_offset){
|
||||||
isVisible = this.isVisible(view, offset, offset, container);
|
isVisible = this.isVisible(view, offset, offset, container);
|
||||||
|
|
||||||
if(isVisible === true) {
|
if(isVisible === true) {
|
||||||
|
if (!view.displayed) {
|
||||||
promises.push(view.display(this.request));
|
promises.push(view.display(this.request));
|
||||||
|
}
|
||||||
visible.push(view);
|
visible.push(view);
|
||||||
} else {
|
} else {
|
||||||
this.q.enqueue(view.destroy.bind(view));
|
this.q.enqueue(view.destroy.bind(view));
|
||||||
|
@ -205,7 +236,11 @@ ContinuousViewManager.prototype.update = function(_offset){
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){
|
ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){
|
||||||
var next, prev;
|
var last, first, next, prev;
|
||||||
|
|
||||||
|
var checking = new RSVP.defer();
|
||||||
|
var newViews = [];
|
||||||
|
|
||||||
var horizontal = (this.settings.axis === "horizontal");
|
var horizontal = (this.settings.axis === "horizontal");
|
||||||
var delta = this.settings.offset || 0;
|
var delta = this.settings.offset || 0;
|
||||||
|
|
||||||
|
@ -217,43 +252,46 @@ ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){
|
||||||
delta = _offsetTop;
|
delta = _offsetTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bounds = this._bounds; //this.bounds(); // bounds saved this until resize
|
var bounds = this._bounds; // bounds saved this until resize
|
||||||
|
|
||||||
var offset = horizontal ? this.scrollLeft : this.scrollTop;
|
var offset = horizontal ? this.scrollLeft : this.scrollTop;
|
||||||
var visibleLength = horizontal ? bounds.width : bounds.height;
|
var visibleLength = horizontal ? bounds.width : bounds.height;
|
||||||
var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
|
var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
|
||||||
|
|
||||||
var checking = new RSVP.defer();
|
|
||||||
var promises = [];
|
|
||||||
|
|
||||||
if (offset + visibleLength + delta >= contentLength) {
|
if (offset + visibleLength + delta >= contentLength) {
|
||||||
next = this.views.last().section.next();
|
last = this.views.last();
|
||||||
|
next = last && last.section.next();
|
||||||
if(next) {
|
if(next) {
|
||||||
promises.push(this.append(next));
|
newViews.push(this._append(next));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset - delta < 0 ) {
|
if (offset - delta < 0 ) {
|
||||||
prev = this.views.first().section.prev();
|
first = this.views.first();
|
||||||
|
prev = first && first.section.prev();
|
||||||
if(prev) {
|
if(prev) {
|
||||||
promises.push(this.prepend(prev));
|
newViews.push(this._prepend(prev));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(promises.length){
|
if(newViews.length){
|
||||||
return RSVP.all(promises)
|
// RSVP.all(promises)
|
||||||
.then(function(posts) {
|
// .then(function() {
|
||||||
// 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.update.bind(this));
|
return this.q.enqueue(function(){
|
||||||
// this.update(offset);
|
return this.update(delta);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
} else {
|
|
||||||
checking.resolve();
|
|
||||||
|
|
||||||
|
// }.bind(this));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
checking.resolve(false);
|
||||||
return checking.promise;
|
return checking.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.trim = function(){
|
ContinuousViewManager.prototype.trim = function(){
|
||||||
|
@ -309,6 +347,13 @@ ContinuousViewManager.prototype.erase = function(view, above){ //Trim
|
||||||
};
|
};
|
||||||
|
|
||||||
ContinuousViewManager.prototype.addEventListeners = function(stage){
|
ContinuousViewManager.prototype.addEventListeners = function(stage){
|
||||||
|
|
||||||
|
window.addEventListener('unload', function(e){
|
||||||
|
this.ignore = true;
|
||||||
|
// this.scrollTo(0,0);
|
||||||
|
this.destroy();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
this.addScrollListeners();
|
this.addScrollListeners();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -340,11 +385,6 @@ ContinuousViewManager.prototype.addScrollListeners = function() {
|
||||||
|
|
||||||
scroller.addEventListener("scroll", this.onScroll.bind(this));
|
scroller.addEventListener("scroll", this.onScroll.bind(this));
|
||||||
|
|
||||||
window.addEventListener('unload', function(e){
|
|
||||||
this.ignore = true;
|
|
||||||
this.destroy();
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
// this.tick.call(window, this.onScroll.bind(this));
|
// this.tick.call(window, this.onScroll.bind(this));
|
||||||
|
|
||||||
this.scrolled = false;
|
this.scrolled = false;
|
||||||
|
@ -373,8 +413,10 @@ ContinuousViewManager.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.bind(this));
|
this.q.enqueue(function() {
|
||||||
this.check();
|
this.check();
|
||||||
|
}.bind(this));
|
||||||
|
// this.check();
|
||||||
|
|
||||||
this.scrollDeltaVert = 0;
|
this.scrollDeltaVert = 0;
|
||||||
this.scrollDeltaHorz = 0;
|
this.scrollDeltaHorz = 0;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
var RSVP = require('rsvp');
|
var RSVP = require('rsvp');
|
||||||
var core = require('../core');
|
var core = require('../core');
|
||||||
var ContinuousViewManager = require('./continuous');
|
var ContinuousViewManager = require('./continuous');
|
||||||
var Map = require('../map');
|
var Mapping = require('../map');
|
||||||
var Layout = require('../layout');
|
var Layout = require('../layout');
|
||||||
|
|
||||||
function PaginatedViewManager(options) {
|
function PaginatedViewManager(options) {
|
||||||
|
@ -21,11 +21,15 @@ function PaginatedViewManager(options) {
|
||||||
|
|
||||||
core.defaults(this.settings, options.settings || {});
|
core.defaults(this.settings, options.settings || {});
|
||||||
|
|
||||||
|
// Gap can be 0, byt defaults doesn't handle that
|
||||||
|
if (options.settings.gap != "undefined" && options.settings.gap === 0) {
|
||||||
|
this.settings.gap = options.settings.gap;
|
||||||
|
}
|
||||||
|
|
||||||
this.isForcedSingle = this.settings.forceSingle;
|
this.isForcedSingle = this.settings.forceSingle;
|
||||||
|
|
||||||
this.viewSettings.axis = this.settings.axis;
|
this.viewSettings.axis = this.settings.axis;
|
||||||
|
|
||||||
// this.start();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PaginatedViewManager.prototype = Object.create(ContinuousViewManager.prototype);
|
PaginatedViewManager.prototype = Object.create(ContinuousViewManager.prototype);
|
||||||
|
@ -52,7 +56,7 @@ PaginatedViewManager.prototype.forceSingle = function(bool){
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PaginatedViewManager.prototype.addEventListeners = 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);
|
||||||
|
@ -63,21 +67,21 @@ PaginatedViewManager.prototype.addEventListeners = function(){
|
||||||
|
|
||||||
// this.hooks.content.register(this.adjustImages.bind(this));
|
// this.hooks.content.register(this.adjustImages.bind(this));
|
||||||
|
|
||||||
this.currentPage = 0;
|
// this.currentPage = 0;
|
||||||
|
|
||||||
window.addEventListener('unload', function(e){
|
// window.addEventListener('unload', function(e){
|
||||||
this.ignore = true;
|
// this.ignore = true;
|
||||||
this.destroy();
|
// this.destroy();
|
||||||
}.bind(this));
|
// }.bind(this));
|
||||||
|
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
|
||||||
PaginatedViewManager.prototype.applyLayoutMethod = function() {
|
PaginatedViewManager.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);
|
||||||
|
console.log(this.settings.globalLayoutProperties);
|
||||||
this.layout = new Layout.Reflowable();
|
this.layout = new Layout.Reflowable();
|
||||||
|
|
||||||
this.updateLayout();
|
this.updateLayout();
|
||||||
|
@ -87,9 +91,9 @@ PaginatedViewManager.prototype.applyLayoutMethod = function() {
|
||||||
this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]);
|
this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]);
|
||||||
|
|
||||||
// Set the look ahead offset for what is visible
|
// Set the look ahead offset for what is visible
|
||||||
this.settings.offeset = this.layout.delta;
|
this.settings.offset = this.layout.delta;
|
||||||
|
|
||||||
this.mapping = new Map(this.layout);
|
this.mapping = new Mapping(this.layout);
|
||||||
|
|
||||||
// this.hooks.layout.register(this.layout.format.bind(this));
|
// this.hooks.layout.register(this.layout.format.bind(this));
|
||||||
|
|
||||||
|
@ -139,15 +143,14 @@ PaginatedViewManager.prototype.next = function(){
|
||||||
this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);
|
this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);
|
||||||
}
|
}
|
||||||
// this.reportLocation();
|
// this.reportLocation();
|
||||||
this.check();
|
// this.check();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PaginatedViewManager.prototype.prev = function(){
|
PaginatedViewManager.prototype.prev = function(){
|
||||||
|
|
||||||
this.scrollBy(-this.layout.delta, 0);
|
this.scrollBy(-this.layout.delta, 0);
|
||||||
// this.reportLocation();
|
// this.reportLocation();
|
||||||
this.check();
|
// this.check();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -221,8 +224,6 @@ PaginatedViewManager.prototype.onResized = function(e) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Paginate.prototype.display = function(what){
|
|
||||||
// return this.display(what);
|
|
||||||
// };
|
|
||||||
|
|
||||||
module.exports = PaginatedViewManager;
|
module.exports = PaginatedViewManager;
|
||||||
|
|
|
@ -5,12 +5,14 @@ var Views = require('../views');
|
||||||
var EpubCFI = require('../epubcfi');
|
var EpubCFI = require('../epubcfi');
|
||||||
var Layout = require('../layout');
|
var Layout = require('../layout');
|
||||||
var Mapping = require('../map');
|
var Mapping = require('../map');
|
||||||
|
var Queue = require('../queue');
|
||||||
|
|
||||||
function SingleViewManager(options) {
|
function SingleViewManager(options) {
|
||||||
|
|
||||||
this.View = options.view;
|
this.View = options.view;
|
||||||
this.request = options.request;
|
this.request = options.request;
|
||||||
this.q = options.queue;
|
this.renditionQueue = options.queue;
|
||||||
|
this.q = new Queue(this);
|
||||||
|
|
||||||
this.settings = core.extend(this.settings || {}, {
|
this.settings = core.extend(this.settings || {}, {
|
||||||
infinite: true,
|
infinite: true,
|
||||||
|
@ -75,7 +77,15 @@ SingleViewManager.prototype.render = function(element, size){
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.addEventListeners = function(){
|
SingleViewManager.prototype.addEventListeners = function(){
|
||||||
|
window.addEventListener('unload', function(e){
|
||||||
|
this.destroy();
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
SingleViewManager.prototype.destroy = function(){
|
||||||
|
// this.views.each(function(view){
|
||||||
|
// view.destroy();
|
||||||
|
// });
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.onResized = function(e) {
|
SingleViewManager.prototype.onResized = function(e) {
|
||||||
|
@ -143,7 +153,7 @@ SingleViewManager.prototype.display = function(section, target){
|
||||||
// Create a new view
|
// Create a new view
|
||||||
view = this.createView(section);
|
view = this.createView(section);
|
||||||
|
|
||||||
return this.add(view)
|
this.add(view)
|
||||||
.then(function(){
|
.then(function(){
|
||||||
|
|
||||||
// Move to correct place within the section, if needed
|
// Move to correct place within the section, if needed
|
||||||
|
@ -152,14 +162,18 @@ SingleViewManager.prototype.display = function(section, target){
|
||||||
this.moveTo(offset);
|
this.moveTo(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.views.show();
|
||||||
|
|
||||||
|
displaying.resolve();
|
||||||
|
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
// .then(function(){
|
// .then(function(){
|
||||||
// return this.hooks.display.trigger(view);
|
// return this.hooks.display.trigger(view);
|
||||||
// }.bind(this))
|
// }.bind(this))
|
||||||
.then(function(){
|
// .then(function(){
|
||||||
this.views.show();
|
// this.views.show();
|
||||||
}.bind(this));
|
// }.bind(this));
|
||||||
|
return displayed;
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.afterDisplayed = function(view){
|
SingleViewManager.prototype.afterDisplayed = function(view){
|
||||||
|
@ -183,7 +197,7 @@ SingleViewManager.prototype.add = function(view){
|
||||||
view.onResize = this.afterResized.bind(this);
|
view.onResize = this.afterResized.bind(this);
|
||||||
|
|
||||||
return view.display(this.request);
|
return view.display(this.request);
|
||||||
// return this.renderer(view, this.views.hidden);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// SingleViewManager.prototype.resizeView = function(view) {
|
// SingleViewManager.prototype.resizeView = function(view) {
|
||||||
|
@ -278,10 +292,9 @@ SingleViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.visible = function(){
|
SingleViewManager.prototype.visible = function(){
|
||||||
return this.views.displayed();
|
// return this.views.displayed();
|
||||||
/*
|
var container = this.bounds();
|
||||||
var container = this.stage.bounds();
|
var views = this.views.displayed();
|
||||||
var views = this.views;
|
|
||||||
var viewsLength = views.length;
|
var viewsLength = views.length;
|
||||||
var visible = [];
|
var visible = [];
|
||||||
var isVisible;
|
var isVisible;
|
||||||
|
@ -297,7 +310,6 @@ SingleViewManager.prototype.visible = function(){
|
||||||
|
|
||||||
}
|
}
|
||||||
return visible;
|
return visible;
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SingleViewManager.prototype.scrollBy = function(x, y, silent){
|
SingleViewManager.prototype.scrollBy = function(x, y, silent){
|
||||||
|
|
|
@ -10,7 +10,13 @@ Map.prototype.section = function(view) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Map.prototype.page = function(view, start, end) {
|
Map.prototype.page = function(view, start, end) {
|
||||||
var root = view.contents.document.body;
|
var contents = view.contents;
|
||||||
|
var root = contents && contents.document ? contents.document.body : false;
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return this.rangePairToCfiPair(view.section, {
|
return this.rangePairToCfiPair(view.section, {
|
||||||
start: this.findStart(root, start, end),
|
start: this.findStart(root, start, end),
|
||||||
end: this.findEnd(root, start, end)
|
end: this.findEnd(root, start, end)
|
||||||
|
|
|
@ -5,10 +5,9 @@ var replace = require('./replacements');
|
||||||
var Hook = require('./hook');
|
var Hook = require('./hook');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
var Queue = require('./queue');
|
var Queue = require('./queue');
|
||||||
var View = require('./view');
|
// var View = require('./view');
|
||||||
var Views = require('./views');
|
var Views = require('./views');
|
||||||
var Layout = require('./layout');
|
var Layout = require('./layout');
|
||||||
var Map = require('./map');
|
|
||||||
|
|
||||||
function Rendition(book, options) {
|
function Rendition(book, options) {
|
||||||
|
|
||||||
|
@ -112,6 +111,7 @@ Rendition.prototype.start = function(){
|
||||||
this.manager = new this.ViewManager({
|
this.manager = new this.ViewManager({
|
||||||
view: this.View,
|
view: this.View,
|
||||||
queue: this.q,
|
queue: this.q,
|
||||||
|
request: this.book.request,
|
||||||
settings: this.settings
|
settings: this.settings
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -135,14 +135,14 @@ Rendition.prototype.start = function(){
|
||||||
// Container must be attached before rendering can begin
|
// Container must be attached before rendering can begin
|
||||||
Rendition.prototype.attachTo = function(element){
|
Rendition.prototype.attachTo = function(element){
|
||||||
|
|
||||||
|
this.start();
|
||||||
|
|
||||||
// Start rendering
|
// Start rendering
|
||||||
this.manager.render(element, {
|
this.manager.render(element, {
|
||||||
"width" : this.settings.width,
|
"width" : this.settings.width,
|
||||||
"height" : this.settings.height
|
"height" : this.settings.height
|
||||||
});
|
});
|
||||||
|
|
||||||
this.start();
|
|
||||||
|
|
||||||
// Trigger Attached
|
// Trigger Attached
|
||||||
this.trigger("attached");
|
this.trigger("attached");
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ Stage.prototype.size = function(_width, _height){
|
||||||
};
|
};
|
||||||
|
|
||||||
Stage.prototype.bounds = function(){
|
Stage.prototype.bounds = function(){
|
||||||
return this.element.getBoundingClientRect();
|
return this.container.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stage.prototype.getSheet = function(){
|
Stage.prototype.getSheet = function(){
|
||||||
|
|
763
src/view.js
763
src/view.js
|
@ -1,763 +0,0 @@
|
||||||
var RSVP = require('rsvp');
|
|
||||||
var core = require('./core');
|
|
||||||
var EpubCFI = require('./epubcfi');
|
|
||||||
|
|
||||||
function View(section, options) {
|
|
||||||
this.settings = core.extend({
|
|
||||||
ignoreClass : ''
|
|
||||||
}, options || {});
|
|
||||||
|
|
||||||
this.id = "epubjs-view:" + core.uuid();
|
|
||||||
this.section = section;
|
|
||||||
this.index = section.index;
|
|
||||||
|
|
||||||
this.element = document.createElement('div');
|
|
||||||
this.element.classList.add("epub-view");
|
|
||||||
|
|
||||||
|
|
||||||
// this.element.style.minHeight = "100px";
|
|
||||||
this.element.style.height = "0px";
|
|
||||||
this.element.style.width = "0px";
|
|
||||||
this.element.style.overflow = "hidden";
|
|
||||||
|
|
||||||
this.added = false;
|
|
||||||
this.displayed = false;
|
|
||||||
this.rendered = false;
|
|
||||||
|
|
||||||
//this.width = 0;
|
|
||||||
//this.height = 0;
|
|
||||||
|
|
||||||
// Blank Cfi for Parsing
|
|
||||||
this.epubcfi = new EpubCFI();
|
|
||||||
|
|
||||||
if(this.settings.axis && this.settings.axis == "horizontal"){
|
|
||||||
this.element.style.display = "inline-block";
|
|
||||||
} else {
|
|
||||||
this.element.style.display = "block";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dom events to listen for
|
|
||||||
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.create = function() {
|
|
||||||
|
|
||||||
if(this.iframe) {
|
|
||||||
return this.iframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
View.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.layout();
|
|
||||||
this.expand();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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.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.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;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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.document.body.scrollWidth;
|
|
||||||
// Reset iframe size back
|
|
||||||
this.iframe.style.width = prev;
|
|
||||||
return width;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.contentHeight = function(min) {
|
|
||||||
var prev;
|
|
||||||
var height;
|
|
||||||
|
|
||||||
prev = this.iframe.style.height;
|
|
||||||
this.iframe.style.height = (min || 0) + "px";
|
|
||||||
height = this.document.body.scrollHeight;
|
|
||||||
this.iframe.style.height = prev;
|
|
||||||
return height;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.textWidth = function() {
|
|
||||||
var width;
|
|
||||||
var range = this.document.createRange();
|
|
||||||
|
|
||||||
// Select the contents of frame
|
|
||||||
range.selectNodeContents(this.document.body);
|
|
||||||
|
|
||||||
// get the width of the text content
|
|
||||||
width = range.getBoundingClientRect().width;
|
|
||||||
return width;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.textHeight = function() {
|
|
||||||
var height;
|
|
||||||
var range = this.document.createRange();
|
|
||||||
|
|
||||||
range.selectNodeContents(this.document.body);
|
|
||||||
|
|
||||||
height = range.getBoundingClientRect().height;
|
|
||||||
return height;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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));
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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.window = this.iframe.contentWindow;
|
|
||||||
this.document = this.iframe.contentDocument;
|
|
||||||
this.rendering = false;
|
|
||||||
loading.resolve(this);
|
|
||||||
|
|
||||||
}.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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
View.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){
|
|
||||||
layoutFunc(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onLayout(this);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.onLayout = function(view) {
|
|
||||||
// stub
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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();
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.removeListeners = function() {
|
|
||||||
|
|
||||||
this.removeEventListeners();
|
|
||||||
|
|
||||||
this.removeSelectionListeners();
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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
|
|
||||||
View.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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);
|
|
||||||
// };
|
|
||||||
|
|
||||||
View.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.display = function() {
|
|
||||||
var displayed = new RSVP.defer();
|
|
||||||
|
|
||||||
this.displayed = true;
|
|
||||||
|
|
||||||
this.layout();
|
|
||||||
|
|
||||||
this.listeners();
|
|
||||||
|
|
||||||
this.expand();
|
|
||||||
|
|
||||||
this.trigger("displayed", this);
|
|
||||||
this.onDisplayed(this);
|
|
||||||
|
|
||||||
displayed.resolve(this);
|
|
||||||
|
|
||||||
return displayed.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.show = function() {
|
|
||||||
|
|
||||||
this.element.style.visibility = "visible";
|
|
||||||
|
|
||||||
if(this.iframe){
|
|
||||||
this.iframe.style.visibility = "visible";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.trigger("shown", this);
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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);
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.position = function() {
|
|
||||||
return this.element.getBoundingClientRect();
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.onDisplayed = function(view) {
|
|
||||||
// Stub, override with a custom functions
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.bounds = function() {
|
|
||||||
if(!this.elementBounds) {
|
|
||||||
this.elementBounds = core.bounds(this.element);
|
|
||||||
}
|
|
||||||
return this.elementBounds;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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";
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.root = function() {
|
|
||||||
if(!this.document) return null;
|
|
||||||
return this.document.documentElement;
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.locationOf = function(target) {
|
|
||||||
var parentPos = this.iframe.getBoundingClientRect();
|
|
||||||
var targetPos = {"left": 0, "top": 0};
|
|
||||||
|
|
||||||
if(!this.document) return;
|
|
||||||
|
|
||||||
if(this.epubcfi.isCfiString(target)) {
|
|
||||||
range = new EpubCFI(cfi).toRange(this.document, this.settings.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 {
|
|
||||||
"left": window.scrollX + parentPos.left + targetPos.left,
|
|
||||||
"top": window.scrollY + parentPos.top + targetPos.top
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.addCss = 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
|
|
||||||
View.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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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));
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.addEventListeners = function(){
|
|
||||||
if(!this.document) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.listenedEvents.forEach(function(eventName){
|
|
||||||
this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.removeEventListeners = function(){
|
|
||||||
if(!this.document) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.listenedEvents.forEach(function(eventName){
|
|
||||||
this.document.removeEventListener(eventName, this.triggerEvent, false);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Pass browser events
|
|
||||||
View.prototype.triggerEvent = function(e){
|
|
||||||
this.trigger(e.type, e);
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.addSelectionListeners = function(){
|
|
||||||
if(!this.document) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false);
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.removeSelectionListeners = function(){
|
|
||||||
if(!this.document) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.document.removeEventListener("selectionchange", this.onSelectionChange, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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);
|
|
||||||
};
|
|
||||||
|
|
||||||
View.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
View.prototype.range = function(_cfi, ignoreClass){
|
|
||||||
var cfi = new EpubCFI(_cfi);
|
|
||||||
return cfi.toRange(this.document, ignoreClass || this.settings.ignoreClass);
|
|
||||||
};
|
|
||||||
|
|
||||||
RSVP.EventTarget.mixin(View.prototype);
|
|
||||||
|
|
||||||
module.exports = View;
|
|
|
@ -172,10 +172,11 @@ IframeView.prototype.size = function(_width, _height) {
|
||||||
var width = _width || this.settings.width;
|
var width = _width || this.settings.width;
|
||||||
var height = _height || this.settings.height;
|
var height = _height || this.settings.height;
|
||||||
|
|
||||||
if(this.layout.name === "pre-paginated") {
|
// if(this.layout.name === "pre-paginated") {
|
||||||
// TODO: check if these are different than the size set in chapter
|
// // TODO: check if these are different than the size set in chapter
|
||||||
this.lock("both", width, height);
|
// this.lock("both", width, height);
|
||||||
} else if(this.settings.axis === "horizontal") {
|
// } else
|
||||||
|
if(this.settings.axis === "horizontal") {
|
||||||
this.lock("height", width, height);
|
this.lock("height", width, height);
|
||||||
} else {
|
} else {
|
||||||
this.lock("width", width, height);
|
this.lock("width", width, height);
|
||||||
|
@ -332,7 +333,6 @@ IframeView.prototype.reframe = function(width, height) {
|
||||||
// this._needsReframe = true;
|
// this._needsReframe = true;
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if(core.isNumber(width)){
|
if(core.isNumber(width)){
|
||||||
this.element.style.width = width + "px";
|
this.element.style.width = width + "px";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue