summaryrefslogtreecommitdiff
path: root/lib/epub.js/src/managers/default/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/epub.js/src/managers/default/index.js')
-rw-r--r--lib/epub.js/src/managers/default/index.js1073
1 files changed, 1073 insertions, 0 deletions
diff --git a/lib/epub.js/src/managers/default/index.js b/lib/epub.js/src/managers/default/index.js
new file mode 100644
index 0000000..b24a4f6
--- /dev/null
+++ b/lib/epub.js/src/managers/default/index.js
@@ -0,0 +1,1073 @@
+import EventEmitter from "event-emitter";
+import {extend, defer, windowBounds, isNumber} from "../../utils/core";
+import scrollType from "../../utils/scrolltype";
+import Mapping from "../../mapping";
+import Queue from "../../utils/queue";
+import Stage from "../helpers/stage";
+import Views from "../helpers/views";
+import { EVENTS } from "../../utils/constants";
+
+class DefaultViewManager {
+ constructor(options) {
+
+ this.name = "default";
+ this.optsSettings = options.settings;
+ this.View = options.view;
+ this.request = options.request;
+ this.renditionQueue = options.queue;
+ this.q = new Queue(this);
+
+ this.settings = extend(this.settings || {}, {
+ infinite: true,
+ hidden: false,
+ width: undefined,
+ height: undefined,
+ axis: undefined,
+ writingMode: undefined,
+ flow: "scrolled",
+ ignoreClass: "",
+ fullsize: undefined
+ });
+
+ extend(this.settings, options.settings || {});
+
+ this.viewSettings = {
+ ignoreClass: this.settings.ignoreClass,
+ axis: this.settings.axis,
+ flow: this.settings.flow,
+ layout: this.layout,
+ method: this.settings.method, // srcdoc, blobUrl, write
+ width: 0,
+ height: 0,
+ forceEvenPages: true
+ };
+
+ this.rendered = false;
+
+ }
+
+ render(element, size){
+ let tag = element.tagName;
+
+ if (typeof this.settings.fullsize === "undefined" &&
+ tag && (tag.toLowerCase() == "body" ||
+ tag.toLowerCase() == "html")) {
+ this.settings.fullsize = true;
+ }
+
+ if (this.settings.fullsize) {
+ this.settings.overflow = "visible";
+ this.overflow = this.settings.overflow;
+ }
+
+ this.settings.size = size;
+
+ this.settings.rtlScrollType = scrollType();
+
+ // Save the stage
+ this.stage = new Stage({
+ width: size.width,
+ height: size.height,
+ overflow: this.overflow,
+ hidden: this.settings.hidden,
+ axis: this.settings.axis,
+ fullsize: this.settings.fullsize,
+ direction: this.settings.direction
+ });
+
+ this.stage.attachTo(element);
+
+ // 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.bounds();
+ this._stageSize = this.stage.size();
+
+ // Set the dimensions for views
+ this.viewSettings.width = this._stageSize.width;
+ this.viewSettings.height = this._stageSize.height;
+
+ // Function to handle a resize event.
+ // Will only attach if width and height are both fixed.
+ this.stage.onResize(this.onResized.bind(this));
+
+ this.stage.onOrientationChange(this.onOrientationChange.bind(this));
+
+ // Add Event Listeners
+ this.addEventListeners();
+
+ // Add Layout method
+ // this.applyLayoutMethod();
+ if (this.layout) {
+ this.updateLayout();
+ }
+
+ this.rendered = true;
+
+ }
+
+ addEventListeners(){
+ var scroller;
+
+ window.addEventListener("unload", function(e){
+ this.destroy();
+ }.bind(this));
+
+ if(!this.settings.fullsize) {
+ scroller = this.container;
+ } else {
+ scroller = window;
+ }
+
+ this._onScroll = this.onScroll.bind(this);
+ scroller.addEventListener("scroll", this._onScroll);
+ }
+
+ removeEventListeners(){
+ var scroller;
+
+ if(!this.settings.fullsize) {
+ scroller = this.container;
+ } else {
+ scroller = window;
+ }
+
+ scroller.removeEventListener("scroll", this._onScroll);
+ this._onScroll = undefined;
+ }
+
+ destroy(){
+ clearTimeout(this.orientationTimeout);
+ clearTimeout(this.resizeTimeout);
+ clearTimeout(this.afterScrolled);
+
+ this.clear();
+
+ this.removeEventListeners();
+
+ this.stage.destroy();
+
+ this.rendered = false;
+
+ /*
+
+ clearTimeout(this.trimTimeout);
+ if(this.settings.hidden) {
+ this.element.removeChild(this.wrapper);
+ } else {
+ this.element.removeChild(this.container);
+ }
+ */
+ }
+
+ onOrientationChange(e) {
+ let {orientation} = window;
+
+ if(this.optsSettings.resizeOnOrientationChange) {
+ this.resize();
+ }
+
+ // Per ampproject:
+ // In IOS 10.3, the measured size of an element is incorrect if the
+ // element size depends on window size directly and the measurement
+ // happens in window.resize event. Adding a timeout for correct
+ // measurement. See https://github.com/ampproject/amphtml/issues/8479
+ clearTimeout(this.orientationTimeout);
+ this.orientationTimeout = setTimeout(function(){
+ this.orientationTimeout = undefined;
+
+ if(this.optsSettings.resizeOnOrientationChange) {
+ this.resize();
+ }
+
+ this.emit(EVENTS.MANAGERS.ORIENTATION_CHANGE, orientation);
+ }.bind(this), 500);
+
+ }
+
+ onResized(e) {
+ this.resize();
+ }
+
+ resize(width, height, epubcfi){
+ let stageSize = this.stage.size(width, height);
+
+ // For Safari, wait for orientation to catch up
+ // if the window is a square
+ this.winBounds = windowBounds();
+ if (this.orientationTimeout &&
+ this.winBounds.width === this.winBounds.height) {
+ // reset the stage size for next resize
+ this._stageSize = undefined;
+ return;
+ }
+
+ if (this._stageSize &&
+ this._stageSize.width === stageSize.width &&
+ this._stageSize.height === stageSize.height ) {
+ // Size is the same, no need to resize
+ return;
+ }
+
+ this._stageSize = stageSize;
+
+ this._bounds = this.bounds();
+
+ // Clear current views
+ this.clear();
+
+ // Update for new views
+ this.viewSettings.width = this._stageSize.width;
+ this.viewSettings.height = this._stageSize.height;
+
+ this.updateLayout();
+
+ this.emit(EVENTS.MANAGERS.RESIZED, {
+ width: this._stageSize.width,
+ height: this._stageSize.height
+ }, epubcfi);
+ }
+
+ createView(section, forceRight) {
+ return new this.View(section, extend(this.viewSettings, { forceRight }) );
+ }
+
+ handleNextPrePaginated(forceRight, section, action) {
+ let next;
+
+ if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
+ if (forceRight || section.index === 0) {
+ // First page (cover) should stand alone for pre-paginated books
+ return;
+ }
+ next = section.next();
+ if (next && !next.properties.includes("page-spread-left")) {
+ return action.call(this, next);
+ }
+ }
+ }
+
+ display(section, target){
+
+ var displaying = new defer();
+ var displayed = displaying.promise;
+
+ // Check if moving to target is needed
+ if (target === section.href || isNumber(target)) {
+ target = undefined;
+ }
+
+ // 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 in view
+ if(visible && section && this.layout.name !== "pre-paginated") {
+ let offset = visible.offset();
+
+ if (this.settings.direction === "ltr") {
+ this.scrollTo(offset.left, offset.top, true);
+ } else {
+ let width = visible.width();
+ this.scrollTo(offset.left + width, offset.top, true);
+ }
+
+ if(target) {
+ let offset = visible.locationOf(target);
+ let width = visible.width();
+ this.moveTo(offset, width);
+ }
+
+ displaying.resolve();
+ return displayed;
+ }
+
+ // Hide all current views
+ this.clear();
+
+ let forceRight = false;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && section.properties.includes("page-spread-right")) {
+ forceRight = true;
+ }
+
+ this.add(section, forceRight)
+ .then(function(view){
+
+ // Move to correct place within the section, if needed
+ if(target) {
+ let offset = view.locationOf(target);
+ let width = view.width();
+ this.moveTo(offset, width);
+ }
+
+ }.bind(this), (err) => {
+ displaying.reject(err);
+ })
+ .then(function(){
+ return this.handleNextPrePaginated(forceRight, section, this.add);
+ }.bind(this))
+ .then(function(){
+
+ this.views.show();
+
+ displaying.resolve();
+
+ }.bind(this));
+ // .then(function(){
+ // return this.hooks.display.trigger(view);
+ // }.bind(this))
+ // .then(function(){
+ // this.views.show();
+ // }.bind(this));
+ return displayed;
+ }
+
+ afterDisplayed(view){
+ this.emit(EVENTS.MANAGERS.ADDED, view);
+ }
+
+ afterResized(view){
+ this.emit(EVENTS.MANAGERS.RESIZE, view.section);
+ }
+
+ moveTo(offset, width){
+ var distX = 0,
+ distY = 0;
+
+ if(!this.isPaginated) {
+ distY = offset.top;
+ } else {
+ distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
+
+ if (distX + this.layout.delta > this.container.scrollWidth) {
+ distX = this.container.scrollWidth - this.layout.delta;
+ }
+
+ distY = Math.floor(offset.top / this.layout.delta) * this.layout.delta;
+
+ if (distY + this.layout.delta > this.container.scrollHeight) {
+ distY = this.container.scrollHeight - this.layout.delta;
+ }
+ }
+ if(this.settings.direction === 'rtl'){
+ /***
+ the `floor` function above (L343) is on positive values, so we should add one `layout.delta`
+ to distX or use `Math.ceil` function, or multiply offset.left by -1
+ before `Math.floor`
+ */
+ distX = distX + this.layout.delta
+ distX = distX - width
+ }
+ this.scrollTo(distX, distY, true);
+ }
+
+ add(section, forceRight){
+ var view = this.createView(section, forceRight);
+
+ this.views.append(view);
+
+ // view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ view.on(EVENTS.VIEWS.AXIS, (axis) => {
+ this.updateAxis(axis);
+ });
+
+ view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
+ this.updateWritingMode(mode);
+ });
+
+ return view.display(this.request);
+ }
+
+ append(section, forceRight){
+ var view = this.createView(section, forceRight);
+ this.views.append(view);
+
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ view.on(EVENTS.VIEWS.AXIS, (axis) => {
+ this.updateAxis(axis);
+ });
+
+ view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
+ this.updateWritingMode(mode);
+ });
+
+ return view.display(this.request);
+ }
+
+ prepend(section, forceRight){
+ var view = this.createView(section, forceRight);
+
+ view.on(EVENTS.VIEWS.RESIZED, (bounds) => {
+ this.counter(bounds);
+ });
+
+ this.views.prepend(view);
+
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ view.on(EVENTS.VIEWS.AXIS, (axis) => {
+ this.updateAxis(axis);
+ });
+
+ view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
+ this.updateWritingMode(mode);
+ });
+
+ return view.display(this.request);
+ }
+
+ counter(bounds){
+ if(this.settings.axis === "vertical") {
+ this.scrollBy(0, bounds.heightDelta, true);
+ } else {
+ this.scrollBy(bounds.widthDelta, 0, true);
+ }
+
+ }
+
+ // resizeView(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);
+ // }
+ //
+ // };
+
+ next(){
+ var next;
+ var left;
+
+ let dir = this.settings.direction;
+
+ if(!this.views.length) return;
+
+ if(this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;
+
+ if(left <= this.container.scrollWidth) {
+ this.scrollBy(this.layout.delta, 0, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+ } else if (this.isPaginated && this.settings.axis === "horizontal" && dir === "rtl") {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ if (this.settings.rtlScrollType === "default"){
+ left = this.container.scrollLeft;
+
+ if (left > 0) {
+ this.scrollBy(this.layout.delta, 0, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+ } else {
+ left = this.container.scrollLeft + ( this.layout.delta * -1 );
+
+ if (left > this.container.scrollWidth * -1){
+ this.scrollBy(this.layout.delta, 0, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+ }
+
+ } else if (this.isPaginated && this.settings.axis === "vertical") {
+
+ this.scrollTop = this.container.scrollTop;
+
+ let top = this.container.scrollTop + this.container.offsetHeight;
+
+ if(top < this.container.scrollHeight) {
+ this.scrollBy(0, this.layout.height, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+
+ } else {
+ next = this.views.last().section.next();
+ }
+
+ if(next) {
+ this.clear();
+ // The new section may have a different writing-mode from the old section. Thus, we need to update layout.
+ this.updateLayout();
+
+ let forceRight = false;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && next.properties.includes("page-spread-right")) {
+ forceRight = true;
+ }
+
+ return this.append(next, forceRight)
+ .then(function(){
+ return this.handleNextPrePaginated(forceRight, next, this.append);
+ }.bind(this), (err) => {
+ return err;
+ })
+ .then(function(){
+
+ // Reset position to start for scrolled-doc vertical-rl in default mode
+ if (!this.isPaginated &&
+ this.settings.axis === "horizontal" &&
+ this.settings.direction === "rtl" &&
+ this.settings.rtlScrollType === "default") {
+
+ this.scrollTo(this.container.scrollWidth, 0, true);
+ }
+ this.views.show();
+ }.bind(this));
+ }
+
+
+ }
+
+ prev(){
+ var prev;
+ var left;
+ let dir = this.settings.direction;
+
+ if(!this.views.length) return;
+
+ if(this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ left = this.container.scrollLeft;
+
+ if(left > 0) {
+ this.scrollBy(-this.layout.delta, 0, true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+
+ } else if (this.isPaginated && this.settings.axis === "horizontal" && dir === "rtl") {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ if (this.settings.rtlScrollType === "default"){
+ left = this.container.scrollLeft + this.container.offsetWidth;
+
+ if (left < this.container.scrollWidth) {
+ this.scrollBy(-this.layout.delta, 0, true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+ }
+ else{
+ left = this.container.scrollLeft;
+
+ if (left < 0) {
+ this.scrollBy(-this.layout.delta, 0, true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+ }
+
+ } else if (this.isPaginated && this.settings.axis === "vertical") {
+
+ this.scrollTop = this.container.scrollTop;
+
+ let top = this.container.scrollTop;
+
+ if(top > 0) {
+ this.scrollBy(0, -(this.layout.height), true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+
+ } else {
+
+ prev = this.views.first().section.prev();
+
+ }
+
+ if(prev) {
+ this.clear();
+ // The new section may have a different writing-mode from the old section. Thus, we need to update layout.
+ this.updateLayout();
+
+ let forceRight = false;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && typeof prev.prev() !== "object") {
+ forceRight = true;
+ }
+
+ return this.prepend(prev, forceRight)
+ .then(function(){
+ var left;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
+ left = prev.prev();
+ if (left) {
+ return this.prepend(left);
+ }
+ }
+ }.bind(this), (err) => {
+ return err;
+ })
+ .then(function(){
+ if(this.isPaginated && this.settings.axis === "horizontal") {
+ if (this.settings.direction === "rtl") {
+ if (this.settings.rtlScrollType === "default"){
+ this.scrollTo(0, 0, true);
+ }
+ else{
+ this.scrollTo((this.container.scrollWidth * -1) + this.layout.delta, 0, true);
+ }
+ } else {
+ this.scrollTo(this.container.scrollWidth - this.layout.delta, 0, true);
+ }
+ }
+ this.views.show();
+ }.bind(this));
+ }
+ }
+
+ current(){
+ var visible = this.visible();
+ if(visible.length){
+ // Current is the last visible view
+ return visible[visible.length-1];
+ }
+ return null;
+ }
+
+ clear () {
+
+ // this.q.clear();
+
+ if (this.views) {
+ this.views.hide();
+ this.scrollTo(0,0, true);
+ this.views.clear();
+ }
+ }
+
+ currentLocation(){
+ this.updateLayout();
+ if (this.isPaginated && this.settings.axis === "horizontal") {
+ this.location = this.paginatedLocation();
+ } else {
+ this.location = this.scrolledLocation();
+ }
+ return this.location;
+ }
+
+ scrolledLocation() {
+ let visible = this.visible();
+ let container = this.container.getBoundingClientRect();
+ let pageHeight = (container.height < window.innerHeight) ? container.height : window.innerHeight;
+ let pageWidth = (container.width < window.innerWidth) ? container.width : window.innerWidth;
+ let vertical = (this.settings.axis === "vertical");
+ let rtl = (this.settings.direction === "rtl");
+
+ let offset = 0;
+ let used = 0;
+
+ if(this.settings.fullsize) {
+ offset = vertical ? window.scrollY : window.scrollX;
+ }
+
+ let sections = visible.map((view) => {
+ let {index, href} = view.section;
+ let position = view.position();
+ let width = view.width();
+ let height = view.height();
+
+ let startPos;
+ let endPos;
+ let stopPos;
+ let totalPages;
+
+ if (vertical) {
+ startPos = offset + container.top - position.top + used;
+ endPos = startPos + pageHeight - used;
+ totalPages = this.layout.count(height, pageHeight).pages;
+ stopPos = pageHeight;
+ } else {
+ startPos = offset + container.left - position.left + used;
+ endPos = startPos + pageWidth - used;
+ totalPages = this.layout.count(width, pageWidth).pages;
+ stopPos = pageWidth;
+ }
+
+ let currPage = Math.ceil(startPos / stopPos);
+ let pages = [];
+ let endPage = Math.ceil(endPos / stopPos);
+
+ // Reverse page counts for horizontal rtl
+ if (this.settings.direction === "rtl" && !vertical) {
+ let tempStartPage = currPage;
+ currPage = totalPages - endPage;
+ endPage = totalPages - tempStartPage;
+ }
+
+ pages = [];
+ for (var i = currPage; i <= endPage; i++) {
+ let pg = i + 1;
+ pages.push(pg);
+ }
+
+ let mapping = this.mapping.page(view.contents, view.section.cfiBase, startPos, endPos);
+
+ return {
+ index,
+ href,
+ pages,
+ totalPages,
+ mapping
+ };
+ });
+
+ return sections;
+ }
+
+ paginatedLocation(){
+ let visible = this.visible();
+ let container = this.container.getBoundingClientRect();
+
+ let left = 0;
+ let used = 0;
+
+ if(this.settings.fullsize) {
+ left = window.scrollX;
+ }
+
+ let sections = visible.map((view) => {
+ let {index, href} = view.section;
+ let offset;
+ let position = view.position();
+ let width = view.width();
+
+ // Find mapping
+ let start;
+ let end;
+ let pageWidth;
+
+ if (this.settings.direction === "rtl") {
+ offset = container.right - left;
+ pageWidth = Math.min(Math.abs(offset - position.left), this.layout.width) - used;
+ end = position.width - (position.right - offset) - used;
+ start = end - pageWidth;
+ } else {
+ offset = container.left + left;
+ pageWidth = Math.min(position.right - offset, this.layout.width) - used;
+ start = offset - position.left + used;
+ end = start + pageWidth;
+ }
+
+ used += pageWidth;
+
+ let mapping = this.mapping.page(view.contents, view.section.cfiBase, start, end);
+
+ let totalPages = this.layout.count(width).pages;
+ let startPage = Math.floor(start / this.layout.pageWidth);
+ let pages = [];
+ let endPage = Math.floor(end / this.layout.pageWidth);
+
+ // start page should not be negative
+ if (startPage < 0) {
+ startPage = 0;
+ endPage = endPage + 1;
+ }
+
+ // Reverse page counts for rtl
+ if (this.settings.direction === "rtl") {
+ let tempStartPage = startPage;
+ startPage = totalPages - endPage;
+ endPage = totalPages - tempStartPage;
+ }
+
+
+ for (var i = startPage + 1; i <= endPage; i++) {
+ let pg = i;
+ pages.push(pg);
+ }
+
+ return {
+ index,
+ href,
+ pages,
+ totalPages,
+ mapping
+ };
+ });
+
+ return sections;
+ }
+
+ isVisible(view, offsetPrev, offsetNext, _container){
+ var position = view.position();
+ var container = _container || this.bounds();
+
+ 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;
+
+ }
+
+ visible(){
+ var container = this.bounds();
+ var views = this.views.displayed();
+ var viewsLength = views.length;
+ var visible = [];
+ var isVisible;
+ var view;
+
+ for (var i = 0; i < viewsLength; i++) {
+ view = views[i];
+ isVisible = this.isVisible(view, 0, 0, container);
+
+ if(isVisible === true) {
+ visible.push(view);
+ }
+
+ }
+ return visible;
+ }
+
+ scrollBy(x, y, silent){
+ let dir = this.settings.direction === "rtl" ? -1 : 1;
+
+ if(silent) {
+ this.ignore = true;
+ }
+
+ if(!this.settings.fullsize) {
+ if(x) this.container.scrollLeft += x * dir;
+ if(y) this.container.scrollTop += y;
+ } else {
+ window.scrollBy(x * dir, y * dir);
+ }
+ this.scrolled = true;
+ }
+
+ scrollTo(x, y, silent){
+ if(silent) {
+ this.ignore = true;
+ }
+
+ if(!this.settings.fullsize) {
+ this.container.scrollLeft = x;
+ this.container.scrollTop = y;
+ } else {
+ window.scrollTo(x,y);
+ }
+ this.scrolled = true;
+ }
+
+ onScroll(){
+ let scrollTop;
+ let scrollLeft;
+
+ if(!this.settings.fullsize) {
+ scrollTop = this.container.scrollTop;
+ scrollLeft = this.container.scrollLeft;
+ } else {
+ scrollTop = window.scrollY;
+ scrollLeft = window.scrollX;
+ }
+
+ this.scrollTop = scrollTop;
+ this.scrollLeft = scrollLeft;
+
+ if(!this.ignore) {
+ this.emit(EVENTS.MANAGERS.SCROLL, {
+ top: scrollTop,
+ left: scrollLeft
+ });
+
+ clearTimeout(this.afterScrolled);
+ this.afterScrolled = setTimeout(function () {
+ this.emit(EVENTS.MANAGERS.SCROLLED, {
+ top: this.scrollTop,
+ left: this.scrollLeft
+ });
+ }.bind(this), 20);
+
+
+
+ } else {
+ this.ignore = false;
+ }
+
+ }
+
+ bounds() {
+ var bounds;
+
+ bounds = this.stage.bounds();
+
+ return bounds;
+ }
+
+ applyLayout(layout) {
+
+ this.layout = layout;
+ this.updateLayout();
+ if (this.views && this.views.length > 0 && this.layout.name === "pre-paginated") {
+ this.display(this.views.first().section);
+ }
+ // this.manager.layout(this.layout.format);
+ }
+
+ updateLayout() {
+
+ if (!this.stage) {
+ return;
+ }
+
+ this._stageSize = this.stage.size();
+
+ if(!this.isPaginated) {
+ 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.layout.divisor;
+
+ // 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);
+ }
+
+ setLayout(layout){
+
+ this.viewSettings.layout = layout;
+
+ this.mapping = new Mapping(layout.props, this.settings.direction, this.settings.axis);
+
+ if(this.views) {
+
+ this.views.forEach(function(view){
+ if (view) {
+ view.setLayout(layout);
+ }
+ });
+
+ }
+
+ }
+
+ updateWritingMode(mode) {
+ this.writingMode = mode;
+ }
+
+ updateAxis(axis, forceUpdate){
+
+ if (!forceUpdate && axis === this.settings.axis) {
+ return;
+ }
+
+ this.settings.axis = axis;
+
+ this.stage && this.stage.axis(axis);
+
+ this.viewSettings.axis = axis;
+
+ if (this.mapping) {
+ this.mapping = new Mapping(this.layout.props, this.settings.direction, this.settings.axis);
+ }
+
+ if (this.layout) {
+ if (axis === "vertical") {
+ this.layout.spread("none");
+ } else {
+ this.layout.spread(this.layout.settings.spread);
+ }
+ }
+ }
+
+ updateFlow(flow, defaultScrolledOverflow="auto"){
+ let isPaginated = (flow === "paginated" || flow === "auto");
+
+ this.isPaginated = isPaginated;
+
+ if (flow === "scrolled-doc" ||
+ flow === "scrolled-continuous" ||
+ flow === "scrolled") {
+ this.updateAxis("vertical");
+ } else {
+ this.updateAxis("horizontal");
+ }
+
+ this.viewSettings.flow = flow;
+
+ if (!this.settings.overflow) {
+ this.overflow = isPaginated ? "hidden" : defaultScrolledOverflow;
+ } else {
+ this.overflow = this.settings.overflow;
+ }
+
+ this.stage && this.stage.overflow(this.overflow);
+
+ this.updateLayout();
+
+ }
+
+ getContents(){
+ var contents = [];
+ if (!this.views) {
+ return contents;
+ }
+ this.views.forEach(function(view){
+ const viewContents = view && view.contents;
+ if (viewContents) {
+ contents.push(viewContents);
+ }
+ });
+ return contents;
+ }
+
+ direction(dir="ltr") {
+ this.settings.direction = dir;
+
+ this.stage && this.stage.direction(dir);
+
+ this.viewSettings.direction = dir;
+
+ this.updateLayout();
+ }
+
+ isRendered() {
+ return this.rendered;
+ }
+}
+
+//-- Enable binding events to Manager
+EventEmitter(DefaultViewManager.prototype);
+
+export default DefaultViewManager;