From 27fec5a305db528dd5cb3b2bf0333a7aa5aaad87 Mon Sep 17 00:00:00 2001 From: fchasen Date: Mon, 22 Jun 2015 23:28:30 -0400 Subject: [PATCH] Removed gulp-order, rsvp from npm --- dist/epub.js | 7864 +++++++++++++++++++++++----------------------- dist/epub.min.js | 6 +- gulpfile.js | 4 +- package.json | 1 - 4 files changed, 3936 insertions(+), 3939 deletions(-) diff --git a/dist/epub.js b/dist/epub.js index 50f0b93..6732288 100644 --- a/dist/epub.js +++ b/dist/epub.js @@ -1,3939 +1,9 @@ -EPUBJS.Book = function(_url){ - // Promises - this.opening = new RSVP.defer(); - this.opened = this.opening.promise; - this.isOpen = false; - - this.url = undefined; - - this.spine = new EPUBJS.Spine(this.request); - - this.loading = { - manifest: new RSVP.defer(), - spine: new RSVP.defer(), - metadata: new RSVP.defer(), - cover: new RSVP.defer(), - navigation: new RSVP.defer(), - pageList: new RSVP.defer() - }; - - this.loaded = { - manifest: this.loading.manifest.promise, - spine: this.loading.spine.promise, - metadata: this.loading.metadata.promise, - cover: this.loading.cover.promise, - navigation: this.loading.navigation.promise, - pageList: this.loading.pageList.promise - }; - - this.ready = RSVP.hash(this.loaded); - - // Queue for methods used before opening - this.isRendered = false; - this._q = EPUBJS.core.queue(this); - - this.request = this.requestMethod.bind(this); - - if(_url) { - this.open(_url); - } -}; - -EPUBJS.Book.prototype.open = function(_url){ - var uri; - var parse = new EPUBJS.Parser(); - var epubPackage; - var book = this; - var containerPath = "META-INF/container.xml"; - var location; - - if(!_url) { - this.opening.resolve(this); - return this.opened; - } - - // Reuse parsed url or create a new uri object - if(typeof(_url) === "object") { - uri = _url; - } else { - uri = EPUBJS.core.uri(_url); - } - - // Find path to the Container - if(uri.extension === "opf") { - // Direct link to package, no container - this.packageUrl = uri.href; - this.containerUrl = ''; - - if(uri.origin) { - this.url = uri.base; - } else if(window){ - location = EPUBJS.core.uri(window.location.href); - this.url = EPUBJS.core.resolveUrl(location.base, uri.directory); - } else { - this.url = uri.directory; - } - - epubPackage = this.request(this.packageUrl); - - } else if(uri.extension === "epub" || uri.extension === "zip" ) { - // Book is archived - this.archived = true; - this.url = ''; - } - - // Find the path to the Package from the container - else if (!uri.extension) { - - this.containerUrl = _url + containerPath; - - epubPackage = this.request(this.containerUrl). - then(function(containerXml){ - return parse.container(containerXml); // Container has path to content - }). - then(function(paths){ - var packageUri = EPUBJS.core.uri(paths.packagePath); - book.packageUrl = _url + paths.packagePath; - book.encoding = paths.encoding; - - // Set Url relative to the content - if(packageUri.origin) { - book.url = packageUri.base; - } else if(window){ - location = EPUBJS.core.uri(window.location.href); - book.url = EPUBJS.core.resolveUrl(location.base, _url + packageUri.directory); - } else { - book.url = packageUri.directory; - } - - return book.request(book.packageUrl); - }).catch(function(error) { - // handle errors in either of the two requests - console.error("Could not load book at: " + (this.packageUrl || this.containerPath)); - book.trigger("book:loadFailed", (this.packageUrl || this.containerPath)); - book.opening.reject(error); - }); - } - - - epubPackage.then(function(packageXml) { - // Get package information from epub opf - book.unpack(packageXml); - - // Resolve promises - book.loading.manifest.resolve(book.package.manifest); - book.loading.metadata.resolve(book.package.metadata); - book.loading.spine.resolve(book.spine); - book.loading.cover.resolve(book.cover); - - this.isOpen = true; - - // Clear queue of any waiting book request - - // Resolve book opened promise - book.opening.resolve(book); - - }).catch(function(error) { - // handle errors in parsing the book - console.error(error.message, error.stack); - book.opening.reject(error); - }); - - return this.opened; -}; - -EPUBJS.Book.prototype.unpack = function(packageXml){ - var book = this, - parse = new EPUBJS.Parser(); - - book.package = parse.packageContents(packageXml); // Extract info from contents - book.package.baseUrl = book.url; // Provides a url base for resolving paths - - this.spine.load(book.package); - - book.navigation = new EPUBJS.Navigation(book.package, this.request); - book.navigation.load().then(function(toc){ - book.toc = toc; - book.loading.navigation.resolve(book.toc); - }); - - // //-- Set Global Layout setting based on metadata - // MOVE TO RENDER - // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata); - - book.cover = book.url + book.package.coverPath; -}; - -// Alias for book.spine.get -EPUBJS.Book.prototype.section = function(target) { - return this.spine.get(target); -}; - -// Sugar to render a book -EPUBJS.Book.prototype.renderTo = function(element, options) { - var renderer = (options && options.method) ? - options.method.charAt(0).toUpperCase() + options.method.substr(1) : - "Rendition"; - - this.rendition = new EPUBJS[renderer](this, options); - this.rendition.attachTo(element); - return this.rendition; -}; - -EPUBJS.Book.prototype.requestMethod = function(_url) { - // Switch request methods - if(this.archived) { - // TODO: handle archived - } else { - return EPUBJS.core.request(_url, 'xml', this.requestCredentials, this.requestHeaders); - } - -}; - -EPUBJS.Book.prototype.setRequestCredentials = function(_credentials) { - this.requestCredentials = _credentials; -}; - -EPUBJS.Book.prototype.setRequestHeaders = function(_headers) { - this.requestHeaders = _headers; -}; -//-- Enable binding events to book -RSVP.EventTarget.mixin(EPUBJS.Book.prototype); - -//-- Handle RSVP Errors -RSVP.on('error', function(event) { - //console.error(event, event.detail); -}); - -RSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections -// RSVP.on('created', listener); -// RSVP.on('chained', listener); -// RSVP.on('fulfilled', listener); -RSVP.on('rejected', function(event){ - console.error(event.detail.message, event.detail.stack); -}); -EPUBJS.Continuous = function(book, options) { - - EPUBJS.Rendition.apply(this, arguments); // call super constructor. - - this.settings = EPUBJS.core.extend(this.settings || {}, { - infinite: true, - overflow: "auto", - axis: "vertical", - offset: 500, - offsetDelta: 250 - }); - - EPUBJS.core.extend(this.settings, options); - - if(this.settings.hidden) { - this.wrapper = this.wrap(this.container); - } - - -}; - -// subclass extends superclass -EPUBJS.Continuous.prototype = Object.create(EPUBJS.Rendition.prototype); -EPUBJS.Continuous.prototype.constructor = EPUBJS.Continuous; - -EPUBJS.Continuous.prototype.attachListeners = function(){ - - // Listen to window for resize event if width or height is set to a percent - if(!EPUBJS.core.isNumber(this.settings.width) || - !EPUBJS.core.isNumber(this.settings.height) ) { - window.addEventListener("resize", this.onResized.bind(this), false); - } - - - if(this.settings.infinite) { - this.start(); - } - - -}; - -EPUBJS.Continuous.prototype._display = function(target){ - - var displaying = new RSVP.defer(); - var displayed = displaying.promise; - - var section; - var view; - var cfi, spinePos; - - if(this.epubcfi.isCfiString(target)) { - cfi = this.epubcfi.parse(target); - spinePos = cfi.spinePos; - section = this.book.spine.get(spinePos); - } else { - section = this.book.spine.get(target); - } - - this.displaying = true; - this.hide(); - - if(section){ - view = new EPUBJS.View(section, this.viewSettings); - - // This will clear all previous views - this.q.enqueue(this.fill, view).then(function(){ - - // Move to correct place within the section, if needed - this.q.enqueue(function(){ - - var offset = view.locationOf(target); - - return this.moveTo(offset); - - }); - - this.q.enqueue(this.check); - - this.q.enqueue(this.show); - - // This hook doesn't prevent showing, but waits to resolve until - // all the hooks have finished. Might want to block showing. - this.hooks.display.trigger(view) - .then(function(){ - this.trigger("displayed", section); - displaying.resolve(this); - }.bind(this)); - - }.bind(this)); - - // view.displayed.then(function(){ - // this.trigger("displayed", section); - // this.displaying = false; - // displaying.resolve(this); - //}.bind(this)); - displaying.resolve(this); - - } else { - displaying.reject(new Error("No Section Found")); - } - - return displayed; -}; - - -EPUBJS.Continuous.prototype.moveTo = function(offset){ - var bounds = this.bounds(); - var dist = Math.floor(offset.top / bounds.height) * bounds.height; - - return this.check(0, dist+this.settings.offset).then(function(){ - - if(this.settings.axis === "vertical") { - this.scrollBy(0, dist); - } else { - this.scrollBy(dist, 0); - } - - }.bind(this)); -}; - -EPUBJS.Continuous.prototype.afterDisplayed = function(currView){ - var next = currView.section.next(); - var prev = currView.section.prev(); - var index = this.views.indexOf(currView); - - var prevView, nextView; - - if(index + 1 === this.views.length && next) { - nextView = new EPUBJS.View(next, this.viewSettings); - this.q.enqueue(this.append, nextView); - } - - if(index === 0 && prev) { - prevView = new EPUBJS.View(prev, this.viewSettings); - this.q.enqueue(this.prepend, prevView); - } - - // this.removeShownListeners(currView); - // currView.onShown = this.afterDisplayed.bind(this); - - this.trigger("added", currView.section); - -}; - - -// Remove Previous Listeners if present -EPUBJS.Continuous.prototype.removeShownListeners = function(view){ - - // view.off("shown", this.afterDisplayed); - // view.off("shown", this.afterDisplayedAbove); - view.onDisplayed = function(){}; - -}; - -EPUBJS.Continuous.prototype.append = function(view){ - this.views.push(view); - this.container.appendChild(view.element); - - // view.on("shown", this.afterDisplayed.bind(this)); - view.onDisplayed = this.afterDisplayed.bind(this); - - //this.q.enqueue(this.check); - return this.check(); -}; - -EPUBJS.Continuous.prototype.prepend = function(view){ - this.views.unshift(view); - this.container.insertBefore(view.element, this.container.firstChild); - - // view.on("shown", this.afterDisplayedAbove.bind(this)); - view.onDisplayed = this.afterDisplayed.bind(this); - - view.on("resized", this.counter.bind(this)); - - // this.q.enqueue(this.check); - return this.check(); -}; - -EPUBJS.Continuous.prototype.counter = function(bounds){ - - if(this.settings.axis === "vertical") { - this.scrollBy(0, bounds.heightDelta, true); - } else { - this.scrollBy(bounds.widthDelta, 0, true); - } - -}; - -EPUBJS.Continuous.prototype.fill = function(view){ - - if(this.views.length){ - this.clear(); - } - - this.views.push(view); - - this.container.appendChild(view.element); - - // view.on("shown", this.afterDisplayed.bind(this)); - view.onDisplayed = this.afterDisplayed.bind(this); - - return this.render(view) - .then(function(){ - return this.check(); - }.bind(this)); -}; - -EPUBJS.Continuous.prototype.insert = function(view, index) { - this.views.splice(index, 0, view); - - if(index < this.cotainer.children.length){ - this.container.insertBefore(view.element, this.container.children[index]); - } else { - this.container.appendChild(view.element); - } - - // this.q.enqueue(this.check); - return this.check(); -}; - -// // Remove the render element and clean up listeners -// EPUBJS.Continuous.prototype.remove = function(view) { -// var index = this.views.indexOf(view); -// if(index > -1) { -// this.views.splice(index, 1); -// } - -// this.container.removeChild(view.element); - -// view.off("resized"); - -// if(view.displayed){ -// view.destroy(); -// } - -// view = null; - -// }; - -EPUBJS.Continuous.prototype.first = function() { - return this.views[0]; -}; - -EPUBJS.Continuous.prototype.last = function() { - return this.views[this.views.length-1]; -}; - -EPUBJS.Continuous.prototype.each = function(func) { - return this.views.forEach(func); -}; - -EPUBJS.Continuous.prototype.check = function(_offset){ - var checking = new RSVP.defer(); - var container = this.bounds(); - var promises = []; - var offset = _offset || this.settings.offset; - - - this.views.forEach(function(view){ - var visible = this.isVisible(view, offset, offset, container); - - if(visible) { - - if(!view.displayed && !view.rendering) { - // console.log("render",view.section.index) - promises.push(this.render(view)); - } - - } else { - - if(view.displayed) { - // console.log("destroy", view.section.index) - this.q.enqueue(view.destroy.bind(view)); - // view.destroy(); - // this.q.enqueue(this.trim); - clearTimeout(this.trimTimeout); - this.trimTimeout = setTimeout(function(){ - this.q.enqueue(this.trim); - }.bind(this), 250); - } - - } - - }.bind(this)); - - - if(promises.length){ - - return RSVP.all(promises) - .then(function(posts) { - // Check to see if anything new is on screen after rendering - this.q.enqueue(this.check); - - }.bind(this)); - - } else { - checking.resolve(); - - return checking.promise; - } - -}; - -// EPUBJS.Continuous.prototype.trim = function(){ -// var task = new RSVP.defer(); -// var above = true; - -// this.views.forEach(function(view, i){ -// // var view = this.views[i]; -// var prevShown = i > 0 ? this.views[i-1].displayed : false; -// var nextShown = (i+1 < this.views.length) ? this.views[i+1].displayed : false; -// if(!view.displayed && !prevShown && !nextShown) { -// // Remove -// this.erase(view, above); -// } -// if(nextShown) { -// above = false; -// } -// }.bind(this)); - -// task.resolve(); -// return task.promise; -// }; - -EPUBJS.Continuous.prototype.trim = function(){ - var task = new RSVP.defer(); - var displayed = this.displayed(); - var first = displayed[0]; - var last = displayed[displayed.length-1]; - var firstIndex = this.views.indexOf(first); - var lastIndex = this.views.indexOf(last); - var above = this.views.slice(0, firstIndex); - var below = this.views.slice(lastIndex+1); - - // Erase all but last above - for (var i = 0; i < above.length-1; i++) { - this.erase(above[i], above); - } - - // Erase all except first below - for (var j = 1; j < below.length; j++) { - this.erase(below[j]); - } - - task.resolve(); - return task.promise; -}; - -EPUBJS.Continuous.prototype.erase = function(view, above){ //Trim - - var prevTop; - var prevLeft; - - if(this.settings.height) { - prevTop = this.container.scrollTop; - prevLeft = this.container.scrollLeft; - } else { - prevTop = window.scrollY; - prevLeft = window.scrollX; - } - - var bounds = view.bounds(); - - this.remove(view); - - if(above) { - - if(this.settings.axis === "vertical") { - this.scrollTo(0, prevTop - bounds.height, true); - } else { - this.scrollTo(prevLeft - bounds.width, 0, true); - } - } - -}; - - -EPUBJS.Continuous.prototype.checkCurrent = function(position) { - var view, top; - var container = this.container.getBoundingClientRect(); - var length = this.views.length - 1; - - if(this.rendering) { - return; - } - - if(this.settings.axis === "horizontal") { - // TODO: Check for current horizontal - } else { - - for (var i = length; i >= 0; i--) { - view = this.views[i]; - top = view.bounds().top; - if(top < container.bottom) { - - if(this.current == view.section) { - break; - } - - this.current = view.section; - this.trigger("current", this.current); - break; - } - } - - } - -}; - -EPUBJS.Continuous.prototype.start = function() { - var scroller; - - this.tick = EPUBJS.core.requestAnimationFrame; - - if(this.settings.height) { - this.prevScrollTop = this.container.scrollTop; - this.prevScrollLeft = this.container.scrollLeft; - } else { - this.prevScrollTop = window.scrollY; - this.prevScrollLeft = window.scrollX; - } - - this.scrollDeltaVert = 0; - this.scrollDeltaHorz = 0; - - if(this.settings.height) { - scroller = this.container; - } else { - scroller = window; - } - - window.addEventListener("scroll", function(e){ - if(!this.ignore) { - this.scrolled = true; - } else { - this.ignore = false; - } - }.bind(this)); - - window.addEventListener('unload', function(e){ - this.ignore = true; - this.destroy(); - }.bind(this)); - - this.tick.call(window, this.onScroll.bind(this)); - - this.scrolled = false; - -}; - -EPUBJS.Continuous.prototype.onScroll = function(){ - - if(this.scrolled) { - - if(this.settings.height) { - scrollTop = this.container.scrollTop; - scrollLeft = this.container.scrollLeft; - } else { - scrollTop = window.scrollY; - scrollLeft = window.scrollX; - } - - if(!this.ignore) { - - // this.trigger("scroll", { - // top: scrollTop, - // left: scrollLeft - // }); - - if((this.scrollDeltaVert === 0 && - this.scrollDeltaHorz === 0) || - this.scrollDeltaVert > this.settings.offsetDelta || - this.scrollDeltaHorz > this.settings.offsetDelta) { - - this.q.enqueue(this.check); - - this.scrollDeltaVert = 0; - this.scrollDeltaHorz = 0; - - } - - } else { - this.ignore = false; - } - - this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop); - this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft); - - if(this.settings.height) { - this.prevScrollTop = this.container.scrollTop; - this.prevScrollLeft = this.container.scrollLeft; - } else { - this.prevScrollTop = window.scrollY; - this.prevScrollLeft = window.scrollX; - } - - - clearTimeout(this.scrollTimeout); - this.scrollTimeout = setTimeout(function(){ - this.scrollDeltaVert = 0; - this.scrollDeltaHorz = 0; - }.bind(this), 150); - - - this.scrolled = false; - } - - this.tick.call(window, this.onScroll.bind(this)); - -}; - -EPUBJS.Continuous.prototype.scrollBy = function(x, y, silent){ - if(silent) { - this.ignore = true; - } - - if(this.settings.height) { - - if(x) this.container.scrollLeft += x; - if(y) this.container.scrollTop += y; - - } else { - window.scrollBy(x,y); - } - // console.log("scrollBy", x, y); - this.scrolled = true; -}; - -EPUBJS.Continuous.prototype.scrollTo = function(x, y, silent){ - if(silent) { - this.ignore = true; - } - - if(this.settings.height) { - this.container.scrollLeft = x; - this.container.scrollTop = y; - } else { - window.scrollTo(x,y); - } - // console.log("scrollTo", x, y); - this.scrolled = true; - // if(this.container.scrollLeft != x){ - // setTimeout(function() { - // this.scrollTo(x, y, silent); - // }.bind(this), 10); - // return; - // }; - }; - - EPUBJS.Continuous.prototype.resizeView = function(view) { - - if(this.settings.axis === "horizontal") { - view.lock("height", this.stage.width, this.stage.height); - } else { - view.lock("width", this.stage.width, this.stage.height); - } - -}; - -EPUBJS.Continuous.prototype.currentLocation = function(){ - var visible = this.visible(); - var startPage, endPage; - - var container = this.container.getBoundingClientRect(); - - if(visible.length === 1) { - return this.map.page(visible[0]); - } - - if(visible.length > 1) { - - startPage = this.map.page(visible[0]); - endPage = this.map.page(visible[visible.length-1]); - - return { - start: startPage.start, - end: endPage.end - }; - } - -}; - -/* -EPUBJS.Continuous.prototype.current = function(what){ - var view, top; - var container = this.container.getBoundingClientRect(); - var length = this.views.length - 1; - - if(this.settings.axis === "horizontal") { - - for (var i = length; i >= 0; i--) { - view = this.views[i]; - left = view.position().left; - - if(left < container.right) { - - if(this._current == view) { - break; - } - - this._current = view; - break; - } - } - - } else { - - for (var i = length; i >= 0; i--) { - view = this.views[i]; - top = view.bounds().top; - if(top < container.bottom) { - - if(this._current == view) { - break; - } - - this._current = view; - - break; - } - } - - } - - return this._current; -}; -*/ -EPUBJS.core = {}; - -EPUBJS.core.request = function(url, type, withCredentials, headers) { - var supportsURL = window.URL; - var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer"; - - var deferred = new RSVP.defer(); - - var xhr = new XMLHttpRequest(); - - //-- Check from PDF.js: - // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js - var xhrPrototype = XMLHttpRequest.prototype; - - var header; - - if (!('overrideMimeType' in xhrPrototype)) { - // IE10 might have response, but not overrideMimeType - Object.defineProperty(xhrPrototype, 'overrideMimeType', { - value: function xmlHttpRequestOverrideMimeType(mimeType) {} - }); - } - if(withCredentials) { - xhr.withCredentials = true; - } - - xhr.open("GET", url, true); - - for(header in headers) { - xhr.setRequestHeader(header, headers[header]); - } - - xhr.onreadystatechange = handler; - - if(type == 'blob'){ - xhr.responseType = BLOB_RESPONSE; - } - - if(type == "json") { - xhr.setRequestHeader("Accept", "application/json"); - } - - if(type == 'xml') { - xhr.overrideMimeType('text/xml'); - } - - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls - var r; - - if(type == 'xml'){ - - // If this.responseXML wasn't set, try to parse using a DOMParser from text - if(!this.responseXML){ - r = new DOMParser().parseFromString(this.response, "text/xml"); - } else { - r = this.responseXML; - } - - }else - if(type == 'json'){ - r = JSON.parse(this.response); - }else - if(type == 'blob'){ - - if(supportsURL) { - r = this.response; - } else { - //-- Safari doesn't support responseType blob, so create a blob from arraybuffer - r = new Blob([this.response]); - } - - }else{ - r = this.response; - } - - deferred.resolve(r); - } else { - deferred.reject({ - status: this.status, - message : this.response, - stack : new Error().stack - }); - } - } - } - - return deferred.promise; -}; - -//-- Parse the different parts of a url, returning a object -EPUBJS.core.uri = function(url){ - var uri = { - protocol : '', - host : '', - path : '', - origin : '', - directory : '', - base : '', - filename : '', - extension : '', - fragment : '', - href : url - }, - doubleSlash = url.indexOf('://'), - search = url.indexOf('?'), - fragment = url.indexOf("#"), - withoutProtocol, - dot, - firstSlash; - - if(fragment != -1) { - uri.fragment = url.slice(fragment + 1); - url = url.slice(0, fragment); - } - - if(search != -1) { - uri.search = url.slice(search + 1); - url = url.slice(0, search); - href = url; - } - - if(doubleSlash != -1) { - uri.protocol = url.slice(0, doubleSlash); - withoutProtocol = url.slice(doubleSlash+3); - firstSlash = withoutProtocol.indexOf('/'); - - if(firstSlash === -1) { - uri.host = uri.path; - uri.path = ""; - } else { - uri.host = withoutProtocol.slice(0, firstSlash); - uri.path = withoutProtocol.slice(firstSlash); - } - - - uri.origin = uri.protocol + "://" + uri.host; - - uri.directory = EPUBJS.core.folder(uri.path); - - uri.base = uri.origin + uri.directory; - // return origin; - } else { - uri.path = url; - uri.directory = EPUBJS.core.folder(url); - uri.base = uri.directory; - } - - //-- Filename - uri.filename = url.replace(uri.base, ''); - dot = uri.filename.lastIndexOf('.'); - if(dot != -1) { - uri.extension = uri.filename.slice(dot+1); - } - return uri; -}; - -//-- Parse out the folder, will return everything before the last slash -EPUBJS.core.folder = function(url){ - - var lastSlash = url.lastIndexOf('/'); - - if(lastSlash == -1) var folder = ''; - - folder = url.slice(0, lastSlash + 1); - - return folder; - -}; - - -EPUBJS.core.queue = function(_scope){ - var _q = []; - var scope = _scope; - // Add an item to the queue - var enqueue = function(funcName, args, context) { - _q.push({ - "funcName" : funcName, - "args" : args, - "context" : context - }); - return _q; - }; - // Run one item - var dequeue = function(){ - var inwait; - if(_q.length) { - inwait = _q.shift(); - // Defer to any current tasks - // setTimeout(function(){ - scope[inwait.funcName].apply(inwait.context || scope, inwait.args); - // }, 0); - } - }; - - // Run All - var flush = function(){ - while(_q.length) { - dequeue(); - } - }; - // Clear all items in wait - var clear = function(){ - _q = []; - }; - - var length = function(){ - return _q.length; - }; - - return { - "enqueue" : enqueue, - "dequeue" : dequeue, - "flush" : flush, - "clear" : clear, - "length" : length - }; -}; - -EPUBJS.core.isElement = function(obj) { - return !!(obj && obj.nodeType == 1); -}; - -// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript -EPUBJS.core.uuid = function() { - var d = new Date().getTime(); - var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = (d + Math.random()*16)%16 | 0; - d = Math.floor(d/16); - return (c=='x' ? r : (r&0x7|0x8)).toString(16); - }); - return uuid; -}; - -// From Lodash -EPUBJS.core.values = function(object) { - var index = -1, - props = Object.keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; - } - return result; -}; - -EPUBJS.core.resolveUrl = function(base, path) { - var url = [], - segments = [], - baseUri = EPUBJS.core.uri(base), - pathUri = EPUBJS.core.uri(path), - baseDirectory = baseUri.directory, - pathDirectory = pathUri.directory, - directories = [], - // folders = base.split("/"), - paths; - - // if(uri.host) { - // return path; - // } - - if(baseDirectory[0] === "/") { - baseDirectory = baseDirectory.substring(1); - } - - if(pathDirectory[pathDirectory.length-1] === "/") { - baseDirectory = baseDirectory.substring(0, baseDirectory.length-1); - } - - if(pathDirectory[0] === "/") { - pathDirectory = pathDirectory.substring(1); - } - - if(pathDirectory[pathDirectory.length-1] === "/") { - pathDirectory = pathDirectory.substring(0, pathDirectory.length-1); - } - - if(baseDirectory) { - directories = baseDirectory.split("/"); - } - - paths = pathDirectory.split("/"); - - paths.reverse().forEach(function(part, index){ - if(part === ".."){ - directories.pop(); - } else if(part === directories[directories.length-1]) { - directories.pop(); - segments.unshift(part); - } else { - segments.unshift(part); - } - }); - - url = [baseUri.origin]; - - if(directories.length) { - url = url.concat(directories); - } - - if(segments) { - url = url.concat(segments); - } - - url = url.concat(pathUri.filename); - - return url.join("/"); -}; - -EPUBJS.core.documentHeight = function() { - return Math.max( - document.documentElement.clientHeight, - document.body.scrollHeight, - document.documentElement.scrollHeight, - document.body.offsetHeight, - document.documentElement.offsetHeight - ); -}; - -EPUBJS.core.isNumber = function(n) { - return !isNaN(parseFloat(n)) && isFinite(n); -}; - -EPUBJS.core.prefixed = function(unprefixed) { - var vendors = ["Webkit", "Moz", "O", "ms" ], - prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'], - upper = unprefixed[0].toUpperCase() + unprefixed.slice(1), - length = vendors.length; - - if (typeof(document.body.style[unprefixed]) != 'undefined') { - return unprefixed; - } - - for ( var i=0; i < length; i++ ) { - if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') { - return vendors[i] + upper; - } - } - - return unprefixed; -}; - -EPUBJS.core.defaults = function(obj) { - for (var i = 1, length = arguments.length; i < length; i++) { - var source = arguments[i]; - for (var prop in source) { - if (obj[prop] === void 0) obj[prop] = source[prop]; - } - } - return obj; -}; - -EPUBJS.core.extend = function(target) { - var sources = [].slice.call(arguments, 1); - sources.forEach(function (source) { - if(!source) return; - Object.getOwnPropertyNames(source).forEach(function(propName) { - Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName)); - }); - }); - return target; -}; - -// Fast quicksort insert for sorted array -- based on: -// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers -EPUBJS.core.insert = function(item, array, compareFunction) { - var location = EPUBJS.core.locationOf(item, array, compareFunction); - array.splice(location, 0, item); - - return location; -}; -// Returns where something would fit in -EPUBJS.core.locationOf = function(item, array, compareFunction, _start, _end) { - var start = _start || 0; - var end = _end || array.length; - var pivot = parseInt(start + (end - start) / 2); - var compared; - if(!compareFunction){ - compareFunction = function(a, b) { - if(a > b) return 1; - if(a < b) return -1; - if(a = b) return 0; - }; - } - if(end-start <= 0) { - return pivot; - } - - compared = compareFunction(array[pivot], item); - if(end-start === 1) { - return compared > 0 ? pivot : pivot + 1; - } - - if(compared === 0) { - return pivot; - } - if(compared === -1) { - return EPUBJS.core.locationOf(item, array, compareFunction, pivot, end); - } else{ - return EPUBJS.core.locationOf(item, array, compareFunction, start, pivot); - } -}; -// Returns -1 of mpt found -EPUBJS.core.indexOfSorted = function(item, array, compareFunction, _start, _end) { - var start = _start || 0; - var end = _end || array.length; - var pivot = parseInt(start + (end - start) / 2); - var compared; - if(!compareFunction){ - compareFunction = function(a, b) { - if(a > b) return 1; - if(a < b) return -1; - if(a = b) return 0; - }; - } - if(end-start <= 0) { - return -1; // Not found - } - - compared = compareFunction(array[pivot], item); - if(end-start === 1) { - return compared === 0 ? pivot : -1; - } - if(compared === 0) { - return pivot; // Found - } - if(compared === -1) { - return EPUBJS.core.indexOfSorted(item, array, compareFunction, pivot, end); - } else{ - return EPUBJS.core.indexOfSorted(item, array, compareFunction, start, pivot); - } -}; - -EPUBJS.core.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; - -EPUBJS.core.bounds = function(el) { - - var style = window.getComputedStyle(el); - var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; - var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; - - var width = 0; - var height = 0; - - widthProps.forEach(function(prop){ - width += parseFloat(style[prop]) || 0; - }); - - heightProps.forEach(function(prop){ - height += parseFloat(style[prop]) || 0; - }); - - return { - height: height, - width: width - }; - -}; - -EPUBJS.core.borders = function(el) { - - var style = window.getComputedStyle(el); - var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; - var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; - - var width = 0; - var height = 0; - - widthProps.forEach(function(prop){ - width += parseFloat(style[prop]) || 0; - }); - - heightProps.forEach(function(prop){ - height += parseFloat(style[prop]) || 0; - }); - - return { - height: height, - width: width - }; - -}; - -EPUBJS.core.windowBounds = function() { - - var width = window.innerWidth; - var height = window.innerHeight; - - return { - top: 0, - left: 0, - right: width, - bottom: height, - width: width, - height: height - }; - -}; - -//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496 -EPUBJS.core.cleanStringForXpath = function(str) { - var parts = str.match(/[^'"]+|['"]/g); - parts = parts.map(function(part){ - if (part === "'") { - return '\"\'\"'; // output "'" - } - - if (part === '"') { - return "\'\"\'"; // output '"' - } - return "\'" + part + "\'"; - }); - return "concat(\'\'," + parts.join(",") + ")"; -}; - -EPUBJS.core.indexOfTextNode = function(textNode){ - var parent = textNode.parentNode; - var children = parent.childNodes; - var sib; - var index = -1; - for (var i = 0; i < children.length; i++) { - sib = children[i]; - if(sib.nodeType === Node.TEXT_NODE){ - index++; - } - if(sib == textNode) break; - } - - return index; -}; -if (typeof EPUBJS === 'undefined') { - (typeof window !== 'undefined' ? window : this).EPUBJS = {}; -} - -EPUBJS.VERSION = "0.3.0"; - -(function(root) { - "use strict"; - var ePub = function(_url) { - return new EPUBJS.Book(_url); - }; - - // CommonJS - if (typeof exports === "object") { - root.RSVP = require("rsvp"); - module.exports = ePub; - // RequireJS - } else if (typeof define === "function" && define.amd) { - define(ePub); - // Global - } else { - root.ePub = ePub; - } - -})(this); - - -EPUBJS.EpubCFI = function(cfiStr){ - if(cfiStr) return this.parse(cfiStr); -}; - -EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) { - var pos = parseInt(_pos), - spineNodeIndex = _spineNodeIndex + 1, - cfi = '/'+spineNodeIndex+'/'; - - cfi += (pos + 1) * 2; - - if(id) cfi += "[" + id + "]"; - - //cfi += "!"; - - return cfi; -}; - -EPUBJS.EpubCFI.prototype.generatePathComponent = function(steps) { - var parts = []; - - steps.forEach(function(part){ - var segment = ''; - segment += (part.index + 1) * 2; - - if(part.id) { - segment += "[" + part.id + "]"; - } - - parts.push(segment); - }); - - return parts.join('/'); -}; - -EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) { - var steps = this.pathTo(element); - var path = this.generatePathComponent(steps); - if(!path.length) { - // Start of Chapter - return "epubcfi(" + chapter + "!/4/)"; - } else { - // First Text Node - return "epubcfi(" + chapter + "!" + path + "/1:0)"; - } -}; - -EPUBJS.EpubCFI.prototype.pathTo = function(node) { - var stack = [], - children; - - while(node && node.parentNode !== null && node.parentNode.nodeType != 9) { - children = node.parentNode.children; - - stack.unshift({ - 'id' : node.id, - // 'classList' : node.classList, - 'tagName' : node.tagName, - 'index' : children ? Array.prototype.indexOf.call(children, node) : 0 - }); - - node = node.parentNode; - } - - return stack; -}; - -EPUBJS.EpubCFI.prototype.getChapterComponent = function(cfiStr) { - - var splitStr = cfiStr.split("!"); - - return splitStr[0]; -}; - -EPUBJS.EpubCFI.prototype.getPathComponent = function(cfiStr) { - - var splitStr = cfiStr.split("!"); - var pathComponent = splitStr[1] ? splitStr[1].split(":") : ''; - - return pathComponent[0]; -}; - -EPUBJS.EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) { - var splitStr = cfiStr.split(":"); - return splitStr[1] || ''; -}; - - -EPUBJS.EpubCFI.prototype.parse = function(cfiStr) { - var cfi = {}, - chapSegment, - chapterComponent, - pathComponent, - charecterOffsetComponent, - assertion, - chapId, - path, - end, - endInt, - text, - parseStep = function(part){ - var type, index, has_brackets, id; - - type = "element"; - index = parseInt(part) / 2 - 1; - has_brackets = part.match(/\[(.*)\]/); - if(has_brackets && has_brackets[1]){ - id = has_brackets[1]; - } - - return { - "type" : type, - 'index' : index, - 'id' : id || false - }; - }; - - if(typeof cfiStr !== "string") { - return {spinePos: -1}; - } - - cfi.str = cfiStr; - - if(cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length-1] === ")") { - // Remove intial epubcfi( and ending ) - cfiStr = cfiStr.slice(8, cfiStr.length-1); - } - - chapterComponent = this.getChapterComponent(cfiStr); - pathComponent = this.getPathComponent(cfiStr) || ''; - charecterOffsetComponent = this.getCharecterOffsetComponent(cfiStr); - // Make sure this is a valid cfi or return - if(!chapterComponent) { - return {spinePos: -1}; - } - - // Chapter segment is always the second one - chapSegment = chapterComponent.split("/")[2] || ''; - if(!chapSegment) return {spinePos:-1}; - - cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0; - - chapId = chapSegment.match(/\[(.*)\]/); - - cfi.spineId = chapId ? chapId[1] : false; - - if(pathComponent.indexOf(',') != -1) { - // Handle ranges -- not supported yet - console.warn("CFI Ranges are not supported"); - } - - path = pathComponent.split('/'); - end = path.pop(); - - cfi.steps = []; - - path.forEach(function(part){ - var step; - - if(part) { - step = parseStep(part); - cfi.steps.push(step); - } - }); - - //-- Check if END is a text node or element - endInt = parseInt(end); - if(!isNaN(endInt)) { - - if(endInt % 2 === 0) { // Even = is an element - cfi.steps.push(parseStep(end)); - } else { - cfi.steps.push({ - "type" : "text", - 'index' : (endInt - 1 ) / 2 - }); - } - - } - - assertion = charecterOffsetComponent.match(/\[(.*)\]/); - if(assertion && assertion[1]){ - cfi.characterOffset = parseInt(charecterOffsetComponent.split('[')[0]); - // We arent handling these assertions yet - cfi.textLocationAssertion = assertion[1]; - } else { - cfi.characterOffset = parseInt(charecterOffsetComponent); - } - - return cfi; -}; - -EPUBJS.EpubCFI.prototype.addMarker = function(cfi, _doc, _marker) { - var doc = _doc || document; - var marker = _marker || this.createMarker(doc); - var parent; - var lastStep; - var text; - var split; - - if(typeof cfi === 'string') { - cfi = this.parse(cfi); - } - // Get the terminal step - lastStep = cfi.steps[cfi.steps.length-1]; - - // check spinePos - if(cfi.spinePos === -1) { - // Not a valid CFI - return false; - } - - // Find the CFI elements parent - parent = this.findParent(cfi, doc); - - if(!parent) { - // CFI didn't return an element - // Maybe it isnt in the current chapter? - return false; - } - - if(lastStep && lastStep.type === "text") { - text = parent.childNodes[lastStep.index]; - if(cfi.characterOffset){ - split = text.splitText(cfi.characterOffset); - marker.classList.add("EPUBJS-CFI-SPLIT"); - parent.insertBefore(marker, split); - } else { - parent.insertBefore(marker, text); - } - } else { - parent.insertBefore(marker, parent.firstChild); - } - - return marker; -}; - -EPUBJS.EpubCFI.prototype.createMarker = function(_doc) { - var doc = _doc || document; - var element = doc.createElement('span'); - element.id = "EPUBJS-CFI-MARKER:"+ EPUBJS.core.uuid(); - element.classList.add("EPUBJS-CFI-MARKER"); - - return element; -}; - -EPUBJS.EpubCFI.prototype.removeMarker = function(marker, _doc) { - var doc = _doc || document; - // var id = marker.id; - - // Cleanup textnodes if they were split - if(marker.classList.contains("EPUBJS-CFI-SPLIT")){ - nextSib = marker.nextSibling; - prevSib = marker.previousSibling; - if(nextSib && - prevSib && - nextSib.nodeType === 3 && - prevSib.nodeType === 3){ - - prevSib.textContent += nextSib.textContent; - marker.parentNode.removeChild(nextSib); - } - marker.parentNode.removeChild(marker); - } else if(marker.classList.contains("EPUBJS-CFI-MARKER")) { - // Remove only elements added as markers - marker.parentNode.removeChild(marker); - } - -}; - -EPUBJS.EpubCFI.prototype.findParent = function(cfi, _doc) { - var doc = _doc || document, - element = doc.getElementsByTagName('html')[0], - children = Array.prototype.slice.call(element.children), - num, index, part, sections, - text, textBegin, textEnd; - - if(typeof cfi === 'string') { - cfi = this.parse(cfi); - } - - sections = cfi.steps.slice(0); // Clone steps array - if(!sections.length) { - return doc.getElementsByTagName('body')[0]; - } - - while(sections && sections.length > 0) { - part = sections.shift(); - // Find textNodes Parent - if(part.type === "text") { - text = element.childNodes[part.index]; - element = text.parentNode || element; - // Find element by id if present - } else if(part.id){ - element = doc.getElementById(part.id); - // Find element in parent - }else{ - element = children[part.index]; - } - // Element can't be found - if(typeof element === "undefined") { - console.error("No Element For", part, cfi.str); - return false; - } - // Get current element children and continue through steps - children = Array.prototype.slice.call(element.children); - } - - return element; -}; - -EPUBJS.EpubCFI.prototype.compare = function(cfiOne, cfiTwo) { - if(typeof cfiOne === 'string') { - cfiOne = new EPUBJS.EpubCFI(cfiOne); - } - if(typeof cfiTwo === 'string') { - cfiTwo = new EPUBJS.EpubCFI(cfiTwo); - } - // Compare Spine Positions - if(cfiOne.spinePos > cfiTwo.spinePos) { - return 1; - } - if(cfiOne.spinePos < cfiTwo.spinePos) { - return -1; - } - - - // Compare Each Step in the First item - for (var i = 0; i < cfiOne.steps.length; i++) { - if(!cfiTwo.steps[i]) { - return 1; - } - if(cfiOne.steps[i].index > cfiTwo.steps[i].index) { - return 1; - } - if(cfiOne.steps[i].index < cfiTwo.steps[i].index) { - return -1; - } - // Otherwise continue checking - } - - // All steps in First present in Second - if(cfiOne.steps.length < cfiTwo.steps.length) { - return -1; - } - - // Compare the charecter offset of the text node - if(cfiOne.characterOffset > cfiTwo.characterOffset) { - return 1; - } - if(cfiOne.characterOffset < cfiTwo.characterOffset) { - return -1; - } - - // CFI's are equal - return 0; -}; - -EPUBJS.EpubCFI.prototype.generateCfiFromHref = function(href, book) { - var uri = EPUBJS.core.uri(href); - var path = uri.path; - var fragment = uri.fragment; - var spinePos = book.spineIndexByURL[path]; - var loaded; - var deferred = new RSVP.defer(); - var epubcfi = new EPUBJS.EpubCFI(); - var spineItem; - - if(typeof spinePos !== "undefined"){ - spineItem = book.spine[spinePos]; - loaded = book.loadXml(spineItem.url); - loaded.then(function(doc){ - var element = doc.getElementById(fragment); - var cfi; - cfi = epubcfi.generateCfiFromElement(element, spineItem.cfiBase); - deferred.resolve(cfi); - }); - } - - return deferred.promise; -}; - -EPUBJS.EpubCFI.prototype.generateCfiFromTextNode = function(anchor, offset, base) { - var parent = anchor.parentNode; - var steps = this.pathTo(parent); - var path = this.generatePathComponent(steps); - var index = 1 + (2 * Array.prototype.indexOf.call(parent.childNodes, anchor)); - return "epubcfi(" + base + "!" + path + "/"+index+":"+(offset || 0)+")"; -}; - -EPUBJS.EpubCFI.prototype.generateCfiFromRangeAnchor = function(range, base) { - var anchor = range.anchorNode; - var offset = range.anchorOffset; - return this.generateCfiFromTextNode(anchor, offset, base); -}; - -EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) { - var start, startElement, startSteps, startPath, startOffset, startIndex; - var end, endElement, endSteps, endPath, endOffset, endIndex; - - start = range.startContainer; - - if(start.nodeType === 3) { // text node - startElement = start.parentNode; - //startIndex = 1 + (2 * Array.prototype.indexOf.call(startElement.childNodes, start)); - startIndex = 1 + (2 * EPUBJS.core.indexOfTextNode(start)); - startSteps = this.pathTo(startElement); - } else if(range.collapsed) { - return this.generateCfiFromElement(start, base); // single element - } else { - startSteps = this.pathTo(start); - } - - startPath = this.generatePathComponent(startSteps); - startOffset = range.startOffset; - - if(!range.collapsed) { - end = range.endContainer; - - if(end.nodeType === 3) { // text node - endElement = end.parentNode; - // endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end)); - endIndex = 1 + (2 * EPUBJS.core.indexOfTextNode(end)); - - endSteps = this.pathTo(endElement); - } else { - endSteps = this.pathTo(end); - } - - endPath = this.generatePathComponent(endSteps); - endOffset = range.endOffset; - - return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")"; - - } else { - return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")"; - } -}; - -EPUBJS.EpubCFI.prototype.generateXpathFromSteps = function(steps) { - var xpath = [".", "*"]; - - steps.forEach(function(step){ - var position = step.index + 1; - - if(step.id){ - xpath.push("*[position()=" + position + " and @id='" + step.id + "']"); - } else if(step.type === "text") { - xpath.push("text()[" + position + "]"); - } else { - xpath.push("*[" + position + "]"); - } - }); - - return xpath.join("/"); -}; - - -EPUBJS.EpubCFI.prototype.generateRangeFromCfi = function(cfi, _doc) { - var doc = _doc || document; - var range = doc.createRange(); - var lastStep; - var xpath; - var startContainer; - var textLength; - - if(typeof cfi === 'string') { - cfi = this.parse(cfi); - } - - // check spinePos - if(cfi.spinePos === -1) { - // Not a valid CFI - return false; - } - - xpath = this.generateXpathFromSteps(cfi.steps); - - // Get the terminal step - lastStep = cfi.steps[cfi.steps.length-1]; - startContainer = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; - - if(!startContainer) { - return null; - } - - if(startContainer && cfi.characterOffset >= 0) { - textLength = startContainer.length; - - if(cfi.characterOffset < textLength) { - range.setStart(startContainer, cfi.characterOffset); - range.setEnd(startContainer, textLength ); - } else { - console.debug("offset greater than length:", cfi.characterOffset, textLength); - range.setStart(startContainer, textLength - 1 ); - range.setEnd(startContainer, textLength ); - } - } else if(startContainer) { - range.selectNode(startContainer); - } - // doc.defaultView.getSelection().addRange(range); - return range; -}; - -EPUBJS.EpubCFI.prototype.isCfiString = function(target) { - if(typeof target === "string" && - target.indexOf("epubcfi(") === 0) { - return true; - } - - return false; -}; -EPUBJS.Hook = function(context){ - this.context = context || this; - this.hooks = []; -}; - -//-- Hooks allow for injecting async functions that must all complete in order before finishing -// Functions must return a promise. - -// this.beforeDisplay = new EPUBJS.Hook(); -// this.beforeDisplay.register(function(){}); -// this.beforeDisplay.trigger(args).then(function(){}); - -// Adds a function to be run before a hook completes -EPUBJS.Hook.prototype.register = function(func){ - this.hooks.push(func); -}; - -// Triggers a hook to run all functions -EPUBJS.Hook.prototype.trigger = function(){ - var args = arguments; - var context = this.context; - var promises = []; - - this.hooks.forEach(function(task, i) { - var executing = task.apply(context, args); - - if(executing && typeof executing["then"] === "function") { - // Task is a function that returns a promise - promises.push(executing); - } - // Otherwise Task resolves immediately, continue - }); - - - return RSVP.all(promises); -}; -EPUBJS.Layout = EPUBJS.Layout || {}; - -EPUBJS.Layout.Reflowable = function(){ - -}; - -EPUBJS.Layout.Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){ - - var divisor = _devisor || 1; - - //-- Check the width and create even width columns - var fullWidth = Math.floor(_width); - var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1; - - var section = Math.floor(width / 8); - var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1); - - var colWidth; - var spreadWidth; - var delta; - - //-- Double Page - if(divisor > 1) { - colWidth = Math.floor((width - gap) / divisor); - } else { - colWidth = width; - } - - spreadWidth = colWidth * divisor; - - delta = (colWidth + gap) * divisor; - - - - this.columnAxis = EPUBJS.core.prefixed('columnAxis'); - this.columnGap = EPUBJS.core.prefixed('columnGap'); - this.columnWidth = EPUBJS.core.prefixed('columnWidth'); - this.columnFill = EPUBJS.core.prefixed('columnFill'); - - this.width = width; - this.height = _height; - this.spread = spreadWidth; - this.delta = delta; - - this.column = colWidth; - this.gap = gap; - this.divisor = divisor; - -}; - -EPUBJS.Layout.Reflowable.prototype.format = function(view){ - - var $doc = view.document.documentElement; - var $body = view.document.body;//view.document.querySelector("body"); - - $doc.style.overflow = "hidden"; - - // Must be set to the new calculated width or the columns will be off - // $body.style.width = this.width + "px"; - $doc.style.width = this.width + "px"; - - //-- Adjust height - $body.style.height = this.height + "px"; - - //-- Add columns - $body.style[this.columnAxis] = "horizontal"; - $body.style[this.columnFill] = "auto"; - $body.style[this.columnGap] = this.gap+"px"; - $body.style[this.columnWidth] = this.column+"px"; - - // Add extra padding for the gap between this and the next view - view.iframe.style.marginRight = this.gap+"px"; -}; - -EPUBJS.Layout.Reflowable.prototype.count = function(view) { - var totalWidth = view.root().scrollWidth; - var spreads = Math.ceil(totalWidth / this.spread); - - return { - spreads : spreads, - pages : spreads * this.divisor - }; -}; - -EPUBJS.Layout.Fixed = function(_width, _height){ - -}; - -EPUBJS.Layout.Fixed.prototype.calculate = function(_width, _height){ - -}; - -EPUBJS.Layout.Fixed.prototype.format = function(view){ - var width, height; - - var $doc = view.document.documentElement; - var $viewport = documentElement.querySelector("[name=viewport"); - - /** - * check for the viewport size - * - */ - if($viewport && $viewport.hasAttribute("content")) { - content = $viewport.getAttribute("content"); - contents = content.split(','); - if(contents[0]){ - width = contents[0].replace("width=", ''); - } - if(contents[1]){ - height = contents[1].replace("height=", ''); - } - } - - //-- Adjust width and height - // $doc.style.width = width + "px" || "auto"; - // $doc.style.height = height + "px" || "auto"; - view.resize(width, height); - - //-- Scroll - $doc.style.overflow = "auto"; - -}; - -EPUBJS.Layout.Fixed.prototype.count = function(){ - return { - spreads : 1, - pages : 1 - }; -}; - -EPUBJS.Layout.Scroll = function(){ - -}; - -EPUBJS.Layout.Scroll.prototype.calculate = function(_width, _height){ - this.spread = _width; - this.column = _width; - this.gap = 0; -}; - -EPUBJS.Layout.Scroll.prototype.format = function(view){ - - var $doc = view.document.documentElement; - - $doc.style.width = "auto"; - $doc.style.height = "auto"; - -}; - -EPUBJS.Layout.Scroll.prototype.count = function(){ - return { - spreads : 1, - pages : 1 - }; -}; - -EPUBJS.Map = function(layout){ - this.layout = layout; -}; - -EPUBJS.Map.prototype.section = function(view) { - var ranges = this.findRanges(view); - var map = this.rangeListToCfiList(view, ranges); - - return map; -}; - -EPUBJS.Map.prototype.page = function(view, start, end) { - var root = view.document.body; - return this.rangePairToCfiPair(view.section, { - start: this.findStart(root, start, end), - end: this.findEnd(root, start, end) - }); -}; - -EPUBJS.Map.prototype.walk = function(root, func) { - //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false); - var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { - acceptNode: function (node) { - if ( node.data.trim().length > 0 ) { - return NodeFilter.FILTER_ACCEPT; - } else { - return NodeFilter.FILTER_REJECT; - } - } - }, false); - var node; - var result; - while ((node = treeWalker.nextNode())) { - result = func(node); - if(result) break; - } - - return result; -}; - -EPUBJS.Map.prototype.findRanges = function(view){ - var columns = []; - var count = this.layout.count(view); - var column = this.layout.column; - var gap = this.layout.gap; - var start, end; - - for (var i = 0; i < count.pages; i++) { - start = (column + gap) * i; - end = (column * (i+1)) + (gap * i); - columns.push({ - start: this.findStart(view.document.body, start, end), - end: this.findEnd(view.document.body, start, end) - }); - } - - return columns; -}; - -EPUBJS.Map.prototype.findStart = function(root, start, end){ - var stack = [root]; - var $el; - var found; - var $prev = root; - while (stack.length) { - - $el = stack.shift(); - - found = this.walk($el, function(node){ - var left, right; - var elPos; - var elRange; - - - if(node.nodeType == Node.TEXT_NODE){ - elRange = document.createRange(); - elRange.selectNodeContents(node); - elPos = elRange.getBoundingClientRect(); - } else { - elPos = node.getBoundingClientRect(); - } - - left = elPos.left; - right = elPos.right; - - if( left >= start && left <= end ) { - return node; - } else if (right > start) { - return node; - } else { - $prev = node; - stack.push(node); - } - - }); - - if(found) { - return this.findTextStartRange(found, start, end); - } - - } - - // Return last element - return this.findTextStartRange($prev, start, end); -}; - -EPUBJS.Map.prototype.findEnd = function(root, start, end){ - var stack = [root]; - var $el; - var $prev = root; - var found; - - while (stack.length) { - - $el = stack.shift(); - - found = this.walk($el, function(node){ - - var left, right; - var elPos; - var elRange; - - - if(node.nodeType == Node.TEXT_NODE){ - elRange = document.createRange(); - elRange.selectNodeContents(node); - elPos = elRange.getBoundingClientRect(); - } else { - elPos = node.getBoundingClientRect(); - } - - left = elPos.left; - right = elPos.right; - - if(left > end && $prev) { - return $prev; - } else if(right > end) { - return node; - } else { - $prev = node; - stack.push(node); - } - - }); - - - if(found){ - return this.findTextEndRange(found, start, end); - } - - } - - // end of chapter - return this.findTextEndRange($prev, start, end); -}; - - -EPUBJS.Map.prototype.findTextStartRange = function(node, start, end){ - var ranges = this.splitTextNodeIntoRanges(node); - var prev; - var range; - var pos; - - for (var i = 0; i < ranges.length; i++) { - range = ranges[i]; - - pos = range.getBoundingClientRect(); - - if( pos.left >= start ) { - return range; - } - - prev = range; - - } - - return ranges[0]; -}; - -EPUBJS.Map.prototype.findTextEndRange = function(node, start, end){ - var ranges = this.splitTextNodeIntoRanges(node); - var prev; - var range; - var pos; - - for (var i = 0; i < ranges.length; i++) { - range = ranges[i]; - - pos = range.getBoundingClientRect(); - - if(pos.left > end && prev) { - return prev; - } else if(pos.right > end) { - return range; - } - - prev = range; - - } - - // Ends before limit - return ranges[ranges.length-1]; - -}; - -EPUBJS.Map.prototype.splitTextNodeIntoRanges = function(node, _splitter){ - var ranges = []; - var textContent = node.textContent || ""; - var text = textContent.trim(); - var range; - var rect; - var list; - var doc = node.ownerDocument; - var splitter = _splitter || " "; - - pos = text.indexOf(splitter); - - if(pos === -1 || node.nodeType != Node.TEXT_NODE) { - range = doc.createRange(); - range.selectNodeContents(node); - return [range]; - } - - range = doc.createRange(); - range.setStart(node, 0); - range.setEnd(node, pos); - ranges.push(range); - range = false; - - while ( pos != -1 ) { - - pos = text.indexOf(splitter, pos + 1); - if(pos > 0) { - - if(range) { - range.setEnd(node, pos); - ranges.push(range); - } - - range = doc.createRange(); - range.setStart(node, pos+1); - } - } - - if(range) { - range.setEnd(node, text.length); - ranges.push(range); - } - - return ranges; -}; - - - -EPUBJS.Map.prototype.rangePairToCfiPair = function(section, rangePair){ - - var startRange = rangePair.start; - var endRange = rangePair.end; - - startRange.collapse(true); - endRange.collapse(true); - - startCfi = section.cfiFromRange(startRange); - endCfi = section.cfiFromRange(endRange); - - return { - start: startCfi, - end: endCfi - }; - -}; - -EPUBJS.Map.prototype.rangeListToCfiList = function(view, columns){ - var map = []; - var rangePair, cifPair; - - for (var i = 0; i < columns.length; i++) { - cifPair = this.rangePairToCfiPair(view.section, columns[i]); - - map.push(cifPair); - - } - - return map; -}; -EPUBJS.Navigation = function(_package, _request){ - var navigation = this; - var parse = new EPUBJS.Parser(); - var request = _request || EPUBJS.core.request; - - this.package = _package; - this.toc = []; - this.tocByHref = {}; - this.tocById = {}; - - if(_package.navPath) { - this.navUrl = _package.baseUrl + _package.navPath; - this.nav = {}; - - this.nav.load = function(_request){ - var loading = new RSVP.defer(); - var loaded = loading.promise; - - request(navigation.navUrl, 'xml').then(function(xml){ - navigation.toc = parse.nav(xml); - navigation.loaded(navigation.toc); - loading.resolve(navigation.toc); - }); - - return loaded; - }; - - } - - if(_package.ncxPath) { - this.ncxUrl = _package.baseUrl + _package.ncxPath; - this.ncx = {}; - - this.ncx.load = function(_request){ - var loading = new RSVP.defer(); - var loaded = loading.promise; - - request(navigation.ncxUrl, 'xml').then(function(xml){ - navigation.toc = parse.ncx(xml); - navigation.loaded(navigation.toc); - loading.resolve(navigation.toc); - }); - - return loaded; - }; - - } -}; - -// Load the navigation -EPUBJS.Navigation.prototype.load = function(_request) { - var request = _request || EPUBJS.core.request; - var loading, loaded; - - if(this.nav) { - loading = this.nav.load(); - } else if(this.ncx) { - loading = this.ncx.load(); - } else { - loaded = new RSVP.defer(); - loaded.resolve([]); - loading = loaded.promise; - } - - return loading; - -}; - -EPUBJS.Navigation.prototype.loaded = function(toc) { - var item; - - for (var i = 0; i < toc.length; i++) { - item = toc[i]; - this.tocByHref[item.href] = i; - this.tocById[item.id] = i; - } - -}; - -// Get an item from the navigation -EPUBJS.Navigation.prototype.get = function(target) { - var index; - - if(!target) { - return this.toc; - } - - if(target.indexOf("#") === 0) { - index = this.tocById[target.substring(1)]; - } else if(target in this.tocByHref){ - index = this.tocByHref[target]; - } - - return this.toc[index]; -}; -EPUBJS.Paginate = function(book, options) { - - EPUBJS.Continuous.apply(this, arguments); - - this.settings = EPUBJS.core.extend(this.settings || {}, { - width: 600, - height: 400, - axis: "horizontal", - forceSingle: false, - minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always) - gap: "auto", //-- "auto" or int - overflow: "hidden", - infinite: false - }); - - EPUBJS.core.extend(this.settings, options); - - this.isForcedSingle = this.settings.forceSingle; - - this.viewSettings = { - axis: this.settings.axis - }; - - this.start(); -}; - -EPUBJS.Paginate.prototype = Object.create(EPUBJS.Continuous.prototype); -EPUBJS.Paginate.prototype.constructor = EPUBJS.Paginate; - - -EPUBJS.Paginate.prototype.determineSpreads = function(cutoff){ - if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) { - return 1; //-- Single Page - }else{ - return 2; //-- Double Page - } -}; - -EPUBJS.Paginate.prototype.forceSingle = function(bool){ - if(bool === false) { - this.isForcedSingle = false; - // this.spreads = false; - } else { - this.isForcedSingle = true; - // this.spreads = this.determineSpreads(this.minSpreadWidth); - } - this.applyLayoutMethod(); -}; - -/** -* Uses the settings to determine which Layout Method is needed -* Triggers events based on the method choosen -* Takes: Layout settings object -* Returns: String of appropriate for EPUBJS.Layout function -*/ -// EPUBJS.Paginate.prototype.determineLayout = function(settings){ -// // Default is layout: reflowable & spread: auto -// var spreads = this.determineSpreads(this.settings.minSpreadWidth); -// console.log("spreads", spreads, this.settings.minSpreadWidth) -// var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable"; -// var scroll = false; -// -// if(settings.layout === "pre-paginated") { -// layoutMethod = "Fixed"; -// scroll = true; -// spreads = false; -// } -// -// if(settings.layout === "reflowable" && settings.spread === "none") { -// layoutMethod = "Reflowable"; -// scroll = false; -// spreads = false; -// } -// -// if(settings.layout === "reflowable" && settings.spread === "both") { -// layoutMethod = "ReflowableSpreads"; -// scroll = false; -// spreads = true; -// } -// -// this.spreads = spreads; -// -// return layoutMethod; -// }; - -EPUBJS.Paginate.prototype.start = function(){ - // On display - // this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties); - // this.layoutMethod = this.determineLayout(this.layoutSettings); - // this.layout = new EPUBJS.Layout[this.layoutMethod](); - //this.hooks.display.register(this.registerLayoutMethod.bind(this)); - // this.hooks.display.register(this.reportLocation); - this.on('displayed', this.reportLocation.bind(this)); - - this.hooks.content.register(this.adjustImages.bind(this)); - - this.currentPage = 0; - - window.addEventListener('unload', function(e){ - this.ignore = true; - this.destroy(); - }.bind(this)); - -}; - -// EPUBJS.Rendition.prototype.createView = function(section) { -// var view = new EPUBJS.View(section, this.viewSettings); - - -// return view; -// }; - -EPUBJS.Paginate.prototype.applyLayoutMethod = function() { - //var task = new RSVP.defer(); - - // this.spreads = this.determineSpreads(this.settings.minSpreadWidth); - - this.layout = new EPUBJS.Layout.Reflowable(); - - this.updateLayout(); - - // Set the look ahead offset for what is visible - - this.map = new EPUBJS.Map(this.layout); - - // this.hooks.layout.register(this.layout.format.bind(this)); - - //task.resolve(); - //return task.promise; - // return layout; -}; - -EPUBJS.Paginate.prototype.updateLayout = function() { - - this.spreads = this.determineSpreads(this.settings.minSpreadWidth); - - this.layout.calculate( - this.stage.width, - this.stage.height, - this.settings.gap, - this.spreads - ); - - this.settings.offset = this.layout.delta; - -}; - -EPUBJS.Paginate.prototype.moveTo = function(offset){ - var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta; - return this.check(0, dist+this.settings.offset).then(function(){ - this.scrollBy(dist, 0); - }.bind(this)); -}; - -EPUBJS.Paginate.prototype.page = function(pg){ - - // this.currentPage = pg; - // this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0); - //-- Return false if page is greater than the total - // return false; -}; - -EPUBJS.Paginate.prototype.next = function(){ - - return this.q.enqueue(function(){ - this.scrollBy(this.layout.delta, 0); - this.reportLocation(); - return this.check(); - }); - - // return this.page(this.currentPage + 1); -}; - -EPUBJS.Paginate.prototype.prev = function(){ - - return this.q.enqueue(function(){ - this.scrollBy(-this.layout.delta, 0); - this.reportLocation(); - return this.check(); - }); - // return this.page(this.currentPage - 1); -}; - -EPUBJS.Paginate.prototype.reportLocation = function(){ - return this.q.enqueue(function(){ - this.location = this.currentLocation(); - this.trigger("locationChanged", this.location); - }.bind(this)); -}; - -EPUBJS.Paginate.prototype.currentLocation = function(){ - var visible = this.visible(); - var startA, startB, endA, endB; - var pageLeft, pageRight; - var container = this.container.getBoundingClientRect(); - - if(visible.length === 1) { - startA = container.left - visible[0].position().left; - endA = startA + this.layout.spread; - - return this.map.page(visible[0], startA, endA); - } - - if(visible.length > 1) { - - // Left Col - startA = container.left - visible[0].position().left; - endA = startA + this.layout.column; - - // Right Col - startB = container.left + this.layout.spread - visible[visible.length-1].position().left; - endB = startB + this.layout.column; - - pageLeft = this.map.page(visible[0], startA, endA); - pageRight = this.map.page(visible[visible.length-1], startB, endB); - - return { - start: pageLeft.start, - end: pageRight.end - }; - } - -}; - -EPUBJS.Paginate.prototype.resize = function(width, height){ - // Clear the queue - this.q.clear(); - - this.stageSize(width, height); - - this.updateLayout(); - - this.display(this.location.start); - - this.trigger("resized", { - width: this.stage.width, - height: this.stage.height - }); - -}; - -EPUBJS.Paginate.prototype.onResized = function(e) { - - this.clear(); - - clearTimeout(this.resizeTimeout); - this.resizeTimeout = setTimeout(function(){ - this.resize(); - }.bind(this), 150); -}; - -EPUBJS.Paginate.prototype.adjustImages = function(view) { - - view.addStylesheetRules([ - ["img", - ["max-width", (this.layout.spread) + "px"], - ["max-height", (this.layout.height) + "px"] - ] - ]); - return new RSVP.Promise(function(resolve, reject){ - // Wait to apply - setTimeout(function() { - resolve(); - }, 1); - }); -}; - -// EPUBJS.Paginate.prototype.display = function(what){ -// return this.display(what); -// }; -EPUBJS.Parser = function(){}; - -EPUBJS.Parser.prototype.container = function(containerXml){ - //-- - var rootfile, fullpath, folder, encoding; - - if(!containerXml) { - console.error("Container File Not Found"); - return; - } - - rootfile = containerXml.querySelector("rootfile"); - - if(!rootfile) { - console.error("No RootFile Found"); - return; - } - - fullpath = rootfile.getAttribute('full-path'); - folder = EPUBJS.core.uri(fullpath).directory; - encoding = containerXml.xmlEncoding; - - //-- Now that we have the path we can parse the contents - return { - 'packagePath' : fullpath, - 'basePath' : folder, - 'encoding' : encoding - }; -}; - -EPUBJS.Parser.prototype.identifier = function(packageXml){ - var metadataNode; - - if(!packageXml) { - console.error("Package File Not Found"); - return; - } - - metadataNode = packageXml.querySelector("metadata"); - - if(!metadataNode) { - console.error("No Metadata Found"); - return; - } - - return this.getElementText(metadataNode, "identifier"); -}; - -EPUBJS.Parser.prototype.packageContents = function(packageXml){ - var parse = this; - var metadataNode, manifestNode, spineNode; - var manifest, navPath, ncxPath, coverPath; - var spineNodeIndex; - var spine; - var spineIndexByURL; - - if(!packageXml) { - console.error("Package File Not Found"); - return; - } - - metadataNode = packageXml.querySelector("metadata"); - if(!metadataNode) { - console.error("No Metadata Found"); - return; - } - - manifestNode = packageXml.querySelector("manifest"); - if(!manifestNode) { - console.error("No Manifest Found"); - return; - } - - spineNode = packageXml.querySelector("spine"); - if(!spineNode) { - console.error("No Spine Found"); - return; - } - - manifest = parse.manifest(manifestNode); - navPath = parse.findNavPath(manifestNode); - ncxPath = parse.findNcxPath(manifestNode); - coverPath = parse.findCoverPath(manifestNode); - - spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode); - - spine = parse.spine(spineNode, manifest); - - return { - 'metadata' : parse.metadata(metadataNode), - 'spine' : spine, - 'manifest' : manifest, - 'navPath' : navPath, - 'ncxPath' : ncxPath, - 'coverPath': coverPath, - 'spineNodeIndex' : spineNodeIndex - }; -}; - -//-- Find TOC NAV: media-type="application/xhtml+xml" href="toc.ncx" -EPUBJS.Parser.prototype.findNavPath = function(manifestNode){ - var node = manifestNode.querySelector("item[properties^='nav']"); - return node ? node.getAttribute('href') : false; -}; - -//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx" -EPUBJS.Parser.prototype.findNcxPath = function(manifestNode){ - var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); - return node ? node.getAttribute('href') : false; -}; - -//-- Find Cover: -EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){ - var node = manifestNode.querySelector("item[properties='cover-image']"); - return node ? node.getAttribute('href') : false; -}; - -//-- Expanded to match Readium web components -EPUBJS.Parser.prototype.metadata = function(xml){ - var metadata = {}, - p = this; - - metadata.title = p.getElementText(xml, 'title'); - metadata.creator = p.getElementText(xml, 'creator'); - metadata.description = p.getElementText(xml, 'description'); - - metadata.pubdate = p.getElementText(xml, 'date'); - - metadata.publisher = p.getElementText(xml, 'publisher'); - - metadata.identifier = p.getElementText(xml, "identifier"); - metadata.language = p.getElementText(xml, "language"); - metadata.rights = p.getElementText(xml, "rights"); - - metadata.modified_date = p.querySelectorText(xml, "meta[property='dcterms:modified']"); - metadata.layout = p.querySelectorText(xml, "meta[property='rendition:layout']"); - metadata.orientation = p.querySelectorText(xml, "meta[property='rendition:orientation']"); - metadata.spread = p.querySelectorText(xml, "meta[property='rendition:spread']"); - // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction"); - - return metadata; -}; - -EPUBJS.Parser.prototype.getElementText = function(xml, tag){ - var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag), - el; - - if(!found || found.length === 0) return ''; - - el = found[0]; - - if(el.childNodes.length){ - return el.childNodes[0].nodeValue; - } - - return ''; - -}; - -EPUBJS.Parser.prototype.querySelectorText = function(xml, q){ - var el = xml.querySelector(q); - - if(el && el.childNodes.length){ - return el.childNodes[0].nodeValue; - } - - return ''; -}; - -EPUBJS.Parser.prototype.manifest = function(manifestXml){ - var manifest = {}; - - //-- Turn items into an array - var selected = manifestXml.querySelectorAll("item"), - items = Array.prototype.slice.call(selected); - - //-- Create an object with the id as key - items.forEach(function(item){ - var id = item.getAttribute('id'), - href = item.getAttribute('href') || '', - type = item.getAttribute('media-type') || '', - properties = item.getAttribute('properties') || ''; - - manifest[id] = { - 'href' : href, - // 'url' : href, - 'type' : type, - 'properties' : properties.length ? properties.split(' ') : [] - }; - - }); - - return manifest; - -}; - -EPUBJS.Parser.prototype.spine = function(spineXml, manifest){ - var spine = []; - - var selected = spineXml.getElementsByTagName("itemref"), - items = Array.prototype.slice.call(selected); - - var epubcfi = new EPUBJS.EpubCFI(); - - //-- Add to array to mantain ordering and cross reference with manifest - items.forEach(function(item, index){ - var idref = item.getAttribute('idref'); - // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id); - var props = item.getAttribute('properties') || ''; - var propArray = props.length ? props.split(' ') : []; - // var manifestProps = manifest[Id].properties; - // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : []; - - var itemref = { - 'idref' : idref, - 'linear' : item.getAttribute('linear') || '', - 'properties' : propArray, - // 'href' : manifest[Id].href, - // 'url' : manifest[Id].url, - 'index' : index - // 'cfiBase' : cfiBase - }; - spine.push(itemref); - }); - - return spine; -}; - -EPUBJS.Parser.prototype.nav = function(navHtml){ - var navEl = navHtml.querySelector('nav[*|type="toc"]'), //-- [*|type="toc"] * Doesn't seem to work - idCounter = 0; - - if(!navEl) return []; - - // Implements `> ol > li` - function findListItems(parent){ - var items = []; - - Array.prototype.slice.call(parent.childNodes).forEach(function(node){ - if('ol' == node.tagName){ - Array.prototype.slice.call(node.childNodes).forEach(function(item){ - if('li' == item.tagName){ - items.push(item); - } - }); - } - }); - - return items; - - } - - // Implements `> a, > span` - function findAnchorOrSpan(parent){ - var item = null; - - Array.prototype.slice.call(parent.childNodes).forEach(function(node){ - if('a' == node.tagName || 'span' == node.tagName){ - item = node; - } - }); - - return item; - } - - function getTOC(parent){ - var list = [], - nodes = findListItems(parent), - items = Array.prototype.slice.call(nodes), - length = items.length, - node; - - if(length === 0) return false; - - items.forEach(function(item){ - var id = item.getAttribute('id') || false, - content = findAnchorOrSpan(item), - href = content.getAttribute('href') || '', - text = content.textContent || "", - split = href.split("#"), - baseUrl = split[0], - subitems = getTOC(item); - // spinePos = spineIndexByURL[baseUrl], - // spineItem = bookSpine[spinePos], - // cfi = spineItem ? spineItem.cfi : ''; - - // if(!id) { - // if(spinePos) { - // spineItem = bookSpine[spinePos]; - // id = spineItem.id; - // cfi = spineItem.cfi; - // } else { - // id = 'epubjs-autogen-toc-id-' + (idCounter++); - // } - // } - - // item.setAttribute('id', id); // Ensure all elements have an id - list.push({ - "id": id, - "href": href, - "label": text, - "subitems" : subitems, - "parent" : parent ? parent.getAttribute('id') : null - // "cfi" : cfi - }); - - }); - - return list; - } - - return getTOC(navEl); -}; - -EPUBJS.Parser.prototype.ncx = function(tocXml){ - var navMap = tocXml.querySelector("navMap"); - if(!navMap) return []; - - function getTOC(parent){ - var list = [], - snapshot = tocXml.evaluate("*[local-name()='navPoint']", parent, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), - length = snapshot.snapshotLength; - - if(length === 0) return []; - - for ( var i=length-1 ; i >= 0; i-- ) { - var item = snapshot.snapshotItem(i); - - var id = item.getAttribute('id') || false, - content = item.querySelector("content"), - src = content.getAttribute('src'), - navLabel = item.querySelector("navLabel"), - text = navLabel.textContent ? navLabel.textContent : "", - split = src.split("#"), - baseUrl = split[0], - // spinePos = spineIndexByURL[baseUrl], - // spineItem = bookSpine[spinePos], - subitems = getTOC(item); - // cfi = spineItem ? spineItem.cfi : ''; - - // if(!id) { - // if(spinePos) { - // spineItem = bookSpine[spinePos]; - // id = spineItem.id; - // cfi = spineItem.cfi; - // } else { - // id = 'epubjs-autogen-toc-id-' + (idCounter++); - // } - // } - - list.unshift({ - "id": id, - "href": src, - "label": text, - // "spinePos": spinePos, - "subitems" : subitems, - "parent" : parent ? parent.getAttribute('id') : null, - // "cfi" : cfi - }); - - } - - return list; - } - - return getTOC(navMap); -}; -EPUBJS.Queue = function(_context){ - this._q = []; - this.context = _context; - this.tick = EPUBJS.core.requestAnimationFrame; - this.running = false; -}; - -// Add an item to the queue -EPUBJS.Queue.prototype.enqueue = function() { - var deferred, promise; - var queued; - var task = [].shift.call(arguments); - var args = arguments; - - // Handle single args without context - // if(args && !Array.isArray(args)) { - // args = [args]; - // } - - if(typeof task === "function"){ - - deferred = new RSVP.defer(); - promise = deferred.promise; - - queued = { - "task" : task, - "args" : args, - //"context" : context, - "deferred" : deferred, - "promise" : promise - }; - - } else { - // Task is a promise - queued = { - "promise" : task - }; - - } - - this._q.push(queued); - - // Wait to start queue flush - setTimeout(this.flush.bind(this), 0); - - return queued.promise; -}; - -// Run one item -EPUBJS.Queue.prototype.dequeue = function(){ - var inwait, task, result; - - if(this._q.length) { - inwait = this._q.shift(); - task = inwait.task; - if(task){ - // console.log(task) - - result = task.apply(this.context, inwait.args); - - if(result && typeof result["then"] === "function") { - // Task is a function that returns a promise - return result.then(function(){ - inwait.deferred.resolve.apply(this.context, arguments); - }.bind(this)); - } else { - // Task resolves immediately - inwait.deferred.resolve.apply(this.context, result); - return inwait.promise; - } - - - - } else if(inwait.promise) { - // Task is a promise - return inwait.promise; - } - - } else { - inwait = new RSVP.defer(); - inwait.deferred.resolve(); - return inwait.promise; - } - -}; - -// Run All Immediately -EPUBJS.Queue.prototype.dump = function(){ - while(this._q.length) { - this.dequeue(); - } -}; - -// Run all sequentially, at convince - -EPUBJS.Queue.prototype.run = function(){ - if(!this.running && this._q.length) { - this.running = true; - this.dequeue().then(function(){ - this.running = false; - }.bind(this)); - } - - this.tick.call(window, this.run.bind(this)); -}; - -// Flush all, as quickly as possible -EPUBJS.Queue.prototype.flush = function(){ - if(this.running){ - return this.running; - } - - if(this._q.length) { - this.running = this.dequeue(). - then(function(){ - this.running = undefined; - return this.flush(); - }.bind(this)); - - return this.running; - } - -}; - -// Clear all items in wait -EPUBJS.Queue.prototype.clear = function(){ - this._q = []; - this.running = false; -}; - -EPUBJS.Queue.prototype.length = function(){ - return this._q.length; -}; - -// Create a new task from a callback -EPUBJS.Task = function(task, args, context){ - - return function(){ - var toApply = arguments || []; - - return new RSVP.Promise(function(resolve, reject) { - var callback = function(value){ - resolve(value); - }; - // Add the callback to the arguments list - toApply.push(callback); - - // Apply all arguments to the functions - task.apply(this, toApply); - - }.bind(this)); - - }; - -}; -EPUBJS.Rendition = function(book, options) { - - this.settings = EPUBJS.core.extend(this.settings || {}, { - infinite: true, - hidden: false, - width: false, - height: null, - layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'}, - axis: "vertical" - }); - - EPUBJS.core.extend(this.settings, options); - - this.viewSettings = {}; - - this.book = book; - - this.views = []; - - //-- Adds Hook methods to the Rendition prototype - this.hooks = {}; - this.hooks.display = new EPUBJS.Hook(this); - this.hooks.content = new EPUBJS.Hook(this); - this.hooks.layout = new EPUBJS.Hook(this); - this.hooks.render = new EPUBJS.Hook(this); - this.hooks.show = new EPUBJS.Hook(this); - - this.hooks.content.register(EPUBJS.replace.links.bind(this)); - - // this.hooks.display.register(this.afterDisplay.bind(this)); - - this.epubcfi = new EPUBJS.EpubCFI(); - - this.q = new EPUBJS.Queue(this); - - this.q.enqueue(this.book.opened); - - this.q.enqueue(this.parseLayoutProperties); - -}; - -/** -* Creates an element to render to. -* Resizes to passed width and height or to the elements size -*/ -EPUBJS.Rendition.prototype.initialize = function(_options){ - var options = _options || {}; - var height = options.height;// !== false ? options.height : "100%"; - var width = options.width;// !== false ? options.width : "100%"; - var hidden = options.hidden || false; - var container; - var wrapper; - - if(options.height && EPUBJS.core.isNumber(options.height)) { - height = options.height + "px"; - } - - if(options.width && EPUBJS.core.isNumber(options.width)) { - width = options.width + "px"; - } - - // Create new container element - container = document.createElement("div"); - - container.id = "epubjs-container:" + EPUBJS.core.uuid(); - container.classList.add("epub-container"); - - // Style Element - container.style.fontSize = "0"; - container.style.wordSpacing = "0"; - container.style.lineHeight = "0"; - container.style.verticalAlign = "top"; - - if(this.settings.axis === "horizontal") { - container.style.whiteSpace = "nowrap"; - } - - if(width){ - container.style.width = width; - } - - if(height){ - container.style.height = height; - } - - container.style.overflow = this.settings.overflow; - - return container; -}; - -EPUBJS.Rendition.wrap = function(container) { - var wrapper = document.createElement("div"); - - wrapper.style.visibility = "hidden"; - wrapper.style.overflow = "hidden"; - wrapper.style.width = "0"; - wrapper.style.height = "0"; - - wrapper.appendChild(container); - return wrapper; -}; - -// Call to attach the container to an element in the dom -// Container must be attached before rendering can begin -EPUBJS.Rendition.prototype.attachTo = function(_element){ - var bounds; - - this.container = this.initialize({ - "width" : this.settings.width, - "height" : this.settings.height - }); - - if(EPUBJS.core.isElement(_element)) { - this.element = _element; - } else if (typeof _element === "string") { - this.element = document.getElementById(_element); - } - - if(!this.element){ - console.error("Not an Element"); - return; - } - - if(this.settings.hidden) { - this.wrapper = this.wrap(this.container); - this.element.appendChild(this.wrapper); - } else { - this.element.appendChild(this.container); - } - - // Attach Listeners - this.attachListeners(); - - // Calculate Stage Size - this.stageSize(); - - // Add Layout method - this.applyLayoutMethod(); - - // Trigger Attached - this.trigger("attached"); - - // Start processing queue - // this.q.run(); - -}; - -EPUBJS.Rendition.prototype.attachListeners = function(){ - - // Listen to window for resize event if width or height is set to 100% - if(!EPUBJS.core.isNumber(this.settings.width) || - !EPUBJS.core.isNumber(this.settings.height) ) { - window.addEventListener("resize", this.onResized.bind(this), false); - } - -}; - -EPUBJS.Rendition.prototype.bounds = function() { - return this.container.getBoundingClientRect(); -}; - -EPUBJS.Rendition.prototype.display = function(target){ - - return this.q.enqueue(this._display, target); - -}; - -EPUBJS.Rendition.prototype._display = function(target){ - - var displaying = new RSVP.defer(); - var displayed = displaying.promise; - - var section; - var view; - var cfi, spinePos; - - if(this.epubcfi.isCfiString(target)) { - cfi = this.epubcfi.parse(target); - spinePos = cfi.spinePos; - section = this.book.spine.get(spinePos); - } else { - section = this.book.spine.get(target); - } - - this.displaying = true; - - // Hide current views - this.hide(); - - if(section){ - view = this.createView(section); - - // Show view - this.q.enqueue(this.append, view); - - // Move to correct place within the section, if needed - // this.moveTo(what) - - // Show views - this.show(); - - // This hook doesn't prevent showing, but waits to resolve until - // all the hooks have finished. Might want to block showing. - this.hooks.display.trigger(view) - .then(function(){ - this.trigger("displayed", section); - displaying.resolve(this); - }.bind(this)); - - } else { - displaying.reject(new Error("No Section Found")); - } - - return displayed; - -}; -// Takes a cfi, fragment or page? -EPUBJS.Rendition.prototype.moveTo = function(what){ - -}; - -EPUBJS.Rendition.prototype.render = function(view, show) { - - view.create(); - - view.onLayout = this.layout.format.bind(this.layout); - - // Fit to size of the container, apply padding - this.resizeView(view); - - // Render Chain - return view.render(this.book.request) - .then(function(){ - return this.hooks.content.trigger(view, this); - }.bind(this)) - .then(function(){ - return this.hooks.layout.trigger(view, this); - }.bind(this)) - .then(function(){ - return view.display(); - }.bind(this)) - .then(function(){ - return this.hooks.render.trigger(view, this); - }.bind(this)) - .then(function(){ - - if(show !== false && this.hidden === false) { - this.q.enqueue(function(view){ - view.show(); - }, view); - } - - - // this.map = new EPUBJS.Map(view, this.layout); - this.trigger("rendered", view.section); - - }.bind(this)) - .catch(function(e){ - this.trigger("loaderror", e); - }.bind(this)); - -}; - - -EPUBJS.Rendition.prototype.afterDisplayed = function(view){ - this.trigger("added", view.section); -}; - -EPUBJS.Rendition.prototype.append = function(view){ - // Clear existing views - this.clear(); - - this.views.push(view); - // view.appendTo(this.container); - this.container.appendChild(view.element); - - // view.on("displayed", this.afterDisplayed.bind(this)); - view.onDisplayed = this.afterDisplayed.bind(this); - // this.resizeView(view); - - return this.render(view); -}; - -EPUBJS.Rendition.prototype.clear = function(){ - // Remove all views - this.views.forEach(function(view){ - this._remove(view); - }.bind(this)); - this.views = []; -}; - -EPUBJS.Rendition.prototype.remove = function(view) { - var index = this.views.indexOf(view); - - if(index > -1) { - this.views.splice(index, 1); - } - - - this._remove(view); - -}; - -EPUBJS.Rendition.prototype._remove = function(view) { - view.off("resized"); - - if(view.displayed){ - view.destroy(); - } - - this.container.removeChild(view.element); - view = null; -}; - -EPUBJS.Rendition.prototype.resizeView = function(view) { - - if(this.globalLayoutProperties.layout === "pre-paginated") { - view.lock("both", this.stage.width, this.stage.height); - } else { - view.lock("width", this.stage.width, this.stage.height); - } - -}; - -EPUBJS.Rendition.prototype.stageSize = function(_width, _height){ - var bounds; - var width = _width || this.settings.width; - var height = _height || this.settings.height; - - // If width or height are set to false, inherit them from containing element - if(width === false) { - bounds = this.element.getBoundingClientRect(); - - if(bounds.width) { - width = bounds.width; - this.container.style.width = bounds.width + "px"; - } - } - - if(height === false) { - bounds = bounds || this.element.getBoundingClientRect(); - - if(bounds.height) { - height = bounds.height; - this.container.style.height = bounds.height + "px"; - } - - } - - if(width && !EPUBJS.core.isNumber(width)) { - bounds = this.container.getBoundingClientRect(); - width = bounds.width; - //height = bounds.height; - } - - if(height && !EPUBJS.core.isNumber(height)) { - bounds = bounds || this.container.getBoundingClientRect(); - //width = bounds.width; - height = bounds.height; - } - - - this.containerStyles = window.getComputedStyle(this.container); - this.containerPadding = { - left: parseFloat(this.containerStyles["padding-left"]) || 0, - right: parseFloat(this.containerStyles["padding-right"]) || 0, - top: parseFloat(this.containerStyles["padding-top"]) || 0, - bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0 - }; - - this.stage = { - width: width - - this.containerPadding.left - - this.containerPadding.right, - height: height - - this.containerPadding.top - - this.containerPadding.bottom - }; - - return this.stage; - -}; - -EPUBJS.Rendition.prototype.applyLayoutMethod = function() { - - this.layout = new EPUBJS.Layout.Scroll(); - this.updateLayout(); - - this.map = new EPUBJS.Map(this.layout); -}; - -EPUBJS.Rendition.prototype.updateLayout = function() { - - this.layout.calculate(this.stage.width, this.stage.height); - -}; - -EPUBJS.Rendition.prototype.resize = function(width, height){ - - this.stageSize(width, height); - - this.updateLayout(); - - this.views.forEach(this.resizeView.bind(this)); - - this.trigger("resized", { - width: this.stage.width, - height: this.stage.height - }); - -}; - -EPUBJS.Rendition.prototype.onResized = function(e) { - this.resize(); -}; - -EPUBJS.Rendition.prototype.createView = function(section) { - return new EPUBJS.View(section, this.viewSettings); -}; - -EPUBJS.Rendition.prototype.next = function(){ - - return this.q.enqueue(function(){ - - var next; - var view; - - if(!this.views.length) return; - - next = this.views[0].section.next(); - - if(next) { - view = this.createView(next); - return this.append(view); - } - - }); - -}; - -EPUBJS.Rendition.prototype.prev = function(){ - - return this.q.enqueue(function(){ - - var prev; - var view; - - if(!this.views.length) return; - - prev = this.views[0].section.prev(); - if(prev) { - view = this.createView(prev); - return this.append(view); - } - - }); - -}; - -//-- http://www.idpf.org/epub/fxl/ -EPUBJS.Rendition.prototype.parseLayoutProperties = function(_metadata){ - var metadata = _metadata || this.book.package.metadata; - var layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || "reflowable"; - var spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || "auto"; - var orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || "auto"; - this.globalLayoutProperties = { - layout : layout, - spread : spread, - orientation : orientation - }; - return this.globalLayoutProperties; -}; - - -EPUBJS.Rendition.prototype.current = function(){ - var visible = this.visible(); - if(visible.length){ - // Current is the last visible view - return visible[visible.length-1]; - } - return null; -}; - -EPUBJS.Rendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){ - var position = view.position(); - var container = _container || this.container.getBoundingClientRect(); - - if(this.settings.axis === "horizontal" && - (position.right > container.left - offsetPrev) && - !(position.left >= container.right + offsetNext)) { - - return true; - - } else if(this.settings.axis === "vertical" && - (position.bottom > container.top - offsetPrev) && - !(position.top >= container.bottom + offsetNext)) { - - return true; - } - - return false; - -}; - -EPUBJS.Rendition.prototype.visible = function(){ - var container = this.bounds(); - var visible = []; - var isVisible; - var view; - - for (var i = 0; i < this.views.length; i++) { - view = this.views[i]; - isVisible = this.isVisible(view, 0, 0, container); - - if(isVisible === true) { - visible.push(view); - } - - } - - return visible; - -}; - -EPUBJS.Rendition.prototype.bounds = function(func) { - var bounds; - - if(!this.settings.height) { - bounds = EPUBJS.core.windowBounds(); - } else { - bounds = this.container.getBoundingClientRect(); - } - - return bounds; -}; - -EPUBJS.Rendition.prototype.displayed = function(){ - var displayed = []; - var view; - for (var i = 0; i < this.views.length; i++) { - view = this.views[i]; - if(view.displayed){ - displayed.push(view); - } - } - return displayed; -}; - -EPUBJS.Rendition.prototype.show = function(){ - var view; - for (var i = 0; i < this.views.length; i++) { - view = this.views[i]; - if(view.displayed){ - view.show(); - } - } - this.hidden = false; -}; - -EPUBJS.Rendition.prototype.hide = function(){ - var view; - for (var i = 0; i < this.views.length; i++) { - view = this.views[i]; - if(view.displayed){ - view.hide(); - } - } - this.hidden = true; -}; - -EPUBJS.Rendition.prototype.destroy = function(){ - // Clear the queue - this.q.clear(); - - this.clear(); - - clearTimeout(this.trimTimeout); - if(this.settings.hidden) { - this.element.removeChild(this.wrapper); - } else { - this.element.removeChild(this.container); - } - -}; - -EPUBJS.Rendition.prototype.reportLocation = function(){ - return this.q.enqueue(function(){ - this.location = this.currentLocation(); - this.trigger("locationChanged", this.location); - }.bind(this)); -}; - -EPUBJS.Rendition.prototype.currentLocation = function(){ - var view; - var start, end; - - if(this.views.length) { - view = this.views[0]; - // start = container.left - view.position().left; - // end = start + this.layout.spread; - - return this.map.page(view); - } - -}; - -//-- Enable binding events to Renderer -RSVP.EventTarget.mixin(EPUBJS.Rendition.prototype); - -EPUBJS.replace = {}; -EPUBJS.replace.links = function(view, renderer) { - - var links = view.document.querySelectorAll("a[href]"); - var replaceLinks = function(link){ - var href = link.getAttribute("href"); - var uri = new EPUBJS.core.uri(href); - - - if(uri.protocol){ - - link.setAttribute("target", "_blank"); - - }else{ - - // relative = EPUBJS.core.resolveUrl(directory, href); - // if(uri.fragment && !base) { - // link.onclick = function(){ - // renderer.fragment(href); - // return false; - // }; - // } else { - - //} - - if(href.indexOf("#") === 0) { - // do nothing with fragment yet - } else { - link.onclick = function(){ - renderer.display(href); - return false; - }; - } - - } - }; - - for (var i = 0; i < links.length; i++) { - replaceLinks(links[i]); - } - - -}; /*! * @overview RSVP - a tiny implementation of Promises/A+. * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors * @license Licensed under MIT license * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE - * @version 3.0.13 + * @version 3.0.14 */ (function() { @@ -5538,6 +1608,1732 @@ EPUBJS.replace.links = function(view, renderer) { this['RSVP'] = rsvp$umd$$RSVP; } }).call(this); +if (typeof EPUBJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).EPUBJS = {}; +} + +EPUBJS.VERSION = "0.3.0"; + +(function(root) { + "use strict"; + var ePub = function(_url) { + return new EPUBJS.Book(_url); + }; + + // CommonJS + if (typeof exports === "object") { + root.RSVP = require("rsvp"); + module.exports = ePub; + // RequireJS + } else if (typeof define === "function" && define.amd) { + define(ePub); + // Global + } else { + root.ePub = ePub; + } + +})(this); + + +EPUBJS.core = {}; + +EPUBJS.core.request = function(url, type, withCredentials, headers) { + var supportsURL = window.URL; + var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer"; + + var deferred = new RSVP.defer(); + + var xhr = new XMLHttpRequest(); + + //-- Check from PDF.js: + // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js + var xhrPrototype = XMLHttpRequest.prototype; + + var header; + + if (!('overrideMimeType' in xhrPrototype)) { + // IE10 might have response, but not overrideMimeType + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) {} + }); + } + if(withCredentials) { + xhr.withCredentials = true; + } + + xhr.open("GET", url, true); + + for(header in headers) { + xhr.setRequestHeader(header, headers[header]); + } + + xhr.onreadystatechange = handler; + + if(type == 'blob'){ + xhr.responseType = BLOB_RESPONSE; + } + + if(type == "json") { + xhr.setRequestHeader("Accept", "application/json"); + } + + if(type == 'xml') { + xhr.overrideMimeType('text/xml'); + } + + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls + var r; + + if(type == 'xml'){ + + // If this.responseXML wasn't set, try to parse using a DOMParser from text + if(!this.responseXML){ + r = new DOMParser().parseFromString(this.response, "text/xml"); + } else { + r = this.responseXML; + } + + }else + if(type == 'json'){ + r = JSON.parse(this.response); + }else + if(type == 'blob'){ + + if(supportsURL) { + r = this.response; + } else { + //-- Safari doesn't support responseType blob, so create a blob from arraybuffer + r = new Blob([this.response]); + } + + }else{ + r = this.response; + } + + deferred.resolve(r); + } else { + deferred.reject({ + status: this.status, + message : this.response, + stack : new Error().stack + }); + } + } + } + + return deferred.promise; +}; + +//-- Parse the different parts of a url, returning a object +EPUBJS.core.uri = function(url){ + var uri = { + protocol : '', + host : '', + path : '', + origin : '', + directory : '', + base : '', + filename : '', + extension : '', + fragment : '', + href : url + }, + doubleSlash = url.indexOf('://'), + search = url.indexOf('?'), + fragment = url.indexOf("#"), + withoutProtocol, + dot, + firstSlash; + + if(fragment != -1) { + uri.fragment = url.slice(fragment + 1); + url = url.slice(0, fragment); + } + + if(search != -1) { + uri.search = url.slice(search + 1); + url = url.slice(0, search); + href = url; + } + + if(doubleSlash != -1) { + uri.protocol = url.slice(0, doubleSlash); + withoutProtocol = url.slice(doubleSlash+3); + firstSlash = withoutProtocol.indexOf('/'); + + if(firstSlash === -1) { + uri.host = uri.path; + uri.path = ""; + } else { + uri.host = withoutProtocol.slice(0, firstSlash); + uri.path = withoutProtocol.slice(firstSlash); + } + + + uri.origin = uri.protocol + "://" + uri.host; + + uri.directory = EPUBJS.core.folder(uri.path); + + uri.base = uri.origin + uri.directory; + // return origin; + } else { + uri.path = url; + uri.directory = EPUBJS.core.folder(url); + uri.base = uri.directory; + } + + //-- Filename + uri.filename = url.replace(uri.base, ''); + dot = uri.filename.lastIndexOf('.'); + if(dot != -1) { + uri.extension = uri.filename.slice(dot+1); + } + return uri; +}; + +//-- Parse out the folder, will return everything before the last slash +EPUBJS.core.folder = function(url){ + + var lastSlash = url.lastIndexOf('/'); + + if(lastSlash == -1) var folder = ''; + + folder = url.slice(0, lastSlash + 1); + + return folder; + +}; + + +EPUBJS.core.queue = function(_scope){ + var _q = []; + var scope = _scope; + // Add an item to the queue + var enqueue = function(funcName, args, context) { + _q.push({ + "funcName" : funcName, + "args" : args, + "context" : context + }); + return _q; + }; + // Run one item + var dequeue = function(){ + var inwait; + if(_q.length) { + inwait = _q.shift(); + // Defer to any current tasks + // setTimeout(function(){ + scope[inwait.funcName].apply(inwait.context || scope, inwait.args); + // }, 0); + } + }; + + // Run All + var flush = function(){ + while(_q.length) { + dequeue(); + } + }; + // Clear all items in wait + var clear = function(){ + _q = []; + }; + + var length = function(){ + return _q.length; + }; + + return { + "enqueue" : enqueue, + "dequeue" : dequeue, + "flush" : flush, + "clear" : clear, + "length" : length + }; +}; + +EPUBJS.core.isElement = function(obj) { + return !!(obj && obj.nodeType == 1); +}; + +// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript +EPUBJS.core.uuid = function() { + var d = new Date().getTime(); + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random()*16)%16 | 0; + d = Math.floor(d/16); + return (c=='x' ? r : (r&0x7|0x8)).toString(16); + }); + return uuid; +}; + +// From Lodash +EPUBJS.core.values = function(object) { + var index = -1, + props = Object.keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; +}; + +EPUBJS.core.resolveUrl = function(base, path) { + var url = [], + segments = [], + baseUri = EPUBJS.core.uri(base), + pathUri = EPUBJS.core.uri(path), + baseDirectory = baseUri.directory, + pathDirectory = pathUri.directory, + directories = [], + // folders = base.split("/"), + paths; + + // if(uri.host) { + // return path; + // } + + if(baseDirectory[0] === "/") { + baseDirectory = baseDirectory.substring(1); + } + + if(pathDirectory[pathDirectory.length-1] === "/") { + baseDirectory = baseDirectory.substring(0, baseDirectory.length-1); + } + + if(pathDirectory[0] === "/") { + pathDirectory = pathDirectory.substring(1); + } + + if(pathDirectory[pathDirectory.length-1] === "/") { + pathDirectory = pathDirectory.substring(0, pathDirectory.length-1); + } + + if(baseDirectory) { + directories = baseDirectory.split("/"); + } + + paths = pathDirectory.split("/"); + + paths.reverse().forEach(function(part, index){ + if(part === ".."){ + directories.pop(); + } else if(part === directories[directories.length-1]) { + directories.pop(); + segments.unshift(part); + } else { + segments.unshift(part); + } + }); + + url = [baseUri.origin]; + + if(directories.length) { + url = url.concat(directories); + } + + if(segments) { + url = url.concat(segments); + } + + url = url.concat(pathUri.filename); + + return url.join("/"); +}; + +EPUBJS.core.documentHeight = function() { + return Math.max( + document.documentElement.clientHeight, + document.body.scrollHeight, + document.documentElement.scrollHeight, + document.body.offsetHeight, + document.documentElement.offsetHeight + ); +}; + +EPUBJS.core.isNumber = function(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +}; + +EPUBJS.core.prefixed = function(unprefixed) { + var vendors = ["Webkit", "Moz", "O", "ms" ], + prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'], + upper = unprefixed[0].toUpperCase() + unprefixed.slice(1), + length = vendors.length; + + if (typeof(document.body.style[unprefixed]) != 'undefined') { + return unprefixed; + } + + for ( var i=0; i < length; i++ ) { + if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') { + return vendors[i] + upper; + } + } + + return unprefixed; +}; + +EPUBJS.core.defaults = function(obj) { + for (var i = 1, length = arguments.length; i < length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + return obj; +}; + +EPUBJS.core.extend = function(target) { + var sources = [].slice.call(arguments, 1); + sources.forEach(function (source) { + if(!source) return; + Object.getOwnPropertyNames(source).forEach(function(propName) { + Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName)); + }); + }); + return target; +}; + +// Fast quicksort insert for sorted array -- based on: +// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers +EPUBJS.core.insert = function(item, array, compareFunction) { + var location = EPUBJS.core.locationOf(item, array, compareFunction); + array.splice(location, 0, item); + + return location; +}; +// Returns where something would fit in +EPUBJS.core.locationOf = function(item, array, compareFunction, _start, _end) { + var start = _start || 0; + var end = _end || array.length; + var pivot = parseInt(start + (end - start) / 2); + var compared; + if(!compareFunction){ + compareFunction = function(a, b) { + if(a > b) return 1; + if(a < b) return -1; + if(a = b) return 0; + }; + } + if(end-start <= 0) { + return pivot; + } + + compared = compareFunction(array[pivot], item); + if(end-start === 1) { + return compared > 0 ? pivot : pivot + 1; + } + + if(compared === 0) { + return pivot; + } + if(compared === -1) { + return EPUBJS.core.locationOf(item, array, compareFunction, pivot, end); + } else{ + return EPUBJS.core.locationOf(item, array, compareFunction, start, pivot); + } +}; +// Returns -1 of mpt found +EPUBJS.core.indexOfSorted = function(item, array, compareFunction, _start, _end) { + var start = _start || 0; + var end = _end || array.length; + var pivot = parseInt(start + (end - start) / 2); + var compared; + if(!compareFunction){ + compareFunction = function(a, b) { + if(a > b) return 1; + if(a < b) return -1; + if(a = b) return 0; + }; + } + if(end-start <= 0) { + return -1; // Not found + } + + compared = compareFunction(array[pivot], item); + if(end-start === 1) { + return compared === 0 ? pivot : -1; + } + if(compared === 0) { + return pivot; // Found + } + if(compared === -1) { + return EPUBJS.core.indexOfSorted(item, array, compareFunction, pivot, end); + } else{ + return EPUBJS.core.indexOfSorted(item, array, compareFunction, start, pivot); + } +}; + +EPUBJS.core.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + +EPUBJS.core.bounds = function(el) { + + var style = window.getComputedStyle(el); + var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; + var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; + + var width = 0; + var height = 0; + + widthProps.forEach(function(prop){ + width += parseFloat(style[prop]) || 0; + }); + + heightProps.forEach(function(prop){ + height += parseFloat(style[prop]) || 0; + }); + + return { + height: height, + width: width + }; + +}; + +EPUBJS.core.borders = function(el) { + + var style = window.getComputedStyle(el); + var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; + var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; + + var width = 0; + var height = 0; + + widthProps.forEach(function(prop){ + width += parseFloat(style[prop]) || 0; + }); + + heightProps.forEach(function(prop){ + height += parseFloat(style[prop]) || 0; + }); + + return { + height: height, + width: width + }; + +}; + +EPUBJS.core.windowBounds = function() { + + var width = window.innerWidth; + var height = window.innerHeight; + + return { + top: 0, + left: 0, + right: width, + bottom: height, + width: width, + height: height + }; + +}; + +//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496 +EPUBJS.core.cleanStringForXpath = function(str) { + var parts = str.match(/[^'"]+|['"]/g); + parts = parts.map(function(part){ + if (part === "'") { + return '\"\'\"'; // output "'" + } + + if (part === '"') { + return "\'\"\'"; // output '"' + } + return "\'" + part + "\'"; + }); + return "concat(\'\'," + parts.join(",") + ")"; +}; + +EPUBJS.core.indexOfTextNode = function(textNode){ + var parent = textNode.parentNode; + var children = parent.childNodes; + var sib; + var index = -1; + for (var i = 0; i < children.length; i++) { + sib = children[i]; + if(sib.nodeType === Node.TEXT_NODE){ + index++; + } + if(sib == textNode) break; + } + + return index; +}; +EPUBJS.Queue = function(_context){ + this._q = []; + this.context = _context; + this.tick = EPUBJS.core.requestAnimationFrame; + this.running = false; +}; + +// Add an item to the queue +EPUBJS.Queue.prototype.enqueue = function() { + var deferred, promise; + var queued; + var task = [].shift.call(arguments); + var args = arguments; + + // Handle single args without context + // if(args && !Array.isArray(args)) { + // args = [args]; + // } + + if(typeof task === "function"){ + + deferred = new RSVP.defer(); + promise = deferred.promise; + + queued = { + "task" : task, + "args" : args, + //"context" : context, + "deferred" : deferred, + "promise" : promise + }; + + } else { + // Task is a promise + queued = { + "promise" : task + }; + + } + + this._q.push(queued); + + // Wait to start queue flush + setTimeout(this.flush.bind(this), 0); + + return queued.promise; +}; + +// Run one item +EPUBJS.Queue.prototype.dequeue = function(){ + var inwait, task, result; + + if(this._q.length) { + inwait = this._q.shift(); + task = inwait.task; + if(task){ + // console.log(task) + + result = task.apply(this.context, inwait.args); + + if(result && typeof result["then"] === "function") { + // Task is a function that returns a promise + return result.then(function(){ + inwait.deferred.resolve.apply(this.context, arguments); + }.bind(this)); + } else { + // Task resolves immediately + inwait.deferred.resolve.apply(this.context, result); + return inwait.promise; + } + + + + } else if(inwait.promise) { + // Task is a promise + return inwait.promise; + } + + } else { + inwait = new RSVP.defer(); + inwait.deferred.resolve(); + return inwait.promise; + } + +}; + +// Run All Immediately +EPUBJS.Queue.prototype.dump = function(){ + while(this._q.length) { + this.dequeue(); + } +}; + +// Run all sequentially, at convince + +EPUBJS.Queue.prototype.run = function(){ + if(!this.running && this._q.length) { + this.running = true; + this.dequeue().then(function(){ + this.running = false; + }.bind(this)); + } + + this.tick.call(window, this.run.bind(this)); +}; + +// Flush all, as quickly as possible +EPUBJS.Queue.prototype.flush = function(){ + if(this.running){ + return this.running; + } + + if(this._q.length) { + this.running = this.dequeue(). + then(function(){ + this.running = undefined; + return this.flush(); + }.bind(this)); + + return this.running; + } + +}; + +// Clear all items in wait +EPUBJS.Queue.prototype.clear = function(){ + this._q = []; + this.running = false; +}; + +EPUBJS.Queue.prototype.length = function(){ + return this._q.length; +}; + +// Create a new task from a callback +EPUBJS.Task = function(task, args, context){ + + return function(){ + var toApply = arguments || []; + + return new RSVP.Promise(function(resolve, reject) { + var callback = function(value){ + resolve(value); + }; + // Add the callback to the arguments list + toApply.push(callback); + + // Apply all arguments to the functions + task.apply(this, toApply); + + }.bind(this)); + + }; + +}; +EPUBJS.Hook = function(context){ + this.context = context || this; + this.hooks = []; +}; + +//-- Hooks allow for injecting async functions that must all complete in order before finishing +// Functions must return a promise. + +// this.beforeDisplay = new EPUBJS.Hook(); +// this.beforeDisplay.register(function(){}); +// this.beforeDisplay.trigger(args).then(function(){}); + +// Adds a function to be run before a hook completes +EPUBJS.Hook.prototype.register = function(func){ + this.hooks.push(func); +}; + +// Triggers a hook to run all functions +EPUBJS.Hook.prototype.trigger = function(){ + var args = arguments; + var context = this.context; + var promises = []; + + this.hooks.forEach(function(task, i) { + var executing = task.apply(context, args); + + if(executing && typeof executing["then"] === "function") { + // Task is a function that returns a promise + promises.push(executing); + } + // Otherwise Task resolves immediately, continue + }); + + + return RSVP.all(promises); +}; +EPUBJS.Parser = function(){}; + +EPUBJS.Parser.prototype.container = function(containerXml){ + //-- + var rootfile, fullpath, folder, encoding; + + if(!containerXml) { + console.error("Container File Not Found"); + return; + } + + rootfile = containerXml.querySelector("rootfile"); + + if(!rootfile) { + console.error("No RootFile Found"); + return; + } + + fullpath = rootfile.getAttribute('full-path'); + folder = EPUBJS.core.uri(fullpath).directory; + encoding = containerXml.xmlEncoding; + + //-- Now that we have the path we can parse the contents + return { + 'packagePath' : fullpath, + 'basePath' : folder, + 'encoding' : encoding + }; +}; + +EPUBJS.Parser.prototype.identifier = function(packageXml){ + var metadataNode; + + if(!packageXml) { + console.error("Package File Not Found"); + return; + } + + metadataNode = packageXml.querySelector("metadata"); + + if(!metadataNode) { + console.error("No Metadata Found"); + return; + } + + return this.getElementText(metadataNode, "identifier"); +}; + +EPUBJS.Parser.prototype.packageContents = function(packageXml){ + var parse = this; + var metadataNode, manifestNode, spineNode; + var manifest, navPath, ncxPath, coverPath; + var spineNodeIndex; + var spine; + var spineIndexByURL; + + if(!packageXml) { + console.error("Package File Not Found"); + return; + } + + metadataNode = packageXml.querySelector("metadata"); + if(!metadataNode) { + console.error("No Metadata Found"); + return; + } + + manifestNode = packageXml.querySelector("manifest"); + if(!manifestNode) { + console.error("No Manifest Found"); + return; + } + + spineNode = packageXml.querySelector("spine"); + if(!spineNode) { + console.error("No Spine Found"); + return; + } + + manifest = parse.manifest(manifestNode); + navPath = parse.findNavPath(manifestNode); + ncxPath = parse.findNcxPath(manifestNode); + coverPath = parse.findCoverPath(manifestNode); + + spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode); + + spine = parse.spine(spineNode, manifest); + + return { + 'metadata' : parse.metadata(metadataNode), + 'spine' : spine, + 'manifest' : manifest, + 'navPath' : navPath, + 'ncxPath' : ncxPath, + 'coverPath': coverPath, + 'spineNodeIndex' : spineNodeIndex + }; +}; + +//-- Find TOC NAV: media-type="application/xhtml+xml" href="toc.ncx" +EPUBJS.Parser.prototype.findNavPath = function(manifestNode){ + var node = manifestNode.querySelector("item[properties^='nav']"); + return node ? node.getAttribute('href') : false; +}; + +//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx" +EPUBJS.Parser.prototype.findNcxPath = function(manifestNode){ + var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); + return node ? node.getAttribute('href') : false; +}; + +//-- Find Cover: +EPUBJS.Parser.prototype.findCoverPath = function(manifestNode){ + var node = manifestNode.querySelector("item[properties='cover-image']"); + return node ? node.getAttribute('href') : false; +}; + +//-- Expanded to match Readium web components +EPUBJS.Parser.prototype.metadata = function(xml){ + var metadata = {}, + p = this; + + metadata.title = p.getElementText(xml, 'title'); + metadata.creator = p.getElementText(xml, 'creator'); + metadata.description = p.getElementText(xml, 'description'); + + metadata.pubdate = p.getElementText(xml, 'date'); + + metadata.publisher = p.getElementText(xml, 'publisher'); + + metadata.identifier = p.getElementText(xml, "identifier"); + metadata.language = p.getElementText(xml, "language"); + metadata.rights = p.getElementText(xml, "rights"); + + metadata.modified_date = p.querySelectorText(xml, "meta[property='dcterms:modified']"); + metadata.layout = p.querySelectorText(xml, "meta[property='rendition:layout']"); + metadata.orientation = p.querySelectorText(xml, "meta[property='rendition:orientation']"); + metadata.spread = p.querySelectorText(xml, "meta[property='rendition:spread']"); + // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction"); + + return metadata; +}; + +EPUBJS.Parser.prototype.getElementText = function(xml, tag){ + var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag), + el; + + if(!found || found.length === 0) return ''; + + el = found[0]; + + if(el.childNodes.length){ + return el.childNodes[0].nodeValue; + } + + return ''; + +}; + +EPUBJS.Parser.prototype.querySelectorText = function(xml, q){ + var el = xml.querySelector(q); + + if(el && el.childNodes.length){ + return el.childNodes[0].nodeValue; + } + + return ''; +}; + +EPUBJS.Parser.prototype.manifest = function(manifestXml){ + var manifest = {}; + + //-- Turn items into an array + var selected = manifestXml.querySelectorAll("item"), + items = Array.prototype.slice.call(selected); + + //-- Create an object with the id as key + items.forEach(function(item){ + var id = item.getAttribute('id'), + href = item.getAttribute('href') || '', + type = item.getAttribute('media-type') || '', + properties = item.getAttribute('properties') || ''; + + manifest[id] = { + 'href' : href, + // 'url' : href, + 'type' : type, + 'properties' : properties.length ? properties.split(' ') : [] + }; + + }); + + return manifest; + +}; + +EPUBJS.Parser.prototype.spine = function(spineXml, manifest){ + var spine = []; + + var selected = spineXml.getElementsByTagName("itemref"), + items = Array.prototype.slice.call(selected); + + var epubcfi = new EPUBJS.EpubCFI(); + + //-- Add to array to mantain ordering and cross reference with manifest + items.forEach(function(item, index){ + var idref = item.getAttribute('idref'); + // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id); + var props = item.getAttribute('properties') || ''; + var propArray = props.length ? props.split(' ') : []; + // var manifestProps = manifest[Id].properties; + // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : []; + + var itemref = { + 'idref' : idref, + 'linear' : item.getAttribute('linear') || '', + 'properties' : propArray, + // 'href' : manifest[Id].href, + // 'url' : manifest[Id].url, + 'index' : index + // 'cfiBase' : cfiBase + }; + spine.push(itemref); + }); + + return spine; +}; + +EPUBJS.Parser.prototype.nav = function(navHtml){ + var navEl = navHtml.querySelector('nav[*|type="toc"]'), //-- [*|type="toc"] * Doesn't seem to work + idCounter = 0; + + if(!navEl) return []; + + // Implements `> ol > li` + function findListItems(parent){ + var items = []; + + Array.prototype.slice.call(parent.childNodes).forEach(function(node){ + if('ol' == node.tagName){ + Array.prototype.slice.call(node.childNodes).forEach(function(item){ + if('li' == item.tagName){ + items.push(item); + } + }); + } + }); + + return items; + + } + + // Implements `> a, > span` + function findAnchorOrSpan(parent){ + var item = null; + + Array.prototype.slice.call(parent.childNodes).forEach(function(node){ + if('a' == node.tagName || 'span' == node.tagName){ + item = node; + } + }); + + return item; + } + + function getTOC(parent){ + var list = [], + nodes = findListItems(parent), + items = Array.prototype.slice.call(nodes), + length = items.length, + node; + + if(length === 0) return false; + + items.forEach(function(item){ + var id = item.getAttribute('id') || false, + content = findAnchorOrSpan(item), + href = content.getAttribute('href') || '', + text = content.textContent || "", + split = href.split("#"), + baseUrl = split[0], + subitems = getTOC(item); + // spinePos = spineIndexByURL[baseUrl], + // spineItem = bookSpine[spinePos], + // cfi = spineItem ? spineItem.cfi : ''; + + // if(!id) { + // if(spinePos) { + // spineItem = bookSpine[spinePos]; + // id = spineItem.id; + // cfi = spineItem.cfi; + // } else { + // id = 'epubjs-autogen-toc-id-' + (idCounter++); + // } + // } + + // item.setAttribute('id', id); // Ensure all elements have an id + list.push({ + "id": id, + "href": href, + "label": text, + "subitems" : subitems, + "parent" : parent ? parent.getAttribute('id') : null + // "cfi" : cfi + }); + + }); + + return list; + } + + return getTOC(navEl); +}; + +EPUBJS.Parser.prototype.ncx = function(tocXml){ + var navMap = tocXml.querySelector("navMap"); + if(!navMap) return []; + + function getTOC(parent){ + var list = [], + snapshot = tocXml.evaluate("*[local-name()='navPoint']", parent, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), + length = snapshot.snapshotLength; + + if(length === 0) return []; + + for ( var i=length-1 ; i >= 0; i-- ) { + var item = snapshot.snapshotItem(i); + + var id = item.getAttribute('id') || false, + content = item.querySelector("content"), + src = content.getAttribute('src'), + navLabel = item.querySelector("navLabel"), + text = navLabel.textContent ? navLabel.textContent : "", + split = src.split("#"), + baseUrl = split[0], + // spinePos = spineIndexByURL[baseUrl], + // spineItem = bookSpine[spinePos], + subitems = getTOC(item); + // cfi = spineItem ? spineItem.cfi : ''; + + // if(!id) { + // if(spinePos) { + // spineItem = bookSpine[spinePos]; + // id = spineItem.id; + // cfi = spineItem.cfi; + // } else { + // id = 'epubjs-autogen-toc-id-' + (idCounter++); + // } + // } + + list.unshift({ + "id": id, + "href": src, + "label": text, + // "spinePos": spinePos, + "subitems" : subitems, + "parent" : parent ? parent.getAttribute('id') : null, + // "cfi" : cfi + }); + + } + + return list; + } + + return getTOC(navMap); +}; +EPUBJS.EpubCFI = function(cfiStr){ + if(cfiStr) return this.parse(cfiStr); +}; + +EPUBJS.EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) { + var pos = parseInt(_pos), + spineNodeIndex = _spineNodeIndex + 1, + cfi = '/'+spineNodeIndex+'/'; + + cfi += (pos + 1) * 2; + + if(id) cfi += "[" + id + "]"; + + //cfi += "!"; + + return cfi; +}; + +EPUBJS.EpubCFI.prototype.generatePathComponent = function(steps) { + var parts = []; + + steps.forEach(function(part){ + var segment = ''; + segment += (part.index + 1) * 2; + + if(part.id) { + segment += "[" + part.id + "]"; + } + + parts.push(segment); + }); + + return parts.join('/'); +}; + +EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) { + var steps = this.pathTo(element); + var path = this.generatePathComponent(steps); + if(!path.length) { + // Start of Chapter + return "epubcfi(" + chapter + "!/4/)"; + } else { + // First Text Node + return "epubcfi(" + chapter + "!" + path + "/1:0)"; + } +}; + +EPUBJS.EpubCFI.prototype.pathTo = function(node) { + var stack = [], + children; + + while(node && node.parentNode !== null && node.parentNode.nodeType != 9) { + children = node.parentNode.children; + + stack.unshift({ + 'id' : node.id, + // 'classList' : node.classList, + 'tagName' : node.tagName, + 'index' : children ? Array.prototype.indexOf.call(children, node) : 0 + }); + + node = node.parentNode; + } + + return stack; +}; + +EPUBJS.EpubCFI.prototype.getChapterComponent = function(cfiStr) { + + var splitStr = cfiStr.split("!"); + + return splitStr[0]; +}; + +EPUBJS.EpubCFI.prototype.getPathComponent = function(cfiStr) { + + var splitStr = cfiStr.split("!"); + var pathComponent = splitStr[1] ? splitStr[1].split(":") : ''; + + return pathComponent[0]; +}; + +EPUBJS.EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) { + var splitStr = cfiStr.split(":"); + return splitStr[1] || ''; +}; + + +EPUBJS.EpubCFI.prototype.parse = function(cfiStr) { + var cfi = {}, + chapSegment, + chapterComponent, + pathComponent, + charecterOffsetComponent, + assertion, + chapId, + path, + end, + endInt, + text, + parseStep = function(part){ + var type, index, has_brackets, id; + + type = "element"; + index = parseInt(part) / 2 - 1; + has_brackets = part.match(/\[(.*)\]/); + if(has_brackets && has_brackets[1]){ + id = has_brackets[1]; + } + + return { + "type" : type, + 'index' : index, + 'id' : id || false + }; + }; + + if(typeof cfiStr !== "string") { + return {spinePos: -1}; + } + + cfi.str = cfiStr; + + if(cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length-1] === ")") { + // Remove intial epubcfi( and ending ) + cfiStr = cfiStr.slice(8, cfiStr.length-1); + } + + chapterComponent = this.getChapterComponent(cfiStr); + pathComponent = this.getPathComponent(cfiStr) || ''; + charecterOffsetComponent = this.getCharecterOffsetComponent(cfiStr); + // Make sure this is a valid cfi or return + if(!chapterComponent) { + return {spinePos: -1}; + } + + // Chapter segment is always the second one + chapSegment = chapterComponent.split("/")[2] || ''; + if(!chapSegment) return {spinePos:-1}; + + cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0; + + chapId = chapSegment.match(/\[(.*)\]/); + + cfi.spineId = chapId ? chapId[1] : false; + + if(pathComponent.indexOf(',') != -1) { + // Handle ranges -- not supported yet + console.warn("CFI Ranges are not supported"); + } + + path = pathComponent.split('/'); + end = path.pop(); + + cfi.steps = []; + + path.forEach(function(part){ + var step; + + if(part) { + step = parseStep(part); + cfi.steps.push(step); + } + }); + + //-- Check if END is a text node or element + endInt = parseInt(end); + if(!isNaN(endInt)) { + + if(endInt % 2 === 0) { // Even = is an element + cfi.steps.push(parseStep(end)); + } else { + cfi.steps.push({ + "type" : "text", + 'index' : (endInt - 1 ) / 2 + }); + } + + } + + assertion = charecterOffsetComponent.match(/\[(.*)\]/); + if(assertion && assertion[1]){ + cfi.characterOffset = parseInt(charecterOffsetComponent.split('[')[0]); + // We arent handling these assertions yet + cfi.textLocationAssertion = assertion[1]; + } else { + cfi.characterOffset = parseInt(charecterOffsetComponent); + } + + return cfi; +}; + +EPUBJS.EpubCFI.prototype.addMarker = function(cfi, _doc, _marker) { + var doc = _doc || document; + var marker = _marker || this.createMarker(doc); + var parent; + var lastStep; + var text; + var split; + + if(typeof cfi === 'string') { + cfi = this.parse(cfi); + } + // Get the terminal step + lastStep = cfi.steps[cfi.steps.length-1]; + + // check spinePos + if(cfi.spinePos === -1) { + // Not a valid CFI + return false; + } + + // Find the CFI elements parent + parent = this.findParent(cfi, doc); + + if(!parent) { + // CFI didn't return an element + // Maybe it isnt in the current chapter? + return false; + } + + if(lastStep && lastStep.type === "text") { + text = parent.childNodes[lastStep.index]; + if(cfi.characterOffset){ + split = text.splitText(cfi.characterOffset); + marker.classList.add("EPUBJS-CFI-SPLIT"); + parent.insertBefore(marker, split); + } else { + parent.insertBefore(marker, text); + } + } else { + parent.insertBefore(marker, parent.firstChild); + } + + return marker; +}; + +EPUBJS.EpubCFI.prototype.createMarker = function(_doc) { + var doc = _doc || document; + var element = doc.createElement('span'); + element.id = "EPUBJS-CFI-MARKER:"+ EPUBJS.core.uuid(); + element.classList.add("EPUBJS-CFI-MARKER"); + + return element; +}; + +EPUBJS.EpubCFI.prototype.removeMarker = function(marker, _doc) { + var doc = _doc || document; + // var id = marker.id; + + // Cleanup textnodes if they were split + if(marker.classList.contains("EPUBJS-CFI-SPLIT")){ + nextSib = marker.nextSibling; + prevSib = marker.previousSibling; + if(nextSib && + prevSib && + nextSib.nodeType === 3 && + prevSib.nodeType === 3){ + + prevSib.textContent += nextSib.textContent; + marker.parentNode.removeChild(nextSib); + } + marker.parentNode.removeChild(marker); + } else if(marker.classList.contains("EPUBJS-CFI-MARKER")) { + // Remove only elements added as markers + marker.parentNode.removeChild(marker); + } + +}; + +EPUBJS.EpubCFI.prototype.findParent = function(cfi, _doc) { + var doc = _doc || document, + element = doc.getElementsByTagName('html')[0], + children = Array.prototype.slice.call(element.children), + num, index, part, sections, + text, textBegin, textEnd; + + if(typeof cfi === 'string') { + cfi = this.parse(cfi); + } + + sections = cfi.steps.slice(0); // Clone steps array + if(!sections.length) { + return doc.getElementsByTagName('body')[0]; + } + + while(sections && sections.length > 0) { + part = sections.shift(); + // Find textNodes Parent + if(part.type === "text") { + text = element.childNodes[part.index]; + element = text.parentNode || element; + // Find element by id if present + } else if(part.id){ + element = doc.getElementById(part.id); + // Find element in parent + }else{ + element = children[part.index]; + } + // Element can't be found + if(typeof element === "undefined") { + console.error("No Element For", part, cfi.str); + return false; + } + // Get current element children and continue through steps + children = Array.prototype.slice.call(element.children); + } + + return element; +}; + +EPUBJS.EpubCFI.prototype.compare = function(cfiOne, cfiTwo) { + if(typeof cfiOne === 'string') { + cfiOne = new EPUBJS.EpubCFI(cfiOne); + } + if(typeof cfiTwo === 'string') { + cfiTwo = new EPUBJS.EpubCFI(cfiTwo); + } + // Compare Spine Positions + if(cfiOne.spinePos > cfiTwo.spinePos) { + return 1; + } + if(cfiOne.spinePos < cfiTwo.spinePos) { + return -1; + } + + + // Compare Each Step in the First item + for (var i = 0; i < cfiOne.steps.length; i++) { + if(!cfiTwo.steps[i]) { + return 1; + } + if(cfiOne.steps[i].index > cfiTwo.steps[i].index) { + return 1; + } + if(cfiOne.steps[i].index < cfiTwo.steps[i].index) { + return -1; + } + // Otherwise continue checking + } + + // All steps in First present in Second + if(cfiOne.steps.length < cfiTwo.steps.length) { + return -1; + } + + // Compare the charecter offset of the text node + if(cfiOne.characterOffset > cfiTwo.characterOffset) { + return 1; + } + if(cfiOne.characterOffset < cfiTwo.characterOffset) { + return -1; + } + + // CFI's are equal + return 0; +}; + +EPUBJS.EpubCFI.prototype.generateCfiFromHref = function(href, book) { + var uri = EPUBJS.core.uri(href); + var path = uri.path; + var fragment = uri.fragment; + var spinePos = book.spineIndexByURL[path]; + var loaded; + var deferred = new RSVP.defer(); + var epubcfi = new EPUBJS.EpubCFI(); + var spineItem; + + if(typeof spinePos !== "undefined"){ + spineItem = book.spine[spinePos]; + loaded = book.loadXml(spineItem.url); + loaded.then(function(doc){ + var element = doc.getElementById(fragment); + var cfi; + cfi = epubcfi.generateCfiFromElement(element, spineItem.cfiBase); + deferred.resolve(cfi); + }); + } + + return deferred.promise; +}; + +EPUBJS.EpubCFI.prototype.generateCfiFromTextNode = function(anchor, offset, base) { + var parent = anchor.parentNode; + var steps = this.pathTo(parent); + var path = this.generatePathComponent(steps); + var index = 1 + (2 * Array.prototype.indexOf.call(parent.childNodes, anchor)); + return "epubcfi(" + base + "!" + path + "/"+index+":"+(offset || 0)+")"; +}; + +EPUBJS.EpubCFI.prototype.generateCfiFromRangeAnchor = function(range, base) { + var anchor = range.anchorNode; + var offset = range.anchorOffset; + return this.generateCfiFromTextNode(anchor, offset, base); +}; + +EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) { + var start, startElement, startSteps, startPath, startOffset, startIndex; + var end, endElement, endSteps, endPath, endOffset, endIndex; + + start = range.startContainer; + + if(start.nodeType === 3) { // text node + startElement = start.parentNode; + //startIndex = 1 + (2 * Array.prototype.indexOf.call(startElement.childNodes, start)); + startIndex = 1 + (2 * EPUBJS.core.indexOfTextNode(start)); + startSteps = this.pathTo(startElement); + } else if(range.collapsed) { + return this.generateCfiFromElement(start, base); // single element + } else { + startSteps = this.pathTo(start); + } + + startPath = this.generatePathComponent(startSteps); + startOffset = range.startOffset; + + if(!range.collapsed) { + end = range.endContainer; + + if(end.nodeType === 3) { // text node + endElement = end.parentNode; + // endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end)); + endIndex = 1 + (2 * EPUBJS.core.indexOfTextNode(end)); + + endSteps = this.pathTo(endElement); + } else { + endSteps = this.pathTo(end); + } + + endPath = this.generatePathComponent(endSteps); + endOffset = range.endOffset; + + return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")"; + + } else { + return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")"; + } +}; + +EPUBJS.EpubCFI.prototype.generateXpathFromSteps = function(steps) { + var xpath = [".", "*"]; + + steps.forEach(function(step){ + var position = step.index + 1; + + if(step.id){ + xpath.push("*[position()=" + position + " and @id='" + step.id + "']"); + } else if(step.type === "text") { + xpath.push("text()[" + position + "]"); + } else { + xpath.push("*[" + position + "]"); + } + }); + + return xpath.join("/"); +}; + + +EPUBJS.EpubCFI.prototype.generateRangeFromCfi = function(cfi, _doc) { + var doc = _doc || document; + var range = doc.createRange(); + var lastStep; + var xpath; + var startContainer; + var textLength; + + if(typeof cfi === 'string') { + cfi = this.parse(cfi); + } + + // check spinePos + if(cfi.spinePos === -1) { + // Not a valid CFI + return false; + } + + xpath = this.generateXpathFromSteps(cfi.steps); + + // Get the terminal step + lastStep = cfi.steps[cfi.steps.length-1]; + startContainer = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; + + if(!startContainer) { + return null; + } + + if(startContainer && cfi.characterOffset >= 0) { + textLength = startContainer.length; + + if(cfi.characterOffset < textLength) { + range.setStart(startContainer, cfi.characterOffset); + range.setEnd(startContainer, textLength ); + } else { + console.debug("offset greater than length:", cfi.characterOffset, textLength); + range.setStart(startContainer, textLength - 1 ); + range.setEnd(startContainer, textLength ); + } + } else if(startContainer) { + range.selectNode(startContainer); + } + // doc.defaultView.getSelection().addRange(range); + return range; +}; + +EPUBJS.EpubCFI.prototype.isCfiString = function(target) { + if(typeof target === "string" && + target.indexOf("epubcfi(") === 0) { + return true; + } + + return false; +}; +EPUBJS.Navigation = function(_package, _request){ + var navigation = this; + var parse = new EPUBJS.Parser(); + var request = _request || EPUBJS.core.request; + + this.package = _package; + this.toc = []; + this.tocByHref = {}; + this.tocById = {}; + + if(_package.navPath) { + this.navUrl = _package.baseUrl + _package.navPath; + this.nav = {}; + + this.nav.load = function(_request){ + var loading = new RSVP.defer(); + var loaded = loading.promise; + + request(navigation.navUrl, 'xml').then(function(xml){ + navigation.toc = parse.nav(xml); + navigation.loaded(navigation.toc); + loading.resolve(navigation.toc); + }); + + return loaded; + }; + + } + + if(_package.ncxPath) { + this.ncxUrl = _package.baseUrl + _package.ncxPath; + this.ncx = {}; + + this.ncx.load = function(_request){ + var loading = new RSVP.defer(); + var loaded = loading.promise; + + request(navigation.ncxUrl, 'xml').then(function(xml){ + navigation.toc = parse.ncx(xml); + navigation.loaded(navigation.toc); + loading.resolve(navigation.toc); + }); + + return loaded; + }; + + } +}; + +// Load the navigation +EPUBJS.Navigation.prototype.load = function(_request) { + var request = _request || EPUBJS.core.request; + var loading, loaded; + + if(this.nav) { + loading = this.nav.load(); + } else if(this.ncx) { + loading = this.ncx.load(); + } else { + loaded = new RSVP.defer(); + loaded.resolve([]); + loading = loaded.promise; + } + + return loading; + +}; + +EPUBJS.Navigation.prototype.loaded = function(toc) { + var item; + + for (var i = 0; i < toc.length; i++) { + item = toc[i]; + this.tocByHref[item.href] = i; + this.tocById[item.id] = i; + } + +}; + +// Get an item from the navigation +EPUBJS.Navigation.prototype.get = function(target) { + var index; + + if(!target) { + return this.toc; + } + + if(target.indexOf("#") === 0) { + index = this.tocById[target.substring(1)]; + } else if(target in this.tocByHref){ + index = this.tocByHref[target]; + } + + return this.toc[index]; +}; EPUBJS.Section = function(item){ this.idref = item.idref; this.linear = item.linear; @@ -5777,6 +3573,263 @@ EPUBJS.Spine.prototype.remove = function(section) { return this.spineItems.splice(index, 1); } }; +EPUBJS.replace = {}; +EPUBJS.replace.links = function(view, renderer) { + + var links = view.document.querySelectorAll("a[href]"); + var replaceLinks = function(link){ + var href = link.getAttribute("href"); + var uri = new EPUBJS.core.uri(href); + + + if(uri.protocol){ + + link.setAttribute("target", "_blank"); + + }else{ + + // relative = EPUBJS.core.resolveUrl(directory, href); + // if(uri.fragment && !base) { + // link.onclick = function(){ + // renderer.fragment(href); + // return false; + // }; + // } else { + + //} + + if(href.indexOf("#") === 0) { + // do nothing with fragment yet + } else { + link.onclick = function(){ + renderer.display(href); + return false; + }; + } + + } + }; + + for (var i = 0; i < links.length; i++) { + replaceLinks(links[i]); + } + + +}; +EPUBJS.Book = function(_url){ + // Promises + this.opening = new RSVP.defer(); + this.opened = this.opening.promise; + this.isOpen = false; + + this.url = undefined; + + this.spine = new EPUBJS.Spine(this.request); + + this.loading = { + manifest: new RSVP.defer(), + spine: new RSVP.defer(), + metadata: new RSVP.defer(), + cover: new RSVP.defer(), + navigation: new RSVP.defer(), + pageList: new RSVP.defer() + }; + + this.loaded = { + manifest: this.loading.manifest.promise, + spine: this.loading.spine.promise, + metadata: this.loading.metadata.promise, + cover: this.loading.cover.promise, + navigation: this.loading.navigation.promise, + pageList: this.loading.pageList.promise + }; + + this.ready = RSVP.hash(this.loaded); + + // Queue for methods used before opening + this.isRendered = false; + this._q = EPUBJS.core.queue(this); + + this.request = this.requestMethod.bind(this); + + if(_url) { + this.open(_url); + } +}; + +EPUBJS.Book.prototype.open = function(_url){ + var uri; + var parse = new EPUBJS.Parser(); + var epubPackage; + var book = this; + var containerPath = "META-INF/container.xml"; + var location; + + if(!_url) { + this.opening.resolve(this); + return this.opened; + } + + // Reuse parsed url or create a new uri object + if(typeof(_url) === "object") { + uri = _url; + } else { + uri = EPUBJS.core.uri(_url); + } + + // Find path to the Container + if(uri.extension === "opf") { + // Direct link to package, no container + this.packageUrl = uri.href; + this.containerUrl = ''; + + if(uri.origin) { + this.url = uri.base; + } else if(window){ + location = EPUBJS.core.uri(window.location.href); + this.url = EPUBJS.core.resolveUrl(location.base, uri.directory); + } else { + this.url = uri.directory; + } + + epubPackage = this.request(this.packageUrl); + + } else if(uri.extension === "epub" || uri.extension === "zip" ) { + // Book is archived + this.archived = true; + this.url = ''; + } + + // Find the path to the Package from the container + else if (!uri.extension) { + + this.containerUrl = _url + containerPath; + + epubPackage = this.request(this.containerUrl). + then(function(containerXml){ + return parse.container(containerXml); // Container has path to content + }). + then(function(paths){ + var packageUri = EPUBJS.core.uri(paths.packagePath); + book.packageUrl = _url + paths.packagePath; + book.encoding = paths.encoding; + + // Set Url relative to the content + if(packageUri.origin) { + book.url = packageUri.base; + } else if(window){ + location = EPUBJS.core.uri(window.location.href); + book.url = EPUBJS.core.resolveUrl(location.base, _url + packageUri.directory); + } else { + book.url = packageUri.directory; + } + + return book.request(book.packageUrl); + }).catch(function(error) { + // handle errors in either of the two requests + console.error("Could not load book at: " + (this.packageUrl || this.containerPath)); + book.trigger("book:loadFailed", (this.packageUrl || this.containerPath)); + book.opening.reject(error); + }); + } + + + epubPackage.then(function(packageXml) { + // Get package information from epub opf + book.unpack(packageXml); + + // Resolve promises + book.loading.manifest.resolve(book.package.manifest); + book.loading.metadata.resolve(book.package.metadata); + book.loading.spine.resolve(book.spine); + book.loading.cover.resolve(book.cover); + + this.isOpen = true; + + // Clear queue of any waiting book request + + // Resolve book opened promise + book.opening.resolve(book); + + }).catch(function(error) { + // handle errors in parsing the book + console.error(error.message, error.stack); + book.opening.reject(error); + }); + + return this.opened; +}; + +EPUBJS.Book.prototype.unpack = function(packageXml){ + var book = this, + parse = new EPUBJS.Parser(); + + book.package = parse.packageContents(packageXml); // Extract info from contents + book.package.baseUrl = book.url; // Provides a url base for resolving paths + + this.spine.load(book.package); + + book.navigation = new EPUBJS.Navigation(book.package, this.request); + book.navigation.load().then(function(toc){ + book.toc = toc; + book.loading.navigation.resolve(book.toc); + }); + + // //-- Set Global Layout setting based on metadata + // MOVE TO RENDER + // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata); + + book.cover = book.url + book.package.coverPath; +}; + +// Alias for book.spine.get +EPUBJS.Book.prototype.section = function(target) { + return this.spine.get(target); +}; + +// Sugar to render a book +EPUBJS.Book.prototype.renderTo = function(element, options) { + var renderer = (options && options.method) ? + options.method.charAt(0).toUpperCase() + options.method.substr(1) : + "Rendition"; + + this.rendition = new EPUBJS[renderer](this, options); + this.rendition.attachTo(element); + return this.rendition; +}; + +EPUBJS.Book.prototype.requestMethod = function(_url) { + // Switch request methods + if(this.archived) { + // TODO: handle archived + } else { + return EPUBJS.core.request(_url, 'xml', this.requestCredentials, this.requestHeaders); + } + +}; + +EPUBJS.Book.prototype.setRequestCredentials = function(_credentials) { + this.requestCredentials = _credentials; +}; + +EPUBJS.Book.prototype.setRequestHeaders = function(_headers) { + this.requestHeaders = _headers; +}; +//-- Enable binding events to book +RSVP.EventTarget.mixin(EPUBJS.Book.prototype); + +//-- Handle RSVP Errors +RSVP.on('error', function(event) { + //console.error(event, event.detail); +}); + +RSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections +// RSVP.on('created', listener); +// RSVP.on('chained', listener); +// RSVP.on('fulfilled', listener); +RSVP.on('rejected', function(event){ + console.error(event.detail.message, event.detail.stack); +}); EPUBJS.View = function(section, options) { this.settings = options || {}; @@ -6421,4 +4474,1951 @@ EPUBJS.View.prototype.addStylesheetRules = function(rules) { } }; -RSVP.EventTarget.mixin(EPUBJS.View.prototype); \ No newline at end of file +RSVP.EventTarget.mixin(EPUBJS.View.prototype); +EPUBJS.Layout = EPUBJS.Layout || {}; + +EPUBJS.Layout.Reflowable = function(){ + +}; + +EPUBJS.Layout.Reflowable.prototype.calculate = function(_width, _height, _gap, _devisor){ + + var divisor = _devisor || 1; + + //-- Check the width and create even width columns + var fullWidth = Math.floor(_width); + var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1; + + var section = Math.floor(width / 8); + var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1); + + var colWidth; + var spreadWidth; + var delta; + + //-- Double Page + if(divisor > 1) { + colWidth = Math.floor((width - gap) / divisor); + } else { + colWidth = width; + } + + spreadWidth = colWidth * divisor; + + delta = (colWidth + gap) * divisor; + + + + this.columnAxis = EPUBJS.core.prefixed('columnAxis'); + this.columnGap = EPUBJS.core.prefixed('columnGap'); + this.columnWidth = EPUBJS.core.prefixed('columnWidth'); + this.columnFill = EPUBJS.core.prefixed('columnFill'); + + this.width = width; + this.height = _height; + this.spread = spreadWidth; + this.delta = delta; + + this.column = colWidth; + this.gap = gap; + this.divisor = divisor; + +}; + +EPUBJS.Layout.Reflowable.prototype.format = function(view){ + + var $doc = view.document.documentElement; + var $body = view.document.body;//view.document.querySelector("body"); + + $doc.style.overflow = "hidden"; + + // Must be set to the new calculated width or the columns will be off + // $body.style.width = this.width + "px"; + $doc.style.width = this.width + "px"; + + //-- Adjust height + $body.style.height = this.height + "px"; + + //-- Add columns + $body.style[this.columnAxis] = "horizontal"; + $body.style[this.columnFill] = "auto"; + $body.style[this.columnGap] = this.gap+"px"; + $body.style[this.columnWidth] = this.column+"px"; + + // Add extra padding for the gap between this and the next view + view.iframe.style.marginRight = this.gap+"px"; +}; + +EPUBJS.Layout.Reflowable.prototype.count = function(view) { + var totalWidth = view.root().scrollWidth; + var spreads = Math.ceil(totalWidth / this.spread); + + return { + spreads : spreads, + pages : spreads * this.divisor + }; +}; + +EPUBJS.Layout.Fixed = function(_width, _height){ + +}; + +EPUBJS.Layout.Fixed.prototype.calculate = function(_width, _height){ + +}; + +EPUBJS.Layout.Fixed.prototype.format = function(view){ + var width, height; + + var $doc = view.document.documentElement; + var $viewport = documentElement.querySelector("[name=viewport"); + + /** + * check for the viewport size + * + */ + if($viewport && $viewport.hasAttribute("content")) { + content = $viewport.getAttribute("content"); + contents = content.split(','); + if(contents[0]){ + width = contents[0].replace("width=", ''); + } + if(contents[1]){ + height = contents[1].replace("height=", ''); + } + } + + //-- Adjust width and height + // $doc.style.width = width + "px" || "auto"; + // $doc.style.height = height + "px" || "auto"; + view.resize(width, height); + + //-- Scroll + $doc.style.overflow = "auto"; + +}; + +EPUBJS.Layout.Fixed.prototype.count = function(){ + return { + spreads : 1, + pages : 1 + }; +}; + +EPUBJS.Layout.Scroll = function(){ + +}; + +EPUBJS.Layout.Scroll.prototype.calculate = function(_width, _height){ + this.spread = _width; + this.column = _width; + this.gap = 0; +}; + +EPUBJS.Layout.Scroll.prototype.format = function(view){ + + var $doc = view.document.documentElement; + + $doc.style.width = "auto"; + $doc.style.height = "auto"; + +}; + +EPUBJS.Layout.Scroll.prototype.count = function(){ + return { + spreads : 1, + pages : 1 + }; +}; + +EPUBJS.Rendition = function(book, options) { + + this.settings = EPUBJS.core.extend(this.settings || {}, { + infinite: true, + hidden: false, + width: false, + height: null, + layoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'}, + axis: "vertical" + }); + + EPUBJS.core.extend(this.settings, options); + + this.viewSettings = {}; + + this.book = book; + + this.views = []; + + //-- Adds Hook methods to the Rendition prototype + this.hooks = {}; + this.hooks.display = new EPUBJS.Hook(this); + this.hooks.content = new EPUBJS.Hook(this); + this.hooks.layout = new EPUBJS.Hook(this); + this.hooks.render = new EPUBJS.Hook(this); + this.hooks.show = new EPUBJS.Hook(this); + + this.hooks.content.register(EPUBJS.replace.links.bind(this)); + + // this.hooks.display.register(this.afterDisplay.bind(this)); + + this.epubcfi = new EPUBJS.EpubCFI(); + + this.q = new EPUBJS.Queue(this); + + this.q.enqueue(this.book.opened); + + this.q.enqueue(this.parseLayoutProperties); + +}; + +/** +* Creates an element to render to. +* Resizes to passed width and height or to the elements size +*/ +EPUBJS.Rendition.prototype.initialize = function(_options){ + var options = _options || {}; + var height = options.height;// !== false ? options.height : "100%"; + var width = options.width;// !== false ? options.width : "100%"; + var hidden = options.hidden || false; + var container; + var wrapper; + + if(options.height && EPUBJS.core.isNumber(options.height)) { + height = options.height + "px"; + } + + if(options.width && EPUBJS.core.isNumber(options.width)) { + width = options.width + "px"; + } + + // Create new container element + container = document.createElement("div"); + + container.id = "epubjs-container:" + EPUBJS.core.uuid(); + container.classList.add("epub-container"); + + // Style Element + container.style.fontSize = "0"; + container.style.wordSpacing = "0"; + container.style.lineHeight = "0"; + container.style.verticalAlign = "top"; + + if(this.settings.axis === "horizontal") { + container.style.whiteSpace = "nowrap"; + } + + if(width){ + container.style.width = width; + } + + if(height){ + container.style.height = height; + } + + container.style.overflow = this.settings.overflow; + + return container; +}; + +EPUBJS.Rendition.wrap = function(container) { + var wrapper = document.createElement("div"); + + wrapper.style.visibility = "hidden"; + wrapper.style.overflow = "hidden"; + wrapper.style.width = "0"; + wrapper.style.height = "0"; + + wrapper.appendChild(container); + return wrapper; +}; + +// Call to attach the container to an element in the dom +// Container must be attached before rendering can begin +EPUBJS.Rendition.prototype.attachTo = function(_element){ + var bounds; + + this.container = this.initialize({ + "width" : this.settings.width, + "height" : this.settings.height + }); + + if(EPUBJS.core.isElement(_element)) { + this.element = _element; + } else if (typeof _element === "string") { + this.element = document.getElementById(_element); + } + + if(!this.element){ + console.error("Not an Element"); + return; + } + + if(this.settings.hidden) { + this.wrapper = this.wrap(this.container); + this.element.appendChild(this.wrapper); + } else { + this.element.appendChild(this.container); + } + + // Attach Listeners + this.attachListeners(); + + // Calculate Stage Size + this.stageSize(); + + // Add Layout method + this.applyLayoutMethod(); + + // Trigger Attached + this.trigger("attached"); + + // Start processing queue + // this.q.run(); + +}; + +EPUBJS.Rendition.prototype.attachListeners = function(){ + + // Listen to window for resize event if width or height is set to 100% + if(!EPUBJS.core.isNumber(this.settings.width) || + !EPUBJS.core.isNumber(this.settings.height) ) { + window.addEventListener("resize", this.onResized.bind(this), false); + } + +}; + +EPUBJS.Rendition.prototype.bounds = function() { + return this.container.getBoundingClientRect(); +}; + +EPUBJS.Rendition.prototype.display = function(target){ + + return this.q.enqueue(this._display, target); + +}; + +EPUBJS.Rendition.prototype._display = function(target){ + + var displaying = new RSVP.defer(); + var displayed = displaying.promise; + + var section; + var view; + var cfi, spinePos; + + if(this.epubcfi.isCfiString(target)) { + cfi = this.epubcfi.parse(target); + spinePos = cfi.spinePos; + section = this.book.spine.get(spinePos); + } else { + section = this.book.spine.get(target); + } + + this.displaying = true; + + // Hide current views + this.hide(); + + if(section){ + view = this.createView(section); + + // Show view + this.q.enqueue(this.append, view); + + // Move to correct place within the section, if needed + // this.moveTo(what) + + // Show views + this.show(); + + // This hook doesn't prevent showing, but waits to resolve until + // all the hooks have finished. Might want to block showing. + this.hooks.display.trigger(view) + .then(function(){ + this.trigger("displayed", section); + displaying.resolve(this); + }.bind(this)); + + } else { + displaying.reject(new Error("No Section Found")); + } + + return displayed; + +}; +// Takes a cfi, fragment or page? +EPUBJS.Rendition.prototype.moveTo = function(what){ + +}; + +EPUBJS.Rendition.prototype.render = function(view, show) { + + view.create(); + + view.onLayout = this.layout.format.bind(this.layout); + + // Fit to size of the container, apply padding + this.resizeView(view); + + // Render Chain + return view.render(this.book.request) + .then(function(){ + return this.hooks.content.trigger(view, this); + }.bind(this)) + .then(function(){ + return this.hooks.layout.trigger(view, this); + }.bind(this)) + .then(function(){ + return view.display(); + }.bind(this)) + .then(function(){ + return this.hooks.render.trigger(view, this); + }.bind(this)) + .then(function(){ + + if(show !== false && this.hidden === false) { + this.q.enqueue(function(view){ + view.show(); + }, view); + } + + + // this.map = new EPUBJS.Map(view, this.layout); + this.trigger("rendered", view.section); + + }.bind(this)) + .catch(function(e){ + this.trigger("loaderror", e); + }.bind(this)); + +}; + + +EPUBJS.Rendition.prototype.afterDisplayed = function(view){ + this.trigger("added", view.section); +}; + +EPUBJS.Rendition.prototype.append = function(view){ + // Clear existing views + this.clear(); + + this.views.push(view); + // view.appendTo(this.container); + this.container.appendChild(view.element); + + // view.on("displayed", this.afterDisplayed.bind(this)); + view.onDisplayed = this.afterDisplayed.bind(this); + // this.resizeView(view); + + return this.render(view); +}; + +EPUBJS.Rendition.prototype.clear = function(){ + // Remove all views + this.views.forEach(function(view){ + this._remove(view); + }.bind(this)); + this.views = []; +}; + +EPUBJS.Rendition.prototype.remove = function(view) { + var index = this.views.indexOf(view); + + if(index > -1) { + this.views.splice(index, 1); + } + + + this._remove(view); + +}; + +EPUBJS.Rendition.prototype._remove = function(view) { + view.off("resized"); + + if(view.displayed){ + view.destroy(); + } + + this.container.removeChild(view.element); + view = null; +}; + +EPUBJS.Rendition.prototype.resizeView = function(view) { + + if(this.globalLayoutProperties.layout === "pre-paginated") { + view.lock("both", this.stage.width, this.stage.height); + } else { + view.lock("width", this.stage.width, this.stage.height); + } + +}; + +EPUBJS.Rendition.prototype.stageSize = function(_width, _height){ + var bounds; + var width = _width || this.settings.width; + var height = _height || this.settings.height; + + // If width or height are set to false, inherit them from containing element + if(width === false) { + bounds = this.element.getBoundingClientRect(); + + if(bounds.width) { + width = bounds.width; + this.container.style.width = bounds.width + "px"; + } + } + + if(height === false) { + bounds = bounds || this.element.getBoundingClientRect(); + + if(bounds.height) { + height = bounds.height; + this.container.style.height = bounds.height + "px"; + } + + } + + if(width && !EPUBJS.core.isNumber(width)) { + bounds = this.container.getBoundingClientRect(); + width = bounds.width; + //height = bounds.height; + } + + if(height && !EPUBJS.core.isNumber(height)) { + bounds = bounds || this.container.getBoundingClientRect(); + //width = bounds.width; + height = bounds.height; + } + + + this.containerStyles = window.getComputedStyle(this.container); + this.containerPadding = { + left: parseFloat(this.containerStyles["padding-left"]) || 0, + right: parseFloat(this.containerStyles["padding-right"]) || 0, + top: parseFloat(this.containerStyles["padding-top"]) || 0, + bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0 + }; + + this.stage = { + width: width - + this.containerPadding.left - + this.containerPadding.right, + height: height - + this.containerPadding.top - + this.containerPadding.bottom + }; + + return this.stage; + +}; + +EPUBJS.Rendition.prototype.applyLayoutMethod = function() { + + this.layout = new EPUBJS.Layout.Scroll(); + this.updateLayout(); + + this.map = new EPUBJS.Map(this.layout); +}; + +EPUBJS.Rendition.prototype.updateLayout = function() { + + this.layout.calculate(this.stage.width, this.stage.height); + +}; + +EPUBJS.Rendition.prototype.resize = function(width, height){ + + this.stageSize(width, height); + + this.updateLayout(); + + this.views.forEach(this.resizeView.bind(this)); + + this.trigger("resized", { + width: this.stage.width, + height: this.stage.height + }); + +}; + +EPUBJS.Rendition.prototype.onResized = function(e) { + this.resize(); +}; + +EPUBJS.Rendition.prototype.createView = function(section) { + return new EPUBJS.View(section, this.viewSettings); +}; + +EPUBJS.Rendition.prototype.next = function(){ + + return this.q.enqueue(function(){ + + var next; + var view; + + if(!this.views.length) return; + + next = this.views[0].section.next(); + + if(next) { + view = this.createView(next); + return this.append(view); + } + + }); + +}; + +EPUBJS.Rendition.prototype.prev = function(){ + + return this.q.enqueue(function(){ + + var prev; + var view; + + if(!this.views.length) return; + + prev = this.views[0].section.prev(); + if(prev) { + view = this.createView(prev); + return this.append(view); + } + + }); + +}; + +//-- http://www.idpf.org/epub/fxl/ +EPUBJS.Rendition.prototype.parseLayoutProperties = function(_metadata){ + var metadata = _metadata || this.book.package.metadata; + var layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || "reflowable"; + var spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || "auto"; + var orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || "auto"; + this.globalLayoutProperties = { + layout : layout, + spread : spread, + orientation : orientation + }; + return this.globalLayoutProperties; +}; + + +EPUBJS.Rendition.prototype.current = function(){ + var visible = this.visible(); + if(visible.length){ + // Current is the last visible view + return visible[visible.length-1]; + } + return null; +}; + +EPUBJS.Rendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){ + var position = view.position(); + var container = _container || this.container.getBoundingClientRect(); + + if(this.settings.axis === "horizontal" && + (position.right > container.left - offsetPrev) && + !(position.left >= container.right + offsetNext)) { + + return true; + + } else if(this.settings.axis === "vertical" && + (position.bottom > container.top - offsetPrev) && + !(position.top >= container.bottom + offsetNext)) { + + return true; + } + + return false; + +}; + +EPUBJS.Rendition.prototype.visible = function(){ + var container = this.bounds(); + var visible = []; + var isVisible; + var view; + + for (var i = 0; i < this.views.length; i++) { + view = this.views[i]; + isVisible = this.isVisible(view, 0, 0, container); + + if(isVisible === true) { + visible.push(view); + } + + } + + return visible; + +}; + +EPUBJS.Rendition.prototype.bounds = function(func) { + var bounds; + + if(!this.settings.height) { + bounds = EPUBJS.core.windowBounds(); + } else { + bounds = this.container.getBoundingClientRect(); + } + + return bounds; +}; + +EPUBJS.Rendition.prototype.displayed = function(){ + var displayed = []; + var view; + for (var i = 0; i < this.views.length; i++) { + view = this.views[i]; + if(view.displayed){ + displayed.push(view); + } + } + return displayed; +}; + +EPUBJS.Rendition.prototype.show = function(){ + var view; + for (var i = 0; i < this.views.length; i++) { + view = this.views[i]; + if(view.displayed){ + view.show(); + } + } + this.hidden = false; +}; + +EPUBJS.Rendition.prototype.hide = function(){ + var view; + for (var i = 0; i < this.views.length; i++) { + view = this.views[i]; + if(view.displayed){ + view.hide(); + } + } + this.hidden = true; +}; + +EPUBJS.Rendition.prototype.destroy = function(){ + // Clear the queue + this.q.clear(); + + this.clear(); + + clearTimeout(this.trimTimeout); + if(this.settings.hidden) { + this.element.removeChild(this.wrapper); + } else { + this.element.removeChild(this.container); + } + +}; + +EPUBJS.Rendition.prototype.reportLocation = function(){ + return this.q.enqueue(function(){ + this.location = this.currentLocation(); + this.trigger("locationChanged", this.location); + }.bind(this)); +}; + +EPUBJS.Rendition.prototype.currentLocation = function(){ + var view; + var start, end; + + if(this.views.length) { + view = this.views[0]; + // start = container.left - view.position().left; + // end = start + this.layout.spread; + + return this.map.page(view); + } + +}; + +//-- Enable binding events to Renderer +RSVP.EventTarget.mixin(EPUBJS.Rendition.prototype); + +EPUBJS.Continuous = function(book, options) { + + EPUBJS.Rendition.apply(this, arguments); // call super constructor. + + this.settings = EPUBJS.core.extend(this.settings || {}, { + infinite: true, + overflow: "auto", + axis: "vertical", + offset: 500, + offsetDelta: 250 + }); + + EPUBJS.core.extend(this.settings, options); + + if(this.settings.hidden) { + this.wrapper = this.wrap(this.container); + } + + +}; + +// subclass extends superclass +EPUBJS.Continuous.prototype = Object.create(EPUBJS.Rendition.prototype); +EPUBJS.Continuous.prototype.constructor = EPUBJS.Continuous; + +EPUBJS.Continuous.prototype.attachListeners = function(){ + + // Listen to window for resize event if width or height is set to a percent + if(!EPUBJS.core.isNumber(this.settings.width) || + !EPUBJS.core.isNumber(this.settings.height) ) { + window.addEventListener("resize", this.onResized.bind(this), false); + } + + + if(this.settings.infinite) { + this.start(); + } + + +}; + +EPUBJS.Continuous.prototype._display = function(target){ + + var displaying = new RSVP.defer(); + var displayed = displaying.promise; + + var section; + var view; + var cfi, spinePos; + + if(this.epubcfi.isCfiString(target)) { + cfi = this.epubcfi.parse(target); + spinePos = cfi.spinePos; + section = this.book.spine.get(spinePos); + } else { + section = this.book.spine.get(target); + } + + this.displaying = true; + this.hide(); + + if(section){ + view = new EPUBJS.View(section, this.viewSettings); + + // This will clear all previous views + this.q.enqueue(this.fill, view).then(function(){ + + // Move to correct place within the section, if needed + this.q.enqueue(function(){ + + var offset = view.locationOf(target); + + return this.moveTo(offset); + + }); + + this.q.enqueue(this.check); + + this.q.enqueue(this.show); + + // This hook doesn't prevent showing, but waits to resolve until + // all the hooks have finished. Might want to block showing. + this.hooks.display.trigger(view) + .then(function(){ + this.trigger("displayed", section); + displaying.resolve(this); + }.bind(this)); + + }.bind(this)); + + // view.displayed.then(function(){ + // this.trigger("displayed", section); + // this.displaying = false; + // displaying.resolve(this); + //}.bind(this)); + displaying.resolve(this); + + } else { + displaying.reject(new Error("No Section Found")); + } + + return displayed; +}; + + +EPUBJS.Continuous.prototype.moveTo = function(offset){ + var bounds = this.bounds(); + var dist = Math.floor(offset.top / bounds.height) * bounds.height; + + return this.check(0, dist+this.settings.offset).then(function(){ + + if(this.settings.axis === "vertical") { + this.scrollBy(0, dist); + } else { + this.scrollBy(dist, 0); + } + + }.bind(this)); +}; + +EPUBJS.Continuous.prototype.afterDisplayed = function(currView){ + var next = currView.section.next(); + var prev = currView.section.prev(); + var index = this.views.indexOf(currView); + + var prevView, nextView; + + if(index + 1 === this.views.length && next) { + nextView = new EPUBJS.View(next, this.viewSettings); + this.q.enqueue(this.append, nextView); + } + + if(index === 0 && prev) { + prevView = new EPUBJS.View(prev, this.viewSettings); + this.q.enqueue(this.prepend, prevView); + } + + // this.removeShownListeners(currView); + // currView.onShown = this.afterDisplayed.bind(this); + + this.trigger("added", currView.section); + +}; + + +// Remove Previous Listeners if present +EPUBJS.Continuous.prototype.removeShownListeners = function(view){ + + // view.off("shown", this.afterDisplayed); + // view.off("shown", this.afterDisplayedAbove); + view.onDisplayed = function(){}; + +}; + +EPUBJS.Continuous.prototype.append = function(view){ + this.views.push(view); + this.container.appendChild(view.element); + + // view.on("shown", this.afterDisplayed.bind(this)); + view.onDisplayed = this.afterDisplayed.bind(this); + + //this.q.enqueue(this.check); + return this.check(); +}; + +EPUBJS.Continuous.prototype.prepend = function(view){ + this.views.unshift(view); + this.container.insertBefore(view.element, this.container.firstChild); + + // view.on("shown", this.afterDisplayedAbove.bind(this)); + view.onDisplayed = this.afterDisplayed.bind(this); + + view.on("resized", this.counter.bind(this)); + + // this.q.enqueue(this.check); + return this.check(); +}; + +EPUBJS.Continuous.prototype.counter = function(bounds){ + + if(this.settings.axis === "vertical") { + this.scrollBy(0, bounds.heightDelta, true); + } else { + this.scrollBy(bounds.widthDelta, 0, true); + } + +}; + +EPUBJS.Continuous.prototype.fill = function(view){ + + if(this.views.length){ + this.clear(); + } + + this.views.push(view); + + this.container.appendChild(view.element); + + // view.on("shown", this.afterDisplayed.bind(this)); + view.onDisplayed = this.afterDisplayed.bind(this); + + return this.render(view) + .then(function(){ + return this.check(); + }.bind(this)); +}; + +EPUBJS.Continuous.prototype.insert = function(view, index) { + this.views.splice(index, 0, view); + + if(index < this.cotainer.children.length){ + this.container.insertBefore(view.element, this.container.children[index]); + } else { + this.container.appendChild(view.element); + } + + // this.q.enqueue(this.check); + return this.check(); +}; + +// // Remove the render element and clean up listeners +// EPUBJS.Continuous.prototype.remove = function(view) { +// var index = this.views.indexOf(view); +// if(index > -1) { +// this.views.splice(index, 1); +// } + +// this.container.removeChild(view.element); + +// view.off("resized"); + +// if(view.displayed){ +// view.destroy(); +// } + +// view = null; + +// }; + +EPUBJS.Continuous.prototype.first = function() { + return this.views[0]; +}; + +EPUBJS.Continuous.prototype.last = function() { + return this.views[this.views.length-1]; +}; + +EPUBJS.Continuous.prototype.each = function(func) { + return this.views.forEach(func); +}; + +EPUBJS.Continuous.prototype.check = function(_offset){ + var checking = new RSVP.defer(); + var container = this.bounds(); + var promises = []; + var offset = _offset || this.settings.offset; + + + this.views.forEach(function(view){ + var visible = this.isVisible(view, offset, offset, container); + + if(visible) { + + if(!view.displayed && !view.rendering) { + // console.log("render",view.section.index) + promises.push(this.render(view)); + } + + } else { + + if(view.displayed) { + // console.log("destroy", view.section.index) + this.q.enqueue(view.destroy.bind(view)); + // view.destroy(); + // this.q.enqueue(this.trim); + clearTimeout(this.trimTimeout); + this.trimTimeout = setTimeout(function(){ + this.q.enqueue(this.trim); + }.bind(this), 250); + } + + } + + }.bind(this)); + + + if(promises.length){ + + return RSVP.all(promises) + .then(function(posts) { + // Check to see if anything new is on screen after rendering + this.q.enqueue(this.check); + + }.bind(this)); + + } else { + checking.resolve(); + + return checking.promise; + } + +}; + +// EPUBJS.Continuous.prototype.trim = function(){ +// var task = new RSVP.defer(); +// var above = true; + +// this.views.forEach(function(view, i){ +// // var view = this.views[i]; +// var prevShown = i > 0 ? this.views[i-1].displayed : false; +// var nextShown = (i+1 < this.views.length) ? this.views[i+1].displayed : false; +// if(!view.displayed && !prevShown && !nextShown) { +// // Remove +// this.erase(view, above); +// } +// if(nextShown) { +// above = false; +// } +// }.bind(this)); + +// task.resolve(); +// return task.promise; +// }; + +EPUBJS.Continuous.prototype.trim = function(){ + var task = new RSVP.defer(); + var displayed = this.displayed(); + var first = displayed[0]; + var last = displayed[displayed.length-1]; + var firstIndex = this.views.indexOf(first); + var lastIndex = this.views.indexOf(last); + var above = this.views.slice(0, firstIndex); + var below = this.views.slice(lastIndex+1); + + // Erase all but last above + for (var i = 0; i < above.length-1; i++) { + this.erase(above[i], above); + } + + // Erase all except first below + for (var j = 1; j < below.length; j++) { + this.erase(below[j]); + } + + task.resolve(); + return task.promise; +}; + +EPUBJS.Continuous.prototype.erase = function(view, above){ //Trim + + var prevTop; + var prevLeft; + + if(this.settings.height) { + prevTop = this.container.scrollTop; + prevLeft = this.container.scrollLeft; + } else { + prevTop = window.scrollY; + prevLeft = window.scrollX; + } + + var bounds = view.bounds(); + + this.remove(view); + + if(above) { + + if(this.settings.axis === "vertical") { + this.scrollTo(0, prevTop - bounds.height, true); + } else { + this.scrollTo(prevLeft - bounds.width, 0, true); + } + } + +}; + + +EPUBJS.Continuous.prototype.checkCurrent = function(position) { + var view, top; + var container = this.container.getBoundingClientRect(); + var length = this.views.length - 1; + + if(this.rendering) { + return; + } + + if(this.settings.axis === "horizontal") { + // TODO: Check for current horizontal + } else { + + for (var i = length; i >= 0; i--) { + view = this.views[i]; + top = view.bounds().top; + if(top < container.bottom) { + + if(this.current == view.section) { + break; + } + + this.current = view.section; + this.trigger("current", this.current); + break; + } + } + + } + +}; + +EPUBJS.Continuous.prototype.start = function() { + var scroller; + + this.tick = EPUBJS.core.requestAnimationFrame; + + if(this.settings.height) { + this.prevScrollTop = this.container.scrollTop; + this.prevScrollLeft = this.container.scrollLeft; + } else { + this.prevScrollTop = window.scrollY; + this.prevScrollLeft = window.scrollX; + } + + this.scrollDeltaVert = 0; + this.scrollDeltaHorz = 0; + + if(this.settings.height) { + scroller = this.container; + } else { + scroller = window; + } + + window.addEventListener("scroll", function(e){ + if(!this.ignore) { + this.scrolled = true; + } else { + this.ignore = false; + } + }.bind(this)); + + window.addEventListener('unload', function(e){ + this.ignore = true; + this.destroy(); + }.bind(this)); + + this.tick.call(window, this.onScroll.bind(this)); + + this.scrolled = false; + +}; + +EPUBJS.Continuous.prototype.onScroll = function(){ + + if(this.scrolled) { + + if(this.settings.height) { + scrollTop = this.container.scrollTop; + scrollLeft = this.container.scrollLeft; + } else { + scrollTop = window.scrollY; + scrollLeft = window.scrollX; + } + + if(!this.ignore) { + + // this.trigger("scroll", { + // top: scrollTop, + // left: scrollLeft + // }); + + if((this.scrollDeltaVert === 0 && + this.scrollDeltaHorz === 0) || + this.scrollDeltaVert > this.settings.offsetDelta || + this.scrollDeltaHorz > this.settings.offsetDelta) { + + this.q.enqueue(this.check); + + this.scrollDeltaVert = 0; + this.scrollDeltaHorz = 0; + + } + + } else { + this.ignore = false; + } + + this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop); + this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft); + + if(this.settings.height) { + this.prevScrollTop = this.container.scrollTop; + this.prevScrollLeft = this.container.scrollLeft; + } else { + this.prevScrollTop = window.scrollY; + this.prevScrollLeft = window.scrollX; + } + + + clearTimeout(this.scrollTimeout); + this.scrollTimeout = setTimeout(function(){ + this.scrollDeltaVert = 0; + this.scrollDeltaHorz = 0; + }.bind(this), 150); + + + this.scrolled = false; + } + + this.tick.call(window, this.onScroll.bind(this)); + +}; + +EPUBJS.Continuous.prototype.scrollBy = function(x, y, silent){ + if(silent) { + this.ignore = true; + } + + if(this.settings.height) { + + if(x) this.container.scrollLeft += x; + if(y) this.container.scrollTop += y; + + } else { + window.scrollBy(x,y); + } + // console.log("scrollBy", x, y); + this.scrolled = true; +}; + +EPUBJS.Continuous.prototype.scrollTo = function(x, y, silent){ + if(silent) { + this.ignore = true; + } + + if(this.settings.height) { + this.container.scrollLeft = x; + this.container.scrollTop = y; + } else { + window.scrollTo(x,y); + } + // console.log("scrollTo", x, y); + this.scrolled = true; + // if(this.container.scrollLeft != x){ + // setTimeout(function() { + // this.scrollTo(x, y, silent); + // }.bind(this), 10); + // return; + // }; + }; + + EPUBJS.Continuous.prototype.resizeView = function(view) { + + if(this.settings.axis === "horizontal") { + view.lock("height", this.stage.width, this.stage.height); + } else { + view.lock("width", this.stage.width, this.stage.height); + } + +}; + +EPUBJS.Continuous.prototype.currentLocation = function(){ + var visible = this.visible(); + var startPage, endPage; + + var container = this.container.getBoundingClientRect(); + + if(visible.length === 1) { + return this.map.page(visible[0]); + } + + if(visible.length > 1) { + + startPage = this.map.page(visible[0]); + endPage = this.map.page(visible[visible.length-1]); + + return { + start: startPage.start, + end: endPage.end + }; + } + +}; + +/* +EPUBJS.Continuous.prototype.current = function(what){ + var view, top; + var container = this.container.getBoundingClientRect(); + var length = this.views.length - 1; + + if(this.settings.axis === "horizontal") { + + for (var i = length; i >= 0; i--) { + view = this.views[i]; + left = view.position().left; + + if(left < container.right) { + + if(this._current == view) { + break; + } + + this._current = view; + break; + } + } + + } else { + + for (var i = length; i >= 0; i--) { + view = this.views[i]; + top = view.bounds().top; + if(top < container.bottom) { + + if(this._current == view) { + break; + } + + this._current = view; + + break; + } + } + + } + + return this._current; +}; +*/ +EPUBJS.Paginate = function(book, options) { + + EPUBJS.Continuous.apply(this, arguments); + + this.settings = EPUBJS.core.extend(this.settings || {}, { + width: 600, + height: 400, + axis: "horizontal", + forceSingle: false, + minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always) + gap: "auto", //-- "auto" or int + overflow: "hidden", + infinite: false + }); + + EPUBJS.core.extend(this.settings, options); + + this.isForcedSingle = this.settings.forceSingle; + + this.viewSettings = { + axis: this.settings.axis + }; + + this.start(); +}; + +EPUBJS.Paginate.prototype = Object.create(EPUBJS.Continuous.prototype); +EPUBJS.Paginate.prototype.constructor = EPUBJS.Paginate; + + +EPUBJS.Paginate.prototype.determineSpreads = function(cutoff){ + if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) { + return 1; //-- Single Page + }else{ + return 2; //-- Double Page + } +}; + +EPUBJS.Paginate.prototype.forceSingle = function(bool){ + if(bool === false) { + this.isForcedSingle = false; + // this.spreads = false; + } else { + this.isForcedSingle = true; + // this.spreads = this.determineSpreads(this.minSpreadWidth); + } + this.applyLayoutMethod(); +}; + +/** +* Uses the settings to determine which Layout Method is needed +* Triggers events based on the method choosen +* Takes: Layout settings object +* Returns: String of appropriate for EPUBJS.Layout function +*/ +// EPUBJS.Paginate.prototype.determineLayout = function(settings){ +// // Default is layout: reflowable & spread: auto +// var spreads = this.determineSpreads(this.settings.minSpreadWidth); +// console.log("spreads", spreads, this.settings.minSpreadWidth) +// var layoutMethod = spreads ? "ReflowableSpreads" : "Reflowable"; +// var scroll = false; +// +// if(settings.layout === "pre-paginated") { +// layoutMethod = "Fixed"; +// scroll = true; +// spreads = false; +// } +// +// if(settings.layout === "reflowable" && settings.spread === "none") { +// layoutMethod = "Reflowable"; +// scroll = false; +// spreads = false; +// } +// +// if(settings.layout === "reflowable" && settings.spread === "both") { +// layoutMethod = "ReflowableSpreads"; +// scroll = false; +// spreads = true; +// } +// +// this.spreads = spreads; +// +// return layoutMethod; +// }; + +EPUBJS.Paginate.prototype.start = function(){ + // On display + // this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties); + // this.layoutMethod = this.determineLayout(this.layoutSettings); + // this.layout = new EPUBJS.Layout[this.layoutMethod](); + //this.hooks.display.register(this.registerLayoutMethod.bind(this)); + // this.hooks.display.register(this.reportLocation); + this.on('displayed', this.reportLocation.bind(this)); + + this.hooks.content.register(this.adjustImages.bind(this)); + + this.currentPage = 0; + + window.addEventListener('unload', function(e){ + this.ignore = true; + this.destroy(); + }.bind(this)); + +}; + +// EPUBJS.Rendition.prototype.createView = function(section) { +// var view = new EPUBJS.View(section, this.viewSettings); + + +// return view; +// }; + +EPUBJS.Paginate.prototype.applyLayoutMethod = function() { + //var task = new RSVP.defer(); + + // this.spreads = this.determineSpreads(this.settings.minSpreadWidth); + + this.layout = new EPUBJS.Layout.Reflowable(); + + this.updateLayout(); + + // Set the look ahead offset for what is visible + + this.map = new EPUBJS.Map(this.layout); + + // this.hooks.layout.register(this.layout.format.bind(this)); + + //task.resolve(); + //return task.promise; + // return layout; +}; + +EPUBJS.Paginate.prototype.updateLayout = function() { + + this.spreads = this.determineSpreads(this.settings.minSpreadWidth); + + this.layout.calculate( + this.stage.width, + this.stage.height, + this.settings.gap, + this.spreads + ); + + this.settings.offset = this.layout.delta; + +}; + +EPUBJS.Paginate.prototype.moveTo = function(offset){ + var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta; + return this.check(0, dist+this.settings.offset).then(function(){ + this.scrollBy(dist, 0); + }.bind(this)); +}; + +EPUBJS.Paginate.prototype.page = function(pg){ + + // this.currentPage = pg; + // this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0); + //-- Return false if page is greater than the total + // return false; +}; + +EPUBJS.Paginate.prototype.next = function(){ + + return this.q.enqueue(function(){ + this.scrollBy(this.layout.delta, 0); + this.reportLocation(); + return this.check(); + }); + + // return this.page(this.currentPage + 1); +}; + +EPUBJS.Paginate.prototype.prev = function(){ + + return this.q.enqueue(function(){ + this.scrollBy(-this.layout.delta, 0); + this.reportLocation(); + return this.check(); + }); + // return this.page(this.currentPage - 1); +}; + +EPUBJS.Paginate.prototype.reportLocation = function(){ + return this.q.enqueue(function(){ + this.location = this.currentLocation(); + this.trigger("locationChanged", this.location); + }.bind(this)); +}; + +EPUBJS.Paginate.prototype.currentLocation = function(){ + var visible = this.visible(); + var startA, startB, endA, endB; + var pageLeft, pageRight; + var container = this.container.getBoundingClientRect(); + + if(visible.length === 1) { + startA = container.left - visible[0].position().left; + endA = startA + this.layout.spread; + + return this.map.page(visible[0], startA, endA); + } + + if(visible.length > 1) { + + // Left Col + startA = container.left - visible[0].position().left; + endA = startA + this.layout.column; + + // Right Col + startB = container.left + this.layout.spread - visible[visible.length-1].position().left; + endB = startB + this.layout.column; + + pageLeft = this.map.page(visible[0], startA, endA); + pageRight = this.map.page(visible[visible.length-1], startB, endB); + + return { + start: pageLeft.start, + end: pageRight.end + }; + } + +}; + +EPUBJS.Paginate.prototype.resize = function(width, height){ + // Clear the queue + this.q.clear(); + + this.stageSize(width, height); + + this.updateLayout(); + + this.display(this.location.start); + + this.trigger("resized", { + width: this.stage.width, + height: this.stage.height + }); + +}; + +EPUBJS.Paginate.prototype.onResized = function(e) { + + this.clear(); + + clearTimeout(this.resizeTimeout); + this.resizeTimeout = setTimeout(function(){ + this.resize(); + }.bind(this), 150); +}; + +EPUBJS.Paginate.prototype.adjustImages = function(view) { + + view.addStylesheetRules([ + ["img", + ["max-width", (this.layout.spread) + "px"], + ["max-height", (this.layout.height) + "px"] + ] + ]); + return new RSVP.Promise(function(resolve, reject){ + // Wait to apply + setTimeout(function() { + resolve(); + }, 1); + }); +}; + +// EPUBJS.Paginate.prototype.display = function(what){ +// return this.display(what); +// }; +EPUBJS.Map = function(layout){ + this.layout = layout; +}; + +EPUBJS.Map.prototype.section = function(view) { + var ranges = this.findRanges(view); + var map = this.rangeListToCfiList(view, ranges); + + return map; +}; + +EPUBJS.Map.prototype.page = function(view, start, end) { + var root = view.document.body; + return this.rangePairToCfiPair(view.section, { + start: this.findStart(root, start, end), + end: this.findEnd(root, start, end) + }); +}; + +EPUBJS.Map.prototype.walk = function(root, func) { + //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false); + var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { + acceptNode: function (node) { + if ( node.data.trim().length > 0 ) { + return NodeFilter.FILTER_ACCEPT; + } else { + return NodeFilter.FILTER_REJECT; + } + } + }, false); + var node; + var result; + while ((node = treeWalker.nextNode())) { + result = func(node); + if(result) break; + } + + return result; +}; + +EPUBJS.Map.prototype.findRanges = function(view){ + var columns = []; + var count = this.layout.count(view); + var column = this.layout.column; + var gap = this.layout.gap; + var start, end; + + for (var i = 0; i < count.pages; i++) { + start = (column + gap) * i; + end = (column * (i+1)) + (gap * i); + columns.push({ + start: this.findStart(view.document.body, start, end), + end: this.findEnd(view.document.body, start, end) + }); + } + + return columns; +}; + +EPUBJS.Map.prototype.findStart = function(root, start, end){ + var stack = [root]; + var $el; + var found; + var $prev = root; + while (stack.length) { + + $el = stack.shift(); + + found = this.walk($el, function(node){ + var left, right; + var elPos; + var elRange; + + + if(node.nodeType == Node.TEXT_NODE){ + elRange = document.createRange(); + elRange.selectNodeContents(node); + elPos = elRange.getBoundingClientRect(); + } else { + elPos = node.getBoundingClientRect(); + } + + left = elPos.left; + right = elPos.right; + + if( left >= start && left <= end ) { + return node; + } else if (right > start) { + return node; + } else { + $prev = node; + stack.push(node); + } + + }); + + if(found) { + return this.findTextStartRange(found, start, end); + } + + } + + // Return last element + return this.findTextStartRange($prev, start, end); +}; + +EPUBJS.Map.prototype.findEnd = function(root, start, end){ + var stack = [root]; + var $el; + var $prev = root; + var found; + + while (stack.length) { + + $el = stack.shift(); + + found = this.walk($el, function(node){ + + var left, right; + var elPos; + var elRange; + + + if(node.nodeType == Node.TEXT_NODE){ + elRange = document.createRange(); + elRange.selectNodeContents(node); + elPos = elRange.getBoundingClientRect(); + } else { + elPos = node.getBoundingClientRect(); + } + + left = elPos.left; + right = elPos.right; + + if(left > end && $prev) { + return $prev; + } else if(right > end) { + return node; + } else { + $prev = node; + stack.push(node); + } + + }); + + + if(found){ + return this.findTextEndRange(found, start, end); + } + + } + + // end of chapter + return this.findTextEndRange($prev, start, end); +}; + + +EPUBJS.Map.prototype.findTextStartRange = function(node, start, end){ + var ranges = this.splitTextNodeIntoRanges(node); + var prev; + var range; + var pos; + + for (var i = 0; i < ranges.length; i++) { + range = ranges[i]; + + pos = range.getBoundingClientRect(); + + if( pos.left >= start ) { + return range; + } + + prev = range; + + } + + return ranges[0]; +}; + +EPUBJS.Map.prototype.findTextEndRange = function(node, start, end){ + var ranges = this.splitTextNodeIntoRanges(node); + var prev; + var range; + var pos; + + for (var i = 0; i < ranges.length; i++) { + range = ranges[i]; + + pos = range.getBoundingClientRect(); + + if(pos.left > end && prev) { + return prev; + } else if(pos.right > end) { + return range; + } + + prev = range; + + } + + // Ends before limit + return ranges[ranges.length-1]; + +}; + +EPUBJS.Map.prototype.splitTextNodeIntoRanges = function(node, _splitter){ + var ranges = []; + var textContent = node.textContent || ""; + var text = textContent.trim(); + var range; + var rect; + var list; + var doc = node.ownerDocument; + var splitter = _splitter || " "; + + pos = text.indexOf(splitter); + + if(pos === -1 || node.nodeType != Node.TEXT_NODE) { + range = doc.createRange(); + range.selectNodeContents(node); + return [range]; + } + + range = doc.createRange(); + range.setStart(node, 0); + range.setEnd(node, pos); + ranges.push(range); + range = false; + + while ( pos != -1 ) { + + pos = text.indexOf(splitter, pos + 1); + if(pos > 0) { + + if(range) { + range.setEnd(node, pos); + ranges.push(range); + } + + range = doc.createRange(); + range.setStart(node, pos+1); + } + } + + if(range) { + range.setEnd(node, text.length); + ranges.push(range); + } + + return ranges; +}; + + + +EPUBJS.Map.prototype.rangePairToCfiPair = function(section, rangePair){ + + var startRange = rangePair.start; + var endRange = rangePair.end; + + startRange.collapse(true); + endRange.collapse(true); + + startCfi = section.cfiFromRange(startRange); + endCfi = section.cfiFromRange(endRange); + + return { + start: startCfi, + end: endCfi + }; + +}; + +EPUBJS.Map.prototype.rangeListToCfiList = function(view, columns){ + var map = []; + var rangePair, cifPair; + + for (var i = 0; i < columns.length; i++) { + cifPair = this.rangePairToCfiPair(view.section, columns[i]); + + map.push(cifPair); + + } + + return map; +}; \ No newline at end of file diff --git a/dist/epub.min.js b/dist/epub.min.js index 3eeea89..57a4833 100644 --- a/dist/epub.min.js +++ b/dist/epub.min.js @@ -1,3 +1,3 @@ -EPUBJS.Book=function(t){this.opening=new RSVP.defer,this.opened=this.opening.promise,this.isOpen=!1,this.url=void 0,this.spine=new EPUBJS.Spine(this.request),this.loading={manifest:new RSVP.defer,spine:new RSVP.defer,metadata:new RSVP.defer,cover:new RSVP.defer,navigation:new RSVP.defer,pageList:new RSVP.defer},this.loaded={manifest:this.loading.manifest.promise,spine:this.loading.spine.promise,metadata:this.loading.metadata.promise,cover:this.loading.cover.promise,navigation:this.loading.navigation.promise,pageList:this.loading.pageList.promise},this.ready=RSVP.hash(this.loaded),this.isRendered=!1,this._q=EPUBJS.core.queue(this),this.request=this.requestMethod.bind(this),t&&this.open(t)},EPUBJS.Book.prototype.open=function(t){var e,i,n,r=new EPUBJS.Parser,o=this,s="META-INF/container.xml";return t?(e="object"==typeof t?t:EPUBJS.core.uri(t),"opf"===e.extension?(this.packageUrl=e.href,this.containerUrl="",e.origin?this.url=e.base:window?(n=EPUBJS.core.uri(window.location.href),this.url=EPUBJS.core.resolveUrl(n.base,e.directory)):this.url=e.directory,i=this.request(this.packageUrl)):"epub"===e.extension||"zip"===e.extension?(this.archived=!0,this.url=""):e.extension||(this.containerUrl=t+s,i=this.request(this.containerUrl).then(function(t){return r.container(t)}).then(function(e){var i=EPUBJS.core.uri(e.packagePath);return o.packageUrl=t+e.packagePath,o.encoding=e.encoding,i.origin?o.url=i.base:window?(n=EPUBJS.core.uri(window.location.href),o.url=EPUBJS.core.resolveUrl(n.base,t+i.directory)):o.url=i.directory,o.request(o.packageUrl)}).catch(function(t){console.error("Could not load book at: "+(this.packageUrl||this.containerPath)),o.trigger("book:loadFailed",this.packageUrl||this.containerPath),o.opening.reject(t)})),i.then(function(t){o.unpack(t),o.loading.manifest.resolve(o.package.manifest),o.loading.metadata.resolve(o.package.metadata),o.loading.spine.resolve(o.spine),o.loading.cover.resolve(o.cover),this.isOpen=!0,o.opening.resolve(o)}).catch(function(t){console.error(t.message,t.stack),o.opening.reject(t)}),this.opened):(this.opening.resolve(this),this.opened)},EPUBJS.Book.prototype.unpack=function(t){var e=this,i=new EPUBJS.Parser;e.package=i.packageContents(t),e.package.baseUrl=e.url,this.spine.load(e.package),e.navigation=new EPUBJS.Navigation(e.package,this.request),e.navigation.load().then(function(t){e.toc=t,e.loading.navigation.resolve(e.toc)}),e.cover=e.url+e.package.coverPath},EPUBJS.Book.prototype.section=function(t){return this.spine.get(t)},EPUBJS.Book.prototype.renderTo=function(t,e){var i=e&&e.method?e.method.charAt(0).toUpperCase()+e.method.substr(1):"Rendition";return this.rendition=new EPUBJS[i](this,e),this.rendition.attachTo(t),this.rendition},EPUBJS.Book.prototype.requestMethod=function(t){return this.archived?void 0:EPUBJS.core.request(t,"xml",this.requestCredentials,this.requestHeaders)},EPUBJS.Book.prototype.setRequestCredentials=function(t){this.requestCredentials=t},EPUBJS.Book.prototype.setRequestHeaders=function(t){this.requestHeaders=t},RSVP.EventTarget.mixin(EPUBJS.Book.prototype),RSVP.on("error",function(){}),RSVP.configure("instrument",!0),RSVP.on("rejected",function(t){console.error(t.detail.message,t.detail.stack)}),EPUBJS.Continuous=function(t,e){EPUBJS.Rendition.apply(this,arguments),this.settings=EPUBJS.core.extend(this.settings||{},{infinite:!0,overflow:"auto",axis:"vertical",offset:500,offsetDelta:250}),EPUBJS.core.extend(this.settings,e),this.settings.hidden&&(this.wrapper=this.wrap(this.container))},EPUBJS.Continuous.prototype=Object.create(EPUBJS.Rendition.prototype),EPUBJS.Continuous.prototype.constructor=EPUBJS.Continuous,EPUBJS.Continuous.prototype.attachListeners=function(){EPUBJS.core.isNumber(this.settings.width)&&EPUBJS.core.isNumber(this.settings.height)||window.addEventListener("resize",this.onResized.bind(this),!1),this.settings.infinite&&this.start()},EPUBJS.Continuous.prototype._display=function(t){var e,i,n,r,o=new RSVP.defer,s=o.promise;return this.epubcfi.isCfiString(t)?(n=this.epubcfi.parse(t),r=n.spinePos,e=this.book.spine.get(r)):e=this.book.spine.get(t),this.displaying=!0,this.hide(),e?(i=new EPUBJS.View(e,this.viewSettings),this.q.enqueue(this.fill,i).then(function(){this.q.enqueue(function(){var e=i.locationOf(t);return this.moveTo(e)}),this.q.enqueue(this.check),this.q.enqueue(this.show),this.hooks.display.trigger(i).then(function(){this.trigger("displayed",e),o.resolve(this)}.bind(this))}.bind(this)),o.resolve(this)):o.reject(new Error("No Section Found")),s},EPUBJS.Continuous.prototype.moveTo=function(t){var e=this.bounds(),i=Math.floor(t.top/e.height)*e.height;return this.check(0,i+this.settings.offset).then(function(){"vertical"===this.settings.axis?this.scrollBy(0,i):this.scrollBy(i,0)}.bind(this))},EPUBJS.Continuous.prototype.afterDisplayed=function(t){var e,i,n=t.section.next(),r=t.section.prev(),o=this.views.indexOf(t);o+1===this.views.length&&n&&(i=new EPUBJS.View(n,this.viewSettings),this.q.enqueue(this.append,i)),0===o&&r&&(e=new EPUBJS.View(r,this.viewSettings),this.q.enqueue(this.prepend,e)),this.trigger("added",t.section)},EPUBJS.Continuous.prototype.removeShownListeners=function(t){t.onDisplayed=function(){}},EPUBJS.Continuous.prototype.append=function(t){return this.views.push(t),this.container.appendChild(t.element),t.onDisplayed=this.afterDisplayed.bind(this),this.check()},EPUBJS.Continuous.prototype.prepend=function(t){return this.views.unshift(t),this.container.insertBefore(t.element,this.container.firstChild),t.onDisplayed=this.afterDisplayed.bind(this),t.on("resized",this.counter.bind(this)),this.check()},EPUBJS.Continuous.prototype.counter=function(t){"vertical"===this.settings.axis?this.scrollBy(0,t.heightDelta,!0):this.scrollBy(t.widthDelta,0,!0)},EPUBJS.Continuous.prototype.fill=function(t){return this.views.length&&this.clear(),this.views.push(t),this.container.appendChild(t.element),t.onDisplayed=this.afterDisplayed.bind(this),this.render(t).then(function(){return this.check()}.bind(this))},EPUBJS.Continuous.prototype.insert=function(t,e){return this.views.splice(e,0,t),e=0;r--)if(t=this.views[r],e=t.bounds().top,ethis.settings.offsetDelta||this.scrollDeltaHorz>this.settings.offsetDelta)&&(this.q.enqueue(this.check),this.scrollDeltaVert=0,this.scrollDeltaHorz=0),this.scrollDeltaVert+=Math.abs(scrollTop-this.prevScrollTop),this.scrollDeltaHorz+=Math.abs(scrollLeft-this.prevScrollLeft),this.settings.height?(this.prevScrollTop=this.container.scrollTop,this.prevScrollLeft=this.container.scrollLeft):(this.prevScrollTop=window.scrollY,this.prevScrollLeft=window.scrollX),clearTimeout(this.scrollTimeout),this.scrollTimeout=setTimeout(function(){this.scrollDeltaVert=0,this.scrollDeltaHorz=0}.bind(this),150),this.scrolled=!1),this.tick.call(window,this.onScroll.bind(this))},EPUBJS.Continuous.prototype.scrollBy=function(t,e,i){i&&(this.ignore=!0),this.settings.height?(t&&(this.container.scrollLeft+=t),e&&(this.container.scrollTop+=e)):window.scrollBy(t,e),this.scrolled=!0},EPUBJS.Continuous.prototype.scrollTo=function(t,e,i){i&&(this.ignore=!0),this.settings.height?(this.container.scrollLeft=t,this.container.scrollTop=e):window.scrollTo(t,e),this.scrolled=!0},EPUBJS.Continuous.prototype.resizeView=function(t){"horizontal"===this.settings.axis?t.lock("height",this.stage.width,this.stage.height):t.lock("width",this.stage.width,this.stage.height)},EPUBJS.Continuous.prototype.currentLocation=function(){{var t,e,i=this.visible();this.container.getBoundingClientRect()}return 1===i.length?this.map.page(i[0]):i.length>1?(t=this.map.page(i[0]),e=this.map.page(i[i.length-1]),{start:t.start,end:e.end}):void 0},EPUBJS.core={},EPUBJS.core.request=function(t,e,i,n){function r(){if(this.readyState===this.DONE)if(200===this.status||this.responseXML){var t;t="xml"==e?this.responseXML?this.responseXML:(new DOMParser).parseFromString(this.response,"text/xml"):"json"==e?JSON.parse(this.response):"blob"==e?s?this.response:new Blob([this.response]):this.response,a.resolve(t)}else a.reject({status:this.status,message:this.response,stack:(new Error).stack})}var o,s=window.URL,h=s?"blob":"arraybuffer",a=new RSVP.defer,u=new XMLHttpRequest,c=XMLHttpRequest.prototype;"overrideMimeType"in c||Object.defineProperty(c,"overrideMimeType",{value:function(){}}),i&&(u.withCredentials=!0),u.open("GET",t,!0);for(o in n)u.setRequestHeader(o,n[o]);return u.onreadystatechange=r,"blob"==e&&(u.responseType=h),"json"==e&&u.setRequestHeader("Accept","application/json"),"xml"==e&&u.overrideMimeType("text/xml"),u.send(),a.promise},EPUBJS.core.uri=function(t){var e,i,n,r={protocol:"",host:"",path:"",origin:"",directory:"",base:"",filename:"",extension:"",fragment:"",href:t},o=t.indexOf("://"),s=t.indexOf("?"),h=t.indexOf("#");return-1!=h&&(r.fragment=t.slice(h+1),t=t.slice(0,h)),-1!=s&&(r.search=t.slice(s+1),t=t.slice(0,s),href=t),-1!=o?(r.protocol=t.slice(0,o),e=t.slice(o+3),n=e.indexOf("/"),-1===n?(r.host=r.path,r.path=""):(r.host=e.slice(0,n),r.path=e.slice(n)),r.origin=r.protocol+"://"+r.host,r.directory=EPUBJS.core.folder(r.path),r.base=r.origin+r.directory):(r.path=t,r.directory=EPUBJS.core.folder(t),r.base=r.directory),r.filename=t.replace(r.base,""),i=r.filename.lastIndexOf("."),-1!=i&&(r.extension=r.filename.slice(i+1)),r},EPUBJS.core.folder=function(t){var e=t.lastIndexOf("/");if(-1==e)var i="";return i=t.slice(0,e+1)},EPUBJS.core.queue=function(t){var e=[],i=t,n=function(t,i,n){return e.push({funcName:t,args:i,context:n}),e},r=function(){var t;e.length&&(t=e.shift(),i[t.funcName].apply(t.context||i,t.args))},o=function(){for(;e.length;)r()},s=function(){e=[]},h=function(){return e.length};return{enqueue:n,dequeue:r,flush:o,clear:s,length:h}},EPUBJS.core.isElement=function(t){return!(!t||1!=t.nodeType)},EPUBJS.core.uuid=function(){var t=(new Date).getTime(),e="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?i:7&i|8).toString(16)});return e},EPUBJS.core.values=function(t){for(var e=-1,i=Object.keys(t),n=i.length,r=Array(n);++er;r++)if("undefined"!=typeof document.body.style[e[r]+i])return e[r]+i;return t},EPUBJS.core.defaults=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var r in n)void 0===t[r]&&(t[r]=n[r])}return t},EPUBJS.core.extend=function(t){var e=[].slice.call(arguments,1);return e.forEach(function(e){e&&Object.getOwnPropertyNames(e).forEach(function(i){Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))})}),t},EPUBJS.core.insert=function(t,e,i){var n=EPUBJS.core.locationOf(t,e,i);return e.splice(n,0,t),n},EPUBJS.core.locationOf=function(t,e,i,n,r){var o,s=n||0,h=r||e.length,a=parseInt(s+(h-s)/2);return i||(i=function(t,e){return t>e?1:e>t?-1:(t=e)?0:void 0}),0>=h-s?a:(o=i(e[a],t),h-s===1?o>0?a:a+1:0===o?a:-1===o?EPUBJS.core.locationOf(t,e,i,a,h):EPUBJS.core.locationOf(t,e,i,s,a))},EPUBJS.core.indexOfSorted=function(t,e,i,n,r){var o,s=n||0,h=r||e.length,a=parseInt(s+(h-s)/2);return i||(i=function(t,e){return t>e?1:e>t?-1:(t=e)?0:void 0}),0>=h-s?-1:(o=i(e[a],t),h-s===1?0===o?a:-1:0===o?a:-1===o?EPUBJS.core.indexOfSorted(t,e,i,a,h):EPUBJS.core.indexOfSorted(t,e,i,s,a))},EPUBJS.core.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,EPUBJS.core.bounds=function(t){var e=window.getComputedStyle(t),i=["width","paddingRight","paddingLeft","marginRight","marginLeft","borderRightWidth","borderLeftWidth"],n=["height","paddingTop","paddingBottom","marginTop","marginBottom","borderTopWidth","borderBottomWidth"],r=0,o=0;return i.forEach(function(t){r+=parseFloat(e[t])||0}),n.forEach(function(t){o+=parseFloat(e[t])||0}),{height:o,width:r}},EPUBJS.core.borders=function(t){var e=window.getComputedStyle(t),i=["paddingRight","paddingLeft","marginRight","marginLeft","borderRightWidth","borderLeftWidth"],n=["paddingTop","paddingBottom","marginTop","marginBottom","borderTopWidth","borderBottomWidth"],r=0,o=0;return i.forEach(function(t){r+=parseFloat(e[t])||0}),n.forEach(function(t){o+=parseFloat(e[t])||0}),{height:o,width:r}},EPUBJS.core.windowBounds=function(){var t=window.innerWidth,e=window.innerHeight;return{top:0,left:0,right:t,bottom:e,width:t,height:e}},EPUBJS.core.cleanStringForXpath=function(t){var e=t.match(/[^'"]+|['"]/g);return e=e.map(function(t){return"'"===t?'"\'"':'"'===t?"'\"'":"'"+t+"'"}),"concat('',"+e.join(",")+")"},EPUBJS.core.indexOfTextNode=function(t){for(var e,i=t.parentNode,n=i.childNodes,r=-1,o=0;o0;){if(i=n.shift(),"text"===i.type?(r=s.childNodes[i.index],s=r.parentNode||s):s=i.id?o.getElementById(i.id):h[i.index],"undefined"==typeof s)return console.error("No Element For",i,t.str),!1;h=Array.prototype.slice.call(s.children)}return s},EPUBJS.EpubCFI.prototype.compare=function(t,e){if("string"==typeof t&&(t=new EPUBJS.EpubCFI(t)),"string"==typeof e&&(e=new EPUBJS.EpubCFI(e)),t.spinePos>e.spinePos)return 1;if(t.spinePose.steps[i].index)return 1;if(t.steps[i].indexe.characterOffset?1:t.characterOffset=0?(o=r.length,t.characterOffset=0?i:c%2===0?c:c-1;r=h>1?Math.floor((u-p)/h):u,o=r*h,s=(r+p)*h,this.columnAxis=EPUBJS.core.prefixed("columnAxis"),this.columnGap=EPUBJS.core.prefixed("columnGap"),this.columnWidth=EPUBJS.core.prefixed("columnWidth"),this.columnFill=EPUBJS.core.prefixed("columnFill"),this.width=u,this.height=e,this.spread=o,this.delta=s,this.column=r,this.gap=p,this.divisor=h},EPUBJS.Layout.Reflowable.prototype.format=function(t){var e=t.document.documentElement,i=t.document.body;e.style.overflow="hidden",e.style.width=this.width+"px",i.style.height=this.height+"px",i.style[this.columnAxis]="horizontal",i.style[this.columnFill]="auto",i.style[this.columnGap]=this.gap+"px",i.style[this.columnWidth]=this.column+"px",t.iframe.style.marginRight=this.gap+"px"},EPUBJS.Layout.Reflowable.prototype.count=function(t){var e=t.root().scrollWidth,i=Math.ceil(e/this.spread);return{spreads:i,pages:i*this.divisor}},EPUBJS.Layout.Fixed=function(){},EPUBJS.Layout.Fixed.prototype.calculate=function(){},EPUBJS.Layout.Fixed.prototype.format=function(t){var e,i,n=t.document.documentElement,r=documentElement.querySelector("[name=viewport");r&&r.hasAttribute("content")&&(content=r.getAttribute("content"),contents=content.split(","),contents[0]&&(e=contents[0].replace("width=","")),contents[1]&&(i=contents[1].replace("height=",""))),t.resize(e,i),n.style.overflow="auto"},EPUBJS.Layout.Fixed.prototype.count=function(){return{spreads:1,pages:1}},EPUBJS.Layout.Scroll=function(){},EPUBJS.Layout.Scroll.prototype.calculate=function(t){this.spread=t,this.column=t,this.gap=0},EPUBJS.Layout.Scroll.prototype.format=function(t){var e=t.document.documentElement;e.style.width="auto",e.style.height="auto"},EPUBJS.Layout.Scroll.prototype.count=function(){return{spreads:1,pages:1}},EPUBJS.Map=function(t){this.layout=t},EPUBJS.Map.prototype.section=function(t){var e=this.findRanges(t),i=this.rangeListToCfiList(t,e);return i},EPUBJS.Map.prototype.page=function(t,e,i){var n=t.document.body;return this.rangePairToCfiPair(t.section,{start:this.findStart(n,e,i),end:this.findEnd(n,e,i)})},EPUBJS.Map.prototype.walk=function(t,e){for(var i,n,r=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,{acceptNode:function(t){return t.data.trim().length>0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}},!1);(i=r.nextNode())&&!(n=e(i)););return n},EPUBJS.Map.prototype.findRanges=function(t){for(var e,i,n=[],r=this.layout.count(t),o=this.layout.column,s=this.layout.gap,h=0;h=e&&i>=n?t:r>e?t:(s=t,o.push(t),void 0)}))return this.findTextStartRange(r,e,i);return this.findTextStartRange(s,e,i)},EPUBJS.Map.prototype.findEnd=function(t,e,i){for(var n,r,o=[t],s=t;o.length;)if(n=o.shift(),r=this.walk(n,function(t){var e,n,r,h;return t.nodeType==Node.TEXT_NODE?(h=document.createRange(),h.selectNodeContents(t),r=h.getBoundingClientRect()):r=t.getBoundingClientRect(),e=r.left,n=r.right,e>i&&s?s:n>i?t:(s=t,o.push(t),void 0)}))return this.findTextEndRange(r,e,i);return this.findTextEndRange(s,e,i)},EPUBJS.Map.prototype.findTextStartRange=function(t,e){for(var i,n,r,o=this.splitTextNodeIntoRanges(t),s=0;s=e)return n;i=n}return o[0]},EPUBJS.Map.prototype.findTextEndRange=function(t,e,i){for(var n,r,o,s=this.splitTextNodeIntoRanges(t),h=0;hi&&n)return n;if(o.right>i)return r;n=r}return s[s.length-1]},EPUBJS.Map.prototype.splitTextNodeIntoRanges=function(t,e){var i,n=[],r=t.textContent||"",o=r.trim(),s=t.ownerDocument,h=e||" ";if(pos=o.indexOf(h),-1===pos||t.nodeType!=Node.TEXT_NODE)return i=s.createRange(),i.selectNodeContents(t),[i];for(i=s.createRange(),i.setStart(t,0),i.setEnd(t,pos),n.push(i),i=!1;-1!=pos;)pos=o.indexOf(h,pos+1),pos>0&&(i&&(i.setEnd(t,pos),n.push(i)),i=s.createRange(),i.setStart(t,pos+1));return i&&(i.setEnd(t,o.length),n.push(i)),n},EPUBJS.Map.prototype.rangePairToCfiPair=function(t,e){var i=e.start,n=e.end;return i.collapse(!0),n.collapse(!0),startCfi=t.cfiFromRange(i),endCfi=t.cfiFromRange(n),{start:startCfi,end:endCfi}},EPUBJS.Map.prototype.rangeListToCfiList=function(t,e){for(var i,n=[],r=0;r1?(t=h.left-s[0].position().left,i=t+this.layout.column,e=h.left+this.layout.spread-s[s.length-1].position().left,n=e+this.layout.column,r=this.map.page(s[0],t,i),o=this.map.page(s[s.length-1],e,n),{start:r.start,end:o.end}):void 0},EPUBJS.Paginate.prototype.resize=function(t,e){this.q.clear(),this.stageSize(t,e),this.updateLayout(),this.display(this.location.start),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},EPUBJS.Paginate.prototype.onResized=function(){this.clear(),clearTimeout(this.resizeTimeout),this.resizeTimeout=setTimeout(function(){this.resize() -}.bind(this),150)},EPUBJS.Paginate.prototype.adjustImages=function(t){return t.addStylesheetRules([["img",["max-width",this.layout.spread+"px"],["max-height",this.layout.height+"px"]]]),new RSVP.Promise(function(t){setTimeout(function(){t()},1)})},EPUBJS.Parser=function(){},EPUBJS.Parser.prototype.container=function(t){var e,i,n,r;return t?(e=t.querySelector("rootfile"))?(i=e.getAttribute("full-path"),n=EPUBJS.core.uri(i).directory,r=t.xmlEncoding,{packagePath:i,basePath:n,encoding:r}):(console.error("No RootFile Found"),void 0):(console.error("Container File Not Found"),void 0)},EPUBJS.Parser.prototype.identifier=function(t){var e;return t?(e=t.querySelector("metadata"),e?this.getElementText(e,"identifier"):(console.error("No Metadata Found"),void 0)):(console.error("Package File Not Found"),void 0)},EPUBJS.Parser.prototype.packageContents=function(t){var e,i,n,r,o,s,h,a,u,c=this;return t?(e=t.querySelector("metadata"))?(i=t.querySelector("manifest"))?(n=t.querySelector("spine"))?(r=c.manifest(i),o=c.findNavPath(i),s=c.findNcxPath(i),h=c.findCoverPath(i),a=Array.prototype.indexOf.call(n.parentNode.childNodes,n),u=c.spine(n,r),{metadata:c.metadata(e),spine:u,manifest:r,navPath:o,ncxPath:s,coverPath:h,spineNodeIndex:a}):(console.error("No Spine Found"),void 0):(console.error("No Manifest Found"),void 0):(console.error("No Metadata Found"),void 0):(console.error("Package File Not Found"),void 0)},EPUBJS.Parser.prototype.findNavPath=function(t){var e=t.querySelector("item[properties^='nav']");return e?e.getAttribute("href"):!1},EPUBJS.Parser.prototype.findNcxPath=function(t){var e=t.querySelector("item[media-type='application/x-dtbncx+xml']");return e?e.getAttribute("href"):!1},EPUBJS.Parser.prototype.findCoverPath=function(t){var e=t.querySelector("item[properties='cover-image']");return e?e.getAttribute("href"):!1},EPUBJS.Parser.prototype.metadata=function(t){var e={},i=this;return e.title=i.getElementText(t,"title"),e.creator=i.getElementText(t,"creator"),e.description=i.getElementText(t,"description"),e.pubdate=i.getElementText(t,"date"),e.publisher=i.getElementText(t,"publisher"),e.identifier=i.getElementText(t,"identifier"),e.language=i.getElementText(t,"language"),e.rights=i.getElementText(t,"rights"),e.modified_date=i.querySelectorText(t,"meta[property='dcterms:modified']"),e.layout=i.querySelectorText(t,"meta[property='rendition:layout']"),e.orientation=i.querySelectorText(t,"meta[property='rendition:orientation']"),e.spread=i.querySelectorText(t,"meta[property='rendition:spread']"),e},EPUBJS.Parser.prototype.getElementText=function(t,e){var i,n=t.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/",e);return n&&0!==n.length?(i=n[0],i.childNodes.length?i.childNodes[0].nodeValue:""):""},EPUBJS.Parser.prototype.querySelectorText=function(t,e){var i=t.querySelector(e);return i&&i.childNodes.length?i.childNodes[0].nodeValue:""},EPUBJS.Parser.prototype.manifest=function(t){var e={},i=t.querySelectorAll("item"),n=Array.prototype.slice.call(i);return n.forEach(function(t){var i=t.getAttribute("id"),n=t.getAttribute("href")||"",r=t.getAttribute("media-type")||"",o=t.getAttribute("properties")||"";e[i]={href:n,type:r,properties:o.length?o.split(" "):[]}}),e},EPUBJS.Parser.prototype.spine=function(t){{var e=[],i=t.getElementsByTagName("itemref"),n=Array.prototype.slice.call(i);new EPUBJS.EpubCFI}return n.forEach(function(t,i){var n=t.getAttribute("idref"),r=t.getAttribute("properties")||"",o=r.length?r.split(" "):[],s={idref:n,linear:t.getAttribute("linear")||"",properties:o,index:i};e.push(s)}),e},EPUBJS.Parser.prototype.nav=function(t){function e(t){var e=[];return Array.prototype.slice.call(t.childNodes).forEach(function(t){"ol"==t.tagName&&Array.prototype.slice.call(t.childNodes).forEach(function(t){"li"==t.tagName&&e.push(t)})}),e}function i(t){var e=null;return Array.prototype.slice.call(t.childNodes).forEach(function(t){("a"==t.tagName||"span"==t.tagName)&&(e=t)}),e}function n(t){var r=[],o=e(t),s=Array.prototype.slice.call(o),h=s.length;return 0===h?!1:(s.forEach(function(e){var o=e.getAttribute("id")||!1,s=i(e),h=s.getAttribute("href")||"",a=s.textContent||"",u=h.split("#"),c=(u[0],n(e));r.push({id:o,href:h,label:a,subitems:c,parent:t?t.getAttribute("id"):null})}),r)}var r=t.querySelector('nav[*|type="toc"]');return r?n(r):[]},EPUBJS.Parser.prototype.ncx=function(t){function e(i){var n=[],r=t.evaluate("*[local-name()='navPoint']",i,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null),o=r.snapshotLength;if(0===o)return[];for(var s=o-1;s>=0;s--){var h=r.snapshotItem(s),a=h.getAttribute("id")||!1,u=h.querySelector("content"),c=u.getAttribute("src"),p=h.querySelector("navLabel"),l=p.textContent?p.textContent:"",d=c.split("#"),f=(d[0],e(h));n.unshift({id:a,href:c,label:l,subitems:f,parent:i?i.getAttribute("id"):null})}return n}var i=t.querySelector("navMap");return i?e(i):[]},EPUBJS.Queue=function(t){this._q=[],this.context=t,this.tick=EPUBJS.core.requestAnimationFrame,this.running=!1},EPUBJS.Queue.prototype.enqueue=function(){var t,e,i,n=[].shift.call(arguments),r=arguments;return"function"==typeof n?(t=new RSVP.defer,e=t.promise,i={task:n,args:r,deferred:t,promise:e}):i={promise:n},this._q.push(i),setTimeout(this.flush.bind(this),0),i.promise},EPUBJS.Queue.prototype.dequeue=function(){var t,e,i;return this._q.length?(t=this._q.shift(),(e=t.task)?(i=e.apply(this.context,t.args),i&&"function"==typeof i.then?i.then(function(){t.deferred.resolve.apply(this.context,arguments)}.bind(this)):(t.deferred.resolve.apply(this.context,i),t.promise)):t.promise?t.promise:void 0):(t=new RSVP.defer,t.deferred.resolve(),t.promise)},EPUBJS.Queue.prototype.dump=function(){for(;this._q.length;)this.dequeue()},EPUBJS.Queue.prototype.run=function(){!this.running&&this._q.length&&(this.running=!0,this.dequeue().then(function(){this.running=!1}.bind(this))),this.tick.call(window,this.run.bind(this))},EPUBJS.Queue.prototype.flush=function(){return this.running?this.running:this._q.length?(this.running=this.dequeue().then(function(){return this.running=void 0,this.flush()}.bind(this)),this.running):void 0},EPUBJS.Queue.prototype.clear=function(){this._q=[],this.running=!1},EPUBJS.Queue.prototype.length=function(){return this._q.length},EPUBJS.Task=function(t){return function(){var e=arguments||[];return new RSVP.Promise(function(i){var n=function(t){i(t)};e.push(n),t.apply(this,e)}.bind(this))}},EPUBJS.Rendition=function(t,e){this.settings=EPUBJS.core.extend(this.settings||{},{infinite:!0,hidden:!1,width:!1,height:null,layoutOveride:null,axis:"vertical"}),EPUBJS.core.extend(this.settings,e),this.viewSettings={},this.book=t,this.views=[],this.hooks={},this.hooks.display=new EPUBJS.Hook(this),this.hooks.content=new EPUBJS.Hook(this),this.hooks.layout=new EPUBJS.Hook(this),this.hooks.render=new EPUBJS.Hook(this),this.hooks.show=new EPUBJS.Hook(this),this.hooks.content.register(EPUBJS.replace.links.bind(this)),this.epubcfi=new EPUBJS.EpubCFI,this.q=new EPUBJS.Queue(this),this.q.enqueue(this.book.opened),this.q.enqueue(this.parseLayoutProperties)},EPUBJS.Rendition.prototype.initialize=function(t){{var e,i=t||{},n=i.height,r=i.width;i.hidden||!1}return i.height&&EPUBJS.core.isNumber(i.height)&&(n=i.height+"px"),i.width&&EPUBJS.core.isNumber(i.width)&&(r=i.width+"px"),e=document.createElement("div"),e.id="epubjs-container:"+EPUBJS.core.uuid(),e.classList.add("epub-container"),e.style.fontSize="0",e.style.wordSpacing="0",e.style.lineHeight="0",e.style.verticalAlign="top","horizontal"===this.settings.axis&&(e.style.whiteSpace="nowrap"),r&&(e.style.width=r),n&&(e.style.height=n),e.style.overflow=this.settings.overflow,e},EPUBJS.Rendition.wrap=function(t){var e=document.createElement("div");return e.style.visibility="hidden",e.style.overflow="hidden",e.style.width="0",e.style.height="0",e.appendChild(t),e},EPUBJS.Rendition.prototype.attachTo=function(t){return this.container=this.initialize({width:this.settings.width,height:this.settings.height}),EPUBJS.core.isElement(t)?this.element=t:"string"==typeof t&&(this.element=document.getElementById(t)),this.element?(this.settings.hidden?(this.wrapper=this.wrap(this.container),this.element.appendChild(this.wrapper)):this.element.appendChild(this.container),this.attachListeners(),this.stageSize(),this.applyLayoutMethod(),this.trigger("attached"),void 0):(console.error("Not an Element"),void 0)},EPUBJS.Rendition.prototype.attachListeners=function(){EPUBJS.core.isNumber(this.settings.width)&&EPUBJS.core.isNumber(this.settings.height)||window.addEventListener("resize",this.onResized.bind(this),!1)},EPUBJS.Rendition.prototype.bounds=function(){return this.container.getBoundingClientRect()},EPUBJS.Rendition.prototype.display=function(t){return this.q.enqueue(this._display,t)},EPUBJS.Rendition.prototype._display=function(t){var e,i,n,r,o=new RSVP.defer,s=o.promise;return this.epubcfi.isCfiString(t)?(n=this.epubcfi.parse(t),r=n.spinePos,e=this.book.spine.get(r)):e=this.book.spine.get(t),this.displaying=!0,this.hide(),e?(i=this.createView(e),this.q.enqueue(this.append,i),this.show(),this.hooks.display.trigger(i).then(function(){this.trigger("displayed",e),o.resolve(this)}.bind(this))):o.reject(new Error("No Section Found")),s},EPUBJS.Rendition.prototype.moveTo=function(){},EPUBJS.Rendition.prototype.render=function(t,e){return t.create(),t.onLayout=this.layout.format.bind(this.layout),this.resizeView(t),t.render(this.book.request).then(function(){return this.hooks.content.trigger(t,this)}.bind(this)).then(function(){return this.hooks.layout.trigger(t,this)}.bind(this)).then(function(){return t.display()}.bind(this)).then(function(){return this.hooks.render.trigger(t,this)}.bind(this)).then(function(){e!==!1&&this.hidden===!1&&this.q.enqueue(function(t){t.show()},t),this.trigger("rendered",t.section)}.bind(this)).catch(function(t){this.trigger("loaderror",t)}.bind(this))},EPUBJS.Rendition.prototype.afterDisplayed=function(t){this.trigger("added",t.section)},EPUBJS.Rendition.prototype.append=function(t){return this.clear(),this.views.push(t),this.container.appendChild(t.element),t.onDisplayed=this.afterDisplayed.bind(this),this.render(t)},EPUBJS.Rendition.prototype.clear=function(){this.views.forEach(function(t){this._remove(t)}.bind(this)),this.views=[]},EPUBJS.Rendition.prototype.remove=function(t){var e=this.views.indexOf(t);e>-1&&this.views.splice(e,1),this._remove(t)},EPUBJS.Rendition.prototype._remove=function(t){t.off("resized"),t.displayed&&t.destroy(),this.container.removeChild(t.element),t=null},EPUBJS.Rendition.prototype.resizeView=function(t){"pre-paginated"===this.globalLayoutProperties.layout?t.lock("both",this.stage.width,this.stage.height):t.lock("width",this.stage.width,this.stage.height)},EPUBJS.Rendition.prototype.stageSize=function(t,e){var i,n=t||this.settings.width,r=e||this.settings.height;return n===!1&&(i=this.element.getBoundingClientRect(),i.width&&(n=i.width,this.container.style.width=i.width+"px")),r===!1&&(i=i||this.element.getBoundingClientRect(),i.height&&(r=i.height,this.container.style.height=i.height+"px")),n&&!EPUBJS.core.isNumber(n)&&(i=this.container.getBoundingClientRect(),n=i.width),r&&!EPUBJS.core.isNumber(r)&&(i=i||this.container.getBoundingClientRect(),r=i.height),this.containerStyles=window.getComputedStyle(this.container),this.containerPadding={left:parseFloat(this.containerStyles["padding-left"])||0,right:parseFloat(this.containerStyles["padding-right"])||0,top:parseFloat(this.containerStyles["padding-top"])||0,bottom:parseFloat(this.containerStyles["padding-bottom"])||0},this.stage={width:n-this.containerPadding.left-this.containerPadding.right,height:r-this.containerPadding.top-this.containerPadding.bottom},this.stage},EPUBJS.Rendition.prototype.applyLayoutMethod=function(){this.layout=new EPUBJS.Layout.Scroll,this.updateLayout(),this.map=new EPUBJS.Map(this.layout)},EPUBJS.Rendition.prototype.updateLayout=function(){this.layout.calculate(this.stage.width,this.stage.height)},EPUBJS.Rendition.prototype.resize=function(t,e){this.stageSize(t,e),this.updateLayout(),this.views.forEach(this.resizeView.bind(this)),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},EPUBJS.Rendition.prototype.onResized=function(){this.resize()},EPUBJS.Rendition.prototype.createView=function(t){return new EPUBJS.View(t,this.viewSettings)},EPUBJS.Rendition.prototype.next=function(){return this.q.enqueue(function(){var t,e;return this.views.length?(t=this.views[0].section.next(),t?(e=this.createView(t),this.append(e)):void 0):void 0})},EPUBJS.Rendition.prototype.prev=function(){return this.q.enqueue(function(){var t,e;return this.views.length?(t=this.views[0].section.prev(),t?(e=this.createView(t),this.append(e)):void 0):void 0})},EPUBJS.Rendition.prototype.parseLayoutProperties=function(t){var e=t||this.book.package.metadata,i=this.layoutOveride&&this.layoutOveride.layout||e.layout||"reflowable",n=this.layoutOveride&&this.layoutOveride.spread||e.spread||"auto",r=this.layoutOveride&&this.layoutOveride.orientation||e.orientation||"auto";return this.globalLayoutProperties={layout:i,spread:n,orientation:r},this.globalLayoutProperties},EPUBJS.Rendition.prototype.current=function(){var t=this.visible();return t.length?t[t.length-1]:null},EPUBJS.Rendition.prototype.isVisible=function(t,e,i,n){var r=t.position(),o=n||this.container.getBoundingClientRect();return"horizontal"===this.settings.axis&&r.right>o.left-e&&!(r.left>=o.right+i)?!0:"vertical"===this.settings.axis&&r.bottom>o.top-e&&!(r.top>=o.bottom+i)?!0:!1},EPUBJS.Rendition.prototype.visible=function(){for(var t,e,i=this.bounds(),n=[],r=0;ri;i++)if(t[i]===e)return i;return-1}function e(t){var e=t._promiseCallbacks;return e||(e=t._promiseCallbacks={}),e}function i(t,e){return"onerror"===t?(Y.on("error",e),void 0):2!==arguments.length?Y[t]:(Y[t]=e,void 0)}function n(t){return"function"==typeof t||"object"==typeof t&&null!==t}function r(t){return"function"==typeof t}function o(t){return"object"==typeof t&&null!==t}function s(){}function h(){}function a(t){try{return t.then}catch(e){return oe.error=e,oe}}function u(t,e,i,n){try{t.call(e,i,n)}catch(r){return r}}function c(t,e,i){Y.async(function(t){var n=!1,r=u(i,e,function(i){n||(n=!0,e!==i?d(t,i):g(t,i))},function(e){n||(n=!0,y(t,e))},"Settle: "+(t._label||" unknown promise"));!n&&r&&(n=!0,y(t,r))},t)}function p(t,e){e._state===ne?g(t,e._result):t._state===re?y(t,e._result):m(e,void 0,function(i){e!==i?d(t,i):g(t,i)},function(e){y(t,e)})}function l(t,e){if(e.constructor===t.constructor)p(t,e);else{var i=a(e);i===oe?y(t,oe.error):void 0===i?g(t,e):r(i)?c(t,e,i):g(t,e)}}function d(t,e){t===e?g(t,e):n(e)?l(t,e):g(t,e)}function f(t){t._onerror&&t._onerror(t._result),S(t)}function g(t,e){t._state===ie&&(t._result=e,t._state=ne,0===t._subscribers.length?Y.instrument&&ee("fulfilled",t):Y.async(S,t))}function y(t,e){t._state===ie&&(t._state=re,t._result=e,Y.async(f,t))}function m(t,e,i,n){var r=t._subscribers,o=r.length;t._onerror=null,r[o]=e,r[o+ne]=i,r[o+re]=n,0===o&&t._state&&Y.async(S,t)}function S(t){var e=t._subscribers,i=t._state;if(Y.instrument&&ee(i===ne?"fulfilled":"rejected",t),0!==e.length){for(var n,r,o=t._result,s=0;sh;h++)s[h]=t[h];for(n=0;nn;n++)i[n-1]=t[n];return i}function N(t,e){return{then:function(i,n){return t.call(e,i,n)}}}function q(t,e,i,n){var r=_(i,n,e);return r===ge&&y(t,r.value),t}function L(t,e,i,n){return fe.all(e).then(function(e){var r=_(i,n,e);return r===ge&&y(t,r.value),t})}function F(t){return t&&"object"==typeof t?t.constructor===fe?!0:R(t):!1}function O(t,e,i){this._superConstructor(t,e,!1,i)}function I(t,e,i){this._superConstructor(t,e,!0,i)}function V(t,e,i){this._superConstructor(t,e,!1,i)}function A(){return function(){process.nextTick(z)}}function M(){var t=0,e=new qe(z),i=document.createTextNode("");return e.observe(i,{characterData:!0}),function(){i.data=t=++t%2}}function H(){var t=new MessageChannel;return t.port1.onmessage=z,function(){t.port2.postMessage(0)}}function j(){return function(){setTimeout(z,1)}}function z(){for(var t=0;Te>t;t+=2){var e=Fe[t],i=Fe[t+1];e(i),Fe[t]=void 0,Fe[t+1]=void 0}Te=0}function D(t,e){Y.async(t,e)}function W(){Y.on.apply(Y,arguments)}function X(){Y.off.apply(Y,arguments)}var Q={mixin:function(t){return t.on=this.on,t.off=this.off,t.trigger=this.trigger,t._promiseCallbacks=void 0,t},on:function(i,n){var r,o=e(this);r=o[i],r||(r=o[i]=[]),-1===t(r,n)&&r.push(n)},off:function(i,n){var r,o,s=e(this);return n?(r=s[i],o=t(r,n),-1!==o&&r.splice(o,1),void 0):(s[i]=[],void 0)},trigger:function(t,i){var n,r,o=e(this);if(n=o[t])for(var s=0;s1)throw new Error("Second argument not supported");if("object"!=typeof t)throw new TypeError("Argument must be an object");return s.prototype=t,new s},te=[],ee=function(t,e,i){1===te.push({name:t,payload:{guid:e._guidKey+e._id,eventName:t,detail:e._result,childGuid:i&&e._guidKey+i._id,label:e._label,timeStamp:Z(),stack:new Error(e._label).stack}})&&setTimeout(function(){for(var t,e=0;en;n++)this._eachEntry(i[n],n)},U.prototype._eachEntry=function(t,e){var i=this._instanceConstructor;o(t)?t.constructor===i&&t._state!==ie?(t._onerror=null,this._settledAt(t._state,e,t._result)):this._willSettleAt(i.resolve(t),e):(this._remaining--,this._result[e]=this._makeResult(ne,e,t))},U.prototype._settledAt=function(t,e,i){var n=this.promise;n._state===ie&&(this._remaining--,this._abortOnReject&&t===re?y(n,i):this._result[e]=this._makeResult(t,e,i)),0===this._remaining&&g(n,this._result)},U.prototype._makeResult=function(t,e,i){return i},U.prototype._willSettleAt=function(t,e){var i=this;m(t,void 0,function(t){i._settledAt(ne,e,t)},function(t){i._settledAt(re,e,t)})};var ae=function(t,e){return new he(this,t,!0,e).promise},ue=function(t,e){function i(t){d(o,t)}function n(t){y(o,t)}var r=this,o=new r(h,e);if(!G(t))return y(o,new TypeError("You must pass an array to race.")),o;for(var s=t.length,a=0;o._state===ie&&s>a;a++)m(r.resolve(t[a]),void 0,i,n);return o},ce=function(t,e){var i=this;if(t&&"object"==typeof t&&t.constructor===i)return t;var n=new i(h,e);return d(n,t),n},pe=function(t,e){var i=this,n=new i(h,e);return y(n,t),n},le="rsvp_"+Z()+"-",de=0,fe=x;x.cast=ce,x.all=ae,x.race=ue,x.resolve=ce,x.reject=pe,x.prototype={constructor:x,_guidKey:le,_onerror:function(t){Y.trigger("error",t)},then:function(t,e,i){var n=this,r=n._state;if(r===ne&&!t||r===re&&!e)return Y.instrument&&ee("chained",this,this),this;n._onerror=null;var o=new this.constructor(h,i),s=n._result;if(Y.instrument&&ee("chained",n,o),r){var a=arguments[r-1];Y.async(function(){P(r,o,a,s)})}else m(n,o,t,e);return o},"catch":function(t,e){return this.then(null,t,e)},"finally":function(t,e){var i=this.constructor;return this.then(function(e){return i.resolve(t()).then(function(){return e})},function(e){return i.resolve(t()).then(function(){throw e})},e)}};var ge=new C,ye=new C,me=function(t,e){var i=function(){for(var i,n=this,r=arguments.length,o=new Array(r+1),s=!1,a=0;r>a;++a){if(i=arguments[a],!s){if(s=F(i),s===ye){var u=new fe(h);return y(u,ye.value),u}s&&s!==!0&&(i=N(s,i))}o[a]=i}var c=new fe(h);return o[r]=function(t,i){t?y(c,t):void 0===e?d(c,i):e===!0?d(c,k(arguments)):G(e)?d(c,T(arguments,e)):d(c,i)},s?L(c,o,t,n):q(c,o,t,n)};return i.__proto__=t,i},Se=function(t,e){return fe.all(t,e)};O.prototype=$(he.prototype),O.prototype._superConstructor=he,O.prototype._makeResult=w,O.prototype._validationError=function(){return new Error("allSettled must be called with an array")};var ve=function(t,e){return new O(fe,t,e).promise},Ee=function(t,e){return fe.race(t,e)},Pe=I;I.prototype=$(he.prototype),I.prototype._superConstructor=he,I.prototype._init=function(){this._result={}},I.prototype._validateInput=function(t){return t&&"object"==typeof t},I.prototype._validationError=function(){return new Error("Promise.hash must be called with an object")},I.prototype._enumerate=function(){var t=this.promise,e=this._input,i=[];for(var n in e)t._state===ie&&e.hasOwnProperty(n)&&i.push({position:n,entry:e[n]});var r=i.length;this._remaining=r;for(var o,s=0;t._state===ie&&r>s;s++)o=i[s],this._eachEntry(o.entry,o.position)};var Be=function(t,e){return new Pe(fe,t,e).promise};V.prototype=$(Pe.prototype),V.prototype._superConstructor=he,V.prototype._makeResult=w,V.prototype._validationError=function(){return new Error("hashSettled must be called with an object")};var we,Ue=function(t,e){return new V(fe,t,e).promise},be=function(t){throw setTimeout(function(){throw t}),t},Je=function(t){var e={};return e.promise=new fe(function(t,i){e.resolve=t,e.reject=i},t),e},xe=function(t,e,i){return fe.all(t,i).then(function(t){if(!r(e))throw new TypeError("You must pass a function as map's second argument.");for(var n=t.length,o=new Array(n),s=0;n>s;s++)o[s]=e(t[s]);return fe.all(o,i)})},Ce=function(t,e){return fe.resolve(t,e)},Re=function(t,e){return fe.reject(t,e)},_e=function(t,e,i){return fe.all(t,i).then(function(t){if(!r(e))throw new TypeError("You must pass a function as filter's second argument.");for(var n=t.length,o=new Array(n),s=0;n>s;s++)o[s]=e(t[s]);return fe.all(o,i).then(function(e){for(var i=new Array(n),r=0,o=0;n>o;o++)e[o]&&(i[r]=t[o],r++);return i.length=r,i})})},Te=0,ke=function(t,e){Fe[Te]=t,Fe[Te+1]=e,Te+=2,2===Te&&we()},Ne="undefined"!=typeof window?window:{},qe=Ne.MutationObserver||Ne.WebKitMutationObserver,Le="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Fe=new Array(1e3);we="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?A():qe?M():Le?H():j(),Y.async=ke;if("undefined"!=typeof window&&"object"==typeof window.__PROMISE_INSTRUMENTATION__){var Oe=window.__PROMISE_INSTRUMENTATION__;i("instrument",!0);for(var Ie in Oe)Oe.hasOwnProperty(Ie)&&W(Ie,Oe[Ie])}var Ve={race:Ee,Promise:fe,allSettled:ve,hash:Be,hashSettled:Ue,denodeify:me,on:W,off:X,map:xe,filter:_e,resolve:Ce,reject:Re,all:Se,rethrow:be,defer:Je,EventTarget:Q,configure:i,async:D};"function"==typeof define&&define.amd?define(function(){return Ve}):"undefined"!=typeof module&&module.exports?module.exports=Ve:"undefined"!=typeof this&&(this.RSVP=Ve)}.call(this),EPUBJS.Section=function(t){this.idref=t.idref,this.linear=t.linear,this.properties=t.properties,this.index=t.index,this.href=t.href,this.url=t.url,this.next=t.next,this.prev=t.prev,this.epubcfi=new EPUBJS.EpubCFI,this.cfiBase=t.cfiBase,this.hooks={},this.hooks.replacements=new EPUBJS.Hook(this),this.hooks.replacements.register(this.replacements)},EPUBJS.Section.prototype.load=function(t){var e=t||this.request||EPUBJS.core.request,i=new RSVP.defer,n=i.promise;return this.contents?i.resolve(this.contents):e(this.url,"xml").then(function(t){EPUBJS.core.folder(this.url);return this.document=t,this.contents=t.documentElement,this.hooks.replacements.trigger(this.document)}.bind(this)).then(function(){i.resolve(this.contents)}.bind(this)).catch(function(t){i.reject(t)}),n},EPUBJS.Section.prototype.replacements=function(t){var e,i=new RSVP.defer,n=t.createElement("base");return n.setAttribute("href",this.url),t&&(e=t.querySelector("head")),e?(e.insertBefore(n,e.firstChild),i.resolve()):i.reject(new Error("No head to insert into")),i.promise},EPUBJS.Section.prototype.beforeSectionLoad=function(){},EPUBJS.Section.prototype.render=function(t){var e=new RSVP.defer,i=e.promise;return this.load(t).then(function(t){var i=new XMLSerializer,n=i.serializeToString(t);e.resolve(n)}).catch(function(t){e.reject(t)}),i},EPUBJS.Section.prototype.find=function(){},EPUBJS.Section.prototype.reconcileLayoutSettings=function(t){var e={layout:t.layout,spread:t.spread,orientation:t.orientation};return this.properties.forEach(function(t){var i,n,r=t.replace("rendition:",""),o=r.indexOf("-");-1!=o&&(i=r.slice(0,o),n=r.slice(o+1),e[i]=n)}),e},EPUBJS.Section.prototype.cfiFromRange=function(t){return this.epubcfi.generateCfiFromRange(t,this.cfiBase)},EPUBJS.Spine=function(t){this.request=t,this.spineItems=[],this.spineByHref={},this.spineById={}},EPUBJS.Spine.prototype.load=function(t){this.items=t.spine,this.manifest=t.manifest,this.spineNodeIndex=t.spineNodeIndex,this.baseUrl=t.baseUrl||"",this.length=this.items.length,this.epubcfi=new EPUBJS.EpubCFI,this.items.forEach(function(t,e){var i,n=this.manifest[t.idref];t.cfiBase=this.epubcfi.generateChapterComponent(this.spineNodeIndex,t.index,t.idref),n&&(t.href=n.href,t.url=this.baseUrl+t.href,n.properties.length&&t.properties.push.apply(t.properties,n.properties)),t.prev=function(){return this.get(e-1)}.bind(this),t.next=function(){return this.get(e+1)}.bind(this),i=new EPUBJS.Section(t),this.append(i)}.bind(this))},EPUBJS.Spine.prototype.get=function(t){var e=0;return this.epubcfi.isCfiString(t)&&(cfi=this.epubcfi.parse(t),e=cfi.spinePos),!t||"number"!=typeof t&&isNaN(t)!==!1?t&&0===t.indexOf("#")?e=this.spineById[t.substring(1)]:t&&(t=t.split("#")[0],e=this.spineByHref[t]):e=t,this.spineItems[e]||null},EPUBJS.Spine.prototype.append=function(t){var e=this.spineItems.length;return t.index=e,this.spineItems.push(t),this.spineByHref[t.href]=e,this.spineById[t.idref]=e,e},EPUBJS.Spine.prototype.prepend=function(t){this.spineItems.unshift(t);return this.spineByHref[t.href]=0,this.spineById[t.idref]=0,this.spineItems.forEach(function(t,e){t.index=e}),0},EPUBJS.Spine.prototype.insert=function(){},EPUBJS.Spine.prototype.remove=function(t){var e=this.spineItems.indexOf(t);return e>-1?(delete this.spineByHref[t.href],delete this.spineById[t.idref],this.spineItems.splice(e,1)):void 0},EPUBJS.View=function(t,e){this.settings=e||{},this.id="epubjs-view:"+EPUBJS.core.uuid(),this.section=t,this.index=t.index,this.element=document.createElement("div"),this.element.classList.add("epub-view"),this.element.style.height="0px",this.element.style.width="0px",this.element.style.overflow="hidden",this.added=!1,this.displayed=!1,this.rendered=!1,this.epubcfi=new EPUBJS.EpubCFI,this.element.style.display=this.settings.axis&&"horizontal"==this.settings.axis?"inline-block":"block"},EPUBJS.View.prototype.create=function(){return this.iframe?this.iframe:(this.iframe=document.createElement("iframe"),this.iframe.id=this.id,this.iframe.scrolling="no",this.iframe.style.overflow="hidden",this.iframe.seamless="seamless",this.iframe.style.border="none",this.resizing=!0,this.element.style.visibility="hidden",this.iframe.style.visibility="hidden",this.iframe.style.width="0",this.iframe.style.height="0",this._width=0,this._height=0,this.element.appendChild(this.iframe),this.added=!0,this.elementBounds=EPUBJS.core.bounds(this.element),this.supportsSrcdoc=!1,this.iframe)},EPUBJS.View.prototype.lock=function(t,e,i){var n,r=EPUBJS.core.borders(this.element);n=this.iframe?EPUBJS.core.borders(this.iframe):{width:0,height:0},"width"==t&&EPUBJS.core.isNumber(e)&&(this.lockedWidth=e-r.width-n.width,this.resize(this.lockedWidth,e)),"height"==t&&EPUBJS.core.isNumber(i)&&(this.lockedHeight=i-r.height-n.height,this.resize(e,this.lockedHeight)),"both"===t&&EPUBJS.core.isNumber(e)&&EPUBJS.core.isNumber(i)&&(this.lockedWidth=e-r.width-n.width,this.lockedHeight=i-r.height-n.height,this.resize(this.lockedWidth,this.lockedHeight)),this.displayed&&this.iframe&&(this.layout(),this.expand())},EPUBJS.View.prototype.expand=function(){var t,e,i=this.lockedWidth,n=this.lockedHeight;this.iframe&&!this._expanding&&(this._expanding=!0,n&&!i&&(t=this.textWidth(),t!=this._textWidth?(i=this.contentWidth(t),this._textWidth=t,this._contentWidth=i):i=this._contentWidth),i&&!n&&(e=this.textHeight(),e!=this._textHeight?(n=this.contentHeight(e),this._textHeight=e,this._contentHeight=n):n=this._contentHeight),(this._needsReframe||i!=this._width||n!=this._height)&&this.resize(i,n),this._expanding=!1)},EPUBJS.View.prototype.contentWidth=function(){var t,e;return t=this.iframe.style.width,this.iframe.style.width="0px",e=this.document.body.scrollWidth,this.iframe.style.width=t,e},EPUBJS.View.prototype.contentHeight=function(t){var e,i;return e=this.iframe.style.height,this.iframe.style.height=(t||0)+"px",i=this.document.body.scrollHeight,this.iframe.style.height=e,i -},EPUBJS.View.prototype.textWidth=function(){var t,e=this.document.createRange();return e.selectNodeContents(this.document.body),t=e.getBoundingClientRect().width},EPUBJS.View.prototype.textHeight=function(){var t,e=this.document.createRange();return e.selectNodeContents(this.document.body),t=e.getBoundingClientRect().height},EPUBJS.View.prototype.resize=function(t,e){this.iframe&&(EPUBJS.core.isNumber(t)&&(this.iframe.style.width=t+"px",this._width=t),EPUBJS.core.isNumber(e)&&(this.iframe.style.height=e+"px",this._height=e),this.iframeBounds=EPUBJS.core.bounds(this.iframe),this.reframe(this.iframeBounds.width,this.iframeBounds.height))},EPUBJS.View.prototype.reframe=function(t,e){return this.displayed?(EPUBJS.core.isNumber(t)&&(this.element.style.width=t+"px"),EPUBJS.core.isNumber(e)&&(this.element.style.height=e+"px"),this.prevBounds=this.elementBounds,this.elementBounds=EPUBJS.core.bounds(this.element),this.trigger("resized",{width:this.elementBounds.width,height:this.elementBounds.height,widthDelta:this.elementBounds.width-this.prevBounds.width,heightDelta:this.elementBounds.height-this.prevBounds.height}),void 0):(this._needsReframe=!0,void 0)},EPUBJS.View.prototype.resized=function(){},EPUBJS.View.prototype.render=function(t){return this.rendering=!0,this.section.render(t).then(function(t){return this.load(t)}.bind(this))},EPUBJS.View.prototype.load=function(t){var e=new RSVP.defer,i=e.promise;if(!this.iframe)return e.reject(new Error("No Iframe Available")),i;if(this.iframe.onload=function(){this.window=this.iframe.contentWindow,this.document=this.iframe.contentDocument,this.rendering=!1,e.resolve(this)}.bind(this),this.supportsSrcdoc)this.iframe.srcdoc=t;else{if(this.document=this.iframe.contentDocument,!this.document)return e.reject(new Error("No Document Available")),i;this.document.open(),this.document.write(t),this.document.close()}return i},EPUBJS.View.prototype.layout=function(t){this.iframe.style.display="inline-block",this.document.body.style.margin="0",t&&t(this),this.onLayout(this)},EPUBJS.View.prototype.onLayout=function(){},EPUBJS.View.prototype.listeners=function(){this.document.fonts&&"loading"===this.document.fonts.status&&(this.document.fonts.onloadingdone=function(){this.expand()}.bind(this)),this.section.properties.indexOf("scripted")>-1&&(this.observer=this.observe(this.document.body)),this.imageLoadListeners(),this.mediaQueryListeners(),this.resizeListenters()},EPUBJS.View.prototype.resizeListenters=function(){clearTimeout(this.expanding),this.expanding=setTimeout(this.expand.bind(this),350)},EPUBJS.View.prototype.mediaQueryListeners=function(){for(var t=this.document.styleSheets,e=function(t){t.matches&&!this._expanding&&this.expand()}.bind(this),i=0;i-1&&(id=t.substring(t.indexOf("#")),el=this.document.getElementById(id)))return el.getBoundingClientRect();return{left:0,top:0}}},EPUBJS.View.prototype.addCss=function(t){var e=document.createElement("link"),i=!1;return new RSVP.Promise(function(n){return this.document?(e.type="text/css",e.rel="stylesheet",e.href=t,e.onload=e.onreadystatechange=function(){i||this.readyState&&"complete"!=this.readyState||(i=!0,setTimeout(function(){n(!0)},1))},this.document.head.appendChild(e),void 0):(n(!1),void 0)}.bind(this))},EPUBJS.View.prototype.addStylesheetRules=function(t){var e,i=document.createElement("style");if(this.document){this.document.head.appendChild(i),e=i.sheet;for(var n=0,r=t.length;r>n;n++){var o=1,s=t[n],h=t[n][0],a="";"[object Array]"===Object.prototype.toString.call(s[1][0])&&(s=s[1],o=0);for(var u=s.length;u>o;o++){var c=s[o];a+=c[0]+":"+c[1]+(c[2]?" !important":"")+";\n"}e.insertRule(h+"{"+a+"}",e.cssRules.length)}}},RSVP.EventTarget.mixin(EPUBJS.View.prototype); \ No newline at end of file +(function(){"use strict";function t(t,e){for(var i=0,n=t.length;n>i;i++)if(t[i]===e)return i;return-1}function e(t){var e=t._promiseCallbacks;return e||(e=t._promiseCallbacks={}),e}function i(t,e){return"onerror"===t?(Y.on("error",e),void 0):2!==arguments.length?Y[t]:(Y[t]=e,void 0)}function n(t){return"function"==typeof t||"object"==typeof t&&null!==t}function r(t){return"function"==typeof t}function o(t){return"object"==typeof t&&null!==t}function s(){}function h(){}function a(t){try{return t.then}catch(e){return oe.error=e,oe}}function u(t,e,i,n){try{t.call(e,i,n)}catch(r){return r}}function c(t,e,i){Y.async(function(t){var n=!1,r=u(i,e,function(i){n||(n=!0,e!==i?d(t,i):g(t,i))},function(e){n||(n=!0,y(t,e))},"Settle: "+(t._label||" unknown promise"));!n&&r&&(n=!0,y(t,r))},t)}function p(t,e){e._state===ne?g(t,e._result):t._state===re?y(t,e._result):m(e,void 0,function(i){e!==i?d(t,i):g(t,i)},function(e){y(t,e)})}function l(t,e){if(e.constructor===t.constructor)p(t,e);else{var i=a(e);i===oe?y(t,oe.error):void 0===i?g(t,e):r(i)?c(t,e,i):g(t,e)}}function d(t,e){t===e?g(t,e):n(e)?l(t,e):g(t,e)}function f(t){t._onerror&&t._onerror(t._result),S(t)}function g(t,e){t._state===ie&&(t._result=e,t._state=ne,0===t._subscribers.length?Y.instrument&&ee("fulfilled",t):Y.async(S,t))}function y(t,e){t._state===ie&&(t._state=re,t._result=e,Y.async(f,t))}function m(t,e,i,n){var r=t._subscribers,o=r.length;t._onerror=null,r[o]=e,r[o+ne]=i,r[o+re]=n,0===o&&t._state&&Y.async(S,t)}function S(t){var e=t._subscribers,i=t._state;if(Y.instrument&&ee(i===ne?"fulfilled":"rejected",t),0!==e.length){for(var n,r,o=t._result,s=0;sh;h++)s[h]=t[h];for(n=0;nn;n++)i[n-1]=t[n];return i}function N(t,e){return{then:function(i,n){return t.call(e,i,n)}}}function q(t,e,i,n){var r=_(i,n,e);return r===ge&&y(t,r.value),t}function L(t,e,i,n){return fe.all(e).then(function(e){var r=_(i,n,e);return r===ge&&y(t,r.value),t})}function F(t){return t&&"object"==typeof t?t.constructor===fe?!0:R(t):!1}function O(t,e,i){this._superConstructor(t,e,!1,i)}function I(t,e,i){this._superConstructor(t,e,!0,i)}function V(t,e,i){this._superConstructor(t,e,!1,i)}function A(){return function(){process.nextTick(z)}}function M(){var t=0,e=new qe(z),i=document.createTextNode("");return e.observe(i,{characterData:!0}),function(){i.data=t=++t%2}}function H(){var t=new MessageChannel;return t.port1.onmessage=z,function(){t.port2.postMessage(0)}}function j(){return function(){setTimeout(z,1)}}function z(){for(var t=0;Te>t;t+=2){var e=Fe[t],i=Fe[t+1];e(i),Fe[t]=void 0,Fe[t+1]=void 0}Te=0}function D(t,e){Y.async(t,e)}function W(){Y.on.apply(Y,arguments)}function X(){Y.off.apply(Y,arguments)}var Q={mixin:function(t){return t.on=this.on,t.off=this.off,t.trigger=this.trigger,t._promiseCallbacks=void 0,t},on:function(i,n){var r,o=e(this);r=o[i],r||(r=o[i]=[]),-1===t(r,n)&&r.push(n)},off:function(i,n){var r,o,s=e(this);return n?(r=s[i],o=t(r,n),-1!==o&&r.splice(o,1),void 0):(s[i]=[],void 0)},trigger:function(t,i){var n,r,o=e(this);if(n=o[t])for(var s=0;s1)throw new Error("Second argument not supported");if("object"!=typeof t)throw new TypeError("Argument must be an object");return s.prototype=t,new s},te=[],ee=function(t,e,i){1===te.push({name:t,payload:{guid:e._guidKey+e._id,eventName:t,detail:e._result,childGuid:i&&e._guidKey+i._id,label:e._label,timeStamp:Z(),stack:new Error(e._label).stack}})&&setTimeout(function(){for(var t,e=0;en;n++)this._eachEntry(i[n],n)},U.prototype._eachEntry=function(t,e){var i=this._instanceConstructor;o(t)?t.constructor===i&&t._state!==ie?(t._onerror=null,this._settledAt(t._state,e,t._result)):this._willSettleAt(i.resolve(t),e):(this._remaining--,this._result[e]=this._makeResult(ne,e,t))},U.prototype._settledAt=function(t,e,i){var n=this.promise;n._state===ie&&(this._remaining--,this._abortOnReject&&t===re?y(n,i):this._result[e]=this._makeResult(t,e,i)),0===this._remaining&&g(n,this._result)},U.prototype._makeResult=function(t,e,i){return i},U.prototype._willSettleAt=function(t,e){var i=this;m(t,void 0,function(t){i._settledAt(ne,e,t)},function(t){i._settledAt(re,e,t)})};var ae=function(t,e){return new he(this,t,!0,e).promise},ue=function(t,e){function i(t){d(o,t)}function n(t){y(o,t)}var r=this,o=new r(h,e);if(!G(t))return y(o,new TypeError("You must pass an array to race.")),o;for(var s=t.length,a=0;o._state===ie&&s>a;a++)m(r.resolve(t[a]),void 0,i,n);return o},ce=function(t,e){var i=this;if(t&&"object"==typeof t&&t.constructor===i)return t;var n=new i(h,e);return d(n,t),n},pe=function(t,e){var i=this,n=new i(h,e);return y(n,t),n},le="rsvp_"+Z()+"-",de=0,fe=x;x.cast=ce,x.all=ae,x.race=ue,x.resolve=ce,x.reject=pe,x.prototype={constructor:x,_guidKey:le,_onerror:function(t){Y.trigger("error",t)},then:function(t,e,i){var n=this,r=n._state;if(r===ne&&!t||r===re&&!e)return Y.instrument&&ee("chained",this,this),this;n._onerror=null;var o=new this.constructor(h,i),s=n._result;if(Y.instrument&&ee("chained",n,o),r){var a=arguments[r-1];Y.async(function(){P(r,o,a,s)})}else m(n,o,t,e);return o},"catch":function(t,e){return this.then(null,t,e)},"finally":function(t,e){var i=this.constructor;return this.then(function(e){return i.resolve(t()).then(function(){return e})},function(e){return i.resolve(t()).then(function(){throw e})},e)}};var ge=new C,ye=new C,me=function(t,e){var i=function(){for(var i,n=this,r=arguments.length,o=new Array(r+1),s=!1,a=0;r>a;++a){if(i=arguments[a],!s){if(s=F(i),s===ye){var u=new fe(h);return y(u,ye.value),u}s&&s!==!0&&(i=N(s,i))}o[a]=i}var c=new fe(h);return o[r]=function(t,i){t?y(c,t):void 0===e?d(c,i):e===!0?d(c,k(arguments)):G(e)?d(c,T(arguments,e)):d(c,i)},s?L(c,o,t,n):q(c,o,t,n)};return i.__proto__=t,i},Se=function(t,e){return fe.all(t,e)};O.prototype=$(he.prototype),O.prototype._superConstructor=he,O.prototype._makeResult=w,O.prototype._validationError=function(){return new Error("allSettled must be called with an array")};var ve=function(t,e){return new O(fe,t,e).promise},Ee=function(t,e){return fe.race(t,e)},Pe=I;I.prototype=$(he.prototype),I.prototype._superConstructor=he,I.prototype._init=function(){this._result={}},I.prototype._validateInput=function(t){return t&&"object"==typeof t},I.prototype._validationError=function(){return new Error("Promise.hash must be called with an object")},I.prototype._enumerate=function(){var t=this.promise,e=this._input,i=[];for(var n in e)t._state===ie&&e.hasOwnProperty(n)&&i.push({position:n,entry:e[n]});var r=i.length;this._remaining=r;for(var o,s=0;t._state===ie&&r>s;s++)o=i[s],this._eachEntry(o.entry,o.position)};var Be=function(t,e){return new Pe(fe,t,e).promise};V.prototype=$(Pe.prototype),V.prototype._superConstructor=he,V.prototype._makeResult=w,V.prototype._validationError=function(){return new Error("hashSettled must be called with an object")};var we,Ue=function(t,e){return new V(fe,t,e).promise},be=function(t){throw setTimeout(function(){throw t}),t},Je=function(t){var e={};return e.promise=new fe(function(t,i){e.resolve=t,e.reject=i},t),e},xe=function(t,e,i){return fe.all(t,i).then(function(t){if(!r(e))throw new TypeError("You must pass a function as map's second argument.");for(var n=t.length,o=new Array(n),s=0;n>s;s++)o[s]=e(t[s]);return fe.all(o,i)})},Ce=function(t,e){return fe.resolve(t,e)},Re=function(t,e){return fe.reject(t,e)},_e=function(t,e,i){return fe.all(t,i).then(function(t){if(!r(e))throw new TypeError("You must pass a function as filter's second argument.");for(var n=t.length,o=new Array(n),s=0;n>s;s++)o[s]=e(t[s]);return fe.all(o,i).then(function(e){for(var i=new Array(n),r=0,o=0;n>o;o++)e[o]&&(i[r]=t[o],r++);return i.length=r,i})})},Te=0,ke=function(t,e){Fe[Te]=t,Fe[Te+1]=e,Te+=2,2===Te&&we()},Ne="undefined"!=typeof window?window:{},qe=Ne.MutationObserver||Ne.WebKitMutationObserver,Le="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Fe=new Array(1e3);we="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?A():qe?M():Le?H():j(),Y.async=ke;if("undefined"!=typeof window&&"object"==typeof window.__PROMISE_INSTRUMENTATION__){var Oe=window.__PROMISE_INSTRUMENTATION__;i("instrument",!0);for(var Ie in Oe)Oe.hasOwnProperty(Ie)&&W(Ie,Oe[Ie])}var Ve={race:Ee,Promise:fe,allSettled:ve,hash:Be,hashSettled:Ue,denodeify:me,on:W,off:X,map:xe,filter:_e,resolve:Ce,reject:Re,all:Se,rethrow:be,defer:Je,EventTarget:Q,configure:i,async:D};"function"==typeof define&&define.amd?define(function(){return Ve}):"undefined"!=typeof module&&module.exports?module.exports=Ve:"undefined"!=typeof this&&(this.RSVP=Ve)}).call(this),"undefined"==typeof EPUBJS&&(("undefined"!=typeof window?window:this).EPUBJS={}),EPUBJS.VERSION="0.3.0",function(t){"use strict";var e=function(t){return new EPUBJS.Book(t)};"object"==typeof exports?(t.RSVP=require("rsvp"),module.exports=e):"function"==typeof define&&define.amd?define(e):t.ePub=e}(this),EPUBJS.core={},EPUBJS.core.request=function(t,e,i,n){function r(){if(this.readyState===this.DONE)if(200===this.status||this.responseXML){var t;t="xml"==e?this.responseXML?this.responseXML:(new DOMParser).parseFromString(this.response,"text/xml"):"json"==e?JSON.parse(this.response):"blob"==e?s?this.response:new Blob([this.response]):this.response,a.resolve(t)}else a.reject({status:this.status,message:this.response,stack:(new Error).stack})}var o,s=window.URL,h=s?"blob":"arraybuffer",a=new RSVP.defer,u=new XMLHttpRequest,c=XMLHttpRequest.prototype;"overrideMimeType"in c||Object.defineProperty(c,"overrideMimeType",{value:function(){}}),i&&(u.withCredentials=!0),u.open("GET",t,!0);for(o in n)u.setRequestHeader(o,n[o]);return u.onreadystatechange=r,"blob"==e&&(u.responseType=h),"json"==e&&u.setRequestHeader("Accept","application/json"),"xml"==e&&u.overrideMimeType("text/xml"),u.send(),a.promise},EPUBJS.core.uri=function(t){var e,i,n,r={protocol:"",host:"",path:"",origin:"",directory:"",base:"",filename:"",extension:"",fragment:"",href:t},o=t.indexOf("://"),s=t.indexOf("?"),h=t.indexOf("#");return-1!=h&&(r.fragment=t.slice(h+1),t=t.slice(0,h)),-1!=s&&(r.search=t.slice(s+1),t=t.slice(0,s),href=t),-1!=o?(r.protocol=t.slice(0,o),e=t.slice(o+3),n=e.indexOf("/"),-1===n?(r.host=r.path,r.path=""):(r.host=e.slice(0,n),r.path=e.slice(n)),r.origin=r.protocol+"://"+r.host,r.directory=EPUBJS.core.folder(r.path),r.base=r.origin+r.directory):(r.path=t,r.directory=EPUBJS.core.folder(t),r.base=r.directory),r.filename=t.replace(r.base,""),i=r.filename.lastIndexOf("."),-1!=i&&(r.extension=r.filename.slice(i+1)),r},EPUBJS.core.folder=function(t){var e=t.lastIndexOf("/");if(-1==e)var i="";return i=t.slice(0,e+1)},EPUBJS.core.queue=function(t){var e=[],i=t,n=function(t,i,n){return e.push({funcName:t,args:i,context:n}),e},r=function(){var t;e.length&&(t=e.shift(),i[t.funcName].apply(t.context||i,t.args))},o=function(){for(;e.length;)r()},s=function(){e=[]},h=function(){return e.length};return{enqueue:n,dequeue:r,flush:o,clear:s,length:h}},EPUBJS.core.isElement=function(t){return!(!t||1!=t.nodeType)},EPUBJS.core.uuid=function(){var t=(new Date).getTime(),e="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?i:7&i|8).toString(16)});return e},EPUBJS.core.values=function(t){for(var e=-1,i=Object.keys(t),n=i.length,r=Array(n);++er;r++)if("undefined"!=typeof document.body.style[e[r]+i])return e[r]+i;return t},EPUBJS.core.defaults=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var r in n)void 0===t[r]&&(t[r]=n[r])}return t},EPUBJS.core.extend=function(t){var e=[].slice.call(arguments,1);return e.forEach(function(e){e&&Object.getOwnPropertyNames(e).forEach(function(i){Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))})}),t},EPUBJS.core.insert=function(t,e,i){var n=EPUBJS.core.locationOf(t,e,i);return e.splice(n,0,t),n},EPUBJS.core.locationOf=function(t,e,i,n,r){var o,s=n||0,h=r||e.length,a=parseInt(s+(h-s)/2);return i||(i=function(t,e){return t>e?1:e>t?-1:(t=e)?0:void 0}),0>=h-s?a:(o=i(e[a],t),h-s===1?o>0?a:a+1:0===o?a:-1===o?EPUBJS.core.locationOf(t,e,i,a,h):EPUBJS.core.locationOf(t,e,i,s,a))},EPUBJS.core.indexOfSorted=function(t,e,i,n,r){var o,s=n||0,h=r||e.length,a=parseInt(s+(h-s)/2);return i||(i=function(t,e){return t>e?1:e>t?-1:(t=e)?0:void 0}),0>=h-s?-1:(o=i(e[a],t),h-s===1?0===o?a:-1:0===o?a:-1===o?EPUBJS.core.indexOfSorted(t,e,i,a,h):EPUBJS.core.indexOfSorted(t,e,i,s,a))},EPUBJS.core.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,EPUBJS.core.bounds=function(t){var e=window.getComputedStyle(t),i=["width","paddingRight","paddingLeft","marginRight","marginLeft","borderRightWidth","borderLeftWidth"],n=["height","paddingTop","paddingBottom","marginTop","marginBottom","borderTopWidth","borderBottomWidth"],r=0,o=0;return i.forEach(function(t){r+=parseFloat(e[t])||0}),n.forEach(function(t){o+=parseFloat(e[t])||0}),{height:o,width:r}},EPUBJS.core.borders=function(t){var e=window.getComputedStyle(t),i=["paddingRight","paddingLeft","marginRight","marginLeft","borderRightWidth","borderLeftWidth"],n=["paddingTop","paddingBottom","marginTop","marginBottom","borderTopWidth","borderBottomWidth"],r=0,o=0;return i.forEach(function(t){r+=parseFloat(e[t])||0}),n.forEach(function(t){o+=parseFloat(e[t])||0}),{height:o,width:r}},EPUBJS.core.windowBounds=function(){var t=window.innerWidth,e=window.innerHeight;return{top:0,left:0,right:t,bottom:e,width:t,height:e}},EPUBJS.core.cleanStringForXpath=function(t){var e=t.match(/[^'"]+|['"]/g);return e=e.map(function(t){return"'"===t?'"\'"':'"'===t?"'\"'":"'"+t+"'"}),"concat('',"+e.join(",")+")"},EPUBJS.core.indexOfTextNode=function(t){for(var e,i=t.parentNode,n=i.childNodes,r=-1,o=0;o=0;s--){var h=r.snapshotItem(s),a=h.getAttribute("id")||!1,u=h.querySelector("content"),c=u.getAttribute("src"),p=h.querySelector("navLabel"),l=p.textContent?p.textContent:"",d=c.split("#"),f=(d[0],e(h));n.unshift({id:a,href:c,label:l,subitems:f,parent:i?i.getAttribute("id"):null})}return n}var i=t.querySelector("navMap");return i?e(i):[]},EPUBJS.EpubCFI=function(t){return t?this.parse(t):void 0},EPUBJS.EpubCFI.prototype.generateChapterComponent=function(t,e,i){var n=parseInt(e),r=t+1,o="/"+r+"/";return o+=2*(n+1),i&&(o+="["+i+"]"),o},EPUBJS.EpubCFI.prototype.generatePathComponent=function(t){var e=[];return t.forEach(function(t){var i="";i+=2*(t.index+1),t.id&&(i+="["+t.id+"]"),e.push(i)}),e.join("/")},EPUBJS.EpubCFI.prototype.generateCfiFromElement=function(t,e){var i=this.pathTo(t),n=this.generatePathComponent(i);return n.length?"epubcfi("+e+"!"+n+"/1:0)":"epubcfi("+e+"!/4/)"},EPUBJS.EpubCFI.prototype.pathTo=function(t){for(var e,i=[];t&&null!==t.parentNode&&9!=t.parentNode.nodeType;)e=t.parentNode.children,i.unshift({id:t.id,tagName:t.tagName,index:e?Array.prototype.indexOf.call(e,t):0}),t=t.parentNode;return i},EPUBJS.EpubCFI.prototype.getChapterComponent=function(t){var e=t.split("!");return e[0]},EPUBJS.EpubCFI.prototype.getPathComponent=function(t){var e=t.split("!"),i=e[1]?e[1].split(":"):"";return i[0]},EPUBJS.EpubCFI.prototype.getCharecterOffsetComponent=function(t){var e=t.split(":");return e[1]||""},EPUBJS.EpubCFI.prototype.parse=function(t){var e,i,n,r,o,s,h,a,u,c={},p=function(t){var e,i,n,r;return e="element",i=parseInt(t)/2-1,n=t.match(/\[(.*)\]/),n&&n[1]&&(r=n[1]),{type:e,index:i,id:r||!1}};return"string"!=typeof t?{spinePos:-1}:(c.str=t,0===t.indexOf("epubcfi(")&&")"===t[t.length-1]&&(t=t.slice(8,t.length-1)),i=this.getChapterComponent(t),n=this.getPathComponent(t)||"",r=this.getCharecterOffsetComponent(t),i?(e=i.split("/")[2]||"")?(c.spinePos=parseInt(e)/2-1||0,s=e.match(/\[(.*)\]/),c.spineId=s?s[1]:!1,-1!=n.indexOf(",")&&console.warn("CFI Ranges are not supported"),h=n.split("/"),a=h.pop(),c.steps=[],h.forEach(function(t){var e;t&&(e=p(t),c.steps.push(e))}),u=parseInt(a),isNaN(u)||(u%2===0?c.steps.push(p(a)):c.steps.push({type:"text",index:(u-1)/2})),o=r.match(/\[(.*)\]/),o&&o[1]?(c.characterOffset=parseInt(r.split("[")[0]),c.textLocationAssertion=o[1]):c.characterOffset=parseInt(r),c):{spinePos:-1}:{spinePos:-1})},EPUBJS.EpubCFI.prototype.addMarker=function(t,e,i){var n,r,o,s,h=e||document,a=i||this.createMarker(h);return"string"==typeof t&&(t=this.parse(t)),r=t.steps[t.steps.length-1],-1===t.spinePos?!1:(n=this.findParent(t,h))?(r&&"text"===r.type?(o=n.childNodes[r.index],t.characterOffset?(s=o.splitText(t.characterOffset),a.classList.add("EPUBJS-CFI-SPLIT"),n.insertBefore(a,s)):n.insertBefore(a,o)):n.insertBefore(a,n.firstChild),a):!1},EPUBJS.EpubCFI.prototype.createMarker=function(t){var e=t||document,i=e.createElement("span");return i.id="EPUBJS-CFI-MARKER:"+EPUBJS.core.uuid(),i.classList.add("EPUBJS-CFI-MARKER"),i},EPUBJS.EpubCFI.prototype.removeMarker=function(t,e){t.classList.contains("EPUBJS-CFI-SPLIT")?(nextSib=t.nextSibling,prevSib=t.previousSibling,nextSib&&prevSib&&3===nextSib.nodeType&&3===prevSib.nodeType&&(prevSib.textContent+=nextSib.textContent,t.parentNode.removeChild(nextSib)),t.parentNode.removeChild(t)):t.classList.contains("EPUBJS-CFI-MARKER")&&t.parentNode.removeChild(t)},EPUBJS.EpubCFI.prototype.findParent=function(t,e){var i,n,r,o=e||document,s=o.getElementsByTagName("html")[0],h=Array.prototype.slice.call(s.children);if("string"==typeof t&&(t=this.parse(t)),n=t.steps.slice(0),!n.length)return o.getElementsByTagName("body")[0];for(;n&&n.length>0;){if(i=n.shift(),"text"===i.type?(r=s.childNodes[i.index],s=r.parentNode||s):s=i.id?o.getElementById(i.id):h[i.index],"undefined"==typeof s)return console.error("No Element For",i,t.str),!1;h=Array.prototype.slice.call(s.children)}return s},EPUBJS.EpubCFI.prototype.compare=function(t,e){if("string"==typeof t&&(t=new EPUBJS.EpubCFI(t)),"string"==typeof e&&(e=new EPUBJS.EpubCFI(e)),t.spinePos>e.spinePos)return 1;if(t.spinePose.steps[i].index)return 1;if(t.steps[i].indexe.characterOffset?1:t.characterOffset=0?(o=r.length,t.characterOffset-1?(delete this.spineByHref[t.href],delete this.spineById[t.idref],this.spineItems.splice(e,1)):void 0},EPUBJS.replace={},EPUBJS.replace.links=function(t,e){for(var i=t.document.querySelectorAll("a[href]"),n=function(t){var i=t.getAttribute("href"),n=new EPUBJS.core.uri(i);n.protocol?t.setAttribute("target","_blank"):0===i.indexOf("#")||(t.onclick=function(){return e.display(i),!1})},r=0;r-1&&(this.observer=this.observe(this.document.body)),this.imageLoadListeners(),this.mediaQueryListeners(),this.resizeListenters()},EPUBJS.View.prototype.resizeListenters=function(){clearTimeout(this.expanding),this.expanding=setTimeout(this.expand.bind(this),350)},EPUBJS.View.prototype.mediaQueryListeners=function(){for(var t=this.document.styleSheets,e=function(t){t.matches&&!this._expanding&&this.expand()}.bind(this),i=0;i-1&&(id=t.substring(t.indexOf("#")),el=this.document.getElementById(id)))return el.getBoundingClientRect();return{left:0,top:0}}},EPUBJS.View.prototype.addCss=function(t){var e=document.createElement("link"),i=!1;return new RSVP.Promise(function(n){return this.document?(e.type="text/css",e.rel="stylesheet",e.href=t,e.onload=e.onreadystatechange=function(){i||this.readyState&&"complete"!=this.readyState||(i=!0,setTimeout(function(){n(!0)},1))},this.document.head.appendChild(e),void 0):(n(!1),void 0)}.bind(this))},EPUBJS.View.prototype.addStylesheetRules=function(t){var e,i=document.createElement("style");if(this.document){this.document.head.appendChild(i),e=i.sheet;for(var n=0,r=t.length;r>n;n++){var o=1,s=t[n],h=t[n][0],a="";"[object Array]"===Object.prototype.toString.call(s[1][0])&&(s=s[1],o=0);for(var u=s.length;u>o;o++){var c=s[o];a+=c[0]+":"+c[1]+(c[2]?" !important":"")+";\n"}e.insertRule(h+"{"+a+"}",e.cssRules.length)}}},RSVP.EventTarget.mixin(EPUBJS.View.prototype),EPUBJS.Layout=EPUBJS.Layout||{},EPUBJS.Layout.Reflowable=function(){},EPUBJS.Layout.Reflowable.prototype.calculate=function(t,e,i,n){var r,o,s,h=n||1,a=Math.floor(t),u=a%2===0?a:a-1,c=Math.floor(u/8),p=i>=0?i:c%2===0?c:c-1;r=h>1?Math.floor((u-p)/h):u,o=r*h,s=(r+p)*h,this.columnAxis=EPUBJS.core.prefixed("columnAxis"),this.columnGap=EPUBJS.core.prefixed("columnGap"),this.columnWidth=EPUBJS.core.prefixed("columnWidth"),this.columnFill=EPUBJS.core.prefixed("columnFill"),this.width=u,this.height=e,this.spread=o,this.delta=s,this.column=r,this.gap=p,this.divisor=h},EPUBJS.Layout.Reflowable.prototype.format=function(t){var e=t.document.documentElement,i=t.document.body;e.style.overflow="hidden",e.style.width=this.width+"px",i.style.height=this.height+"px",i.style[this.columnAxis]="horizontal",i.style[this.columnFill]="auto",i.style[this.columnGap]=this.gap+"px",i.style[this.columnWidth]=this.column+"px",t.iframe.style.marginRight=this.gap+"px"},EPUBJS.Layout.Reflowable.prototype.count=function(t){var e=t.root().scrollWidth,i=Math.ceil(e/this.spread);return{spreads:i,pages:i*this.divisor}},EPUBJS.Layout.Fixed=function(){},EPUBJS.Layout.Fixed.prototype.calculate=function(){},EPUBJS.Layout.Fixed.prototype.format=function(t){var e,i,n=t.document.documentElement,r=documentElement.querySelector("[name=viewport");r&&r.hasAttribute("content")&&(content=r.getAttribute("content"),contents=content.split(","),contents[0]&&(e=contents[0].replace("width=","")),contents[1]&&(i=contents[1].replace("height=",""))),t.resize(e,i),n.style.overflow="auto"},EPUBJS.Layout.Fixed.prototype.count=function(){return{spreads:1,pages:1}},EPUBJS.Layout.Scroll=function(){},EPUBJS.Layout.Scroll.prototype.calculate=function(t){this.spread=t,this.column=t,this.gap=0},EPUBJS.Layout.Scroll.prototype.format=function(t){var e=t.document.documentElement;e.style.width="auto",e.style.height="auto"},EPUBJS.Layout.Scroll.prototype.count=function(){return{spreads:1,pages:1}},EPUBJS.Rendition=function(t,e){this.settings=EPUBJS.core.extend(this.settings||{},{infinite:!0,hidden:!1,width:!1,height:null,layoutOveride:null,axis:"vertical"}),EPUBJS.core.extend(this.settings,e),this.viewSettings={},this.book=t,this.views=[],this.hooks={},this.hooks.display=new EPUBJS.Hook(this),this.hooks.content=new EPUBJS.Hook(this),this.hooks.layout=new EPUBJS.Hook(this),this.hooks.render=new EPUBJS.Hook(this),this.hooks.show=new EPUBJS.Hook(this),this.hooks.content.register(EPUBJS.replace.links.bind(this)),this.epubcfi=new EPUBJS.EpubCFI,this.q=new EPUBJS.Queue(this),this.q.enqueue(this.book.opened),this.q.enqueue(this.parseLayoutProperties)},EPUBJS.Rendition.prototype.initialize=function(t){{var e,i=t||{},n=i.height,r=i.width;i.hidden||!1}return i.height&&EPUBJS.core.isNumber(i.height)&&(n=i.height+"px"),i.width&&EPUBJS.core.isNumber(i.width)&&(r=i.width+"px"),e=document.createElement("div"),e.id="epubjs-container:"+EPUBJS.core.uuid(),e.classList.add("epub-container"),e.style.fontSize="0",e.style.wordSpacing="0",e.style.lineHeight="0",e.style.verticalAlign="top","horizontal"===this.settings.axis&&(e.style.whiteSpace="nowrap"),r&&(e.style.width=r),n&&(e.style.height=n),e.style.overflow=this.settings.overflow,e},EPUBJS.Rendition.wrap=function(t){var e=document.createElement("div");return e.style.visibility="hidden",e.style.overflow="hidden",e.style.width="0",e.style.height="0",e.appendChild(t),e},EPUBJS.Rendition.prototype.attachTo=function(t){return this.container=this.initialize({width:this.settings.width,height:this.settings.height}),EPUBJS.core.isElement(t)?this.element=t:"string"==typeof t&&(this.element=document.getElementById(t)),this.element?(this.settings.hidden?(this.wrapper=this.wrap(this.container),this.element.appendChild(this.wrapper)):this.element.appendChild(this.container),this.attachListeners(),this.stageSize(),this.applyLayoutMethod(),this.trigger("attached"),void 0):(console.error("Not an Element"),void 0)},EPUBJS.Rendition.prototype.attachListeners=function(){EPUBJS.core.isNumber(this.settings.width)&&EPUBJS.core.isNumber(this.settings.height)||window.addEventListener("resize",this.onResized.bind(this),!1)},EPUBJS.Rendition.prototype.bounds=function(){return this.container.getBoundingClientRect()},EPUBJS.Rendition.prototype.display=function(t){return this.q.enqueue(this._display,t)},EPUBJS.Rendition.prototype._display=function(t){var e,i,n,r,o=new RSVP.defer,s=o.promise;return this.epubcfi.isCfiString(t)?(n=this.epubcfi.parse(t),r=n.spinePos,e=this.book.spine.get(r)):e=this.book.spine.get(t),this.displaying=!0,this.hide(),e?(i=this.createView(e),this.q.enqueue(this.append,i),this.show(),this.hooks.display.trigger(i).then(function(){this.trigger("displayed",e),o.resolve(this)}.bind(this))):o.reject(new Error("No Section Found")),s},EPUBJS.Rendition.prototype.moveTo=function(){},EPUBJS.Rendition.prototype.render=function(t,e){return t.create(),t.onLayout=this.layout.format.bind(this.layout),this.resizeView(t),t.render(this.book.request).then(function(){return this.hooks.content.trigger(t,this)}.bind(this)).then(function(){return this.hooks.layout.trigger(t,this)}.bind(this)).then(function(){return t.display()}.bind(this)).then(function(){return this.hooks.render.trigger(t,this)}.bind(this)).then(function(){e!==!1&&this.hidden===!1&&this.q.enqueue(function(t){t.show()},t),this.trigger("rendered",t.section)}.bind(this)).catch(function(t){this.trigger("loaderror",t)}.bind(this))},EPUBJS.Rendition.prototype.afterDisplayed=function(t){this.trigger("added",t.section)},EPUBJS.Rendition.prototype.append=function(t){return this.clear(),this.views.push(t),this.container.appendChild(t.element),t.onDisplayed=this.afterDisplayed.bind(this),this.render(t)},EPUBJS.Rendition.prototype.clear=function(){this.views.forEach(function(t){this._remove(t)}.bind(this)),this.views=[]},EPUBJS.Rendition.prototype.remove=function(t){var e=this.views.indexOf(t);e>-1&&this.views.splice(e,1),this._remove(t)},EPUBJS.Rendition.prototype._remove=function(t){t.off("resized"),t.displayed&&t.destroy(),this.container.removeChild(t.element),t=null},EPUBJS.Rendition.prototype.resizeView=function(t){"pre-paginated"===this.globalLayoutProperties.layout?t.lock("both",this.stage.width,this.stage.height):t.lock("width",this.stage.width,this.stage.height)},EPUBJS.Rendition.prototype.stageSize=function(t,e){var i,n=t||this.settings.width,r=e||this.settings.height;return n===!1&&(i=this.element.getBoundingClientRect(),i.width&&(n=i.width,this.container.style.width=i.width+"px")),r===!1&&(i=i||this.element.getBoundingClientRect(),i.height&&(r=i.height,this.container.style.height=i.height+"px")),n&&!EPUBJS.core.isNumber(n)&&(i=this.container.getBoundingClientRect(),n=i.width),r&&!EPUBJS.core.isNumber(r)&&(i=i||this.container.getBoundingClientRect(),r=i.height),this.containerStyles=window.getComputedStyle(this.container),this.containerPadding={left:parseFloat(this.containerStyles["padding-left"])||0,right:parseFloat(this.containerStyles["padding-right"])||0,top:parseFloat(this.containerStyles["padding-top"])||0,bottom:parseFloat(this.containerStyles["padding-bottom"])||0},this.stage={width:n-this.containerPadding.left-this.containerPadding.right,height:r-this.containerPadding.top-this.containerPadding.bottom},this.stage},EPUBJS.Rendition.prototype.applyLayoutMethod=function(){this.layout=new EPUBJS.Layout.Scroll,this.updateLayout(),this.map=new EPUBJS.Map(this.layout)},EPUBJS.Rendition.prototype.updateLayout=function(){this.layout.calculate(this.stage.width,this.stage.height)},EPUBJS.Rendition.prototype.resize=function(t,e){this.stageSize(t,e),this.updateLayout(),this.views.forEach(this.resizeView.bind(this)),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},EPUBJS.Rendition.prototype.onResized=function(){this.resize()},EPUBJS.Rendition.prototype.createView=function(t){return new EPUBJS.View(t,this.viewSettings)},EPUBJS.Rendition.prototype.next=function(){return this.q.enqueue(function(){var t,e;return this.views.length?(t=this.views[0].section.next(),t?(e=this.createView(t),this.append(e)):void 0):void 0})},EPUBJS.Rendition.prototype.prev=function(){return this.q.enqueue(function(){var t,e;return this.views.length?(t=this.views[0].section.prev(),t?(e=this.createView(t),this.append(e)):void 0):void 0})},EPUBJS.Rendition.prototype.parseLayoutProperties=function(t){var e=t||this.book.package.metadata,i=this.layoutOveride&&this.layoutOveride.layout||e.layout||"reflowable",n=this.layoutOveride&&this.layoutOveride.spread||e.spread||"auto",r=this.layoutOveride&&this.layoutOveride.orientation||e.orientation||"auto";return this.globalLayoutProperties={layout:i,spread:n,orientation:r},this.globalLayoutProperties},EPUBJS.Rendition.prototype.current=function(){var t=this.visible();return t.length?t[t.length-1]:null},EPUBJS.Rendition.prototype.isVisible=function(t,e,i,n){var r=t.position(),o=n||this.container.getBoundingClientRect();return"horizontal"===this.settings.axis&&r.right>o.left-e&&!(r.left>=o.right+i)?!0:"vertical"===this.settings.axis&&r.bottom>o.top-e&&!(r.top>=o.bottom+i)?!0:!1},EPUBJS.Rendition.prototype.visible=function(){for(var t,e,i=this.bounds(),n=[],r=0;r=0;r--)if(t=this.views[r],e=t.bounds().top,ethis.settings.offsetDelta||this.scrollDeltaHorz>this.settings.offsetDelta)&&(this.q.enqueue(this.check),this.scrollDeltaVert=0,this.scrollDeltaHorz=0),this.scrollDeltaVert+=Math.abs(scrollTop-this.prevScrollTop),this.scrollDeltaHorz+=Math.abs(scrollLeft-this.prevScrollLeft),this.settings.height?(this.prevScrollTop=this.container.scrollTop,this.prevScrollLeft=this.container.scrollLeft):(this.prevScrollTop=window.scrollY,this.prevScrollLeft=window.scrollX),clearTimeout(this.scrollTimeout),this.scrollTimeout=setTimeout(function(){this.scrollDeltaVert=0,this.scrollDeltaHorz=0}.bind(this),150),this.scrolled=!1),this.tick.call(window,this.onScroll.bind(this))},EPUBJS.Continuous.prototype.scrollBy=function(t,e,i){i&&(this.ignore=!0),this.settings.height?(t&&(this.container.scrollLeft+=t),e&&(this.container.scrollTop+=e)):window.scrollBy(t,e),this.scrolled=!0},EPUBJS.Continuous.prototype.scrollTo=function(t,e,i){i&&(this.ignore=!0),this.settings.height?(this.container.scrollLeft=t,this.container.scrollTop=e):window.scrollTo(t,e),this.scrolled=!0},EPUBJS.Continuous.prototype.resizeView=function(t){"horizontal"===this.settings.axis?t.lock("height",this.stage.width,this.stage.height):t.lock("width",this.stage.width,this.stage.height)},EPUBJS.Continuous.prototype.currentLocation=function(){{var t,e,i=this.visible();this.container.getBoundingClientRect()}return 1===i.length?this.map.page(i[0]):i.length>1?(t=this.map.page(i[0]),e=this.map.page(i[i.length-1]),{start:t.start,end:e.end}):void 0 +},EPUBJS.Paginate=function(t,e){EPUBJS.Continuous.apply(this,arguments),this.settings=EPUBJS.core.extend(this.settings||{},{width:600,height:400,axis:"horizontal",forceSingle:!1,minSpreadWidth:800,gap:"auto",overflow:"hidden",infinite:!1}),EPUBJS.core.extend(this.settings,e),this.isForcedSingle=this.settings.forceSingle,this.viewSettings={axis:this.settings.axis},this.start()},EPUBJS.Paginate.prototype=Object.create(EPUBJS.Continuous.prototype),EPUBJS.Paginate.prototype.constructor=EPUBJS.Paginate,EPUBJS.Paginate.prototype.determineSpreads=function(t){return this.isForcedSingle||!t||this.bounds().width1?(t=h.left-s[0].position().left,i=t+this.layout.column,e=h.left+this.layout.spread-s[s.length-1].position().left,n=e+this.layout.column,r=this.map.page(s[0],t,i),o=this.map.page(s[s.length-1],e,n),{start:r.start,end:o.end}):void 0},EPUBJS.Paginate.prototype.resize=function(t,e){this.q.clear(),this.stageSize(t,e),this.updateLayout(),this.display(this.location.start),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},EPUBJS.Paginate.prototype.onResized=function(){this.clear(),clearTimeout(this.resizeTimeout),this.resizeTimeout=setTimeout(function(){this.resize()}.bind(this),150)},EPUBJS.Paginate.prototype.adjustImages=function(t){return t.addStylesheetRules([["img",["max-width",this.layout.spread+"px"],["max-height",this.layout.height+"px"]]]),new RSVP.Promise(function(t){setTimeout(function(){t()},1)})},EPUBJS.Map=function(t){this.layout=t},EPUBJS.Map.prototype.section=function(t){var e=this.findRanges(t),i=this.rangeListToCfiList(t,e);return i},EPUBJS.Map.prototype.page=function(t,e,i){var n=t.document.body;return this.rangePairToCfiPair(t.section,{start:this.findStart(n,e,i),end:this.findEnd(n,e,i)})},EPUBJS.Map.prototype.walk=function(t,e){for(var i,n,r=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,{acceptNode:function(t){return t.data.trim().length>0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}},!1);(i=r.nextNode())&&!(n=e(i)););return n},EPUBJS.Map.prototype.findRanges=function(t){for(var e,i,n=[],r=this.layout.count(t),o=this.layout.column,s=this.layout.gap,h=0;h=e&&i>=n?t:r>e?t:(s=t,o.push(t),void 0)}))return this.findTextStartRange(r,e,i);return this.findTextStartRange(s,e,i)},EPUBJS.Map.prototype.findEnd=function(t,e,i){for(var n,r,o=[t],s=t;o.length;)if(n=o.shift(),r=this.walk(n,function(t){var e,n,r,h;return t.nodeType==Node.TEXT_NODE?(h=document.createRange(),h.selectNodeContents(t),r=h.getBoundingClientRect()):r=t.getBoundingClientRect(),e=r.left,n=r.right,e>i&&s?s:n>i?t:(s=t,o.push(t),void 0)}))return this.findTextEndRange(r,e,i);return this.findTextEndRange(s,e,i)},EPUBJS.Map.prototype.findTextStartRange=function(t,e){for(var i,n,r,o=this.splitTextNodeIntoRanges(t),s=0;s=e)return n;i=n}return o[0]},EPUBJS.Map.prototype.findTextEndRange=function(t,e,i){for(var n,r,o,s=this.splitTextNodeIntoRanges(t),h=0;hi&&n)return n;if(o.right>i)return r;n=r}return s[s.length-1]},EPUBJS.Map.prototype.splitTextNodeIntoRanges=function(t,e){var i,n=[],r=t.textContent||"",o=r.trim(),s=t.ownerDocument,h=e||" ";if(pos=o.indexOf(h),-1===pos||t.nodeType!=Node.TEXT_NODE)return i=s.createRange(),i.selectNodeContents(t),[i];for(i=s.createRange(),i.setStart(t,0),i.setEnd(t,pos),n.push(i),i=!1;-1!=pos;)pos=o.indexOf(h,pos+1),pos>0&&(i&&(i.setEnd(t,pos),n.push(i)),i=s.createRange(),i.setStart(t,pos+1));return i&&(i.setEnd(t,o.length),n.push(i)),n},EPUBJS.Map.prototype.rangePairToCfiPair=function(t,e){var i=e.start,n=e.end;return i.collapse(!0),n.collapse(!0),startCfi=t.cfiFromRange(i),endCfi=t.cfiFromRange(n),{start:startCfi,end:endCfi}},EPUBJS.Map.prototype.rangeListToCfiList=function(t,e){for(var i,n=[],r=0;r