From 59f049035720e54a7afd30fc7b53459462a60f35 Mon Sep 17 00:00:00 2001 From: danielweck Date: Sun, 8 Feb 2015 23:23:40 +0000 Subject: [PATCH 01/26] initial support for EPUB3 Multiple Renditions. Media Queries auto-reload works, but user settings not configurable via UI yet. No rendition mapping (navigation). --- epub-modules/Readium.js | 8 +- .../src/models/publication_fetcher.js | 140 +++++++++++++++++- 2 files changed, 141 insertions(+), 7 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index 06b5dfed3..70ba65bc0 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -70,9 +70,9 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', this.reader = new ReadiumSDK.Views.ReaderView(readerOptions); - this.openPackageDocument = function(bookRoot, callback, openPageRequest) { + this.openPackageDocument = function(bookRoot, callback, openPageRequest, renditionSelection) { if (_currentPublicationFetcher) { - _currentPublicationFetcher.flushCache(); + _currentPublicationFetcher.cleanup(); } var cacheSizeEvictThreshold = null; @@ -80,7 +80,7 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', cacheSizeEvictThreshold = readiumOptions.cacheSizeEvictThreshold; } - _currentPublicationFetcher = new PublicationFetcher(bookRoot, jsLibRoot, window, cacheSizeEvictThreshold, _contentDocumentTextPreprocessor); + _currentPublicationFetcher = new PublicationFetcher(bookRoot, jsLibRoot, window, cacheSizeEvictThreshold, _contentDocumentTextPreprocessor, renditionSelection); _currentPublicationFetcher.initialize(function() { @@ -110,7 +110,7 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', this.closePackageDocument = function() { if (_currentPublicationFetcher) { - _currentPublicationFetcher.flushCache(); + _currentPublicationFetcher.cleanup(); } }; diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index f0cb8320f..0dab7eef2 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -16,7 +16,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso function (require, module, $, URI, MarkupParser, PlainResourceFetcher, ZipResourceFetcher, ContentDocumentFetcher, ResourceCache, EncryptionHandler) { - var PublicationFetcher = function(bookRoot, jsLibRoot, sourceWindow, cacheSizeEvictThreshold, contentDocumentTextPreprocessor) { + var PublicationFetcher = function(bookRoot, jsLibRoot, sourceWindow, cacheSizeEvictThreshold, contentDocumentTextPreprocessor, renditionSelection) { var self = this; @@ -34,7 +34,11 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var _packageDomInitializationDeferred; var _publicationResourcesCache = new ResourceCache(sourceWindow, cacheSizeEvictThreshold); + var _mediaQuery = undefined; + var _mediaQueryEventCallback = undefined; + var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; + var _renditionSelection = renditionSelection; this.markupParser = new MarkupParser(); @@ -124,6 +128,15 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso _publicationResourcesCache.flushCache(); }; + this.cleanup = function() { + self.flushCache(); + + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + _mediaQueryEventCallback = undefined; + } + }; + this.getPackageUrl = function() { return _resourceFetcher.getPackageUrl(); }; @@ -163,9 +176,130 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }; this.getRootFile = function(containerXmlDom) { - var rootFile = $('rootfile', containerXmlDom); + //console.debug(containerXmlDom.documentElement.innerHTML); + + //console.debug("_renditionSelectionrenditionMedia: ", _renditionSelection.renditionMedia); + console.debug("_renditionSelection.renditionLayout: ", _renditionSelection.renditionLayout); + console.debug("_renditionSelection.renditionLanguage: ", _renditionSelection.renditionLanguage); + console.debug("_renditionSelection.renditionAccessMode: ", _renditionSelection.renditionAccessMode); + + + var rootFiles = $('rootfile', containerXmlDom); + //console.debug(rootFiles); + + + var rootFile = undefined; + if (rootFiles.length == 1 || !_renditionSelection) { + rootFile = rootFiles; + } else { + + for (var i = rootFiles.length - 1; i >= 0; i--) { + + console.debug("----- ROOT FILE #" + i); + + var rf = $(rootFiles[i]); + + var renditionMedia = rf.attr('rendition:media'); + var renditionLayout = rf.attr('rendition:layout'); + var renditionLanguage = rf.attr('rendition:language'); + var renditionAccessMode = rf.attr('rendition:accessMode'); + + var renditionLabel = rf.attr('rendition:label'); + + console.debug("renditionMedia: ", renditionMedia); + console.debug("renditionLayout: ", renditionLayout); + console.debug("renditionLanguage: ", renditionLanguage); + console.debug("renditionAccessMode: ", renditionAccessMode); + + console.debug("renditionLabel: ", renditionLabel); + + var selected = true; + if (renditionMedia && renditionMedia !== "" && window.matchMedia) { + + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + + _mediaQueryEventCallback = undefined; + _mediaQuery = undefined; + } + + _mediaQuery = window.matchMedia(renditionMedia); + + _mediaQueryEventCallback = function(mq) { + console.debug("Rendition Selection Media Query changed: " + mq.media + " (" + mq.matches + ")"); + if (mq.matches) { + // noop + } + if (_renditionSelection.renditionMediaQueryCallback) { + _renditionSelection.renditionMediaQueryCallback(); + } + }; + + _mediaQuery.addListener(_mediaQueryEventCallback); + + if (!_mediaQuery.matches) { + console.debug("=== EJECTED: renditionMedia"); + + selected = selected && false; + //continue; + } + } + + if (_renditionSelection.renditionLayout && _renditionSelection.renditionLayout !== "" && renditionLayout && renditionLayout !== "") { + if (_renditionSelection.renditionLayout !== renditionLayout) { + console.debug("=== EJECTED: renditionLayout"); + + selected = selected && false; + //continue; + } + } + + if (_renditionSelection.renditionLanguage && _renditionSelection.renditionLanguage !== "" && renditionLanguage && renditionLanguage !== "") { + + // TODO: language tag (+ script subtag) match algorithm RFC 4647 http://www.ietf.org/rfc/rfc4647.txt + if (_renditionSelection.renditionLanguage !== renditionLanguage) { + var langTags1 = _renditionSelection.renditionLanguage.split("-"); + var langTags2 = renditionLanguage.split("-"); + + console.debug(langTags1[0]); + console.debug(langTags2[0]); + + if (langTags1[0] !== langTags2[0]) { + console.debug("=== EJECTED: renditionLanguage"); + + selected = selected && false; + //continue; + } + } + } + + if (_renditionSelection.renditionAccessMode && _renditionSelection.renditionAccessMode !== "" && renditionAccessMode && renditionAccessMode !== "") { + if (_renditionSelection.renditionAccessMode !== renditionAccessMode) { + console.debug("=== EJECTED: renditionAccessMode"); + + selected = selected && false; + //continue; + } + } + + if (selected) { + rootFile = rf; + break; + } + } + + if (!rootFile) { + // fallback to index zero ... is that a valid interpretation of the EPUB3 specification?? + // See Processing Model: + //http://www.idpf.org/epub/renditions/multiple/epub-multiple-renditions.html#h.4n44azuq1490 + + rootFile = $(rootFiles[0]); + } + } + var packageFullPath = rootFile.attr('full-path'); - return packageFullPath; + + return packageFullPath; }; this.getPackageDom = function (callback, onerror) { From 4de5699bd7256fa2eaa2313c5b274d4ecc007b00 Mon Sep 17 00:00:00 2001 From: danielweck Date: Mon, 9 Feb 2015 21:17:16 +0000 Subject: [PATCH 02/26] EPUB3 Multiple Renditions: now app client side receives info payload that describes the available choices --- epub-modules/Readium.js | 5 +- .../src/models/publication_fetcher.js | 61 +++++++++++++++++-- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index 70ba65bc0..8c621c853 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -96,8 +96,9 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', self.reader.openBook(openBookData); var options = { - packageDocumentUrl : _currentPublicationFetcher.getPackageUrl(), - metadata: packageDocument.getMetadata() + packageDocumentUrl: _currentPublicationFetcher.getPackageUrl(), + metadata: packageDocument.getMetadata(), + multipleRenditions: _currentPublicationFetcher.getMultipleRenditions() }; if (callback){ diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index 0dab7eef2..4eaae4bbb 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -40,6 +40,12 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; var _renditionSelection = renditionSelection; + // object is generated in getRootFile(), which parses container.xml searching for the appropriate OPF package + var _multipleRenditions = undefined; + this.getMultipleRenditions = function() { + return _multipleRenditions; + }; + this.markupParser = new MarkupParser(); this.initialize = function(callback) { @@ -186,17 +192,52 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var rootFiles = $('rootfile', containerXmlDom); //console.debug(rootFiles); - - + + _multipleRenditions = {}; + _multipleRenditions.renditions = []; + _multipleRenditions.selectedIndex = -1; + var rootFile = undefined; if (rootFiles.length == 1 || !_renditionSelection) { rootFile = rootFiles; + + var renditionMedia = rootFile.attr('rendition:media'); + var renditionLayout = rootFile.attr('rendition:layout'); + var renditionLanguage = rootFile.attr('rendition:language'); + var renditionAccessMode = rootFile.attr('rendition:accessMode'); + + var rendition = {}; + + rendition.Media = renditionMedia; + rendition.Layout = renditionLayout; + rendition.Language = renditionLanguage; + rendition.AccessMode = renditionAccessMode; + rendition.Label = renditionLabel; + + _multipleRenditions.renditions.push(rendition); + _multipleRenditions.selectedIndex = 0; + } else { + for (var i = 0; i < rootFiles.length; i++) { + var rendition = {}; + + rendition.Media = undefined; + rendition.Layout = undefined; + rendition.Language = undefined; + rendition.AccessMode = undefined; + rendition.Label = undefined; + + _multipleRenditions.renditions.push(rendition); + } + var selectedIndex = -1; + for (var i = rootFiles.length - 1; i >= 0; i--) { console.debug("----- ROOT FILE #" + i); + var rendition = _multipleRenditions.renditions[i]; + var rf = $(rootFiles[i]); var renditionMedia = rf.attr('rendition:media'); @@ -213,6 +254,12 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso console.debug("renditionLabel: ", renditionLabel); + rendition.Media = renditionMedia; + rendition.Layout = renditionLayout; + rendition.Language = renditionLanguage; + rendition.AccessMode = renditionAccessMode; + rendition.Label = renditionLabel; + var selected = true; if (renditionMedia && renditionMedia !== "" && window.matchMedia) { @@ -282,9 +329,10 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (selected) { + if (selected && !rootFile) { rootFile = rf; - break; + selectedIndex = i; + //break; } } @@ -293,8 +341,11 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso // See Processing Model: //http://www.idpf.org/epub/renditions/multiple/epub-multiple-renditions.html#h.4n44azuq1490 - rootFile = $(rootFiles[0]); + selectedIndex = 0; + rootFile = $(rootFiles[selectedIndex]); } + + _multipleRenditions.selectedIndex = selectedIndex; } var packageFullPath = rootFile.attr('full-path'); From db456dd4e01027d6266d74d5057730b682065438 Mon Sep 17 00:00:00 2001 From: danielweck Date: Tue, 10 Feb 2015 14:13:24 +0000 Subject: [PATCH 03/26] EPUB3 Multiple Renditions mapping (no cross-navigation yet, just raw data structure) --- .../src/models/plain_resource_fetcher.js | 27 +- .../src/models/publication_fetcher.js | 271 +++++++++++++++++- 2 files changed, 272 insertions(+), 26 deletions(-) diff --git a/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js b/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js index ba7cda99c..6f79c28a6 100644 --- a/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js +++ b/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js @@ -44,19 +44,20 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func // PUBLIC API this.initialize = function(callback) { - - parentFetcher.getXmlFileDom('META-INF/container.xml', function (containerXmlDom) { - _packageDocumentRelativePath = parentFetcher.getRootFile(containerXmlDom); - _packageDocumentAbsoluteUrl = self.resolveURI(_packageDocumentRelativePath); - - callback(); - - }, function(error) { - console.error("unable to find package document: " + error); - _packageDocumentAbsoluteUrl = baseUrl; - - callback(); - }); + + parentFetcher.getPackageFullPath( + function(opfPath) { + _packageDocumentRelativePath = opfPath; + _packageDocumentAbsoluteUrl = self.resolveURI(_packageDocumentRelativePath); + callback(); + }, + function(error) { + console.error("unable to find package document: " + error); + _packageDocumentRelativePath = undefined; + _packageDocumentAbsoluteUrl = baseUrl; + callback(); + } + ); }; this.resolveURI = function (pathRelativeToPackageRoot) { diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index 4eaae4bbb..c7eb43812 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -174,15 +174,227 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }, onerror); }; - this.getPackageFullPath = function(callback, onerror) { - self.getXmlFileDom('META-INF/container.xml', function (containerXmlDom) { - var packageFullPath = self.getRootFile(containerXmlDom); - callback(packageFullPath); - }, onerror); - }; + var buildRenditionMapping = function(callback, containerXmlDom, packageFullPath, cacheOpfDom) { - this.getRootFile = function(containerXmlDom) { + var doCallback = true; + + _multipleRenditions.mappings = []; + + var linkMapping = $('link[rel=mapping]', containerXmlDom); + if (linkMapping.length) { + var href = linkMapping.attr("href"); + console.debug('link[rel=mapping] @href ==> ' + href); + if (href) { + + var hrefParentFolder = ""; + var slashi = href.lastIndexOf("/"); + if (slashi > 0) { + hrefParentFolder = href.substr(0, slashi); + } + hrefParentFolder = "/" + hrefParentFolder; + console.debug(hrefParentFolder); + + doCallback = false; + + self.getXmlFileDom(href, + function (mappingDom) { + //var nav = $('nav[epub\\:type=resource-map]', mappingDom); + //var nav = $('nav[type=resource-map]', mappingDom); + var navs = $('nav', mappingDom); + if (navs.length) { + for (var i = 0; i < navs.length; i++) { + var nav = $(navs[i]); + + var epubtype = nav.attr("epub:type"); + if (epubtype !== "resource-map") { + continue; + } + var uls = $('ul', nav); + for (var j = 0; j < uls.length; j++) { + var ul = $(uls[j]); + + var lias = $('li > a', ul); + for (var k = 0; k < lias.length; k++) { + var lia = $(lias[k]); + var ahref = lia.attr("href"); + var arendition = lia.attr("epub:rendition"); + + var mapping = {}; + _multipleRenditions.mappings.push(mapping); + + mapping.href = ahref; + mapping.rendition = arendition; + + var hashi = mapping.href.indexOf("#epubcfi"); + + // this is relative to the mapping HTML doc, not to the root of the EPUB file tree + mapping.opf = mapping.rendition; + if (!mapping.opf) { + if (hashi > 0) { + var opfPath = mapping.href.substr(0, hashi); + mapping.opf = opfPath; + } + } + mapping.opf = hrefParentFolder + "/" + mapping.opf; + + var cfiOpfSpineItem = undefined; + mapping.cfiFull = undefined; + mapping.cfiPartial = undefined; + if (hashi > 0) { + var offset = hashi + 9; + mapping.cfiFull = mapping.href.substr(offset, mapping.href.length-offset-1); + cfiOpfSpineItem = mapping.cfiFull; + + var excli = mapping.cfiFull.indexOf("!"); + if (excli > 0) { + var offset = excli + 1; + mapping.cfiPartial = mapping.cfiFull.substr(offset, mapping.cfiFull.length-offset); + cfiOpfSpineItem = mapping.cfiFull.substr(0, offset-1); + } + } + + //OPF: packageFullPath + //MAPPING: href + + mapping.target = undefined; + if (mapping.rendition) { + // this is relative to the mapping HTML doc, not to the root of the EPUB file tree + mapping.target = mapping.href; + mapping.target = hrefParentFolder + "/" + mapping.target; + } else { + // this is relative to the root of the EPUB file tree + + console.debug("cfiOpfSpineItem: " + cfiOpfSpineItem); + var slashi = cfiOpfSpineItem.lastIndexOf("/"); + if (slashi > 0) { + var nStr = cfiOpfSpineItem.substr(slashi + 1, 1); + var n = parseInt(nStr); + n = n / 2 - 1; + // n is zero-based index of spine item child element in OPF + + if (mapping.opf) { + var f = function() { + var itemRefIndex = n; + var thisOpfPath = mapping.opf.substr(1); + var mapping_ = mapping; + + var thisOpfPathParentFolder = ""; + var slashi = thisOpfPath.lastIndexOf("/"); + if (slashi > 0) { + thisOpfPathParentFolder = thisOpfPath.substr(0, slashi); + } + thisOpfPathParentFolder = "/" + thisOpfPathParentFolder; + //console.debug(">>> " + thisOpfPathParentFolder); + + var processOpfDom = function(opfDom) { + + var itemRefs = $('itemref', opfDom); + if (itemRefs.length) { + var itemRef = $(itemRefs[itemRefIndex]); + var idref = itemRef.attr("idref"); + + var item = $('#' + idref, opfDom); + if (item.length) { + var itemHref = item.attr("href"); + mapping_.target = itemHref; + mapping_.target = thisOpfPathParentFolder + "/" + mapping_.target; + //console.debug(">>> " + mapping_.target); + console.debug(mapping_); + } + } + }; + + var dom = cacheOpfDom[thisOpfPath]; + if (dom) { + console.debug("*** CACHED OPF DOM: " + thisOpfPath); + processOpfDom(dom); + } + else { + // Async! + // Should never occur, + // because the cacheOpfDom array was initialised in populateCacheOpfDom(), + // based upon renditions declared in META-INF/container.xml + console.debug("*** PARSING OPF DOM: " + thisOpfPath); + self.getXmlFileDom(thisOpfPath, + function (opfDom) { + cacheOpfDom[thisOpfPath] = opfDom; + processOpfDom(opfDom); + }, + function(error) { + } + ); + } + + }(); + } + } + } + + console.debug("============"); + console.log("- href: " + mapping.href); + console.log("- rendition: " + mapping.rendition); + console.log("opf: " + mapping.opf); + console.log("cfiFull: " + mapping.cfiFull); + console.log("cfiPartial: " + mapping.cfiPartial); + console.log("target: " + mapping.target); + } + } + } + } + callback(packageFullPath); + }, + function(error) { + callback(packageFullPath); + } + ); + } + } + + if (doCallback) callback(packageFullPath); + }; + + var populateCacheOpfDom = function(i, cacheOpfDom, callback) { + + var next = function(j) { + if (j < _multipleRenditions.renditions.length) { + console.debug("next populateCacheOpfDom"); + populateCacheOpfDom(j, cacheOpfDom, callback); + } else { + console.debug("callback populateCacheOpfDom"); + callback(); + } + }; + + var rendition = _multipleRenditions.renditions[i]; + + var thisOpfPath = rendition.opfPath.substr(1); + + if (cacheOpfDom[thisOpfPath]) { + + next(i+1); + return; + } + + self.getXmlFileDom(thisOpfPath, + function (opfDom) { + console.error("....cacheOpfDom: " + thisOpfPath); + cacheOpfDom[thisOpfPath] = opfDom; + + next(i+1); + }, + function(error) { + next(i+1); + } + ); + + }; + + + var getRootFile = function(containerXmlDom) { //console.debug(containerXmlDom.documentElement.innerHTML); + + console.debug("@@@@@@@@@@@@@@@@@@ getRootFile"); + //console.debug("_renditionSelectionrenditionMedia: ", _renditionSelection.renditionMedia); console.debug("_renditionSelection.renditionLayout: ", _renditionSelection.renditionLayout); @@ -194,11 +406,13 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso //console.debug(rootFiles); _multipleRenditions = {}; + _multipleRenditions.renditions = []; _multipleRenditions.selectedIndex = -1; + var rootFile = undefined; - if (rootFiles.length == 1 || !_renditionSelection) { + if (rootFiles.length == 1) { rootFile = rootFiles; var renditionMedia = rootFile.attr('rendition:media'); @@ -214,6 +428,9 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso rendition.AccessMode = renditionAccessMode; rendition.Label = renditionLabel; + rendition.opfPath = "/" + rootFile.attr('full-path'); + console.debug("opfPath: ", rendition.opfPath); + _multipleRenditions.renditions.push(rendition); _multipleRenditions.selectedIndex = 0; @@ -260,6 +477,9 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso rendition.AccessMode = renditionAccessMode; rendition.Label = renditionLabel; + rendition.opfPath = "/" + rf.attr('full-path'); + console.debug("opfPath: ", rendition.opfPath); + var selected = true; if (renditionMedia && renditionMedia !== "" && window.matchMedia) { @@ -277,7 +497,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso if (mq.matches) { // noop } - if (_renditionSelection.renditionMediaQueryCallback) { + if (_renditionSelection && _renditionSelection.renditionMediaQueryCallback) { _renditionSelection.renditionMediaQueryCallback(); } }; @@ -292,7 +512,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (_renditionSelection.renditionLayout && _renditionSelection.renditionLayout !== "" && renditionLayout && renditionLayout !== "") { + if (_renditionSelection && _renditionSelection.renditionLayout && _renditionSelection.renditionLayout !== "" && renditionLayout && renditionLayout !== "") { if (_renditionSelection.renditionLayout !== renditionLayout) { console.debug("=== EJECTED: renditionLayout"); @@ -301,7 +521,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (_renditionSelection.renditionLanguage && _renditionSelection.renditionLanguage !== "" && renditionLanguage && renditionLanguage !== "") { + if (_renditionSelection && _renditionSelection.renditionLanguage && _renditionSelection.renditionLanguage !== "" && renditionLanguage && renditionLanguage !== "") { // TODO: language tag (+ script subtag) match algorithm RFC 4647 http://www.ietf.org/rfc/rfc4647.txt if (_renditionSelection.renditionLanguage !== renditionLanguage) { @@ -320,7 +540,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (_renditionSelection.renditionAccessMode && _renditionSelection.renditionAccessMode !== "" && renditionAccessMode && renditionAccessMode !== "") { + if (_renditionSelection && _renditionSelection.renditionAccessMode && _renditionSelection.renditionAccessMode !== "" && renditionAccessMode && renditionAccessMode !== "") { if (_renditionSelection.renditionAccessMode !== renditionAccessMode) { console.debug("=== EJECTED: renditionAccessMode"); @@ -349,9 +569,34 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } var packageFullPath = rootFile.attr('full-path'); - return packageFullPath; }; + + + + var _OpfPath = undefined; + this.getPackageFullPath = function(callback, onerror) { + if (_OpfPath) { + callback(_OpfPath); + return; + } + + self.getXmlFileDom('META-INF/container.xml', function(containerXmlDom) { + + _OpfPath = getRootFile(containerXmlDom); + + var cacheOpfDom = {}; + + if (_multipleRenditions.renditions.length) { + populateCacheOpfDom(0, cacheOpfDom, function() { + buildRenditionMapping(callback, containerXmlDom, _OpfPath, cacheOpfDom); + }); + } else { + buildRenditionMapping(callback, containerXmlDom, _OpfPath, cacheOpfDom); + } + + }, onerror); + }; this.getPackageDom = function (callback, onerror) { if (_packageDom) { From 9e96b82aa99ee0666cd9d2ceeedefd4ffb2bde03 Mon Sep 17 00:00:00 2001 From: danielweck Date: Fri, 13 Feb 2015 17:37:45 +0000 Subject: [PATCH 04/26] save/restore/adjust protocol to handle rendition switch --- epub-modules/Readium.js | 17 ++++++++++++++++- .../src/models/publication_fetcher.js | 18 ++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index 8c621c853..5f3424023 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -90,7 +90,22 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', var openBookOptions = readiumOptions.openBookOptions || {}; var openBookData = $.extend(packageDocument.getSharedJsPackageData(), openBookOptions); + var multipleRenditions = _currentPublicationFetcher.getMultipleRenditions(); + if (openPageRequest) { + + if (multipleRenditions && openPageRequest.opfPath) { + var rendition = multipleRenditions.renditions[multipleRenditions.selectedIndex]; + if (rendition.opfPath !== openPageRequest.opfPath) { + console.debug("RENDITION: DIFFERENT"); +console.log("ADJUSTING READING LOCATION"); +console.debug(JSON.stringify(openPageRequest)); +openPageRequest = undefined; + } else { + console.debug("RENDITION: SAME"); + } + } + openBookData.openPageRequest = openPageRequest; } self.reader.openBook(openBookData); @@ -98,7 +113,7 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', var options = { packageDocumentUrl: _currentPublicationFetcher.getPackageUrl(), metadata: packageDocument.getMetadata(), - multipleRenditions: _currentPublicationFetcher.getMultipleRenditions() + multipleRenditions: multipleRenditions }; if (callback){ diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index c7eb43812..3dec82d51 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -264,7 +264,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } else { // this is relative to the root of the EPUB file tree - console.debug("cfiOpfSpineItem: " + cfiOpfSpineItem); + //console.debug("cfiOpfSpineItem: " + cfiOpfSpineItem); var slashi = cfiOpfSpineItem.lastIndexOf("/"); if (slashi > 0) { var nStr = cfiOpfSpineItem.substr(slashi + 1, 1); @@ -299,14 +299,14 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso mapping_.target = itemHref; mapping_.target = thisOpfPathParentFolder + "/" + mapping_.target; //console.debug(">>> " + mapping_.target); - console.debug(mapping_); + //console.debug(mapping_); } } }; var dom = cacheOpfDom[thisOpfPath]; if (dom) { - console.debug("*** CACHED OPF DOM: " + thisOpfPath); + //console.debug("*** CACHED OPF DOM: " + thisOpfPath); processOpfDom(dom); } else { @@ -330,6 +330,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } + /* console.debug("============"); console.log("- href: " + mapping.href); console.log("- rendition: " + mapping.rendition); @@ -337,6 +338,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso console.log("cfiFull: " + mapping.cfiFull); console.log("cfiPartial: " + mapping.cfiPartial); console.log("target: " + mapping.target); + */ } } } @@ -497,8 +499,8 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso if (mq.matches) { // noop } - if (_renditionSelection && _renditionSelection.renditionMediaQueryCallback) { - _renditionSelection.renditionMediaQueryCallback(); + if (_renditionSelection && _renditionSelection.renditionReload) { + _renditionSelection.renditionReload(); } }; @@ -512,7 +514,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (_renditionSelection && _renditionSelection.renditionLayout && _renditionSelection.renditionLayout !== "" && renditionLayout && renditionLayout !== "") { + if (_renditionSelection && (typeof _renditionSelection.renditionLayout !== "undefined") && renditionLayout && renditionLayout !== "") { if (_renditionSelection.renditionLayout !== renditionLayout) { console.debug("=== EJECTED: renditionLayout"); @@ -521,7 +523,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (_renditionSelection && _renditionSelection.renditionLanguage && _renditionSelection.renditionLanguage !== "" && renditionLanguage && renditionLanguage !== "") { + if (_renditionSelection && (typeof _renditionSelection.renditionLanguage !== "undefined") && renditionLanguage && renditionLanguage !== "") { // TODO: language tag (+ script subtag) match algorithm RFC 4647 http://www.ietf.org/rfc/rfc4647.txt if (_renditionSelection.renditionLanguage !== renditionLanguage) { @@ -540,7 +542,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (_renditionSelection && _renditionSelection.renditionAccessMode && _renditionSelection.renditionAccessMode !== "" && renditionAccessMode && renditionAccessMode !== "") { + if (_renditionSelection && (typeof _renditionSelection.renditionAccessMode !== "undefined") && renditionAccessMode && renditionAccessMode !== "") { if (_renditionSelection.renditionAccessMode !== renditionAccessMode) { console.debug("=== EJECTED: renditionAccessMode"); From 1e5cf23648dda8dd73a3380ec02330010fd4a664 Mon Sep 17 00:00:00 2001 From: danielweck Date: Fri, 13 Feb 2015 23:19:31 +0000 Subject: [PATCH 05/26] CFI save/restore/adjust for EPUB3 multiple renditions: now compares order, elects the nearest one before the bookmark --- epub-modules/Readium.js | 125 +++++++++++++++++- .../src/models/publication_fetcher.js | 6 +- 2 files changed, 126 insertions(+), 5 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index 5f3424023..1d72ee53a 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -86,7 +86,7 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', var _packageParser = new PackageParser(bookRoot, _currentPublicationFetcher); - _packageParser.parse(function(packageDocument){ + _packageParser.parse(function(packageDocument) { var openBookOptions = readiumOptions.openBookOptions || {}; var openBookData = $.extend(packageDocument.getSharedJsPackageData(), openBookOptions); @@ -98,14 +98,131 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', var rendition = multipleRenditions.renditions[multipleRenditions.selectedIndex]; if (rendition.opfPath !== openPageRequest.opfPath) { console.debug("RENDITION: DIFFERENT"); -console.log("ADJUSTING READING LOCATION"); -console.debug(JSON.stringify(openPageRequest)); -openPageRequest = undefined; + + var nearestMapping = undefined; + + if (multipleRenditions.mappings) { + + var cfiTokenise = function(cfi) { +//console.log(cfi); + var arrayOfIndices = []; + + var split = cfi.split("/"); + for (var i = 0; i < split.length; i++) { + var token = split[i]; + var j = token.indexOf("["); + if (j > 0) { + token = token.substr(0, token.length - j); + } + j = token.indexOf("@"); + if (j > 0) { + token = token.substr(0, token.length - j); + } + if (!token.length) continue; + + var index = parseInt(token); +//console.log(index); + arrayOfIndices.push(index); + } + + return arrayOfIndices; + }; + + // cfi1 <= cfi2 + var cfiIsBeforeOrEqual = function(cfi1, cfi2) { + + var i = 0; + while (i < cfi1.length && i < cfi2.length) { + if (cfi1[i] > cfi2[i]) return false; + i++; + } + + return true; + }; + + console.log("ADJUSTING READING LOCATION"); + console.debug(openPageRequest.elementCfi); + var cfi2 = cfiTokenise(openPageRequest.elementCfi); + + for (var i = 0; i < multipleRenditions.mappings.length; i++) { + var mappingUL = multipleRenditions.mappings[i]; + + for (var j = 0; j < mappingUL.length; j++) { + var mapping = mappingUL[j]; + + if (openPageRequest.opfPath === mapping.opf && openPageRequest.idref === mapping.idref) { + var cfi1 = cfiTokenise(mapping.cfiPartial); + if (nearestMapping) { + var cfi3 = cfiTokenise(nearestMapping.cfiPartial); + if (cfiIsBeforeOrEqual(cfi1, cfi3)) { + break; + } + } + if (cfiIsBeforeOrEqual(cfi1, cfi2)) { + + for (var k = 0; k < mappingUL.length; k++) { + var m = mappingUL[k]; + if (rendition.opfPath === m.opf) { + nearestMapping = m; + break; + } + } + + break; + } + } + + //mapping.opf + //openPageRequest.opfPath + + //mapping.idref + //openPageRequest.idref + + //mapping.cfiPartial + //openPageRequest.elementCfi + } + } + } + if (nearestMapping) { + console.log("FOUND!"); + console.debug(nearestMapping); + var elCfi = nearestMapping.cfiPartial; + var split = elCfi.split("/"); + var lastIndex = split[split.length-1]; + var l = lastIndex.indexOf("@"); + if (l > 0) { + lastIndex = lastIndex.substr(0, lastIndex.length-l); + } + + var isOdd = (lastIndex % 2) == 1; + if (isOdd) { + elCfi = ""; + for (var k = 0; k < split.length-1; k++) { + var index = split[k]; + if (!index.length) continue; + elCfi += ("/" + index); + } + + console.debug("ODD: "+elCfi); + } + + var l = elCfi.indexOf("@"); + if (l < 0) { + elCfi += "@0:0"; + } + + openPageRequest.opfPath = nearestMapping.opf; + openPageRequest.idref = nearestMapping.idref; + openPageRequest.elementCfi = elCfi; + } else { + openPageRequest = undefined; + } } else { console.debug("RENDITION: SAME"); } } +console.debug(JSON.stringify(openPageRequest)); openBookData.openPageRequest = openPageRequest; } self.reader.openBook(openBookData); diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index 3dec82d51..187183a30 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -213,6 +213,9 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso for (var j = 0; j < uls.length; j++) { var ul = $(uls[j]); + var mappingUL = []; + _multipleRenditions.mappings.push(mappingUL); + var lias = $('li > a', ul); for (var k = 0; k < lias.length; k++) { var lia = $(lias[k]); @@ -220,7 +223,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var arendition = lia.attr("epub:rendition"); var mapping = {}; - _multipleRenditions.mappings.push(mapping); + mappingUL.push(mapping); mapping.href = ahref; mapping.rendition = arendition; @@ -292,6 +295,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso if (itemRefs.length) { var itemRef = $(itemRefs[itemRefIndex]); var idref = itemRef.attr("idref"); + mapping_.idref = idref; var item = $('#' + idref, opfDom); if (item.length) { From 255bc3e8c4f9cbcb6c1e84161fba358f233badec Mon Sep 17 00:00:00 2001 From: danielweck Date: Mon, 16 Feb 2015 13:21:54 +0000 Subject: [PATCH 06/26] moving code into shared-js --- epub-modules/Readium.js | 137 +----------------- .../src/models/publication_fetcher.js | 1 + .../epub-renderer/src/readium-shared-js | 2 +- 3 files changed, 4 insertions(+), 136 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index 1d72ee53a..0b4767c20 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -91,146 +91,13 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', var openBookData = $.extend(packageDocument.getSharedJsPackageData(), openBookOptions); var multipleRenditions = _currentPublicationFetcher.getMultipleRenditions(); + openBookData = $.extend(openBookData, {multipleRenditions: multipleRenditions}); - if (openPageRequest) { - - if (multipleRenditions && openPageRequest.opfPath) { - var rendition = multipleRenditions.renditions[multipleRenditions.selectedIndex]; - if (rendition.opfPath !== openPageRequest.opfPath) { - console.debug("RENDITION: DIFFERENT"); - - var nearestMapping = undefined; - - if (multipleRenditions.mappings) { - - var cfiTokenise = function(cfi) { -//console.log(cfi); - var arrayOfIndices = []; - - var split = cfi.split("/"); - for (var i = 0; i < split.length; i++) { - var token = split[i]; - var j = token.indexOf("["); - if (j > 0) { - token = token.substr(0, token.length - j); - } - j = token.indexOf("@"); - if (j > 0) { - token = token.substr(0, token.length - j); - } - if (!token.length) continue; - - var index = parseInt(token); -//console.log(index); - arrayOfIndices.push(index); - } - - return arrayOfIndices; - }; - - // cfi1 <= cfi2 - var cfiIsBeforeOrEqual = function(cfi1, cfi2) { - - var i = 0; - while (i < cfi1.length && i < cfi2.length) { - if (cfi1[i] > cfi2[i]) return false; - i++; - } - - return true; - }; - - console.log("ADJUSTING READING LOCATION"); - console.debug(openPageRequest.elementCfi); - var cfi2 = cfiTokenise(openPageRequest.elementCfi); - - for (var i = 0; i < multipleRenditions.mappings.length; i++) { - var mappingUL = multipleRenditions.mappings[i]; - - for (var j = 0; j < mappingUL.length; j++) { - var mapping = mappingUL[j]; - - if (openPageRequest.opfPath === mapping.opf && openPageRequest.idref === mapping.idref) { - var cfi1 = cfiTokenise(mapping.cfiPartial); - if (nearestMapping) { - var cfi3 = cfiTokenise(nearestMapping.cfiPartial); - if (cfiIsBeforeOrEqual(cfi1, cfi3)) { - break; - } - } - if (cfiIsBeforeOrEqual(cfi1, cfi2)) { - - for (var k = 0; k < mappingUL.length; k++) { - var m = mappingUL[k]; - if (rendition.opfPath === m.opf) { - nearestMapping = m; - break; - } - } - - break; - } - } - - //mapping.opf - //openPageRequest.opfPath - - //mapping.idref - //openPageRequest.idref - - //mapping.cfiPartial - //openPageRequest.elementCfi - } - } - } - if (nearestMapping) { - console.log("FOUND!"); - console.debug(nearestMapping); - var elCfi = nearestMapping.cfiPartial; - var split = elCfi.split("/"); - var lastIndex = split[split.length-1]; - var l = lastIndex.indexOf("@"); - if (l > 0) { - lastIndex = lastIndex.substr(0, lastIndex.length-l); - } - - var isOdd = (lastIndex % 2) == 1; - if (isOdd) { - elCfi = ""; - for (var k = 0; k < split.length-1; k++) { - var index = split[k]; - if (!index.length) continue; - elCfi += ("/" + index); - } - - console.debug("ODD: "+elCfi); - } - - var l = elCfi.indexOf("@"); - if (l < 0) { - elCfi += "@0:0"; - } - - openPageRequest.opfPath = nearestMapping.opf; - openPageRequest.idref = nearestMapping.idref; - openPageRequest.elementCfi = elCfi; - } else { - openPageRequest = undefined; - } - } else { - console.debug("RENDITION: SAME"); - } - } - -console.debug(JSON.stringify(openPageRequest)); - openBookData.openPageRequest = openPageRequest; - } self.reader.openBook(openBookData); var options = { packageDocumentUrl: _currentPublicationFetcher.getPackageUrl(), - metadata: packageDocument.getMetadata(), - multipleRenditions: multipleRenditions + metadata: packageDocument.getMetadata() }; if (callback){ diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index 187183a30..b74768740 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -449,6 +449,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso rendition.Language = undefined; rendition.AccessMode = undefined; rendition.Label = undefined; + rendition.opfPath = undefined; _multipleRenditions.renditions.push(rendition); } diff --git a/epub-modules/epub-renderer/src/readium-shared-js b/epub-modules/epub-renderer/src/readium-shared-js index 94a0dc7d5..47bce370a 160000 --- a/epub-modules/epub-renderer/src/readium-shared-js +++ b/epub-modules/epub-renderer/src/readium-shared-js @@ -1 +1 @@ -Subproject commit 94a0dc7d5bae04540b715ce17a68f419394f5e03 +Subproject commit 47bce370a1fade0ab1bb946ef251d643af04fa46 From 5e9a81678415fc3413f292459ee4020b2f023f2c Mon Sep 17 00:00:00 2001 From: danielweck Date: Mon, 16 Feb 2015 13:23:20 +0000 Subject: [PATCH 07/26] submodule --- epub-modules/epub-renderer/src/readium-shared-js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epub-modules/epub-renderer/src/readium-shared-js b/epub-modules/epub-renderer/src/readium-shared-js index 47bce370a..22b451374 160000 --- a/epub-modules/epub-renderer/src/readium-shared-js +++ b/epub-modules/epub-renderer/src/readium-shared-js @@ -1 +1 @@ -Subproject commit 47bce370a1fade0ab1bb946ef251d643af04fa46 +Subproject commit 22b451374a437e55bd23c8337399dabeab5837a8 From db70f8a4fedc6aeb0a042d339241bc947f91d859 Mon Sep 17 00:00:00 2001 From: danielweck Date: Mon, 16 Feb 2015 22:04:33 +0000 Subject: [PATCH 08/26] various refactorings required to get Multiple Renditions to work correctly (resource fetching APIs) --- epub-modules/Readium.js | 6 +- .../src/models/plain_resource_fetcher.js | 45 +++---- .../src/models/publication_fetcher.js | 115 +++++++++--------- .../src/models/zip_resource_fetcher.js | 4 - .../epub-renderer/src/readium-shared-js | 2 +- .../epub/src/models/package_document.js | 6 +- .../src/models/package_document_parser.js | 10 +- rjs_require_config.js | 10 +- 8 files changed, 91 insertions(+), 107 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index 0b4767c20..e47d2e223 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -82,21 +82,21 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', _currentPublicationFetcher = new PublicationFetcher(bookRoot, jsLibRoot, window, cacheSizeEvictThreshold, _contentDocumentTextPreprocessor, renditionSelection); - _currentPublicationFetcher.initialize(function() { + _currentPublicationFetcher.initialize(function(resourceFetcher, multipleRenditions) { + // invokes _currentPublicationFetcher.getPackageDom() var _packageParser = new PackageParser(bookRoot, _currentPublicationFetcher); _packageParser.parse(function(packageDocument) { var openBookOptions = readiumOptions.openBookOptions || {}; var openBookData = $.extend(packageDocument.getSharedJsPackageData(), openBookOptions); - var multipleRenditions = _currentPublicationFetcher.getMultipleRenditions(); openBookData = $.extend(openBookData, {multipleRenditions: multipleRenditions}); self.reader.openBook(openBookData); var options = { - packageDocumentUrl: _currentPublicationFetcher.getPackageUrl(), + //packageDocumentUrl: _currentPublicationFetcher.getPackageUrl(), metadata: packageDocument.getMetadata() }; diff --git a/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js b/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js index 6f79c28a6..e9b7392fa 100644 --- a/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js +++ b/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js @@ -16,13 +16,18 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func var PlainResourceFetcher = function(parentFetcher, baseUrl){ var self = this; - var _packageDocumentAbsoluteUrl; - var _packageDocumentRelativePath; + + var resolveURI = function (pathRelativeToPackageRoot) { + return baseUrl + "/" + pathRelativeToPackageRoot; + }; + + var _packageDocumentRelativePath = parentFetcher.getPackageUrl(); + var _packageDocumentAbsoluteUrl = _packageDocumentRelativePath ? resolveURI(_packageDocumentRelativePath) : baseUrl; // INTERNAL FUNCTIONS function fetchFileContents(pathRelativeToPackageRoot, readCallback, onerror) { - var fileUrl = self.resolveURI(pathRelativeToPackageRoot); + var fileUrl = resolveURI(pathRelativeToPackageRoot); if (typeof pathRelativeToPackageRoot === 'undefined') { throw 'Fetched file relative path is undefined!'; @@ -40,37 +45,14 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func xhr.send(); } - // PUBLIC API - this.initialize = function(callback) { - - parentFetcher.getPackageFullPath( - function(opfPath) { - _packageDocumentRelativePath = opfPath; - _packageDocumentAbsoluteUrl = self.resolveURI(_packageDocumentRelativePath); - callback(); - }, - function(error) { - console.error("unable to find package document: " + error); - _packageDocumentRelativePath = undefined; - _packageDocumentAbsoluteUrl = baseUrl; - callback(); - } - ); - }; - - this.resolveURI = function (pathRelativeToPackageRoot) { - return baseUrl + "/" + pathRelativeToPackageRoot; - }; - - - this.getPackageUrl = function() { - return _packageDocumentAbsoluteUrl; + this.fetchFileContentsData64Uri = function(relativePathRelativeToPackageRoot, fetchCallback, onerror) { + //TODO!? (potentially invoked from PublicationFetcher.relativeToPackageFetchFileContents(), also see ZipResourceFetcher implementation of fetchFileContentsData64Uri()) }; - + this.fetchFileContentsText = function(pathRelativeToPackageRoot, fetchCallback, onerror) { - var fileUrl = self.resolveURI(pathRelativeToPackageRoot); + var fileUrl = resolveURI(pathRelativeToPackageRoot); if (typeof fileUrl === 'undefined') { throw 'Fetched file URL is undefined!'; @@ -130,13 +112,14 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func }, onerror); }; + /* this.getPackageDom = function (callback, onerror) { self.fetchFileContentsText(_packageDocumentRelativePath, function (packageXml) { var packageDom = parentFetcher.markupParser.parseXml(packageXml); callback(packageDom); }, onerror); }; - + */ }; return PlainResourceFetcher; diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index b74768740..282d32c09 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -29,7 +29,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var _shouldConstructDomProgrammatically; var _resourceFetcher; var _encryptionHandler; - var _packageFullPath; + var _packageDom; var _packageDomInitializationDeferred; var _publicationResourcesCache = new ResourceCache(sourceWindow, cacheSizeEvictThreshold); @@ -40,21 +40,37 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; var _renditionSelection = renditionSelection; - // object is generated in getRootFile(), which parses container.xml searching for the appropriate OPF package - var _multipleRenditions = undefined; - this.getMultipleRenditions = function() { - return _multipleRenditions; - }; - this.markupParser = new MarkupParser(); - this.initialize = function(callback) { + function isExploded() { + var ext = ".epub"; + return bookRoot.indexOf(ext, bookRoot.length - ext.length) === -1; + } + + this.initialize = function(callback) { var isEpubExploded = isExploded(); // Non exploded EPUBs (i.e. zipped .epub documents) should be fetched in a programmatical manner: _shouldConstructDomProgrammatically = !isEpubExploded; - createResourceFetcher(isEpubExploded, callback); + + if (isExploded) { + console.log('using new PlainResourceFetcher'); + _resourceFetcher = new PlainResourceFetcher(self, bookRoot); + + } else { + console.log('using new ZipResourceFetcher'); + _resourceFetcher = new ZipResourceFetcher(self, bookRoot, jsLibRoot); + } + + this.getPackageFullPath( + function (packageFullPath, multipleRenditions) { + callback(_resourceFetcher, multipleRenditions); + }, + function() { + callback(_resourceFetcher, undefined); + } + ); }; @@ -73,26 +89,6 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso console.error(err); } - function isExploded() { - - var ext = ".epub"; - return bookRoot.indexOf(ext, bookRoot.length - ext.length) === -1; - } - - function createResourceFetcher(isExploded, callback) { - if (isExploded) { - console.log('using new PlainResourceFetcher'); - _resourceFetcher = new PlainResourceFetcher(self, bookRoot); - _resourceFetcher.initialize(function () { - callback(_resourceFetcher); - }); - return; - } else { - console.log('using new ZipResourceFetcher'); - _resourceFetcher = new ZipResourceFetcher(self, bookRoot, jsLibRoot); - callback(_resourceFetcher); - } - } // PUBLIC API @@ -144,7 +140,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }; this.getPackageUrl = function() { - return _resourceFetcher.getPackageUrl(); + return _OpfPath; // set in initialize() }; this.fetchContentDocument = function (attachedData, loadedDocumentUri, contentDocumentResolvedCallback, errorCallback) { @@ -174,11 +170,11 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }, onerror); }; - var buildRenditionMapping = function(callback, containerXmlDom, packageFullPath, cacheOpfDom) { + var buildRenditionMapping = function(callback, multipleRenditions, containerXmlDom, packageFullPath, cacheOpfDom) { var doCallback = true; - _multipleRenditions.mappings = []; + multipleRenditions.mappings = []; var linkMapping = $('link[rel=mapping]', containerXmlDom); if (linkMapping.length) { @@ -214,7 +210,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var ul = $(uls[j]); var mappingUL = []; - _multipleRenditions.mappings.push(mappingUL); + multipleRenditions.mappings.push(mappingUL); var lias = $('li > a', ul); for (var k = 0; k < lias.length; k++) { @@ -347,31 +343,31 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } } - callback(packageFullPath); + callback(packageFullPath, multipleRenditions); }, function(error) { - callback(packageFullPath); + callback(packageFullPath, multipleRenditions); } ); } } - if (doCallback) callback(packageFullPath); + if (doCallback) callback(packageFullPath, multipleRenditions); }; - var populateCacheOpfDom = function(i, cacheOpfDom, callback) { + var populateCacheOpfDom = function(i, multipleRenditions, cacheOpfDom, callback) { var next = function(j) { - if (j < _multipleRenditions.renditions.length) { + if (j < multipleRenditions.renditions.length) { console.debug("next populateCacheOpfDom"); - populateCacheOpfDom(j, cacheOpfDom, callback); + populateCacheOpfDom(j, multipleRenditions, cacheOpfDom, callback); } else { console.debug("callback populateCacheOpfDom"); callback(); } }; - var rendition = _multipleRenditions.renditions[i]; + var rendition = multipleRenditions.renditions[i]; var thisOpfPath = rendition.opfPath.substr(1); @@ -395,8 +391,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }; - - var getRootFile = function(containerXmlDom) { + var getRootFile = function(containerXmlDom, multipleRenditions) { //console.debug(containerXmlDom.documentElement.innerHTML); console.debug("@@@@@@@@@@@@@@@@@@ getRootFile"); @@ -411,10 +406,8 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var rootFiles = $('rootfile', containerXmlDom); //console.debug(rootFiles); - _multipleRenditions = {}; - - _multipleRenditions.renditions = []; - _multipleRenditions.selectedIndex = -1; + multipleRenditions.renditions = []; + multipleRenditions.selectedIndex = -1; var rootFile = undefined; @@ -437,8 +430,8 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso rendition.opfPath = "/" + rootFile.attr('full-path'); console.debug("opfPath: ", rendition.opfPath); - _multipleRenditions.renditions.push(rendition); - _multipleRenditions.selectedIndex = 0; + multipleRenditions.renditions.push(rendition); + multipleRenditions.selectedIndex = 0; } else { for (var i = 0; i < rootFiles.length; i++) { @@ -451,7 +444,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso rendition.Label = undefined; rendition.opfPath = undefined; - _multipleRenditions.renditions.push(rendition); + multipleRenditions.renditions.push(rendition); } var selectedIndex = -1; @@ -460,7 +453,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso console.debug("----- ROOT FILE #" + i); - var rendition = _multipleRenditions.renditions[i]; + var rendition = multipleRenditions.renditions[i]; var rf = $(rootFiles[i]); @@ -572,7 +565,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso rootFile = $(rootFiles[selectedIndex]); } - _multipleRenditions.selectedIndex = selectedIndex; + multipleRenditions.selectedIndex = selectedIndex; } var packageFullPath = rootFile.attr('full-path'); @@ -580,26 +573,28 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }; - + var _multipleRenditions = undefined; var _OpfPath = undefined; this.getPackageFullPath = function(callback, onerror) { if (_OpfPath) { - callback(_OpfPath); + callback(_OpfPath, _multipleRenditions); return; } self.getXmlFileDom('META-INF/container.xml', function(containerXmlDom) { - _OpfPath = getRootFile(containerXmlDom); + _multipleRenditions = {}; + + _OpfPath = getRootFile(containerXmlDom, _multipleRenditions); var cacheOpfDom = {}; if (_multipleRenditions.renditions.length) { - populateCacheOpfDom(0, cacheOpfDom, function() { - buildRenditionMapping(callback, containerXmlDom, _OpfPath, cacheOpfDom); + populateCacheOpfDom(0, _multipleRenditions, cacheOpfDom, function() { + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _OpfPath, cacheOpfDom); }); } else { - buildRenditionMapping(callback, containerXmlDom, _OpfPath, cacheOpfDom); + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _OpfPath, cacheOpfDom); } }, onerror); @@ -617,8 +612,8 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } else { _packageDomInitializationDeferred = $.Deferred(); _packageDomInitializationDeferred.done(callback); - self.getPackageFullPath(function (packageFullPath) { - _packageFullPath = packageFullPath; + self.getPackageFullPath(function (packageFullPath, multipleRenditions) { + self.getXmlFileDom(packageFullPath, function (packageDom) { _packageDom = packageDom; _packageDomInitializationDeferred.resolve(packageDom); @@ -630,7 +625,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }; this.convertPathRelativeToPackageToRelativeToBase = function (relativeToPackagePath) { - return new URI(relativeToPackagePath).absoluteTo(_packageFullPath).toString(); + return new URI(relativeToPackagePath).absoluteTo(_OpfPath).toString(); }; this.relativeToPackageFetchFileContents = function(relativeToPackagePath, fetchMode, fetchCallback, onerror) { diff --git a/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js b/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js index f27a61659..6e7b26fde 100644 --- a/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js +++ b/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js @@ -67,10 +67,6 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func // PUBLIC API - this.getPackageUrl = function() { - return baseUrl; - }; - this.fetchFileContentsText = function(relativePathRelativeToPackageRoot, fetchCallback, onerror) { fetchFileContents(relativePathRelativeToPackageRoot, function (entry) { diff --git a/epub-modules/epub-renderer/src/readium-shared-js b/epub-modules/epub-renderer/src/readium-shared-js index 22b451374..3b272513a 160000 --- a/epub-modules/epub-renderer/src/readium-shared-js +++ b/epub-modules/epub-renderer/src/readium-shared-js @@ -1 +1 @@ -Subproject commit 22b451374a437e55bd23c8337399dabeab5837a8 +Subproject commit 3b272513a829c4c988a195db5bce4da1e935d588 diff --git a/epub-modules/epub/src/models/package_document.js b/epub-modules/epub/src/models/package_document.js index da4a45633..46b28852e 100644 --- a/epub-modules/epub/src/models/package_document.js +++ b/epub-modules/epub/src/models/package_document.js @@ -15,7 +15,7 @@ define(['require', 'module', 'jquery', 'underscore', 'backbone', 'URIjs'], function (require, module, $, _, Backbone, URI) { // Description: This model provides an interface for navigating an EPUB's package document - var PackageDocument = function(packageDocumentURL, resourceFetcher, metadata, spine, manifest) { + var PackageDocument = function(packageDocRoot, publicationFetcher, metadata, spine, manifest) { var _page_prog_dir; @@ -23,7 +23,6 @@ define(['require', 'module', 'jquery', 'underscore', 'backbone', 'URIjs'], this.getSharedJsPackageData = function () { - var packageDocRoot = packageDocumentURL.substr(0, packageDocumentURL.lastIndexOf("/")); return { rootUrl : packageDocRoot, rendition_viewport : metadata.rendition_viewport, @@ -85,7 +84,7 @@ define(['require', 'module', 'jquery', 'underscore', 'backbone', 'URIjs'], this.getTocText = function(callback) { var toc = this.getToc(); - resourceFetcher.relativeToPackageFetchFileContents(toc, 'text', function (tocDocumentText) { + publicationFetcher.relativeToPackageFetchFileContents(toc, 'text', function (tocDocumentText) { callback(tocDocumentText) }, function (err) { console.error('ERROR fetching TOC from [' + toc + ']:'); @@ -118,6 +117,7 @@ define(['require', 'module', 'jquery', 'underscore', 'backbone', 'URIjs'], $ncxOrderedList = getNcxOrderedList($("navMap", tocDom)); callback($ncxOrderedList[0]); } else { + var packageDocumentURL = publicationFetcher.getPackageUrl(); var packageDocumentAbsoluteURL = new URI(packageDocumentURL).absoluteTo(document.URL); var tocDocumentAbsoluteURL = new URI(that.getToc()).absoluteTo(packageDocumentAbsoluteURL); // add a BASE tag to change the TOC document's baseURI. diff --git a/epub-modules/epub/src/models/package_document_parser.js b/epub-modules/epub/src/models/package_document_parser.js index 278051116..d9e74da64 100644 --- a/epub-modules/epub/src/models/package_document_parser.js +++ b/epub-modules/epub/src/models/package_document_parser.js @@ -21,7 +21,6 @@ define(['require', 'module', 'jquery', 'underscore', 'backbone', 'epub-fetch/mar // instance of `URI` that is used to resolve paths during the process var PackageDocumentParser = function(bookRoot, publicationFetcher) { - var _packageFetcher = publicationFetcher; var _deferredXmlDom = $.Deferred(); var _xmlDom; @@ -76,8 +75,13 @@ define(['require', 'module', 'jquery', 'underscore', 'backbone', 'epub-fetch/mar $.when(updateMetadataWithIBookProperties(metadata)).then(function() { - _packageFetcher.setPackageMetadata(metadata, function () { - var packageDocument = new PackageDocument(publicationFetcher.getPackageUrl(), + publicationFetcher.setPackageMetadata(metadata, function () { + + var packageDocumentURL = publicationFetcher.getPackageUrl(); + var i = packageDocumentURL.lastIndexOf("/"); + var packageDocRoot = i > 0 ? packageDocumentURL.substr(0, i) : ""; + + var packageDocument = new PackageDocument(packageDocRoot, publicationFetcher, metadata, spine, manifest); packageDocument.setPageProgressionDirection(page_prog_dir); diff --git a/rjs_require_config.js b/rjs_require_config.js index fcc000d2e..0e5c5b571 100644 --- a/rjs_require_config.js +++ b/rjs_require_config.js @@ -55,6 +55,7 @@ var requirejs = { mediaOvelayDataInjector: 'epub-modules/epub-renderer/src/readium-shared-js/js/views/media_overlay_data_injector', internalLinksSupport: 'epub-modules/epub-renderer/src/readium-shared-js/js/views/internal_links_support', iframeLoader: 'epub-modules/epub-renderer/src/readium-shared-js/js/views/iframe_loader', + multipleRenditions: 'epub-modules/epub-renderer/src/readium-shared-js/js/models/multiple_renditions', domReady : 'lib/domReady', @@ -296,16 +297,21 @@ var requirejs = { deps:['readiumSDK', 'URIjs'], exports: 'internalLinksSupport' }, - + iframeLoader: { deps:['readiumSDK'], exports: 'iframeLoader' }, + + multipleRenditions: { + exports: 'multipleRenditions' + }, readerView : { deps: [ 'backbone','readiumSDK', 'helpers', 'viewerSettings', 'styleCollection', 'package', 'mediaOverlayPlayer', 'pageOpenRequest', 'fixedView', 'reflowableView', 'mediaOvelayDataInjector', - 'internalLinksSupport', 'iframeLoader', 'annotationsManager', 'scrollView', 'URIjs', 'triggers', 'switches'], + 'internalLinksSupport', 'iframeLoader', 'annotationsManager', 'scrollView', 'URIjs', 'triggers', 'switches', + 'multipleRenditions'], exports:'readerView' }, From 0c7daf97a136b5ec608c8234d07f8556eae7bd79 Mon Sep 17 00:00:00 2001 From: danielweck Date: Mon, 16 Feb 2015 22:46:27 +0000 Subject: [PATCH 09/26] fixes to EPUB3 Multiple Renditions (now working fine, in both zipped and expanded EPUB modes) --- epub-modules/Readium.js | 4 + .../src/models/plain_resource_fetcher.js | 17 +- .../src/models/publication_fetcher.js | 236 +++++++++--------- .../src/models/zip_resource_fetcher.js | 4 + .../epub-renderer/src/readium-shared-js | 2 +- 5 files changed, 132 insertions(+), 131 deletions(-) diff --git a/epub-modules/Readium.js b/epub-modules/Readium.js index e47d2e223..901112e52 100644 --- a/epub-modules/Readium.js +++ b/epub-modules/Readium.js @@ -93,6 +93,10 @@ define(['require', 'text!version.json', 'console_shim', 'jquery', 'underscore', openBookData = $.extend(openBookData, {multipleRenditions: multipleRenditions}); + if (openPageRequest) { + openBookData.openPageRequest = openPageRequest; + } + self.reader.openBook(openBookData); var options = { diff --git a/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js b/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js index e9b7392fa..68c85a2cb 100644 --- a/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js +++ b/epub-modules/epub-fetch/src/models/plain_resource_fetcher.js @@ -21,9 +21,6 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func return baseUrl + "/" + pathRelativeToPackageRoot; }; - var _packageDocumentRelativePath = parentFetcher.getPackageUrl(); - var _packageDocumentAbsoluteUrl = _packageDocumentRelativePath ? resolveURI(_packageDocumentRelativePath) : baseUrl; - // INTERNAL FUNCTIONS function fetchFileContents(pathRelativeToPackageRoot, readCallback, onerror) { @@ -47,6 +44,11 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func // PUBLIC API + this.getPackageUrl = function(opfPath) { + + return resolveURI(opfPath); + }; + this.fetchFileContentsData64Uri = function(relativePathRelativeToPackageRoot, fetchCallback, onerror) { //TODO!? (potentially invoked from PublicationFetcher.relativeToPackageFetchFileContents(), also see ZipResourceFetcher implementation of fetchFileContentsData64Uri()) }; @@ -111,15 +113,6 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func fetchCallback(blob); }, onerror); }; - - /* - this.getPackageDom = function (callback, onerror) { - self.fetchFileContentsText(_packageDocumentRelativePath, function (packageXml) { - var packageDom = parentFetcher.markupParser.parseXml(packageXml); - callback(packageDom); - }, onerror); - }; - */ }; return PlainResourceFetcher; diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index 282d32c09..24393ab6b 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -54,7 +54,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso // Non exploded EPUBs (i.e. zipped .epub documents) should be fetched in a programmatical manner: _shouldConstructDomProgrammatically = !isEpubExploded; - if (isExploded) { + if (isEpubExploded) { console.log('using new PlainResourceFetcher'); _resourceFetcher = new PlainResourceFetcher(self, bookRoot); @@ -63,7 +63,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso _resourceFetcher = new ZipResourceFetcher(self, bookRoot, jsLibRoot); } - this.getPackageFullPath( + getPackageFullPath( function (packageFullPath, multipleRenditions) { callback(_resourceFetcher, multipleRenditions); }, @@ -90,86 +90,6 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } - // PUBLIC API - - /** - * Determine whether the documents fetched using this fetcher require special programmatic handling. - * (resolving of internal resource references). - * @returns {*} true if documents fetched using this fetcher require special programmatic handling - * (resolving of internal resource references). Typically needed for zipped EPUBs or exploded EPUBs that contain - * encrypted resources specified in META-INF/encryption.xml. - * - * false if documents can be fed directly into a window or iframe by src URL without using special fetching logic. - */ - this.shouldConstructDomProgrammatically = function (){ - return _shouldConstructDomProgrammatically; - }; - - /** - * Determine whether the media assets (audio, video, images) within content documents require special - * programmatic handling. - * @returns {*} true if content documents fetched using this fetcher require programmatic fetching - * of media assets. Typically needed for zipped EPUBs. - * - * false if paths to media assets are accessible directly for the browser through their paths relative to - * the base URI of their content document. - */ - this.shouldFetchMediaAssetsProgrammatically = function() { - return _shouldConstructDomProgrammatically && !isExploded(); - }; - - this.getBookRoot = function() { - return bookRoot; - }; - - this.getJsLibRoot = function() { - return jsLibRoot; - }; - - this.flushCache = function() { - _publicationResourcesCache.flushCache(); - }; - - this.cleanup = function() { - self.flushCache(); - - if (_mediaQueryEventCallback) { - _mediaQuery.removeListener(_mediaQueryEventCallback); - _mediaQueryEventCallback = undefined; - } - }; - - this.getPackageUrl = function() { - return _OpfPath; // set in initialize() - }; - - this.fetchContentDocument = function (attachedData, loadedDocumentUri, contentDocumentResolvedCallback, errorCallback) { - - // Resources loaded for previously fetched document no longer need to be pinned: - _publicationResourcesCache.unPinResources(); - var contentDocumentFetcher = new ContentDocumentFetcher(self, attachedData.spineItem, loadedDocumentUri, _publicationResourcesCache, _contentDocumentTextPreprocessor); - contentDocumentFetcher.fetchContentDocumentAndResolveDom(contentDocumentResolvedCallback, function (err) { - _handleError(err); - errorCallback(err); - }); - }; - - this.getFileContentsFromPackage = function(filePathRelativeToPackageRoot, callback, onerror) { - - _resourceFetcher.fetchFileContentsText(filePathRelativeToPackageRoot, function (fileContents) { - callback(fileContents); - }, onerror); - }; - - - - this.getXmlFileDom = function (xmlFilePathRelativeToPackageRoot, callback, onerror) { - self.getFileContentsFromPackage(xmlFilePathRelativeToPackageRoot, function (xmlFileContents) { - var fileDom = self.markupParser.parseXml(xmlFileContents); - callback(fileDom); - }, onerror); - }; - var buildRenditionMapping = function(callback, multipleRenditions, containerXmlDom, packageFullPath, cacheOpfDom) { var doCallback = true; @@ -575,7 +495,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso var _multipleRenditions = undefined; var _OpfPath = undefined; - this.getPackageFullPath = function(callback, onerror) { + getPackageFullPath = function(callback, onerror) { if (_OpfPath) { callback(_OpfPath, _multipleRenditions); return; @@ -600,6 +520,120 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso }, onerror); }; + var readEncriptionData = function(callback) { + self.getXmlFileDom('META-INF/encryption.xml', function (encryptionDom, error) { + + if(error) { + console.log(error); + console.log("Document doesn't make use of encryption."); + _encryptionHandler = new EncryptionHandler(undefined); + callback(); + } + else { + + var encryptions = []; + + + var encryptedData = $('EncryptedData', encryptionDom); + encryptedData.each(function (index, encryptedData) { + var encryptionAlgorithm = $('EncryptionMethod', encryptedData).first().attr('Algorithm'); + + encryptions.push({algorithm: encryptionAlgorithm}); + + // For some reason, jQuery selector "" against XML DOM sometimes doesn't match properly + var cipherReference = $('CipherReference', encryptedData); + cipherReference.each(function (index, CipherReference) { + var cipherReferenceURI = $(CipherReference).attr('URI'); + console.log('Encryption/obfuscation algorithm ' + encryptionAlgorithm + ' specified for ' + + cipherReferenceURI); + encryptions[cipherReferenceURI] = encryptionAlgorithm; + }); + }); + } + + }); + }; + + // PUBLIC API + + /** + * Determine whether the documents fetched using this fetcher require special programmatic handling. + * (resolving of internal resource references). + * @returns {*} true if documents fetched using this fetcher require special programmatic handling + * (resolving of internal resource references). Typically needed for zipped EPUBs or exploded EPUBs that contain + * encrypted resources specified in META-INF/encryption.xml. + * + * false if documents can be fed directly into a window or iframe by src URL without using special fetching logic. + */ + this.shouldConstructDomProgrammatically = function (){ + return _shouldConstructDomProgrammatically; + }; + + /** + * Determine whether the media assets (audio, video, images) within content documents require special + * programmatic handling. + * @returns {*} true if content documents fetched using this fetcher require programmatic fetching + * of media assets. Typically needed for zipped EPUBs. + * + * false if paths to media assets are accessible directly for the browser through their paths relative to + * the base URI of their content document. + */ + this.shouldFetchMediaAssetsProgrammatically = function() { + return _shouldConstructDomProgrammatically && !isExploded(); + }; + + this.getBookRoot = function() { + return bookRoot; + }; + + this.getJsLibRoot = function() { + return jsLibRoot; + }; + + this.flushCache = function() { + _publicationResourcesCache.flushCache(); + }; + + this.cleanup = function() { + self.flushCache(); + + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + _mediaQueryEventCallback = undefined; + } + }; + + this.getPackageUrl = function() { + return _resourceFetcher.getPackageUrl(_OpfPath); // set in initialize() + }; + + this.fetchContentDocument = function (attachedData, loadedDocumentUri, contentDocumentResolvedCallback, errorCallback) { + + // Resources loaded for previously fetched document no longer need to be pinned: + _publicationResourcesCache.unPinResources(); + var contentDocumentFetcher = new ContentDocumentFetcher(self, attachedData.spineItem, loadedDocumentUri, _publicationResourcesCache, _contentDocumentTextPreprocessor); + contentDocumentFetcher.fetchContentDocumentAndResolveDom(contentDocumentResolvedCallback, function (err) { + _handleError(err); + errorCallback(err); + }); + }; + + this.getFileContentsFromPackage = function(filePathRelativeToPackageRoot, callback, onerror) { + + _resourceFetcher.fetchFileContentsText(filePathRelativeToPackageRoot, function (fileContents) { + callback(fileContents); + }, onerror); + }; + + + + this.getXmlFileDom = function (xmlFilePathRelativeToPackageRoot, callback, onerror) { + self.getFileContentsFromPackage(xmlFilePathRelativeToPackageRoot, function (xmlFileContents) { + var fileDom = self.markupParser.parseXml(xmlFileContents); + callback(fileDom); + }, onerror); + }; + this.getPackageDom = function (callback, onerror) { if (_packageDom) { callback(_packageDom); @@ -612,7 +646,7 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } else { _packageDomInitializationDeferred = $.Deferred(); _packageDomInitializationDeferred.done(callback); - self.getPackageFullPath(function (packageFullPath, multipleRenditions) { + getPackageFullPath(function (packageFullPath, multipleRenditions) { self.getXmlFileDom(packageFullPath, function (packageDom) { _packageDom = packageDom; @@ -654,40 +688,6 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso self.getXmlFileDom(self.convertPathRelativeToPackageToRelativeToBase(filePath), callback, errorCallback); }; - function readEncriptionData(callback) { - self.getXmlFileDom('META-INF/encryption.xml', function (encryptionDom, error) { - - if(error) { - console.log(error); - console.log("Document doesn't make use of encryption."); - _encryptionHandler = new EncryptionHandler(undefined); - callback(); - } - else { - - var encryptions = []; - - - var encryptedData = $('EncryptedData', encryptionDom); - encryptedData.each(function (index, encryptedData) { - var encryptionAlgorithm = $('EncryptionMethod', encryptedData).first().attr('Algorithm'); - - encryptions.push({algorithm: encryptionAlgorithm}); - - // For some reason, jQuery selector "" against XML DOM sometimes doesn't match properly - var cipherReference = $('CipherReference', encryptedData); - cipherReference.each(function (index, CipherReference) { - var cipherReferenceURI = $(CipherReference).attr('URI'); - console.log('Encryption/obfuscation algorithm ' + encryptionAlgorithm + ' specified for ' + - cipherReferenceURI); - encryptions[cipherReferenceURI] = encryptionAlgorithm; - }); - }); - } - - }); - } - // Currently needed for deobfuscating fonts this.setPackageMetadata = function(packageMetadata, settingFinishedCallback) { diff --git a/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js b/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js index 6e7b26fde..b4ded683b 100644 --- a/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js +++ b/epub-modules/epub-fetch/src/models/zip_resource_fetcher.js @@ -67,6 +67,10 @@ define(['require', 'module', 'jquery', 'URIjs', './discover_content_type'], func // PUBLIC API + this.getPackageUrl = function(opfPath) { + return baseUrl; + }; + this.fetchFileContentsText = function(relativePathRelativeToPackageRoot, fetchCallback, onerror) { fetchFileContents(relativePathRelativeToPackageRoot, function (entry) { diff --git a/epub-modules/epub-renderer/src/readium-shared-js b/epub-modules/epub-renderer/src/readium-shared-js index 3b272513a..55ae3abb0 160000 --- a/epub-modules/epub-renderer/src/readium-shared-js +++ b/epub-modules/epub-renderer/src/readium-shared-js @@ -1 +1 @@ -Subproject commit 3b272513a829c4c988a195db5bce4da1e935d588 +Subproject commit 55ae3abb0efdf3dad6cabceb975a9ab8a2b41671 From 81ba44c191321c7c97e74834e9e5eacc8783c988 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Feb 2015 10:27:53 +0000 Subject: [PATCH 10/26] default (first) rendition for first-time load or no-preferences app --- .../epub-fetch/src/models/publication_fetcher.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/epub-modules/epub-fetch/src/models/publication_fetcher.js b/epub-modules/epub-fetch/src/models/publication_fetcher.js index 24393ab6b..b6da58ae8 100644 --- a/epub-modules/epub-fetch/src/models/publication_fetcher.js +++ b/epub-modules/epub-fetch/src/models/publication_fetcher.js @@ -431,7 +431,9 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso //continue; } } - +console.log("######################################"); +console.debug(_renditionSelection); +console.log("######################################"); if (_renditionSelection && (typeof _renditionSelection.renditionLayout !== "undefined") && renditionLayout && renditionLayout !== "") { if (_renditionSelection.renditionLayout !== renditionLayout) { console.debug("=== EJECTED: renditionLayout"); @@ -476,7 +478,10 @@ define(['require', 'module', 'jquery', 'URIjs', './markup_parser', './plain_reso } } - if (!rootFile) { + if (!rootFile + // first-time load, or app with no preferences at all + || (_renditionSelection && (typeof _renditionSelection.renditionAccessMode === "undefined") && (typeof _renditionSelection.renditionLanguage === "undefined") && (typeof _renditionSelection.renditionLayout === "undefined")) + ) { // fallback to index zero ... is that a valid interpretation of the EPUB3 specification?? // See Processing Model: //http://www.idpf.org/epub/renditions/multiple/epub-multiple-renditions.html#h.4n44azuq1490 From 4492e1015947750cfbac3d7fbd077c68164c67fc Mon Sep 17 00:00:00 2001 From: danielweck Date: Sat, 21 Feb 2015 00:54:36 +0000 Subject: [PATCH 11/26] missing RequireJS dep --- rjs_require_config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/rjs_require_config.js b/rjs_require_config.js index 0e5c5b571..959d4f15c 100644 --- a/rjs_require_config.js +++ b/rjs_require_config.js @@ -304,6 +304,7 @@ var requirejs = { }, multipleRenditions: { + deps: ['readiumSDK'], exports: 'multipleRenditions' }, From 1a2e01c8a592495d8fa25b0a4e6f2d3a90da05d8 Mon Sep 17 00:00:00 2001 From: danielweck Date: Sun, 12 Jul 2015 06:32:15 +0100 Subject: [PATCH 12/26] fixed Multiple Renditions post-merge (AMD-RequireJS refactoring) --- js/Readium.js | 7 ++++--- js/epub-fetch/plain_resource_fetcher.js | 4 ++-- js/epub-fetch/publication_fetcher.js | 2 +- readium-shared-js | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/js/Readium.js b/js/Readium.js index c1c7c22be..34e53daa9 100644 --- a/js/Readium.js +++ b/js/Readium.js @@ -73,7 +73,7 @@ define(['text!version.json', 'jquery', 'underscore', 'readium_shared_js/views/re this.reader = new ReaderView(readerOptions); ReadiumSDK.reader = this.reader; - this.openPackageDocument = function(bookRoot, callback, openPageRequest) { + this.openPackageDocument = function(bookRoot, callback, openPageRequest, renditionSelection) { if (_currentPublicationFetcher) { _currentPublicationFetcher.flushCache(); } @@ -83,15 +83,16 @@ define(['text!version.json', 'jquery', 'underscore', 'readium_shared_js/views/re cacheSizeEvictThreshold = readiumOptions.cacheSizeEvictThreshold; } - _currentPublicationFetcher = new PublicationFetcher(bookRoot, jsLibRoot, window, cacheSizeEvictThreshold, _contentDocumentTextPreprocessor); + _currentPublicationFetcher = new PublicationFetcher(bookRoot, jsLibRoot, window, cacheSizeEvictThreshold, _contentDocumentTextPreprocessor, renditionSelection); - _currentPublicationFetcher.initialize(function(resourceFetcher) { + _currentPublicationFetcher.initialize(function(resourceFetcher, multipleRenditions) { var _packageParser = new PackageParser(bookRoot, _currentPublicationFetcher); _packageParser.parse(function(packageDocument){ var openBookOptions = readiumOptions.openBookOptions || {}; var openBookData = $.extend(packageDocument.getSharedJsPackageData(), openBookOptions); + openBookData = $.extend(openBookData, {multipleRenditions: multipleRenditions}); if (openPageRequest) { openBookData.openPageRequest = openPageRequest; diff --git a/js/epub-fetch/plain_resource_fetcher.js b/js/epub-fetch/plain_resource_fetcher.js index 000625b49..1bf812d7c 100644 --- a/js/epub-fetch/plain_resource_fetcher.js +++ b/js/epub-fetch/plain_resource_fetcher.js @@ -20,7 +20,7 @@ define(['jquery', 'URIjs', './discover_content_type'], function ($, URI, Content // INTERNAL FUNCTIONS function fetchFileContents(pathRelativeToPackageRoot, readCallback, onerror) { - var fileUrl = resolveURI(pathRelativeToPackageRoot); + var fileUrl = self.resolveURI(pathRelativeToPackageRoot); if (typeof pathRelativeToPackageRoot === 'undefined') { throw 'Fetched file relative path is undefined!'; @@ -45,7 +45,7 @@ define(['jquery', 'URIjs', './discover_content_type'], function ($, URI, Content }; this.fetchFileContentsText = function(pathRelativeToPackageRoot, fetchCallback, onerror) { - var fileUrl = resolveURI(pathRelativeToPackageRoot); + var fileUrl = self.resolveURI(pathRelativeToPackageRoot); if (typeof fileUrl === 'undefined') { throw 'Fetched file URL is undefined!'; diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index c08ec7389..c22a6fd41 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -502,7 +502,7 @@ console.log("######################################"); var _multipleRenditions = undefined; - getPackageFullPath = function(callback, onerror) { + this.getPackageFullPath = function(callback, onerror) { if (_packageFullPath) { callback(_packageFullPath, _multipleRenditions); return; diff --git a/readium-shared-js b/readium-shared-js index bfb18d1a2..b6af3a672 160000 --- a/readium-shared-js +++ b/readium-shared-js @@ -1 +1 @@ -Subproject commit bfb18d1a24da86cda9f92ada86406749bb6d9c2f +Subproject commit b6af3a6723c83b6c6168064cf55beff35db32409 From 43c583dbe1fa51d4ac4f67dbda9aa0653d8bab9d Mon Sep 17 00:00:00 2001 From: danielweck Date: Mon, 28 Sep 2015 10:22:14 +0100 Subject: [PATCH 13/26] merge fix --- js/Readium.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/Readium.js b/js/Readium.js index cccab4dff..3e8a6c5bc 100644 --- a/js/Readium.js +++ b/js/Readium.js @@ -115,7 +115,7 @@ define(['text!version.json', 'jquery', 'underscore', 'readium_shared_js/views/re }; - this.openPackageDocument = function(ebookURL, callback, openPageRequest) { + this.openPackageDocument = function(ebookURL, callback, openPageRequest, renditionSelection) { if (!(ebookURL instanceof Blob) // && ebookURL.indexOf("file://") != 0 @@ -185,7 +185,7 @@ define(['text!version.json', 'jquery', 'underscore', 'readium_shared_js/views/re } } - openPackageDocument_(ebookURL, callback, openPageRequest, contentType); + openPackageDocument_(ebookURL, callback, openPageRequest, contentType, renditionSelection); }; xhr.open('HEAD', ebookURL, true); //xhr.responseType = 'blob'; @@ -195,7 +195,7 @@ define(['text!version.json', 'jquery', 'underscore', 'readium_shared_js/views/re } } - openPackageDocument_(ebookURL, callback, openPageRequest); + openPackageDocument_(ebookURL, callback, openPageRequest, undefined, renditionSelection); }; this.closePackageDocument = function() { From 41bdf9fec0d1762039805689bec9f1013eb1d800 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:28:19 +0000 Subject: [PATCH 14/26] 4x spaces indentation instead of tab character --- js/epub-fetch/publication_fetcher.js | 862 +++++++++++------------ js/epub-fetch/zip_resource_fetcher.js | 2 +- js/epub-model/package_document.js | 2 +- js/epub-model/package_document_parser.js | 10 +- readium-shared-js | 2 +- 5 files changed, 439 insertions(+), 439 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 9f82533ab..93fee1ea7 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -32,19 +32,19 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip var _packageFullPath; var _packageDocumentAbsoluteUrl; - + var _packageDom; var _packageDomInitializationDeferred; var _publicationResourcesCache = new ResourceCache(sourceWindow, cacheSizeEvictThreshold); - var _mediaQuery = undefined; - var _mediaQueryEventCallback = undefined; - + var _mediaQuery = undefined; + var _mediaQueryEventCallback = undefined; + var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; var _contentType = contentType; - var _renditionSelection = renditionSelection; + var _renditionSelection = renditionSelection; this.markupParser = new MarkupParser(); @@ -109,438 +109,438 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip // INTERNAL FUNCTIONS - var buildRenditionMapping = function(callback, multipleRenditions, containerXmlDom, packageFullPath, cacheOpfDom) { - - var doCallback = true; - - multipleRenditions.mappings = []; - - var linkMapping = $('link[rel=mapping]', containerXmlDom); - if (linkMapping.length) { - var href = linkMapping.attr("href"); - console.debug('link[rel=mapping] @href ==> ' + href); - if (href) { - - var hrefParentFolder = ""; - var slashi = href.lastIndexOf("/"); - if (slashi > 0) { - hrefParentFolder = href.substr(0, slashi); - } - hrefParentFolder = "/" + hrefParentFolder; - console.debug(hrefParentFolder); - - doCallback = false; - - self.getXmlFileDom(href, - function (mappingDom) { - //var nav = $('nav[epub\\:type=resource-map]', mappingDom); - //var nav = $('nav[type=resource-map]', mappingDom); - var navs = $('nav', mappingDom); - if (navs.length) { - for (var i = 0; i < navs.length; i++) { - var nav = $(navs[i]); - - var epubtype = nav.attr("epub:type"); - if (epubtype !== "resource-map") { - continue; - } - var uls = $('ul', nav); - for (var j = 0; j < uls.length; j++) { - var ul = $(uls[j]); - - var mappingUL = []; - multipleRenditions.mappings.push(mappingUL); - - var lias = $('li > a', ul); - for (var k = 0; k < lias.length; k++) { - var lia = $(lias[k]); - var ahref = lia.attr("href"); - var arendition = lia.attr("epub:rendition"); - - var mapping = {}; - mappingUL.push(mapping); - - mapping.href = ahref; - mapping.rendition = arendition; - - var hashi = mapping.href.indexOf("#epubcfi"); - - // this is relative to the mapping HTML doc, not to the root of the EPUB file tree - mapping.opf = mapping.rendition; - if (!mapping.opf) { - if (hashi > 0) { - var opfPath = mapping.href.substr(0, hashi); - mapping.opf = opfPath; - } - } - mapping.opf = hrefParentFolder + "/" + mapping.opf; - - var cfiOpfSpineItem = undefined; - mapping.cfiFull = undefined; - mapping.cfiPartial = undefined; - if (hashi > 0) { - var offset = hashi + 9; - mapping.cfiFull = mapping.href.substr(offset, mapping.href.length-offset-1); - cfiOpfSpineItem = mapping.cfiFull; - - var excli = mapping.cfiFull.indexOf("!"); - if (excli > 0) { - var offset = excli + 1; - mapping.cfiPartial = mapping.cfiFull.substr(offset, mapping.cfiFull.length-offset); - cfiOpfSpineItem = mapping.cfiFull.substr(0, offset-1); - } - } - - //OPF: packageFullPath - //MAPPING: href - - mapping.target = undefined; - if (mapping.rendition) { - // this is relative to the mapping HTML doc, not to the root of the EPUB file tree - mapping.target = mapping.href; - mapping.target = hrefParentFolder + "/" + mapping.target; - } else { - // this is relative to the root of the EPUB file tree - - //console.debug("cfiOpfSpineItem: " + cfiOpfSpineItem); - var slashi = cfiOpfSpineItem.lastIndexOf("/"); - if (slashi > 0) { - var nStr = cfiOpfSpineItem.substr(slashi + 1, 1); - var n = parseInt(nStr); - n = n / 2 - 1; - // n is zero-based index of spine item child element in OPF - - if (mapping.opf) { - var f = function() { - var itemRefIndex = n; - var thisOpfPath = mapping.opf.substr(1); - var mapping_ = mapping; - - var thisOpfPathParentFolder = ""; - var slashi = thisOpfPath.lastIndexOf("/"); - if (slashi > 0) { - thisOpfPathParentFolder = thisOpfPath.substr(0, slashi); - } - thisOpfPathParentFolder = "/" + thisOpfPathParentFolder; - //console.debug(">>> " + thisOpfPathParentFolder); - - var processOpfDom = function(opfDom) { - - var itemRefs = $('itemref', opfDom); - if (itemRefs.length) { - var itemRef = $(itemRefs[itemRefIndex]); - var idref = itemRef.attr("idref"); - mapping_.idref = idref; - - var item = $('#' + idref, opfDom); - if (item.length) { - var itemHref = item.attr("href"); - mapping_.target = itemHref; - mapping_.target = thisOpfPathParentFolder + "/" + mapping_.target; - //console.debug(">>> " + mapping_.target); - //console.debug(mapping_); - } - } - }; - - var dom = cacheOpfDom[thisOpfPath]; - if (dom) { - //console.debug("*** CACHED OPF DOM: " + thisOpfPath); - processOpfDom(dom); - } - else { - // Async! - // Should never occur, - // because the cacheOpfDom array was initialised in populateCacheOpfDom(), - // based upon renditions declared in META-INF/container.xml - console.debug("*** PARSING OPF DOM: " + thisOpfPath); - self.getXmlFileDom(thisOpfPath, - function (opfDom) { - cacheOpfDom[thisOpfPath] = opfDom; - processOpfDom(opfDom); - }, - function(error) { - } - ); - } - - }(); - } - } - } - - /* - console.debug("============"); - console.log("- href: " + mapping.href); - console.log("- rendition: " + mapping.rendition); - console.log("opf: " + mapping.opf); - console.log("cfiFull: " + mapping.cfiFull); - console.log("cfiPartial: " + mapping.cfiPartial); - console.log("target: " + mapping.target); - */ - } - } - } - } - callback(packageFullPath, multipleRenditions); - }, - function(error) { - callback(packageFullPath, multipleRenditions); - } - ); - } - } - - if (doCallback) callback(packageFullPath, multipleRenditions); - }; - - var populateCacheOpfDom = function(i, multipleRenditions, cacheOpfDom, callback) { - - var next = function(j) { - if (j < multipleRenditions.renditions.length) { - console.debug("next populateCacheOpfDom"); - populateCacheOpfDom(j, multipleRenditions, cacheOpfDom, callback); - } else { - console.debug("callback populateCacheOpfDom"); - callback(); - } - }; - - var rendition = multipleRenditions.renditions[i]; - - var thisOpfPath = rendition.opfPath.substr(1); - - if (cacheOpfDom[thisOpfPath]) { - - next(i+1); - return; - } - - self.getXmlFileDom(thisOpfPath, - function (opfDom) { - console.error("....cacheOpfDom: " + thisOpfPath); - cacheOpfDom[thisOpfPath] = opfDom; - - next(i+1); - }, - function(error) { - next(i+1); - } - ); - - }; - + var buildRenditionMapping = function(callback, multipleRenditions, containerXmlDom, packageFullPath, cacheOpfDom) { + + var doCallback = true; + + multipleRenditions.mappings = []; + + var linkMapping = $('link[rel=mapping]', containerXmlDom); + if (linkMapping.length) { + var href = linkMapping.attr("href"); + console.debug('link[rel=mapping] @href ==> ' + href); + if (href) { + + var hrefParentFolder = ""; + var slashi = href.lastIndexOf("/"); + if (slashi > 0) { + hrefParentFolder = href.substr(0, slashi); + } + hrefParentFolder = "/" + hrefParentFolder; + console.debug(hrefParentFolder); + + doCallback = false; + + self.getXmlFileDom(href, + function (mappingDom) { + //var nav = $('nav[epub\\:type=resource-map]', mappingDom); + //var nav = $('nav[type=resource-map]', mappingDom); + var navs = $('nav', mappingDom); + if (navs.length) { + for (var i = 0; i < navs.length; i++) { + var nav = $(navs[i]); + + var epubtype = nav.attr("epub:type"); + if (epubtype !== "resource-map") { + continue; + } + var uls = $('ul', nav); + for (var j = 0; j < uls.length; j++) { + var ul = $(uls[j]); + + var mappingUL = []; + multipleRenditions.mappings.push(mappingUL); + + var lias = $('li > a', ul); + for (var k = 0; k < lias.length; k++) { + var lia = $(lias[k]); + var ahref = lia.attr("href"); + var arendition = lia.attr("epub:rendition"); + + var mapping = {}; + mappingUL.push(mapping); + + mapping.href = ahref; + mapping.rendition = arendition; + + var hashi = mapping.href.indexOf("#epubcfi"); + + // this is relative to the mapping HTML doc, not to the root of the EPUB file tree + mapping.opf = mapping.rendition; + if (!mapping.opf) { + if (hashi > 0) { + var opfPath = mapping.href.substr(0, hashi); + mapping.opf = opfPath; + } + } + mapping.opf = hrefParentFolder + "/" + mapping.opf; + + var cfiOpfSpineItem = undefined; + mapping.cfiFull = undefined; + mapping.cfiPartial = undefined; + if (hashi > 0) { + var offset = hashi + 9; + mapping.cfiFull = mapping.href.substr(offset, mapping.href.length-offset-1); + cfiOpfSpineItem = mapping.cfiFull; + + var excli = mapping.cfiFull.indexOf("!"); + if (excli > 0) { + var offset = excli + 1; + mapping.cfiPartial = mapping.cfiFull.substr(offset, mapping.cfiFull.length-offset); + cfiOpfSpineItem = mapping.cfiFull.substr(0, offset-1); + } + } + + //OPF: packageFullPath + //MAPPING: href + + mapping.target = undefined; + if (mapping.rendition) { + // this is relative to the mapping HTML doc, not to the root of the EPUB file tree + mapping.target = mapping.href; + mapping.target = hrefParentFolder + "/" + mapping.target; + } else { + // this is relative to the root of the EPUB file tree + + //console.debug("cfiOpfSpineItem: " + cfiOpfSpineItem); + var slashi = cfiOpfSpineItem.lastIndexOf("/"); + if (slashi > 0) { + var nStr = cfiOpfSpineItem.substr(slashi + 1, 1); + var n = parseInt(nStr); + n = n / 2 - 1; + // n is zero-based index of spine item child element in OPF + + if (mapping.opf) { + var f = function() { + var itemRefIndex = n; + var thisOpfPath = mapping.opf.substr(1); + var mapping_ = mapping; + + var thisOpfPathParentFolder = ""; + var slashi = thisOpfPath.lastIndexOf("/"); + if (slashi > 0) { + thisOpfPathParentFolder = thisOpfPath.substr(0, slashi); + } + thisOpfPathParentFolder = "/" + thisOpfPathParentFolder; + //console.debug(">>> " + thisOpfPathParentFolder); + + var processOpfDom = function(opfDom) { + + var itemRefs = $('itemref', opfDom); + if (itemRefs.length) { + var itemRef = $(itemRefs[itemRefIndex]); + var idref = itemRef.attr("idref"); + mapping_.idref = idref; + + var item = $('#' + idref, opfDom); + if (item.length) { + var itemHref = item.attr("href"); + mapping_.target = itemHref; + mapping_.target = thisOpfPathParentFolder + "/" + mapping_.target; + //console.debug(">>> " + mapping_.target); + //console.debug(mapping_); + } + } + }; + + var dom = cacheOpfDom[thisOpfPath]; + if (dom) { + //console.debug("*** CACHED OPF DOM: " + thisOpfPath); + processOpfDom(dom); + } + else { + // Async! + // Should never occur, + // because the cacheOpfDom array was initialised in populateCacheOpfDom(), + // based upon renditions declared in META-INF/container.xml + console.debug("*** PARSING OPF DOM: " + thisOpfPath); + self.getXmlFileDom(thisOpfPath, + function (opfDom) { + cacheOpfDom[thisOpfPath] = opfDom; + processOpfDom(opfDom); + }, + function(error) { + } + ); + } + + }(); + } + } + } + + /* + console.debug("============"); + console.log("- href: " + mapping.href); + console.log("- rendition: " + mapping.rendition); + console.log("opf: " + mapping.opf); + console.log("cfiFull: " + mapping.cfiFull); + console.log("cfiPartial: " + mapping.cfiPartial); + console.log("target: " + mapping.target); + */ + } + } + } + } + callback(packageFullPath, multipleRenditions); + }, + function(error) { + callback(packageFullPath, multipleRenditions); + } + ); + } + } + + if (doCallback) callback(packageFullPath, multipleRenditions); + }; + + var populateCacheOpfDom = function(i, multipleRenditions, cacheOpfDom, callback) { + + var next = function(j) { + if (j < multipleRenditions.renditions.length) { + console.debug("next populateCacheOpfDom"); + populateCacheOpfDom(j, multipleRenditions, cacheOpfDom, callback); + } else { + console.debug("callback populateCacheOpfDom"); + callback(); + } + }; + + var rendition = multipleRenditions.renditions[i]; + + var thisOpfPath = rendition.opfPath.substr(1); + + if (cacheOpfDom[thisOpfPath]) { + + next(i+1); + return; + } + + self.getXmlFileDom(thisOpfPath, + function (opfDom) { + console.error("....cacheOpfDom: " + thisOpfPath); + cacheOpfDom[thisOpfPath] = opfDom; + + next(i+1); + }, + function(error) { + next(i+1); + } + ); + + }; + var getRootFile = function(containerXmlDom, multipleRenditions) { - //console.debug(containerXmlDom.documentElement.innerHTML); - - console.debug("@@@@@@@@@@@@@@@@@@ getRootFile"); - - - //console.debug("_renditionSelectionrenditionMedia: ", _renditionSelection.renditionMedia); - console.debug("_renditionSelection.renditionLayout: ", _renditionSelection.renditionLayout); - console.debug("_renditionSelection.renditionLanguage: ", _renditionSelection.renditionLanguage); - console.debug("_renditionSelection.renditionAccessMode: ", _renditionSelection.renditionAccessMode); - - + //console.debug(containerXmlDom.documentElement.innerHTML); + + console.debug("@@@@@@@@@@@@@@@@@@ getRootFile"); + + + //console.debug("_renditionSelectionrenditionMedia: ", _renditionSelection.renditionMedia); + console.debug("_renditionSelection.renditionLayout: ", _renditionSelection.renditionLayout); + console.debug("_renditionSelection.renditionLanguage: ", _renditionSelection.renditionLanguage); + console.debug("_renditionSelection.renditionAccessMode: ", _renditionSelection.renditionAccessMode); + + var rootFiles = $('rootfile', containerXmlDom); - //console.debug(rootFiles); - - multipleRenditions.renditions = []; - multipleRenditions.selectedIndex = -1; - - - var rootFile = undefined; - if (rootFiles.length == 1) { - rootFile = rootFiles; - - var renditionMedia = rootFile.attr('rendition:media'); - var renditionLayout = rootFile.attr('rendition:layout'); - var renditionLanguage = rootFile.attr('rendition:language'); - var renditionAccessMode = rootFile.attr('rendition:accessMode'); - - var rendition = {}; - - rendition.Media = renditionMedia; - rendition.Layout = renditionLayout; - rendition.Language = renditionLanguage; - rendition.AccessMode = renditionAccessMode; - rendition.Label = renditionLabel; - - rendition.opfPath = "/" + rootFile.attr('full-path'); - console.debug("opfPath: ", rendition.opfPath); - - multipleRenditions.renditions.push(rendition); - multipleRenditions.selectedIndex = 0; - - } else { - for (var i = 0; i < rootFiles.length; i++) { - var rendition = {}; - - rendition.Media = undefined; - rendition.Layout = undefined; - rendition.Language = undefined; - rendition.AccessMode = undefined; - rendition.Label = undefined; - rendition.opfPath = undefined; - - multipleRenditions.renditions.push(rendition); - } - - var selectedIndex = -1; - - for (var i = rootFiles.length - 1; i >= 0; i--) { - - console.debug("----- ROOT FILE #" + i); - - var rendition = multipleRenditions.renditions[i]; - - var rf = $(rootFiles[i]); - - var renditionMedia = rf.attr('rendition:media'); - var renditionLayout = rf.attr('rendition:layout'); - var renditionLanguage = rf.attr('rendition:language'); - var renditionAccessMode = rf.attr('rendition:accessMode'); - - var renditionLabel = rf.attr('rendition:label'); - - console.debug("renditionMedia: ", renditionMedia); - console.debug("renditionLayout: ", renditionLayout); - console.debug("renditionLanguage: ", renditionLanguage); - console.debug("renditionAccessMode: ", renditionAccessMode); - - console.debug("renditionLabel: ", renditionLabel); - - rendition.Media = renditionMedia; - rendition.Layout = renditionLayout; - rendition.Language = renditionLanguage; - rendition.AccessMode = renditionAccessMode; - rendition.Label = renditionLabel; - - rendition.opfPath = "/" + rf.attr('full-path'); - console.debug("opfPath: ", rendition.opfPath); - - var selected = true; - if (renditionMedia && renditionMedia !== "" && window.matchMedia) { - - if (_mediaQueryEventCallback) { - _mediaQuery.removeListener(_mediaQueryEventCallback); - - _mediaQueryEventCallback = undefined; - _mediaQuery = undefined; - } - - _mediaQuery = window.matchMedia(renditionMedia); - - _mediaQueryEventCallback = function(mq) { - console.debug("Rendition Selection Media Query changed: " + mq.media + " (" + mq.matches + ")"); - if (mq.matches) { - // noop - } - if (_renditionSelection && _renditionSelection.renditionReload) { - _renditionSelection.renditionReload(); - } - }; - - _mediaQuery.addListener(_mediaQueryEventCallback); - - if (!_mediaQuery.matches) { - console.debug("=== EJECTED: renditionMedia"); - - selected = selected && false; - //continue; - } - } + //console.debug(rootFiles); + + multipleRenditions.renditions = []; + multipleRenditions.selectedIndex = -1; + + + var rootFile = undefined; + if (rootFiles.length == 1) { + rootFile = rootFiles; + + var renditionMedia = rootFile.attr('rendition:media'); + var renditionLayout = rootFile.attr('rendition:layout'); + var renditionLanguage = rootFile.attr('rendition:language'); + var renditionAccessMode = rootFile.attr('rendition:accessMode'); + + var rendition = {}; + + rendition.Media = renditionMedia; + rendition.Layout = renditionLayout; + rendition.Language = renditionLanguage; + rendition.AccessMode = renditionAccessMode; + rendition.Label = renditionLabel; + + rendition.opfPath = "/" + rootFile.attr('full-path'); + console.debug("opfPath: ", rendition.opfPath); + + multipleRenditions.renditions.push(rendition); + multipleRenditions.selectedIndex = 0; + + } else { + for (var i = 0; i < rootFiles.length; i++) { + var rendition = {}; + + rendition.Media = undefined; + rendition.Layout = undefined; + rendition.Language = undefined; + rendition.AccessMode = undefined; + rendition.Label = undefined; + rendition.opfPath = undefined; + + multipleRenditions.renditions.push(rendition); + } + + var selectedIndex = -1; + + for (var i = rootFiles.length - 1; i >= 0; i--) { + + console.debug("----- ROOT FILE #" + i); + + var rendition = multipleRenditions.renditions[i]; + + var rf = $(rootFiles[i]); + + var renditionMedia = rf.attr('rendition:media'); + var renditionLayout = rf.attr('rendition:layout'); + var renditionLanguage = rf.attr('rendition:language'); + var renditionAccessMode = rf.attr('rendition:accessMode'); + + var renditionLabel = rf.attr('rendition:label'); + + console.debug("renditionMedia: ", renditionMedia); + console.debug("renditionLayout: ", renditionLayout); + console.debug("renditionLanguage: ", renditionLanguage); + console.debug("renditionAccessMode: ", renditionAccessMode); + + console.debug("renditionLabel: ", renditionLabel); + + rendition.Media = renditionMedia; + rendition.Layout = renditionLayout; + rendition.Language = renditionLanguage; + rendition.AccessMode = renditionAccessMode; + rendition.Label = renditionLabel; + + rendition.opfPath = "/" + rf.attr('full-path'); + console.debug("opfPath: ", rendition.opfPath); + + var selected = true; + if (renditionMedia && renditionMedia !== "" && window.matchMedia) { + + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + + _mediaQueryEventCallback = undefined; + _mediaQuery = undefined; + } + + _mediaQuery = window.matchMedia(renditionMedia); + + _mediaQueryEventCallback = function(mq) { + console.debug("Rendition Selection Media Query changed: " + mq.media + " (" + mq.matches + ")"); + if (mq.matches) { + // noop + } + if (_renditionSelection && _renditionSelection.renditionReload) { + _renditionSelection.renditionReload(); + } + }; + + _mediaQuery.addListener(_mediaQueryEventCallback); + + if (!_mediaQuery.matches) { + console.debug("=== EJECTED: renditionMedia"); + + selected = selected && false; + //continue; + } + } console.log("######################################"); console.debug(_renditionSelection); console.log("######################################"); - if (_renditionSelection && (typeof _renditionSelection.renditionLayout !== "undefined") && renditionLayout && renditionLayout !== "") { - if (_renditionSelection.renditionLayout !== renditionLayout) { - console.debug("=== EJECTED: renditionLayout"); - - selected = selected && false; - //continue; - } - } - - if (_renditionSelection && (typeof _renditionSelection.renditionLanguage !== "undefined") && renditionLanguage && renditionLanguage !== "") { - - // TODO: language tag (+ script subtag) match algorithm RFC 4647 http://www.ietf.org/rfc/rfc4647.txt - if (_renditionSelection.renditionLanguage !== renditionLanguage) { - var langTags1 = _renditionSelection.renditionLanguage.split("-"); - var langTags2 = renditionLanguage.split("-"); - - console.debug(langTags1[0]); - console.debug(langTags2[0]); - - if (langTags1[0] !== langTags2[0]) { - console.debug("=== EJECTED: renditionLanguage"); - - selected = selected && false; - //continue; - } - } - } - - if (_renditionSelection && (typeof _renditionSelection.renditionAccessMode !== "undefined") && renditionAccessMode && renditionAccessMode !== "") { - if (_renditionSelection.renditionAccessMode !== renditionAccessMode) { - console.debug("=== EJECTED: renditionAccessMode"); - - selected = selected && false; - //continue; - } - } - - if (selected && !rootFile) { - rootFile = rf; - selectedIndex = i; - //break; - } - } - - if (!rootFile - // first-time load, or app with no preferences at all - || (_renditionSelection && (typeof _renditionSelection.renditionAccessMode === "undefined") && (typeof _renditionSelection.renditionLanguage === "undefined") && (typeof _renditionSelection.renditionLayout === "undefined")) - ) { - // fallback to index zero ... is that a valid interpretation of the EPUB3 specification?? - // See Processing Model: - //http://www.idpf.org/epub/renditions/multiple/epub-multiple-renditions.html#h.4n44azuq1490 - - selectedIndex = 0; - rootFile = $(rootFiles[selectedIndex]); - } - - multipleRenditions.selectedIndex = selectedIndex; - } - + if (_renditionSelection && (typeof _renditionSelection.renditionLayout !== "undefined") && renditionLayout && renditionLayout !== "") { + if (_renditionSelection.renditionLayout !== renditionLayout) { + console.debug("=== EJECTED: renditionLayout"); + + selected = selected && false; + //continue; + } + } + + if (_renditionSelection && (typeof _renditionSelection.renditionLanguage !== "undefined") && renditionLanguage && renditionLanguage !== "") { + + // TODO: language tag (+ script subtag) match algorithm RFC 4647 http://www.ietf.org/rfc/rfc4647.txt + if (_renditionSelection.renditionLanguage !== renditionLanguage) { + var langTags1 = _renditionSelection.renditionLanguage.split("-"); + var langTags2 = renditionLanguage.split("-"); + + console.debug(langTags1[0]); + console.debug(langTags2[0]); + + if (langTags1[0] !== langTags2[0]) { + console.debug("=== EJECTED: renditionLanguage"); + + selected = selected && false; + //continue; + } + } + } + + if (_renditionSelection && (typeof _renditionSelection.renditionAccessMode !== "undefined") && renditionAccessMode && renditionAccessMode !== "") { + if (_renditionSelection.renditionAccessMode !== renditionAccessMode) { + console.debug("=== EJECTED: renditionAccessMode"); + + selected = selected && false; + //continue; + } + } + + if (selected && !rootFile) { + rootFile = rf; + selectedIndex = i; + //break; + } + } + + if (!rootFile + // first-time load, or app with no preferences at all + || (_renditionSelection && (typeof _renditionSelection.renditionAccessMode === "undefined") && (typeof _renditionSelection.renditionLanguage === "undefined") && (typeof _renditionSelection.renditionLayout === "undefined")) + ) { + // fallback to index zero ... is that a valid interpretation of the EPUB3 specification?? + // See Processing Model: + //http://www.idpf.org/epub/renditions/multiple/epub-multiple-renditions.html#h.4n44azuq1490 + + selectedIndex = 0; + rootFile = $(rootFiles[selectedIndex]); + } + + multipleRenditions.selectedIndex = selectedIndex; + } + var packageFullPath = rootFile.attr('full-path'); - return packageFullPath; + return packageFullPath; }; - - - var _multipleRenditions = undefined; - + + + var _multipleRenditions = undefined; + this.getPackageFullPath = function(callback, onerror) { - if (_packageFullPath) { - callback(_packageFullPath, _multipleRenditions); - return; - } - + if (_packageFullPath) { + callback(_packageFullPath, _multipleRenditions); + return; + } + self.getXmlFileDom('META-INF/container.xml', function(containerXmlDom) { - - _multipleRenditions = {}; - + + _multipleRenditions = {}; + _packageFullPath = getRootFile(containerXmlDom, _multipleRenditions); - - var cacheOpfDom = {}; - - if (_multipleRenditions.renditions.length) { - populateCacheOpfDom(0, _multipleRenditions, cacheOpfDom, function() { - buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPath, cacheOpfDom); - }); - } else { - buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPath, cacheOpfDom); - } - + + var cacheOpfDom = {}; + + if (_multipleRenditions.renditions.length) { + populateCacheOpfDom(0, _multipleRenditions, cacheOpfDom, function() { + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPath, cacheOpfDom); + }); + } else { + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPath, cacheOpfDom); + } + }, onerror); }; @@ -605,10 +605,10 @@ console.log("######################################"); this.cleanup = function() { self.flushCache(); - if (_mediaQueryEventCallback) { - _mediaQuery.removeListener(_mediaQueryEventCallback); - _mediaQueryEventCallback = undefined; - } + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + _mediaQueryEventCallback = undefined; + } }; this.getPackageUrl = function() { diff --git a/js/epub-fetch/zip_resource_fetcher.js b/js/epub-fetch/zip_resource_fetcher.js index d0a7faf93..228025a81 100644 --- a/js/epub-fetch/zip_resource_fetcher.js +++ b/js/epub-fetch/zip_resource_fetcher.js @@ -201,7 +201,7 @@ define(['jquery', 'URIjs', './discover_content_type', 'zip-ext', 'readium_shared return url + (url.charAt(url.length-1) == '/' ? "" : "/") + pathRelativeToPackageRoot; }; - + this.fetchFileContentsText = function(relativePathRelativeToPackageRoot, fetchCallback, onerror) { fetchFileContents(relativePathRelativeToPackageRoot, function (entry) { diff --git a/js/epub-model/package_document.js b/js/epub-model/package_document.js index 816ea3399..aedacaa2b 100644 --- a/js/epub-model/package_document.js +++ b/js/epub-model/package_document.js @@ -122,7 +122,7 @@ define(['jquery', 'underscore', 'URIjs'], $ncxOrderedList = getNcxOrderedList($("navMap", tocDom)); callback($ncxOrderedList[0]); } else { - var packageDocumentURL = publicationFetcher.getPackageUrl(); + var packageDocumentURL = publicationFetcher.getPackageUrl(); var packageDocumentAbsoluteURL = new URI(packageDocumentURL).absoluteTo(document.URL); var tocDocumentAbsoluteURL = new URI(that.getToc()).absoluteTo(packageDocumentAbsoluteURL); // add a BASE tag to change the TOC document's baseURI. diff --git a/js/epub-model/package_document_parser.js b/js/epub-model/package_document_parser.js index 5d1ed8b35..aabc11b0c 100644 --- a/js/epub-model/package_document_parser.js +++ b/js/epub-model/package_document_parser.js @@ -72,11 +72,11 @@ define(['jquery', 'underscore', '../epub-fetch/markup_parser', 'URIjs', './packa $.when(updateMetadataWithIBookProperties(metadata)).then(function() { publicationFetcher.setPackageMetadata(metadata, function () { - - var packageDocumentURL = publicationFetcher.getPackageUrl(); - var i = packageDocumentURL.lastIndexOf("/"); - var packageDocRoot = i > 0 ? packageDocumentURL.substr(0, i) : ""; - + + var packageDocumentURL = publicationFetcher.getPackageUrl(); + var i = packageDocumentURL.lastIndexOf("/"); + var packageDocRoot = i > 0 ? packageDocumentURL.substr(0, i) : ""; + var packageDocument = new PackageDocument(packageDocRoot, publicationFetcher, metadata, spine, manifest); diff --git a/readium-shared-js b/readium-shared-js index bc9f60164..a7865d7ed 160000 --- a/readium-shared-js +++ b/readium-shared-js @@ -1 +1 @@ -Subproject commit bc9f6016472b2f662d60cd68349e31733da90444 +Subproject commit a7865d7ed3afaf23f64821e868d534a99efda825 From 650807a0165eb55dc71eb1c06917faec496f37a8 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:35:13 +0000 Subject: [PATCH 15/26] minor: adjusting code diff to make it more readable in the PR (relative to the develop branch) --- js/epub-fetch/publication_fetcher.js | 58 ++++++++++++++-------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 93fee1ea7..40963fbc5 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -41,13 +41,38 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip var _mediaQueryEventCallback = undefined; var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; - var _contentType = contentType; - var _renditionSelection = renditionSelection; - this.markupParser = new MarkupParser(); + this.initialize = function(callback) { + var isEpubExploded = isExploded(); + + // Non exploded EPUBs (i.e. zipped .epub documents) should be fetched in a programmatical manner: + _shouldConstructDomProgrammatically = !isEpubExploded; + + createResourceFetcher(isEpubExploded, function(resourceFetcher) { + + //NOTE: _resourceFetcher == resourceFetcher + + self.getPackageDom( + function(packageDocumentRelativePath, multipleRenditions) { + _packageFullPath = packageDocumentRelativePath; + _packageDocumentAbsoluteUrl = resourceFetcher.resolveURI(packageDocumentRelativePath); + + callback(resourceFetcher, multipleRenditions); + }, + function(error) { + console.error("unable to find package document: " + error); + + callback(resourceFetcher, undefined); + } + ); + }); + }; + + var _renditionSelection = renditionSelection; + function isExploded() { // binary object means packed EPUB if (ebookURL instanceof Blob || ebookURL instanceof File) return false; @@ -79,33 +104,6 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip // return ebookURL.indexOf(ext, ebookURL.length - ext.length) === -1; } - this.initialize = function(callback) { - var isEpubExploded = isExploded(); - - // Non exploded EPUBs (i.e. zipped .epub documents) should be fetched in a programmatical manner: - _shouldConstructDomProgrammatically = !isEpubExploded; - - createResourceFetcher(isEpubExploded, function(resourceFetcher) { - - //NOTE: _resourceFetcher == resourceFetcher - - self.getPackageDom( - function(packageDocumentRelativePath, multipleRenditions) { - _packageFullPath = packageDocumentRelativePath; - _packageDocumentAbsoluteUrl = resourceFetcher.resolveURI(packageDocumentRelativePath); - - callback(resourceFetcher, multipleRenditions); - }, - function(error) { - console.error("unable to find package document: " + error); - - callback(resourceFetcher, undefined); - } - ); - }); - }; - - // INTERNAL FUNCTIONS From f1aa31d95d0e6a0e5825f74ec4b5f22a47f0b177 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:43:18 +0000 Subject: [PATCH 16/26] minor: removed unnecessary code diff --- js/epub-fetch/zip_resource_fetcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/epub-fetch/zip_resource_fetcher.js b/js/epub-fetch/zip_resource_fetcher.js index 228025a81..200802e54 100644 --- a/js/epub-fetch/zip_resource_fetcher.js +++ b/js/epub-fetch/zip_resource_fetcher.js @@ -201,7 +201,7 @@ define(['jquery', 'URIjs', './discover_content_type', 'zip-ext', 'readium_shared return url + (url.charAt(url.length-1) == '/' ? "" : "/") + pathRelativeToPackageRoot; }; - + this.fetchFileContentsText = function(relativePathRelativeToPackageRoot, fetchCallback, onerror) { fetchFileContents(relativePathRelativeToPackageRoot, function (entry) { From fbb8979e61cfb9e24ad9cb4b70af2f70e14fd521 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:46:23 +0000 Subject: [PATCH 17/26] minor: removed unnecessary code change --- js/epub-fetch/plain_resource_fetcher.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/epub-fetch/plain_resource_fetcher.js b/js/epub-fetch/plain_resource_fetcher.js index 4a2ed7c97..083698e5e 100644 --- a/js/epub-fetch/plain_resource_fetcher.js +++ b/js/epub-fetch/plain_resource_fetcher.js @@ -19,7 +19,7 @@ define(['jquery', 'URIjs', './discover_content_type'], function ($, URI, Content var ebookURL_filepath = parentFetcher.getEbookURL_FilePath(); var self = this; - + // INTERNAL FUNCTIONS function fetchFileContents(pathRelativeToPackageRoot, readCallback, onerror) { @@ -41,6 +41,7 @@ define(['jquery', 'URIjs', './discover_content_type'], function ($, URI, Content xhr.send(); } + // PUBLIC API this.resolveURI = function (pathRelativeToPackageRoot) { From f859414e9783c7864933ba52a72cd97bbd682679 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:49:54 +0000 Subject: [PATCH 18/26] minor code change to minimize diff in PR --- js/epub-fetch/publication_fetcher.js | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 40963fbc5..67981e6dd 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -29,10 +29,8 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip var _shouldConstructDomProgrammatically; var _resourceFetcher; var _encryptionHandler; - var _packageFullPath; var _packageDocumentAbsoluteUrl; - var _packageDom; var _packageDomInitializationDeferred; var _publicationResourcesCache = new ResourceCache(sourceWindow, cacheSizeEvictThreshold); @@ -46,11 +44,12 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip this.markupParser = new MarkupParser(); this.initialize = function(callback) { + var isEpubExploded = isExploded(); // Non exploded EPUBs (i.e. zipped .epub documents) should be fetched in a programmatical manner: _shouldConstructDomProgrammatically = !isEpubExploded; - + createResourceFetcher(isEpubExploded, function(resourceFetcher) { //NOTE: _resourceFetcher == resourceFetcher @@ -72,6 +71,9 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip }; var _renditionSelection = renditionSelection; + + + // INTERNAL FUNCTIONS function isExploded() { // binary object means packed EPUB @@ -103,9 +105,6 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip // var ext = ".epub"; // return ebookURL.indexOf(ext, ebookURL.length - ext.length) === -1; } - - - // INTERNAL FUNCTIONS var buildRenditionMapping = function(callback, multipleRenditions, containerXmlDom, packageFullPath, cacheOpfDom) { @@ -542,6 +541,15 @@ console.log("######################################"); }, onerror); }; + this.cleanup = function() { + self.flushCache(); + + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + _mediaQueryEventCallback = undefined; + } + }; + function createResourceFetcher(isExploded, callback) { if (isExploded) { console.log(' --- using PlainResourceFetcher'); @@ -600,15 +608,6 @@ console.log("######################################"); _publicationResourcesCache.flushCache(); }; - this.cleanup = function() { - self.flushCache(); - - if (_mediaQueryEventCallback) { - _mediaQuery.removeListener(_mediaQueryEventCallback); - _mediaQueryEventCallback = undefined; - } - }; - this.getPackageUrl = function() { return _packageDocumentAbsoluteUrl; }; @@ -711,6 +710,7 @@ console.log("######################################"); // (starting with "/", already relative to the EPUB archive's base folder) // then the returned value is relativeToPackagePath. this.convertPathRelativeToPackageToRelativeToBase = function (relativeToPackagePath) { + return new URI(relativeToPackagePath).absoluteTo(_packageFullPath).toString(); }; From 0c930b19bdaacf36b34eaaffb19bd3e48b81a616 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:51:52 +0000 Subject: [PATCH 19/26] minor code diff improvement --- js/epub-fetch/publication_fetcher.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 67981e6dd..3501335ff 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -35,14 +35,14 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip var _packageDomInitializationDeferred; var _publicationResourcesCache = new ResourceCache(sourceWindow, cacheSizeEvictThreshold); - var _mediaQuery = undefined; - var _mediaQueryEventCallback = undefined; - var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; var _contentType = contentType; this.markupParser = new MarkupParser(); + var _mediaQuery = undefined; + var _mediaQueryEventCallback = undefined; + this.initialize = function(callback) { var isEpubExploded = isExploded(); From 880a2dcaacd161a5925f3d09f629a86fa4e09208 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 15:53:10 +0000 Subject: [PATCH 20/26] minor code shift to cleanup PR diff --- js/epub-fetch/publication_fetcher.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 3501335ff..7719e0eda 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -40,6 +40,7 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip this.markupParser = new MarkupParser(); + var _renditionSelection = renditionSelection; var _mediaQuery = undefined; var _mediaQueryEventCallback = undefined; @@ -70,9 +71,6 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip }); }; - var _renditionSelection = renditionSelection; - - // INTERNAL FUNCTIONS function isExploded() { From d04ce1be13ef9b8844266e28870a971c90f7a886 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 16:32:41 +0000 Subject: [PATCH 21/26] fixed merge bugs --- js/epub-fetch/publication_fetcher.js | 40 +++++++++------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 7719e0eda..4486165e2 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -56,10 +56,7 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip //NOTE: _resourceFetcher == resourceFetcher self.getPackageDom( - function(packageDocumentRelativePath, multipleRenditions) { - _packageFullPath = packageDocumentRelativePath; - _packageDocumentAbsoluteUrl = resourceFetcher.resolveURI(packageDocumentRelativePath); - + function(packageDocument, multipleRenditions) { callback(resourceFetcher, multipleRenditions); }, function(error) { @@ -511,12 +508,12 @@ console.log("######################################"); return packageFullPath; }; - + var _packageFullPathFromContainerXml = undefined; var _multipleRenditions = undefined; - this.getPackageFullPath = function(callback, onerror) { - if (_packageFullPath) { - callback(_packageFullPath, _multipleRenditions); + var getPackageFullPathFromContainerXml = function(callback, onerror) { + if (_packageFullPathFromContainerXml) { + callback(_packageFullPathFromContainerXml, _multipleRenditions); return; } @@ -524,21 +521,21 @@ console.log("######################################"); _multipleRenditions = {}; - _packageFullPath = getRootFile(containerXmlDom, _multipleRenditions); + _packageFullPathFromContainerXml = getRootFile(containerXmlDom, _multipleRenditions); var cacheOpfDom = {}; if (_multipleRenditions.renditions.length) { populateCacheOpfDom(0, _multipleRenditions, cacheOpfDom, function() { - buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPath, cacheOpfDom); + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPathFromContainerXml, cacheOpfDom); }); } else { - buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPath, cacheOpfDom); + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPathFromContainerXml, cacheOpfDom); } }, onerror); }; - + this.cleanup = function() { self.flushCache(); @@ -655,22 +652,9 @@ console.log("######################################"); }, onerror); }; - this.getPackageFullPath = function(callback, onerror) { - self.getXmlFileDom('/META-INF/container.xml', function (containerXmlDom) { - var packageFullPath = self.getRootFile(containerXmlDom); - callback(packageFullPath); - }, onerror); - }; - - this.getRootFile = function(containerXmlDom) { - var rootFile = $('rootfile', containerXmlDom); - var packageFullPath = rootFile.attr('full-path'); - return packageFullPath; - }; - this.getPackageDom = function (callback, onerror) { if (_packageDom) { - callback(_packageDom); + callback(_packageDom, _multipleRenditions); } else { // TODO: use jQuery's Deferred // Register all callbacks interested in initialized packageDom, launch its instantiation only once @@ -681,7 +665,7 @@ console.log("######################################"); _packageDomInitializationDeferred = $.Deferred(); _packageDomInitializationDeferred.done(callback); - self.getPackageFullPath(function (packageFullPath, multipleRenditions) { + getPackageFullPathFromContainerXml(function (packageFullPath, multipleRenditions) { _packageFullPath = packageFullPath; _packageDocumentAbsoluteUrl = _resourceFetcher.resolveURI(_packageFullPath); @@ -696,7 +680,7 @@ console.log("######################################"); self.getXmlFileDom(packageFullPath, function (packageDom) { _packageDom = packageDom; - _packageDomInitializationDeferred.resolve(packageDom); + _packageDomInitializationDeferred.resolve(packageDom, _multipleRenditions); _packageDomInitializationDeferred = undefined; }) }, onerror); From ffdae7a3844a0b4a7550725f0668b76f8f417a89 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 16:39:52 +0000 Subject: [PATCH 22/26] minor: code re-org to improve diff readability --- js/epub-fetch/publication_fetcher.js | 288 +++++++++++++-------------- 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 4486165e2..70302ca99 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -322,6 +322,150 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip }; + var _packageFullPathFromContainerXml = undefined; + var _multipleRenditions = undefined; + + this.cleanup = function() { + self.flushCache(); + + if (_mediaQueryEventCallback) { + _mediaQuery.removeListener(_mediaQueryEventCallback); + _mediaQueryEventCallback = undefined; + } + }; + + function createResourceFetcher(isExploded, callback) { + if (isExploded) { + console.log(' --- using PlainResourceFetcher'); + _resourceFetcher = new PlainResourceFetcher(self); + callback(_resourceFetcher); + } else { + console.log(' --- using ZipResourceFetcher'); + _resourceFetcher = new ZipResourceFetcher(self, jsLibRoot); + callback(_resourceFetcher); + } + } + + + // PUBLIC API + + /** + * Determine whether the documents fetched using this fetcher require special programmatic handling. + * (resolving of internal resource references). + * @returns {*} true if documents fetched using this fetcher require special programmatic handling + * (resolving of internal resource references). Typically needed for zipped EPUBs or exploded EPUBs that contain + * encrypted resources specified in META-INF/encryption.xml. + * + * false if documents can be fed directly into a window or iframe by src URL without using special fetching logic. + */ + this.shouldConstructDomProgrammatically = function (){ + return _shouldConstructDomProgrammatically; + }; + + /** + * Determine whether the media assets (audio, video, images) within content documents require special + * programmatic handling. + * @returns {*} true if content documents fetched using this fetcher require programmatic fetching + * of media assets. Typically needed for zipped EPUBs. + * + * false if paths to media assets are accessible directly for the browser through their paths relative to + * the base URI of their content document. + */ + this.shouldFetchMediaAssetsProgrammatically = function() { + return _shouldConstructDomProgrammatically && !isExploded(); + }; + + this.getEbookURL = function() { + return ebookURL; + }; + + this.getEbookURL_FilePath = function() { + + return Helpers.getEbookUrlFilePath(ebookURL); + }; + + this.getJsLibRoot = function() { + return jsLibRoot; + }; + + this.flushCache = function() { + _publicationResourcesCache.flushCache(); + }; + + this.getPackageUrl = function() { + return _packageDocumentAbsoluteUrl; + }; + + this.getPackageFullPathRelativeToBase = function() { + return _packageFullPath; + }; + + this.fetchContentDocument = function (attachedData, loadedDocumentUri, contentDocumentResolvedCallback, errorCallback) { + + // Resources loaded for previously fetched document no longer need to be pinned: + // DANIEL: what about 2-page synthetic spread of fixed layout documents / spine items? + // See https://github.com/readium/readium-js/issues/104 + _publicationResourcesCache.unPinResources(); + + + var contentDocumentFetcher = new ContentDocumentFetcher(self, attachedData.spineItem, loadedDocumentUri, _publicationResourcesCache, _contentDocumentTextPreprocessor); + contentDocumentFetcher.fetchContentDocumentAndResolveDom(contentDocumentResolvedCallback, errorCallback); + }; + + this.getFileContentsFromPackage = function(filePathRelativeToPackageRoot, callback, onerror) { + + // AVOID INVOKING fetchFileContentsText() directly, use relativeToPackageFetchFileContents() wrapper instead so that additional checks are performed. + + // META-INF/container.xml initial fetch, see this.initialize() + if (!_packageFullPath) { + console.debug("FETCHING (INIT) ... " + filePathRelativeToPackageRoot); + if (filePathRelativeToPackageRoot && filePathRelativeToPackageRoot.charAt(0) == '/') { + filePathRelativeToPackageRoot = filePathRelativeToPackageRoot.substr(1); + } + _resourceFetcher.fetchFileContentsText(filePathRelativeToPackageRoot, function (fileContents) { + callback(fileContents); + }, onerror); + } else { + self.relativeToPackageFetchFileContents(filePathRelativeToPackageRoot, 'text', function (fileContents) { + callback(fileContents); + }, onerror); + } + }; + + + + this.getXmlFileDom = function (xmlFilePathRelativeToPackageRoot, callback, onerror) { + self.getFileContentsFromPackage(xmlFilePathRelativeToPackageRoot, function (xmlFileContents) { + var fileDom = self.markupParser.parseXml(xmlFileContents); + callback(fileDom); + }, onerror); + }; + + var getPackageFullPathFromContainerXml = function(callback, onerror) { + if (_packageFullPathFromContainerXml) { + callback(_packageFullPathFromContainerXml, _multipleRenditions); + return; + } + + self.getXmlFileDom('META-INF/container.xml', function(containerXmlDom) { + + _multipleRenditions = {}; + + _packageFullPathFromContainerXml = getRootFile(containerXmlDom, _multipleRenditions); + + var cacheOpfDom = {}; + + if (_multipleRenditions.renditions.length) { + populateCacheOpfDom(0, _multipleRenditions, cacheOpfDom, function() { + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPathFromContainerXml, cacheOpfDom); + }); + } else { + buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPathFromContainerXml, cacheOpfDom); + } + + }, onerror); + }; + var getRootFile = function(containerXmlDom, multipleRenditions) { //console.debug(containerXmlDom.documentElement.innerHTML); @@ -508,150 +652,6 @@ console.log("######################################"); return packageFullPath; }; - var _packageFullPathFromContainerXml = undefined; - var _multipleRenditions = undefined; - - var getPackageFullPathFromContainerXml = function(callback, onerror) { - if (_packageFullPathFromContainerXml) { - callback(_packageFullPathFromContainerXml, _multipleRenditions); - return; - } - - self.getXmlFileDom('META-INF/container.xml', function(containerXmlDom) { - - _multipleRenditions = {}; - - _packageFullPathFromContainerXml = getRootFile(containerXmlDom, _multipleRenditions); - - var cacheOpfDom = {}; - - if (_multipleRenditions.renditions.length) { - populateCacheOpfDom(0, _multipleRenditions, cacheOpfDom, function() { - buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPathFromContainerXml, cacheOpfDom); - }); - } else { - buildRenditionMapping(callback, _multipleRenditions, containerXmlDom, _packageFullPathFromContainerXml, cacheOpfDom); - } - - }, onerror); - }; - - this.cleanup = function() { - self.flushCache(); - - if (_mediaQueryEventCallback) { - _mediaQuery.removeListener(_mediaQueryEventCallback); - _mediaQueryEventCallback = undefined; - } - }; - - function createResourceFetcher(isExploded, callback) { - if (isExploded) { - console.log(' --- using PlainResourceFetcher'); - _resourceFetcher = new PlainResourceFetcher(self); - callback(_resourceFetcher); - } else { - console.log(' --- using ZipResourceFetcher'); - _resourceFetcher = new ZipResourceFetcher(self, jsLibRoot); - callback(_resourceFetcher); - } - } - - - // PUBLIC API - - /** - * Determine whether the documents fetched using this fetcher require special programmatic handling. - * (resolving of internal resource references). - * @returns {*} true if documents fetched using this fetcher require special programmatic handling - * (resolving of internal resource references). Typically needed for zipped EPUBs or exploded EPUBs that contain - * encrypted resources specified in META-INF/encryption.xml. - * - * false if documents can be fed directly into a window or iframe by src URL without using special fetching logic. - */ - this.shouldConstructDomProgrammatically = function (){ - return _shouldConstructDomProgrammatically; - }; - - /** - * Determine whether the media assets (audio, video, images) within content documents require special - * programmatic handling. - * @returns {*} true if content documents fetched using this fetcher require programmatic fetching - * of media assets. Typically needed for zipped EPUBs. - * - * false if paths to media assets are accessible directly for the browser through their paths relative to - * the base URI of their content document. - */ - this.shouldFetchMediaAssetsProgrammatically = function() { - return _shouldConstructDomProgrammatically && !isExploded(); - }; - - this.getEbookURL = function() { - return ebookURL; - }; - - this.getEbookURL_FilePath = function() { - - return Helpers.getEbookUrlFilePath(ebookURL); - }; - - this.getJsLibRoot = function() { - return jsLibRoot; - }; - - this.flushCache = function() { - _publicationResourcesCache.flushCache(); - }; - - this.getPackageUrl = function() { - return _packageDocumentAbsoluteUrl; - }; - - this.getPackageFullPathRelativeToBase = function() { - return _packageFullPath; - }; - - this.fetchContentDocument = function (attachedData, loadedDocumentUri, contentDocumentResolvedCallback, errorCallback) { - - // Resources loaded for previously fetched document no longer need to be pinned: - // DANIEL: what about 2-page synthetic spread of fixed layout documents / spine items? - // See https://github.com/readium/readium-js/issues/104 - _publicationResourcesCache.unPinResources(); - - - var contentDocumentFetcher = new ContentDocumentFetcher(self, attachedData.spineItem, loadedDocumentUri, _publicationResourcesCache, _contentDocumentTextPreprocessor); - contentDocumentFetcher.fetchContentDocumentAndResolveDom(contentDocumentResolvedCallback, errorCallback); - }; - - this.getFileContentsFromPackage = function(filePathRelativeToPackageRoot, callback, onerror) { - - // AVOID INVOKING fetchFileContentsText() directly, use relativeToPackageFetchFileContents() wrapper instead so that additional checks are performed. - - // META-INF/container.xml initial fetch, see this.initialize() - if (!_packageFullPath) { - console.debug("FETCHING (INIT) ... " + filePathRelativeToPackageRoot); - if (filePathRelativeToPackageRoot && filePathRelativeToPackageRoot.charAt(0) == '/') { - filePathRelativeToPackageRoot = filePathRelativeToPackageRoot.substr(1); - } - _resourceFetcher.fetchFileContentsText(filePathRelativeToPackageRoot, function (fileContents) { - callback(fileContents); - }, onerror); - } else { - self.relativeToPackageFetchFileContents(filePathRelativeToPackageRoot, 'text', function (fileContents) { - callback(fileContents); - }, onerror); - } - }; - - - - this.getXmlFileDom = function (xmlFilePathRelativeToPackageRoot, callback, onerror) { - self.getFileContentsFromPackage(xmlFilePathRelativeToPackageRoot, function (xmlFileContents) { - var fileDom = self.markupParser.parseXml(xmlFileContents); - callback(fileDom); - }, onerror); - }; - this.getPackageDom = function (callback, onerror) { if (_packageDom) { callback(_packageDom, _multipleRenditions); From 1c8600ddaa1a31b426c71d4444ba061afcc48c8c Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 19 Nov 2015 16:43:10 +0000 Subject: [PATCH 23/26] minor code cleanup --- js/epub-fetch/publication_fetcher.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index 70302ca99..944256e07 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -322,9 +322,6 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip }; - var _packageFullPathFromContainerXml = undefined; - var _multipleRenditions = undefined; - this.cleanup = function() { self.flushCache(); @@ -441,6 +438,10 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip }, onerror); }; + + var _packageFullPathFromContainerXml = undefined; + var _multipleRenditions = undefined; + var getPackageFullPathFromContainerXml = function(callback, onerror) { if (_packageFullPathFromContainerXml) { callback(_packageFullPathFromContainerXml, _multipleRenditions); From 362320cc5201fd2b54d0a477c4ec2372e3074c18 Mon Sep 17 00:00:00 2001 From: danielweck Date: Tue, 8 Mar 2016 14:37:18 +0000 Subject: [PATCH 24/26] submod --- readium-shared-js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readium-shared-js b/readium-shared-js index c42a4b4e4..2fa3d7594 160000 --- a/readium-shared-js +++ b/readium-shared-js @@ -1 +1 @@ -Subproject commit c42a4b4e41151a87a40ab6fff2dcbade049e3ffa +Subproject commit 2fa3d7594b7677d0c4610e423270ddada913dc42 From 2b4e4cd416757e07cf121b4cab82b6f97b699c77 Mon Sep 17 00:00:00 2001 From: danielweck Date: Sun, 15 Jan 2017 17:06:20 +0000 Subject: [PATCH 25/26] submodule --- readium-shared-js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readium-shared-js b/readium-shared-js index 378058403..b1f61dd52 160000 --- a/readium-shared-js +++ b/readium-shared-js @@ -1 +1 @@ -Subproject commit 3780584035d0378dce8bb5cac6db7952607fb9b7 +Subproject commit b1f61dd52fa291b87e64ff76792b1a9628b1421b From 90c2cf4a1e3845489ef027554a23b5c1cce71ab6 Mon Sep 17 00:00:00 2001 From: danielweck Date: Thu, 5 Apr 2018 19:57:14 +0100 Subject: [PATCH 26/26] fixed parser --- js/epub-model/package_document_parser.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/epub-model/package_document_parser.js b/js/epub-model/package_document_parser.js index 1ab05d8e7..423a2e6d8 100644 --- a/js/epub-model/package_document_parser.js +++ b/js/epub-model/package_document_parser.js @@ -21,6 +21,7 @@ define(['jquery', 'underscore', '../epub-fetch/markup_parser', 'URIjs', './packa // instance of `URI` that is used to resolve paths during the process var PackageDocumentParser = function(publicationFetcher) { + var _packageFetcher = publicationFetcher; var _deferredXmlDom = $.Deferred(); var _xmlDom; @@ -74,8 +75,9 @@ define(['jquery', 'underscore', '../epub-fetch/markup_parser', 'URIjs', './packa _packageFetcher.setPackageMetadata(metadata, function () { var packageDocumentURL = publicationFetcher.getPackageUrl(); - var i = packageDocumentURL.lastIndexOf("/"); - var packageDocRoot = i > 0 ? packageDocumentURL.substr(0, i) : ""; + // var i = packageDocumentURL.lastIndexOf("/"); + // var packageDocRoot = i > 0 ? packageDocumentURL.substr(0, i) : ""; + var packageDocRoot = packageDocumentURL; var packageDocument = new PackageDocument(packageDocRoot, xmlDom, publicationFetcher, metadata, spine, manifest);