From d95ec97f7f74a0bd8f66a642cd04d20abd3c027f Mon Sep 17 00:00:00 2001 From: Fred Chasen Date: Sun, 12 Feb 2017 13:27:49 -0500 Subject: [PATCH] Add Destroy to view managers --- package.json | 2 +- src/archive.js | 5 +-- src/book.js | 12 ++++--- src/managers/default/index.js | 12 ++++--- src/managers/helpers/stage.js | 17 ++++++++++ src/managers/views/iframe.js | 10 ++++-- src/rendition.js | 39 ++++++++++++---------- src/resources.js | 63 ++++++++++++++++++++++++----------- src/utils/core.js | 14 ++++---- src/utils/queue.js | 3 +- 10 files changed, 118 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 15a5821..ea8c295 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "epubjs", - "version": "0.3.11", + "version": "0.3.12", "description": "Parse and Render Epubs", "main": "lib/index.js", "jsnext:main": "src/index.js", diff --git a/src/archive.js b/src/archive.js index 7050925..2e2ccb8 100644 --- a/src/archive.js +++ b/src/archive.js @@ -247,8 +247,9 @@ class Archive { } destroy() { - this.urlCache.forEach((fromCache) => _URL.revokeObjectURL(fromCache)); - + for (let fromCache in this.urlCache) { + _URL.revokeObjectURL(fromCache); + } this.zip = undefined; this.urlCache = {}; } diff --git a/src/book.js b/src/book.js index 6f39eb6..82eddd1 100644 --- a/src/book.js +++ b/src/book.js @@ -27,7 +27,7 @@ const EPUBJS_VERSION = "0.3"; * @param {boolean} [options.requestCredentials=undefined] send the xhr request withCredentials * @param {object} [options.requestHeaders=undefined] send the xhr request headers * @param {string} [options.encoding=binary] optional to pass 'binary' or base64' for archived Epubs - * @param {string} [options.replacements=base64] use base64, blobUrl, or none for replacing assets in archived Epubs + * @param {string} [options.replacements=none] use base64, blobUrl, or none for replacing assets in archived Epubs * @returns {Book} * @example new Book("/path/to/book.epub", {}) * @example new Book({ replacements: "blobUrl" }) @@ -46,7 +46,7 @@ class Book { requestCredentials: undefined, requestHeaders: undefined, encoding: undefined, - replacements: "base64" + replacements: undefined }); extend(this.settings, options); @@ -351,7 +351,8 @@ class Book { this.resources = new Resources(this.package.manifest, { archive: this.archive, resolver: this.resolve.bind(this), - replacements: this.settings.replacements + request: this.request.bind(this), + replacements: this.settings.replacements || "base64" }); this.loadNavigation(this.package).then(() => { @@ -372,9 +373,12 @@ class Book { this.isOpen = true; - if(this.archived || this.settings.replacements) { + if(this.archived || this.settings.replacements && this.settings.replacements != "none") { this.replacements().then(() => { this.opening.resolve(this); + }) + .catch((err) => { + console.error(err); }); } else { // Resolve book opened promise diff --git a/src/managers/default/index.js b/src/managers/default/index.js index 6c5d4a3..95406ca 100644 --- a/src/managers/default/index.js +++ b/src/managers/default/index.js @@ -85,9 +85,11 @@ class DefaultViewManager { } destroy(){ - // this.views.each(function(view){ - // view.destroy(); - // }); + this.views.each(function(view){ + view.destroy(); + }); + + this.stage.destroy(); /* @@ -108,7 +110,6 @@ class DefaultViewManager { } resize(width, height){ - // Clear the queue this.q.clear(); @@ -119,12 +120,13 @@ class DefaultViewManager { this.viewSettings.width = this._stageSize.width; this.viewSettings.height = this._stageSize.height; + this.updateLayout(); + // Update for existing views this.views.each(function(view) { view.size(this._stageSize.width, this._stageSize.height); }.bind(this)); - this.updateLayout(); this.emit("resized", { width: this.stage.width, diff --git a/src/managers/helpers/stage.js b/src/managers/helpers/stage.js index 9f9592d..eb95f84 100644 --- a/src/managers/helpers/stage.js +++ b/src/managers/helpers/stage.js @@ -225,6 +225,23 @@ class Stage { this.sheet.insertRule(scope + selector + " {" + rules + "}", 0); } + + destroy() { + var base; + + if (this.element) { + + if(this.settings.hidden) { + base = this.wrapper; + } else { + base = this.container; + } + + if(this.element.contains(this.container)) { + this.element.removeChild(this.container); + } + } + } } export default Stage; diff --git a/src/managers/views/iframe.js b/src/managers/views/iframe.js index 0e77afc..6f8ff4c 100644 --- a/src/managers/views/iframe.js +++ b/src/managers/views/iframe.js @@ -237,17 +237,19 @@ class IframeView { if(this.layout.name === "pre-paginated") return; this._expanding = true; - // Expand Horizontally // if(height && !width) { if(this.settings.axis === "horizontal") { // Get the width of the text textWidth = this.contents.textWidth(); + width = this.contentWidth(textWidth); + // Check if the textWidth has changed - if(textWidth != this._textWidth){ + if(width != this._width){ // Get the contentWidth by resizing the iframe // Check with a min reset of the textWidth - width = this.contentWidth(textWidth); + + // width = this.contentWidth(textWidth); columns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap)); @@ -260,6 +262,7 @@ class IframeView { // Save the textWdith this._textWidth = textWidth; + // Save the contentWidth this._contentWidth = width; } else { @@ -344,6 +347,7 @@ class IframeView { // this._needsReframe = true; // return; // } + if(isNumber(width)){ this.element.style.width = width + "px"; } diff --git a/src/rendition.js b/src/rendition.js index fc485c2..4c03274 100644 --- a/src/rendition.js +++ b/src/rendition.js @@ -221,6 +221,9 @@ class Rendition { * @return {Promise} */ _display(target){ + if (!this.book) { + return; + } var isCfiString = this.epubcfi.isCfiString(target); var displaying = new defer(); var displayed = displaying.promise; @@ -513,30 +516,32 @@ class Rendition { */ destroy(){ // Clear the queue - this.q.clear(); - this.q = undefined; + // this.q.clear(); + // this.q = undefined; - this.book = book; + this.manager && this.manager.destroy(); + + this.book = undefined; this.views = null; - this.hooks.display.clear(); - this.hooks.serialize.clear(); - this.hooks.content.clear(); - this.hooks.layout.clear(); - this.hooks.render.clear(); - this.hooks.show.clear(); - this.hooks = {}; + // this.hooks.display.clear(); + // this.hooks.serialize.clear(); + // this.hooks.content.clear(); + // this.hooks.layout.clear(); + // this.hooks.render.clear(); + // this.hooks.show.clear(); + // this.hooks = {}; - this.themes.destroy(); - this.themes = undefined; - - this.epubcfi = undefined; + // this.themes.destroy(); + // this.themes = undefined; + + // this.epubcfi = undefined; + + // this.starting = undefined; + // this.started = undefined; - this.starting = undefined; - this.started = undefined; - this.manager && this.manager.destroy(); } /** diff --git a/src/resources.js b/src/resources.js index 4337ba5..c349f7a 100644 --- a/src/resources.js +++ b/src/resources.js @@ -1,5 +1,7 @@ import {substitute} from "./utils/replacements"; -import {createBase64Url, createBlobUrl} from "./utils/core"; +import {createBase64Url, createBlobUrl, blob2base64} from "./utils/core"; +import Url from "./utils/url"; +import mime from "../libs/mime/mime"; import Path from "./utils/path"; import path from "path-webpack"; @@ -17,7 +19,8 @@ class Resources { this.settings = { replacements: (options && options.replacements) || "base64", archive: (options && options.archive), - resolver: (options && options.resolver) + resolver: (options && options.resolver), + request: (options && options.request) }; this.manifest = manifest; this.resources = Object.keys(manifest). @@ -90,16 +93,34 @@ class Resources { } + createUrl (url) { + var parsedUrl = new Url(url); + var mimeType = mime.lookup(parsedUrl.filename); + + if (this.settings.archive) { + return this.settings.archive.createUrl(url, {"base64": (this.settings.replacements === "base64")}); + } else { + if (this.settings.replacements === "base64") { + return this.settings.request(url, 'blob') + .then((blob) => { + return blob2base64(blob); + }) + .then((blob) => { + return createBase64Url(blob, mimeType); + }); + } else { + return this.settings.request(url, 'blob').then((blob) => { + return createBlobUrl(blob, mimeType); + }) + } + } + } + /** * Create blob urls for all the assets - * @param {Archive} archive - * @param {resolver} resolver Url resolver * @return {Promise} returns replacement urls */ - replacements(archive, resolver){ - archive = archive || this.settings.archive; - resolver = resolver || this.settings.resolver; - + replacements(){ if (this.settings.replacements === "none") { return new Promise(function(resolve) { resolve(this.urls); @@ -108,10 +129,11 @@ class Resources { var replacements = this.urls. map( (url) => { - var absolute = resolver(url); + var absolute = this.settings.resolver(url); - return archive.createUrl(absolute, {"base64": (this.settings.replacements === "base64")}). + return this.createUrl(absolute). catch((err) => { + console.error(err); return null; }); }); @@ -156,14 +178,10 @@ class Resources { * Create a new CSS file with the replaced URLs * @private * @param {string} href the original css file - * @param {[Archive]} archive - * @param {[method]} resolver * @return {Promise} returns a BlobUrl to the new CSS file or a data url */ - createCssFile(href, archive, resolver){ + createCssFile(href){ var newUrl; - archive = archive || this.settings.archive; - resolver = resolver || this.settings.resolver; if (path.isAbsolute(href)) { return new Promise(function(resolve){ @@ -171,14 +189,20 @@ class Resources { }); } - var absolute = resolver(href); + var absolute = this.settings.resolver(href); // Get the text of the css file from the archive - var textResponse = archive.getText(absolute); + var textResponse; + + if (this.settings.archive) { + textResponse = this.settings.archive.getText(absolute); + } else { + textResponse = this.settings.request(absolute, "text"); + } // Get asset links relative to css file var relUrls = this.urls.map( (assetHref) => { - var resolved = resolver(assetHref); + var resolved = this.settings.resolver(assetHref); var relative = new Path(absolute).relative(resolved); return relative; @@ -245,8 +269,7 @@ class Resources { resolve(this.replacementUrls[indexInUrls]); }.bind(this)); } else { - return this.archive.createUrl(path, - {"base64": (this.settings.replacements === "base64")}); + return this.createUrl(path); } } diff --git a/src/utils/core.js b/src/utils/core.js index d5e076f..21a7136 100644 --- a/src/utils/core.js +++ b/src/utils/core.js @@ -407,12 +407,14 @@ export function walk(node,callback){ } } -export function blob2base64(blob, cb) { - var reader = new FileReader(); - reader.readAsDataURL(blob); - reader.onloadend = function() { - cb(reader.result); - }; +export function blob2base64(blob) { + return new Promise(function(resolve, reject) { + var reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onloadend = function() { + resolve(reader.result); + }; + }); } // From: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#backwards_forwards_compatible diff --git a/src/utils/queue.js b/src/utils/queue.js index 47f061b..cbca23e 100644 --- a/src/utils/queue.js +++ b/src/utils/queue.js @@ -72,7 +72,7 @@ class Queue { dequeue(){ var inwait, task, result; - if(this._q.length) { + if(this._q.length && !this.paused) { inwait = this._q.shift(); task = inwait.task; if(task){ @@ -178,6 +178,7 @@ class Queue { clear(){ this._q = []; this.running = false; + this.paused = true; } /**