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