epubjs
Version:
Parse and Render Epubs
698 lines (567 loc) • 18.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _core = require("../../utils/core");
var _default = require("../default");
var _default2 = _interopRequireDefault(_default);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var ContinuousViewManager = function (_DefaultViewManager) {
_inherits(ContinuousViewManager, _DefaultViewManager);
function ContinuousViewManager(options) {
_classCallCheck(this, ContinuousViewManager);
// DefaultViewManager.apply(this, arguments); // call super constructor.
var _this = _possibleConstructorReturn(this, (ContinuousViewManager.__proto__ || Object.getPrototypeOf(ContinuousViewManager)).call(this, options));
_this.name = "continuous";
_this.settings = (0, _core.extend)(_this.settings || {}, {
infinite: true,
overflow: "auto",
axis: "vertical",
offset: 500,
offsetDelta: 250,
width: undefined,
height: undefined
});
(0, _core.extend)(_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.viewSettings.axis = this.settings.axis;
_this.viewSettings = {
ignoreClass: _this.settings.ignoreClass,
axis: _this.settings.axis,
layout: _this.layout,
width: 0,
height: 0
};
_this.scrollTop = 0;
_this.scrollLeft = 0;
return _this;
}
_createClass(ContinuousViewManager, [{
key: "display",
value: function display(section, target) {
return _default2.default.prototype.display.call(this, section, target).then(function () {
return this.fill();
}.bind(this));
}
}, {
key: "fill",
value: function fill(_full) {
var full = _full || new _core.defer();
this.check().then(function (result) {
if (result) {
this.fill(full);
} else {
full.resolve();
}
}.bind(this));
return full.promise;
}
}, {
key: "moveTo",
value: function moveTo(offset) {
// var bounds = this.stage.bounds();
// var dist = Math.floor(offset.top / bounds.height) * bounds.height;
var distX = 0,
distY = 0;
var offsetX = 0,
offsetY = 0;
if (this.settings.axis === "vertical") {
distY = offset.top;
offsetY = offset.top + this.settings.offset;
} else {
distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
offsetX = distX + this.settings.offset;
}
return this.check(offsetX, offsetY).then(function () {
this.scrollBy(distX, distY);
}.bind(this));
}
/*
afterDisplayed(currView){
var next = currView.section.next();
var prev = currView.section.prev();
var index = this.views.indexOf(currView);
var prevView, nextView;
if(index + 1 === this.views.length && next) {
nextView = this.createView(next);
this.q.enqueue(this.append.bind(this), nextView);
}
if(index === 0 && prev) {
prevView = this.createView(prev, this.viewSettings);
this.q.enqueue(this.prepend.bind(this), prevView);
}
// this.removeShownListeners(currView);
// currView.onShown = this.afterDisplayed.bind(this);
this.emit("added", currView.section);
}
*/
}, {
key: "resize",
value: function resize(width, height) {
// Clear the queue
this.q.clear();
this._stageSize = this.stage.size(width, height);
this._bounds = this.bounds();
// Update for new views
this.viewSettings.width = this._stageSize.width;
this.viewSettings.height = this._stageSize.height;
// Update for existing views
this.views.each(function (view) {
view.size(this._stageSize.width, this._stageSize.height);
}.bind(this));
this.updateLayout();
// if(this.location) {
// this.rendition.display(this.location.start);
// }
this.emit("resized", {
width: this.stage.width,
height: this.stage.height
});
}
}, {
key: "onResized",
value: function onResized(e) {
// this.views.clear();
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(function () {
this.resize();
}.bind(this), 150);
}
}, {
key: "afterResized",
value: function afterResized(view) {
this.emit("resize", view.section);
}
// Remove Previous Listeners if present
}, {
key: "removeShownListeners",
value: function removeShownListeners(view) {
// view.off("shown", this.afterDisplayed);
// view.off("shown", this.afterDisplayedAbove);
view.onDisplayed = function () {};
}
// append(section){
// return this.q.enqueue(function() {
//
// this._append(section);
//
//
// }.bind(this));
// };
//
// prepend(section){
// return this.q.enqueue(function() {
//
// this._prepend(section);
//
// }.bind(this));
//
// };
}, {
key: "append",
value: function append(section) {
var view = this.createView(section);
this.views.append(view);
view.onDisplayed = this.afterDisplayed.bind(this);
return view;
}
}, {
key: "prepend",
value: function prepend(section) {
var view = this.createView(section);
view.on("resized", this.counter.bind(this));
this.views.prepend(view);
view.onDisplayed = this.afterDisplayed.bind(this);
return view;
}
}, {
key: "counter",
value: function counter(bounds) {
if (this.settings.axis === "vertical") {
this.scrollBy(0, bounds.heightDelta, true);
} else {
this.scrollBy(bounds.widthDelta, 0, true);
}
}
}, {
key: "update",
value: function update(_offset) {
var container = this.bounds();
var views = this.views.all();
var viewsLength = views.length;
var visible = [];
var offset = typeof _offset != "undefined" ? _offset : this.settings.offset || 0;
var isVisible;
var view;
var updating = new _core.defer();
var promises = [];
for (var i = 0; i < viewsLength; i++) {
view = views[i];
isVisible = this.isVisible(view, offset, offset, container);
if (isVisible === true) {
if (!view.displayed) {
promises.push(view.display(this.request).then(function (view) {
view.show();
}));
}
visible.push(view);
} else {
this.q.enqueue(view.destroy.bind(view));
clearTimeout(this.trimTimeout);
this.trimTimeout = setTimeout(function () {
this.q.enqueue(this.trim.bind(this));
}.bind(this), 250);
}
}
if (promises.length) {
return Promise.all(promises);
} else {
updating.resolve();
return updating.promise;
}
}
}, {
key: "check",
value: function check(_offsetLeft, _offsetTop) {
var last, first, next, prev;
var checking = new _core.defer();
var newViews = [];
var horizontal = this.settings.axis === "horizontal";
var delta = this.settings.offset || 0;
if (_offsetLeft && horizontal) {
delta = _offsetLeft;
}
if (_offsetTop && !horizontal) {
delta = _offsetTop;
}
var bounds = this._bounds; // bounds saved this until resize
var offset = horizontal ? this.scrollLeft : this.scrollTop;
var visibleLength = horizontal ? bounds.width : bounds.height;
var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
if (offset + visibleLength + delta >= contentLength) {
last = this.views.last();
next = last && last.section.next();
if (next) {
newViews.push(this.append(next));
}
}
if (offset - delta < 0) {
first = this.views.first();
prev = first && first.section.prev();
if (prev) {
newViews.push(this.prepend(prev));
}
}
if (newViews.length) {
// Promise.all(promises)
// .then(function() {
// Check to see if anything new is on screen after rendering
return this.q.enqueue(function () {
return this.update(delta);
}.bind(this));
// }.bind(this));
} else {
checking.resolve(false);
return checking.promise;
}
}
}, {
key: "trim",
value: function trim() {
var task = new _core.defer();
var displayed = this.views.displayed();
var first = displayed[0];
var last = displayed[displayed.length - 1];
var firstIndex = this.views.indexOf(first);
var lastIndex = this.views.indexOf(last);
var above = this.views.slice(0, firstIndex);
var below = this.views.slice(lastIndex + 1);
// Erase all but last above
for (var i = 0; i < above.length - 1; i++) {
this.erase(above[i], above);
}
// Erase all except first below
for (var j = 1; j < below.length; j++) {
this.erase(below[j]);
}
task.resolve();
return task.promise;
}
}, {
key: "erase",
value: function erase(view, above) {
//Trim
var prevTop;
var prevLeft;
if (this.settings.height) {
prevTop = this.container.scrollTop;
prevLeft = this.container.scrollLeft;
} else {
prevTop = window.scrollY;
prevLeft = window.scrollX;
}
var bounds = view.bounds();
this.views.remove(view);
if (above) {
if (this.settings.axis === "vertical") {
this.scrollTo(0, prevTop - bounds.height, true);
} else {
this.scrollTo(prevLeft - bounds.width, 0, true);
}
}
}
}, {
key: "addEventListeners",
value: function addEventListeners(stage) {
window.addEventListener("unload", function (e) {
this.ignore = true;
// this.scrollTo(0,0);
this.destroy();
}.bind(this));
this.addScrollListeners();
}
}, {
key: "addScrollListeners",
value: function addScrollListeners() {
var scroller;
this.tick = _core.requestAnimationFrame;
if (this.settings.height) {
this.prevScrollTop = this.container.scrollTop;
this.prevScrollLeft = this.container.scrollLeft;
} else {
this.prevScrollTop = window.scrollY;
this.prevScrollLeft = window.scrollX;
}
this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0;
if (this.settings.height) {
scroller = this.container;
this.scrollTop = this.container.scrollTop;
this.scrollLeft = this.container.scrollLeft;
} else {
scroller = window;
this.scrollTop = window.scrollY;
this.scrollLeft = window.scrollX;
}
scroller.addEventListener("scroll", this.onScroll.bind(this));
// this.tick.call(window, this.onScroll.bind(this));
this.scrolled = false;
}
}, {
key: "onScroll",
value: function onScroll() {
var scrollTop = void 0;
var scrollLeft = void 0;
// if(!this.ignore) {
if (this.settings.height) {
scrollTop = this.container.scrollTop;
scrollLeft = this.container.scrollLeft;
} else {
scrollTop = window.scrollY;
scrollLeft = window.scrollX;
}
this.scrollTop = scrollTop;
this.scrollLeft = scrollLeft;
if (!this.ignore) {
if (this.scrollDeltaVert === 0 && this.scrollDeltaHorz === 0 || this.scrollDeltaVert > this.settings.offsetDelta || this.scrollDeltaHorz > this.settings.offsetDelta) {
this.q.enqueue(function () {
this.check();
}.bind(this));
// this.check();
this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0;
this.emit("scroll", {
top: scrollTop,
left: scrollLeft
});
clearTimeout(this.afterScrolled);
this.afterScrolled = setTimeout(function () {
this.emit("scrolled", {
top: this.scrollTop,
left: this.scrollLeft
});
}.bind(this));
}
} else {
this.ignore = false;
}
this.scrollDeltaVert += Math.abs(scrollTop - this.prevScrollTop);
this.scrollDeltaHorz += Math.abs(scrollLeft - this.prevScrollLeft);
this.prevScrollTop = scrollTop;
this.prevScrollLeft = scrollLeft;
clearTimeout(this.scrollTimeout);
this.scrollTimeout = setTimeout(function () {
this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0;
}.bind(this), 150);
this.scrolled = false;
// }
// this.tick.call(window, this.onScroll.bind(this));
}
// resizeView(view) {
//
// if(this.settings.axis === "horizontal") {
// view.lock("height", this.stage.width, this.stage.height);
// } else {
// view.lock("width", this.stage.width, this.stage.height);
// }
//
// };
}, {
key: "currentLocation",
value: function currentLocation() {
if (this.settings.axis === "vertical") {
this.location = this.scrolledLocation();
} else {
this.location = this.paginatedLocation();
}
return this.location;
}
}, {
key: "scrolledLocation",
value: function scrolledLocation() {
var visible = this.visible();
var startPage, endPage;
// var container = this.container.getBoundingClientRect();
if (visible.length === 1) {
return this.mapping.page(visible[0].contents, visible[0].section.cfiBase);
}
if (visible.length > 1) {
startPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase);
endPage = this.mapping.page(visible[visible.length - 1].contents, visible[visible.length - 1].section.cfiBase);
return {
start: startPage.start,
end: endPage.end
};
}
}
}, {
key: "paginatedLocation",
value: function paginatedLocation() {
var visible = this.visible();
var startA, startB, endA, endB;
var pageLeft, pageRight;
var container = this.container.getBoundingClientRect();
if (visible.length === 1) {
startA = container.left - visible[0].position().left;
endA = startA + this.layout.spreadWidth;
return this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);
}
if (visible.length > 1) {
// Left Col
startA = container.left - visible[0].position().left;
endA = startA + this.layout.columnWidth;
// Right Col
startB = container.left + this.layout.spreadWidth - visible[visible.length - 1].position().left;
endB = startB + this.layout.columnWidth;
pageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);
pageRight = this.mapping.page(visible[visible.length - 1].contents, visible[visible.length - 1].section.cfiBase, startB, endB);
return {
start: pageLeft.start,
end: pageRight.end
};
}
}
/*
current(what){
var view, top;
var container = this.container.getBoundingClientRect();
var length = this.views.length - 1;
if(this.settings.axis === "horizontal") {
for (var i = length; i >= 0; i--) {
view = this.views[i];
left = view.position().left;
if(left < container.right) {
if(this._current == view) {
break;
}
this._current = view;
break;
}
}
} else {
for (var i = length; i >= 0; i--) {
view = this.views[i];
top = view.bounds().top;
if(top < container.bottom) {
if(this._current == view) {
break;
}
this._current = view;
break;
}
}
}
return this._current;
}
*/
}, {
key: "updateLayout",
value: function updateLayout() {
if (!this.stage) {
return;
}
if (this.settings.axis === "vertical") {
this.layout.calculate(this._stageSize.width, this._stageSize.height);
} else {
this.layout.calculate(this._stageSize.width, this._stageSize.height, this.settings.gap);
// Set the look ahead offset for what is visible
this.settings.offset = this.layout.delta;
this.stage.addStyleRules("iframe", [{ "margin-right": this.layout.gap + "px" }]);
}
// Set the dimensions for views
this.viewSettings.width = this.layout.width;
this.viewSettings.height = this.layout.height;
this.setLayout(this.layout);
}
}, {
key: "next",
value: function next() {
if (this.settings.axis === "horizontal") {
this.scrollLeft = this.container.scrollLeft;
if (this.container.scrollLeft + this.container.offsetWidth + this.layout.delta < this.container.scrollWidth) {
this.scrollBy(this.layout.delta, 0);
} else {
this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);
}
} else {
this.scrollBy(0, this.layout.height);
}
}
}, {
key: "prev",
value: function prev() {
if (this.settings.axis === "horizontal") {
this.scrollBy(-this.layout.delta, 0);
} else {
this.scrollBy(0, -this.layout.height);
}
}
}, {
key: "updateFlow",
value: function updateFlow(flow) {
var axis = flow === "paginated" ? "horizontal" : "vertical";
this.settings.axis = axis;
this.viewSettings.axis = axis;
this.settings.overflow = flow === "paginated" ? "hidden" : "auto";
// this.views.each(function(view){
// view.setAxis(axis);
// });
if (this.settings.axis === "vertical") {
this.settings.infinite = true;
} else {
this.settings.infinite = false;
}
}
}]);
return ContinuousViewManager;
}(_default2.default);
exports.default = ContinuousViewManager;
module.exports = exports["default"];