diff --git a/dist/epub.js b/dist/epub.js index 6d0285f..e289282 100644 --- a/dist/epub.js +++ b/dist/epub.js @@ -5253,11 +5253,12 @@ function EpubCFI(cfiFrom, base, options){ this.fromNode(cfiFrom); } else if (type === 'EpubCFI') { return cfiFrom; + } else if (!cfiFrom) { + return this; } else { throw new TypeError('not a valid argument for EpubCFI'); } - return this; }; EpubCFI.prototype.checkType = function(cfi) { @@ -5267,9 +5268,9 @@ EpubCFI.prototype.checkType = function(cfi) { cfi[cfi.length-1] === ")") { return 'string'; // Is a range object - } else if (typeof cfi === 'object' && cfi.startContainer && cfi.startOffset){ +} else if (typeof cfi === 'object' && cfi instanceof window.Range){ return 'range'; - } else if (typeof cfi === 'object' && cfi.nodeType){ // || typeof cfi === 'function' + } else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function' return 'node'; } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){ return 'EpubCFI'; @@ -5499,6 +5500,55 @@ EpubCFI.prototype.toString = function() { return cfiString; }; +EpubCFI.prototype.compare = function(cfiOne, cfiTwo) { + if(typeof cfiOne === 'string') { + cfiOne = new EpubCFI(cfiOne); + } + if(typeof cfiTwo === 'string') { + cfiTwo = new 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.path.steps.length; i++) { + if(!cfiTwo.path.steps[i]) { + return 1; + } + if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) { + return 1; + } + if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) { + return -1; + } + // Otherwise continue checking + } + + // All steps in First present in Second + if(cfiOne.path.steps.length < cfiTwo.path.steps.length) { + return -1; + } + + // Compare the charecter offset of the text node + if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) { + return 1; + } + if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) { + return -1; + } + + // TODO: compare ranges + + // CFI's are equal + return 0; +}; + module.exports = EpubCFI; },{"./core":8,"urijs":5}],10:[function(require,module,exports){ diff --git a/dist/epub.js.map b/dist/epub.js.map index c587993..1b19cc1 100644 --- a/dist/epub.js.map +++ b/dist/epub.js.map @@ -1 +1 @@ -{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","libs/mime/mime.js","node_modules/browserify/lib/_empty.js","node_modules/browserify/node_modules/process/browser.js","node_modules/rsvp/dist/rsvp.js","node_modules/urijs/src/URI.js","src/book.js","src/continuous.js","src/core.js","src/epubcfi.js","src/hook.js","src/layout.js","src/locations.js","src/map.js","src/navigation.js","src/paginate.js","src/parser.js","src/queue.js","src/rendition.js","src/replacements.js","src/request.js","src/section.js","src/spine.js","src/unarchive.js","src/view.js","src/views.js","src/epub.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3KA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7jDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9cA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"epub.js","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n setTimeout(drainQueue, 0);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n","/*!\n * @overview RSVP - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors\n * @license Licensed under MIT license\n * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE\n * @version 3.1.0\n */\n\n(function() {\n \"use strict\";\n function lib$rsvp$utils$$objectOrFunction(x) {\n return typeof x === 'function' || (typeof x === 'object' && x !== null);\n }\n\n function lib$rsvp$utils$$isFunction(x) {\n return typeof x === 'function';\n }\n\n function lib$rsvp$utils$$isMaybeThenable(x) {\n return typeof x === 'object' && x !== null;\n }\n\n var lib$rsvp$utils$$_isArray;\n if (!Array.isArray) {\n lib$rsvp$utils$$_isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n } else {\n lib$rsvp$utils$$_isArray = Array.isArray;\n }\n\n var lib$rsvp$utils$$isArray = lib$rsvp$utils$$_isArray;\n\n var lib$rsvp$utils$$now = Date.now || function() { return new Date().getTime(); };\n\n function lib$rsvp$utils$$F() { }\n\n var lib$rsvp$utils$$o_create = (Object.create || function (o) {\n if (arguments.length > 1) {\n throw new Error('Second argument not supported');\n }\n if (typeof o !== 'object') {\n throw new TypeError('Argument must be an object');\n }\n lib$rsvp$utils$$F.prototype = o;\n return new lib$rsvp$utils$$F();\n });\n function lib$rsvp$events$$indexOf(callbacks, callback) {\n for (var i=0, l=callbacks.length; i 0.5) {\n throw new Error();\n }\n return new Author();\n }\n\n try {\n return findAuthor(); // succeed or fail\n } catch(error) {\n return findOtherAuther();\n } finally {\n // always runs\n // doesn't affect the return value\n }\n ```\n\n Asynchronous example:\n\n ```js\n findAuthor().catch(function(reason){\n return findOtherAuther();\n }).finally(function(){\n // author was either found, or not\n });\n ```\n\n @method finally\n @param {Function} callback\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'finally': function(callback, label) {\n var promise = this;\n var constructor = promise.constructor;\n\n return promise.then(function(value) {\n return constructor.resolve(callback()).then(function(){\n return value;\n });\n }, function(reason) {\n return constructor.resolve(callback()).then(function(){\n throw reason;\n });\n }, label);\n }\n };\n\n function lib$rsvp$all$settled$$AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);\n }\n\n lib$rsvp$all$settled$$AllSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$all$settled$$AllSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$all$settled$$AllSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n lib$rsvp$all$settled$$AllSettled.prototype._validationError = function() {\n return new Error('allSettled must be called with an array');\n };\n\n function lib$rsvp$all$settled$$allSettled(entries, label) {\n return new lib$rsvp$all$settled$$AllSettled(lib$rsvp$promise$$default, entries, label).promise;\n }\n var lib$rsvp$all$settled$$default = lib$rsvp$all$settled$$allSettled;\n function lib$rsvp$all$$all(array, label) {\n return lib$rsvp$promise$$default.all(array, label);\n }\n var lib$rsvp$all$$default = lib$rsvp$all$$all;\n var lib$rsvp$asap$$len = 0;\n var lib$rsvp$asap$$toString = {}.toString;\n var lib$rsvp$asap$$vertxNext;\n function lib$rsvp$asap$$asap(callback, arg) {\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len] = callback;\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len + 1] = arg;\n lib$rsvp$asap$$len += 2;\n if (lib$rsvp$asap$$len === 2) {\n // If len is 1, that means that we need to schedule an async flush.\n // If additional callbacks are queued before the queue is flushed, they\n // will be processed by this flush that we are scheduling.\n lib$rsvp$asap$$scheduleFlush();\n }\n }\n\n var lib$rsvp$asap$$default = lib$rsvp$asap$$asap;\n\n var lib$rsvp$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;\n var lib$rsvp$asap$$browserGlobal = lib$rsvp$asap$$browserWindow || {};\n var lib$rsvp$asap$$BrowserMutationObserver = lib$rsvp$asap$$browserGlobal.MutationObserver || lib$rsvp$asap$$browserGlobal.WebKitMutationObserver;\n var lib$rsvp$asap$$isNode = typeof self === 'undefined' &&\n typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';\n\n // test for web worker but not in IE10\n var lib$rsvp$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&\n typeof importScripts !== 'undefined' &&\n typeof MessageChannel !== 'undefined';\n\n // node\n function lib$rsvp$asap$$useNextTick() {\n var nextTick = process.nextTick;\n // node version 0.10.x displays a deprecation warning when nextTick is used recursively\n // setImmediate should be used instead instead\n var version = process.versions.node.match(/^(?:(\\d+)\\.)?(?:(\\d+)\\.)?(\\*|\\d+)$/);\n if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {\n nextTick = setImmediate;\n }\n return function() {\n nextTick(lib$rsvp$asap$$flush);\n };\n }\n\n // vertx\n function lib$rsvp$asap$$useVertxTimer() {\n return function() {\n lib$rsvp$asap$$vertxNext(lib$rsvp$asap$$flush);\n };\n }\n\n function lib$rsvp$asap$$useMutationObserver() {\n var iterations = 0;\n var observer = new lib$rsvp$asap$$BrowserMutationObserver(lib$rsvp$asap$$flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function() {\n node.data = (iterations = ++iterations % 2);\n };\n }\n\n // web worker\n function lib$rsvp$asap$$useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = lib$rsvp$asap$$flush;\n return function () {\n channel.port2.postMessage(0);\n };\n }\n\n function lib$rsvp$asap$$useSetTimeout() {\n return function() {\n setTimeout(lib$rsvp$asap$$flush, 1);\n };\n }\n\n var lib$rsvp$asap$$queue = new Array(1000);\n function lib$rsvp$asap$$flush() {\n for (var i = 0; i < lib$rsvp$asap$$len; i+=2) {\n var callback = lib$rsvp$asap$$queue[i];\n var arg = lib$rsvp$asap$$queue[i+1];\n\n callback(arg);\n\n lib$rsvp$asap$$queue[i] = undefined;\n lib$rsvp$asap$$queue[i+1] = undefined;\n }\n\n lib$rsvp$asap$$len = 0;\n }\n\n function lib$rsvp$asap$$attemptVertex() {\n try {\n var r = require;\n var vertx = r('vertx');\n lib$rsvp$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return lib$rsvp$asap$$useVertxTimer();\n } catch(e) {\n return lib$rsvp$asap$$useSetTimeout();\n }\n }\n\n var lib$rsvp$asap$$scheduleFlush;\n // Decide what async method to use to triggering processing of queued callbacks:\n if (lib$rsvp$asap$$isNode) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useNextTick();\n } else if (lib$rsvp$asap$$BrowserMutationObserver) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMutationObserver();\n } else if (lib$rsvp$asap$$isWorker) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMessageChannel();\n } else if (lib$rsvp$asap$$browserWindow === undefined && typeof require === 'function') {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$attemptVertex();\n } else {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useSetTimeout();\n }\n function lib$rsvp$defer$$defer(label) {\n var deferred = {};\n\n deferred['promise'] = new lib$rsvp$promise$$default(function(resolve, reject) {\n deferred['resolve'] = resolve;\n deferred['reject'] = reject;\n }, label);\n\n return deferred;\n }\n var lib$rsvp$defer$$default = lib$rsvp$defer$$defer;\n function lib$rsvp$filter$$filter(promises, filterFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(filterFn)) {\n throw new TypeError(\"You must pass a function as filter's second argument.\");\n }\n\n var length = values.length;\n var filtered = new Array(length);\n\n for (var i = 0; i < length; i++) {\n filtered[i] = filterFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(filtered, label).then(function(filtered) {\n var results = new Array(length);\n var newLength = 0;\n\n for (var i = 0; i < length; i++) {\n if (filtered[i]) {\n results[newLength] = values[i];\n newLength++;\n }\n }\n\n results.length = newLength;\n\n return results;\n });\n });\n }\n var lib$rsvp$filter$$default = lib$rsvp$filter$$filter;\n\n function lib$rsvp$promise$hash$$PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n }\n\n var lib$rsvp$promise$hash$$default = lib$rsvp$promise$hash$$PromiseHash;\n\n lib$rsvp$promise$hash$$PromiseHash.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$promise$hash$$PromiseHash.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$promise$hash$$PromiseHash.prototype._init = function() {\n this._result = {};\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validateInput = function(input) {\n return input && typeof input === 'object';\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validationError = function() {\n return new Error('Promise.hash must be called with an object');\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._enumerate = function() {\n var enumerator = this;\n var promise = enumerator.promise;\n var input = enumerator._input;\n var results = [];\n\n for (var key in input) {\n if (promise._state === lib$rsvp$$internal$$PENDING && Object.prototype.hasOwnProperty.call(input, key)) {\n results.push({\n position: key,\n entry: input[key]\n });\n }\n }\n\n var length = results.length;\n enumerator._remaining = length;\n var result;\n\n for (var i = 0; promise._state === lib$rsvp$$internal$$PENDING && i < length; i++) {\n result = results[i];\n enumerator._eachEntry(result.entry, result.position);\n }\n };\n\n function lib$rsvp$hash$settled$$HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n }\n\n lib$rsvp$hash$settled$$HashSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$promise$hash$$default.prototype);\n lib$rsvp$hash$settled$$HashSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$hash$settled$$HashSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n\n lib$rsvp$hash$settled$$HashSettled.prototype._validationError = function() {\n return new Error('hashSettled must be called with an object');\n };\n\n function lib$rsvp$hash$settled$$hashSettled(object, label) {\n return new lib$rsvp$hash$settled$$HashSettled(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$settled$$default = lib$rsvp$hash$settled$$hashSettled;\n function lib$rsvp$hash$$hash(object, label) {\n return new lib$rsvp$promise$hash$$default(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$$default = lib$rsvp$hash$$hash;\n function lib$rsvp$map$$map(promises, mapFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(mapFn)) {\n throw new TypeError(\"You must pass a function as map's second argument.\");\n }\n\n var length = values.length;\n var results = new Array(length);\n\n for (var i = 0; i < length; i++) {\n results[i] = mapFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(results, label);\n });\n }\n var lib$rsvp$map$$default = lib$rsvp$map$$map;\n\n function lib$rsvp$node$$Result() {\n this.value = undefined;\n }\n\n var lib$rsvp$node$$ERROR = new lib$rsvp$node$$Result();\n var lib$rsvp$node$$GET_THEN_ERROR = new lib$rsvp$node$$Result();\n\n function lib$rsvp$node$$getThen(obj) {\n try {\n return obj.then;\n } catch(error) {\n lib$rsvp$node$$ERROR.value= error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n\n function lib$rsvp$node$$tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch(error) {\n lib$rsvp$node$$ERROR.value = error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n function lib$rsvp$node$$makeObject(_, argumentNames) {\n var obj = {};\n var name;\n var i;\n var length = _.length;\n var args = new Array(length);\n\n for (var x = 0; x < length; x++) {\n args[x] = _[x];\n }\n\n for (i = 0; i < argumentNames.length; i++) {\n name = argumentNames[i];\n obj[name] = args[i + 1];\n }\n\n return obj;\n }\n\n function lib$rsvp$node$$arrayResult(_) {\n var length = _.length;\n var args = new Array(length - 1);\n\n for (var i = 1; i < length; i++) {\n args[i - 1] = _[i];\n }\n\n return args;\n }\n\n function lib$rsvp$node$$wrapThenable(then, promise) {\n return {\n then: function(onFulFillment, onRejection) {\n return then.call(promise, onFulFillment, onRejection);\n }\n };\n }\n\n function lib$rsvp$node$$denodeify(nodeFunc, options) {\n var fn = function() {\n var self = this;\n var l = arguments.length;\n var args = new Array(l + 1);\n var arg;\n var promiseInput = false;\n\n for (var i = 0; i < l; ++i) {\n arg = arguments[i];\n\n if (!promiseInput) {\n // TODO: clean this up\n promiseInput = lib$rsvp$node$$needsPromiseInput(arg);\n if (promiseInput === lib$rsvp$node$$GET_THEN_ERROR) {\n var p = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n lib$rsvp$$internal$$reject(p, lib$rsvp$node$$GET_THEN_ERROR.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = lib$rsvp$node$$wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n\n args[l] = function(err, val) {\n if (err)\n lib$rsvp$$internal$$reject(promise, err);\n else if (options === undefined)\n lib$rsvp$$internal$$resolve(promise, val);\n else if (options === true)\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$arrayResult(arguments));\n else if (lib$rsvp$utils$$isArray(options))\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$makeObject(arguments, options));\n else\n lib$rsvp$$internal$$resolve(promise, val);\n };\n\n if (promiseInput) {\n return lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n }\n\n var lib$rsvp$node$$default = lib$rsvp$node$$denodeify;\n\n function lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self) {\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n }\n\n function lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self){\n return lib$rsvp$promise$$default.all(args).then(function(args){\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n });\n }\n\n function lib$rsvp$node$$needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === lib$rsvp$promise$$default) {\n return true;\n } else {\n return lib$rsvp$node$$getThen(arg);\n }\n } else {\n return false;\n }\n }\n var lib$rsvp$platform$$platform;\n\n /* global self */\n if (typeof self === 'object') {\n lib$rsvp$platform$$platform = self;\n\n /* global global */\n } else if (typeof global === 'object') {\n lib$rsvp$platform$$platform = global;\n } else {\n throw new Error('no global: `self` or `global` found');\n }\n\n var lib$rsvp$platform$$default = lib$rsvp$platform$$platform;\n function lib$rsvp$race$$race(array, label) {\n return lib$rsvp$promise$$default.race(array, label);\n }\n var lib$rsvp$race$$default = lib$rsvp$race$$race;\n function lib$rsvp$reject$$reject(reason, label) {\n return lib$rsvp$promise$$default.reject(reason, label);\n }\n var lib$rsvp$reject$$default = lib$rsvp$reject$$reject;\n function lib$rsvp$resolve$$resolve(value, label) {\n return lib$rsvp$promise$$default.resolve(value, label);\n }\n var lib$rsvp$resolve$$default = lib$rsvp$resolve$$resolve;\n function lib$rsvp$rethrow$$rethrow(reason) {\n setTimeout(function() {\n throw reason;\n });\n throw reason;\n }\n var lib$rsvp$rethrow$$default = lib$rsvp$rethrow$$rethrow;\n\n // defaults\n lib$rsvp$config$$config.async = lib$rsvp$asap$$default;\n lib$rsvp$config$$config.after = function(cb) {\n setTimeout(cb, 0);\n };\n var lib$rsvp$$cast = lib$rsvp$resolve$$default;\n function lib$rsvp$$async(callback, arg) {\n lib$rsvp$config$$config.async(callback, arg);\n }\n\n function lib$rsvp$$on() {\n lib$rsvp$config$$config['on'].apply(lib$rsvp$config$$config, arguments);\n }\n\n function lib$rsvp$$off() {\n lib$rsvp$config$$config['off'].apply(lib$rsvp$config$$config, arguments);\n }\n\n // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`\n if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {\n var lib$rsvp$$callbacks = window['__PROMISE_INSTRUMENTATION__'];\n lib$rsvp$config$$configure('instrument', true);\n for (var lib$rsvp$$eventName in lib$rsvp$$callbacks) {\n if (lib$rsvp$$callbacks.hasOwnProperty(lib$rsvp$$eventName)) {\n lib$rsvp$$on(lib$rsvp$$eventName, lib$rsvp$$callbacks[lib$rsvp$$eventName]);\n }\n }\n }\n\n var lib$rsvp$umd$$RSVP = {\n 'race': lib$rsvp$race$$default,\n 'Promise': lib$rsvp$promise$$default,\n 'allSettled': lib$rsvp$all$settled$$default,\n 'hash': lib$rsvp$hash$$default,\n 'hashSettled': lib$rsvp$hash$settled$$default,\n 'denodeify': lib$rsvp$node$$default,\n 'on': lib$rsvp$$on,\n 'off': lib$rsvp$$off,\n 'map': lib$rsvp$map$$default,\n 'filter': lib$rsvp$filter$$default,\n 'resolve': lib$rsvp$resolve$$default,\n 'reject': lib$rsvp$reject$$default,\n 'all': lib$rsvp$all$$default,\n 'rethrow': lib$rsvp$rethrow$$default,\n 'defer': lib$rsvp$defer$$default,\n 'EventTarget': lib$rsvp$events$$default,\n 'configure': lib$rsvp$config$$configure,\n 'async': lib$rsvp$$async\n };\n\n /* global define:true module:true window: true */\n if (typeof define === 'function' && define['amd']) {\n define(function() { return lib$rsvp$umd$$RSVP; });\n } else if (typeof module !== 'undefined' && module['exports']) {\n module['exports'] = lib$rsvp$umd$$RSVP;\n } else if (typeof lib$rsvp$platform$$default !== 'undefined') {\n lib$rsvp$platform$$default['RSVP'] = lib$rsvp$umd$$RSVP;\n }\n}).call(this);\n\n","/*!\n * URI.js - Mutating URLs\n *\n * Version: 1.17.0\n *\n * Author: Rodney Rehm\n * Web: http://medialize.github.io/URI.js/\n *\n * Licensed under\n * MIT License http://www.opensource.org/licenses/mit-license\n * GPL v3 http://opensource.org/licenses/GPL-3.0\n *\n */\n(function (root, factory) {\n 'use strict';\n // https://github.com/umdjs/umd/blob/master/returnExports.js\n if (typeof exports === 'object') {\n // Node\n module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(['./punycode', './IPv6', './SecondLevelDomains'], factory);\n } else {\n // Browser globals (root is window)\n root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root);\n }\n}(this, function (punycode, IPv6, SLD, root) {\n 'use strict';\n /*global location, escape, unescape */\n // FIXME: v2.0.0 renamce non-camelCase properties to uppercase\n /*jshint camelcase: false */\n\n // save current URI variable, if any\n var _URI = root && root.URI;\n\n function URI(url, base) {\n var _urlSupplied = arguments.length >= 1;\n var _baseSupplied = arguments.length >= 2;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof URI)) {\n if (_urlSupplied) {\n if (_baseSupplied) {\n return new URI(url, base);\n }\n\n return new URI(url);\n }\n\n return new URI();\n }\n\n if (url === undefined) {\n if (_urlSupplied) {\n throw new TypeError('undefined is not a valid argument for URI');\n }\n\n if (typeof location !== 'undefined') {\n url = location.href + '';\n } else {\n url = '';\n }\n }\n\n this.href(url);\n\n // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor\n if (base !== undefined) {\n return this.absoluteTo(base);\n }\n\n return this;\n }\n\n URI.version = '1.17.0';\n\n var p = URI.prototype;\n var hasOwn = Object.prototype.hasOwnProperty;\n\n function escapeRegEx(string) {\n // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963\n return string.replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n }\n\n function getType(value) {\n // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value\n if (value === undefined) {\n return 'Undefined';\n }\n\n return String(Object.prototype.toString.call(value)).slice(8, -1);\n }\n\n function isArray(obj) {\n return getType(obj) === 'Array';\n }\n\n function filterArrayValues(data, value) {\n var lookup = {};\n var i, length;\n\n if (getType(value) === 'RegExp') {\n lookup = null;\n } else if (isArray(value)) {\n for (i = 0, length = value.length; i < length; i++) {\n lookup[value[i]] = true;\n }\n } else {\n lookup[value] = true;\n }\n\n for (i = 0, length = data.length; i < length; i++) {\n /*jshint laxbreak: true */\n var _match = lookup && lookup[data[i]] !== undefined\n || !lookup && value.test(data[i]);\n /*jshint laxbreak: false */\n if (_match) {\n data.splice(i, 1);\n length--;\n i--;\n }\n }\n\n return data;\n }\n\n function arrayContains(list, value) {\n var i, length;\n\n // value may be string, number, array, regexp\n if (isArray(value)) {\n // Note: this can be optimized to O(n) (instead of current O(m * n))\n for (i = 0, length = value.length; i < length; i++) {\n if (!arrayContains(list, value[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n var _type = getType(value);\n for (i = 0, length = list.length; i < length; i++) {\n if (_type === 'RegExp') {\n if (typeof list[i] === 'string' && list[i].match(value)) {\n return true;\n }\n } else if (list[i] === value) {\n return true;\n }\n }\n\n return false;\n }\n\n function arraysEqual(one, two) {\n if (!isArray(one) || !isArray(two)) {\n return false;\n }\n\n // arrays can't be equal if they have different amount of content\n if (one.length !== two.length) {\n return false;\n }\n\n one.sort();\n two.sort();\n\n for (var i = 0, l = one.length; i < l; i++) {\n if (one[i] !== two[i]) {\n return false;\n }\n }\n\n return true;\n }\n\n function trimSlashes(text) {\n var trim_expression = /^\\/+|\\/+$/g;\n return text.replace(trim_expression, '');\n }\n\n URI._parts = function() {\n return {\n protocol: null,\n username: null,\n password: null,\n hostname: null,\n urn: null,\n port: null,\n path: null,\n query: null,\n fragment: null,\n // state\n duplicateQueryParameters: URI.duplicateQueryParameters,\n escapeQuerySpace: URI.escapeQuerySpace\n };\n };\n // state: allow duplicate query parameters (a=1&a=1)\n URI.duplicateQueryParameters = false;\n // state: replaces + with %20 (space in query strings)\n URI.escapeQuerySpace = true;\n // static properties\n URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i;\n URI.idn_expression = /[^a-z0-9\\.-]/i;\n URI.punycode_expression = /(xn--)/i;\n // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?\n URI.ip4_expression = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n // credits to Rich Brown\n // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096\n // specification: http://www.ietf.org/rfc/rfc4291.txt\n URI.ip6_expression = /^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$/;\n // expression used is \"gruber revised\" (@gruber v2) determined to be the\n // best solution in a regex-golf we did a couple of ages ago at\n // * http://mathiasbynens.be/demo/url-regex\n // * http://rodneyrehm.de/t/url-regex.html\n URI.find_uri_expression = /\\b((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))/ig;\n URI.findUri = {\n // valid \"scheme://\" or \"www.\"\n start: /\\b(?:([a-z][a-z0-9.+-]*:\\/\\/)|www\\.)/gi,\n // everything up to the next whitespace\n end: /[\\s\\r\\n]|$/,\n // trim trailing punctuation captured by end RegExp\n trim: /[`!()\\[\\]{};:'\".,<>?«»“”„‘’]+$/\n };\n // http://www.iana.org/assignments/uri-schemes.html\n // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports\n URI.defaultPorts = {\n http: '80',\n https: '443',\n ftp: '21',\n gopher: '70',\n ws: '80',\n wss: '443'\n };\n // allowed hostname characters according to RFC 3986\n // ALPHA DIGIT \"-\" \".\" \"_\" \"~\" \"!\" \"$\" \"&\" \"'\" \"(\" \")\" \"*\" \"+\" \",\" \";\" \"=\" %encoded\n // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . -\n URI.invalid_hostname_characters = /[^a-zA-Z0-9\\.-]/;\n // map DOM Elements to their URI attribute\n URI.domAttributes = {\n 'a': 'href',\n 'blockquote': 'cite',\n 'link': 'href',\n 'base': 'href',\n 'script': 'src',\n 'form': 'action',\n 'img': 'src',\n 'area': 'href',\n 'iframe': 'src',\n 'embed': 'src',\n 'source': 'src',\n 'track': 'src',\n 'input': 'src', // but only if type=\"image\"\n 'audio': 'src',\n 'video': 'src'\n };\n URI.getDomAttribute = function(node) {\n if (!node || !node.nodeName) {\n return undefined;\n }\n\n var nodeName = node.nodeName.toLowerCase();\n // should only expose src for type=\"image\"\n if (nodeName === 'input' && node.type !== 'image') {\n return undefined;\n }\n\n return URI.domAttributes[nodeName];\n };\n\n function escapeForDumbFirefox36(value) {\n // https://github.com/medialize/URI.js/issues/91\n return escape(value);\n }\n\n // encoding / decoding according to RFC3986\n function strictEncodeURIComponent(string) {\n // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent\n return encodeURIComponent(string)\n .replace(/[!'()*]/g, escapeForDumbFirefox36)\n .replace(/\\*/g, '%2A');\n }\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n URI.iso8859 = function() {\n URI.encode = escape;\n URI.decode = unescape;\n };\n URI.unicode = function() {\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n };\n URI.characters = {\n pathname: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,\n map: {\n // -._~!'()*\n '%24': '$',\n '%26': '&',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%3A': ':',\n '%40': '@'\n }\n },\n decode: {\n expression: /[\\/\\?#]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23'\n }\n }\n },\n reserved: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,\n map: {\n // gen-delims\n '%3A': ':',\n '%2F': '/',\n '%3F': '?',\n '%23': '#',\n '%5B': '[',\n '%5D': ']',\n '%40': '@',\n // sub-delims\n '%21': '!',\n '%24': '$',\n '%26': '&',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '='\n }\n }\n },\n urnpath: {\n // The characters under `encode` are the characters called out by RFC 2141 as being acceptable\n // for usage in a URN. RFC2141 also calls out \"-\", \".\", and \"_\" as acceptable characters, but\n // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also\n // note that the colon character is not featured in the encoding map; this is because URI.js\n // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it\n // should not appear unencoded in a segment itself.\n // See also the note above about RFC3986 and capitalalized hex digits.\n encode: {\n expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,\n map: {\n '%21': '!',\n '%24': '$',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%40': '@'\n }\n },\n // These characters are the characters called out by RFC2141 as \"reserved\" characters that\n // should never appear in a URN, plus the colon character (see note above).\n decode: {\n expression: /[\\/\\?#:]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23',\n ':': '%3A'\n }\n }\n }\n };\n URI.encodeQuery = function(string, escapeQuerySpace) {\n var escaped = URI.encode(string + '');\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped;\n };\n URI.decodeQuery = function(string, escapeQuerySpace) {\n string += '';\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n try {\n return URI.decode(escapeQuerySpace ? string.replace(/\\+/g, '%20') : string);\n } catch(e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n // generate encode/decode path functions\n var _parts = {'encode':'encode', 'decode':'decode'};\n var _part;\n var generateAccessor = function(_group, _part) {\n return function(string) {\n try {\n return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {\n return URI.characters[_group][_part].map[c];\n });\n } catch (e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n };\n\n for (_part in _parts) {\n URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);\n URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]);\n }\n\n var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) {\n return function(string) {\n // Why pass in names of functions, rather than the function objects themselves? The\n // definitions of some functions (but in particular, URI.decode) will occasionally change due\n // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure\n // that the functions we use here are \"fresh\".\n var actualCodingFunc;\n if (!_innerCodingFuncName) {\n actualCodingFunc = URI[_codingFuncName];\n } else {\n actualCodingFunc = function(string) {\n return URI[_codingFuncName](URI[_innerCodingFuncName](string));\n };\n }\n\n var segments = (string + '').split(_sep);\n\n for (var i = 0, length = segments.length; i < length; i++) {\n segments[i] = actualCodingFunc(segments[i]);\n }\n\n return segments.join(_sep);\n };\n };\n\n // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.\n URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment');\n URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment');\n URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode');\n URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode');\n\n URI.encodeReserved = generateAccessor('reserved', 'encode');\n\n URI.parse = function(string, parts) {\n var pos;\n if (!parts) {\n parts = {};\n }\n // [protocol\"://\"[username[\":\"password]\"@\"]hostname[\":\"port]\"/\"?][path][\"?\"querystring][\"#\"fragment]\n\n // extract fragment\n pos = string.indexOf('#');\n if (pos > -1) {\n // escaping?\n parts.fragment = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract query\n pos = string.indexOf('?');\n if (pos > -1) {\n // escaping?\n parts.query = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract protocol\n if (string.substring(0, 2) === '//') {\n // relative-scheme\n parts.protocol = null;\n string = string.substring(2);\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n pos = string.indexOf(':');\n if (pos > -1) {\n parts.protocol = string.substring(0, pos) || null;\n if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {\n // : may be within the path\n parts.protocol = undefined;\n } else if (string.substring(pos + 1, pos + 3) === '//') {\n string = string.substring(pos + 3);\n\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n string = string.substring(pos + 1);\n parts.urn = true;\n }\n }\n }\n\n // what's left must be the path\n parts.path = string;\n\n // and we're done\n return parts;\n };\n URI.parseHost = function(string, parts) {\n // Copy chrome, IE, opera backslash-handling behavior.\n // Back slashes before the query string get converted to forward slashes\n // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124\n // See: https://code.google.com/p/chromium/issues/detail?id=25916\n // https://github.com/medialize/URI.js/pull/233\n string = string.replace(/\\\\/g, '/');\n\n // extract host:port\n var pos = string.indexOf('/');\n var bracketPos;\n var t;\n\n if (pos === -1) {\n pos = string.length;\n }\n\n if (string.charAt(0) === '[') {\n // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6\n // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts\n // IPv6+port in the format [2001:db8::1]:80 (for the time being)\n bracketPos = string.indexOf(']');\n parts.hostname = string.substring(1, bracketPos) || null;\n parts.port = string.substring(bracketPos + 2, pos) || null;\n if (parts.port === '/') {\n parts.port = null;\n }\n } else {\n var firstColon = string.indexOf(':');\n var firstSlash = string.indexOf('/');\n var nextColon = string.indexOf(':', firstColon + 1);\n if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {\n // IPv6 host contains multiple colons - but no port\n // this notation is actually not allowed by RFC 3986, but we're a liberal parser\n parts.hostname = string.substring(0, pos) || null;\n parts.port = null;\n } else {\n t = string.substring(0, pos).split(':');\n parts.hostname = t[0] || null;\n parts.port = t[1] || null;\n }\n }\n\n if (parts.hostname && string.substring(pos).charAt(0) !== '/') {\n pos++;\n string = '/' + string;\n }\n\n return string.substring(pos) || '/';\n };\n URI.parseAuthority = function(string, parts) {\n string = URI.parseUserinfo(string, parts);\n return URI.parseHost(string, parts);\n };\n URI.parseUserinfo = function(string, parts) {\n // extract username:password\n var firstSlash = string.indexOf('/');\n var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1);\n var t;\n\n // authority@ must come before /path\n if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {\n t = string.substring(0, pos).split(':');\n parts.username = t[0] ? URI.decode(t[0]) : null;\n t.shift();\n parts.password = t[0] ? URI.decode(t.join(':')) : null;\n string = string.substring(pos + 1);\n } else {\n parts.username = null;\n parts.password = null;\n }\n\n return string;\n };\n URI.parseQuery = function(string, escapeQuerySpace) {\n if (!string) {\n return {};\n }\n\n // throw out the funky business - \"?\"[name\"=\"value\"&\"]+\n string = string.replace(/&+/g, '&').replace(/^\\?*&*|&+$/g, '');\n\n if (!string) {\n return {};\n }\n\n var items = {};\n var splits = string.split('&');\n var length = splits.length;\n var v, name, value;\n\n for (var i = 0; i < length; i++) {\n v = splits[i].split('=');\n name = URI.decodeQuery(v.shift(), escapeQuerySpace);\n // no \"=\" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters\n value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;\n\n if (hasOwn.call(items, name)) {\n if (typeof items[name] === 'string' || items[name] === null) {\n items[name] = [items[name]];\n }\n\n items[name].push(value);\n } else {\n items[name] = value;\n }\n }\n\n return items;\n };\n\n URI.build = function(parts) {\n var t = '';\n\n if (parts.protocol) {\n t += parts.protocol + ':';\n }\n\n if (!parts.urn && (t || parts.hostname)) {\n t += '//';\n }\n\n t += (URI.buildAuthority(parts) || '');\n\n if (typeof parts.path === 'string') {\n if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {\n t += '/';\n }\n\n t += parts.path;\n }\n\n if (typeof parts.query === 'string' && parts.query) {\n t += '?' + parts.query;\n }\n\n if (typeof parts.fragment === 'string' && parts.fragment) {\n t += '#' + parts.fragment;\n }\n return t;\n };\n URI.buildHost = function(parts) {\n var t = '';\n\n if (!parts.hostname) {\n return '';\n } else if (URI.ip6_expression.test(parts.hostname)) {\n t += '[' + parts.hostname + ']';\n } else {\n t += parts.hostname;\n }\n\n if (parts.port) {\n t += ':' + parts.port;\n }\n\n return t;\n };\n URI.buildAuthority = function(parts) {\n return URI.buildUserinfo(parts) + URI.buildHost(parts);\n };\n URI.buildUserinfo = function(parts) {\n var t = '';\n\n if (parts.username) {\n t += URI.encode(parts.username);\n\n if (parts.password) {\n t += ':' + URI.encode(parts.password);\n }\n\n t += '@';\n }\n\n return t;\n };\n URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {\n // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html\n // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed\n // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!\n // URI.js treats the query string as being application/x-www-form-urlencoded\n // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type\n\n var t = '';\n var unique, key, i, length;\n for (key in data) {\n if (hasOwn.call(data, key) && key) {\n if (isArray(data[key])) {\n unique = {};\n for (i = 0, length = data[key].length; i < length; i++) {\n if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace);\n if (duplicateQueryParameters !== true) {\n unique[data[key][i] + ''] = true;\n }\n }\n }\n } else if (data[key] !== undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace);\n }\n }\n }\n\n return t.substring(1);\n };\n URI.buildQueryParameter = function(name, value, escapeQuerySpace) {\n // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded\n // don't append \"=\" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization\n return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '');\n };\n\n URI.addQuery = function(data, name, value) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n URI.addQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (data[name] === undefined) {\n data[name] = value;\n return;\n } else if (typeof data[name] === 'string') {\n data[name] = [data[name]];\n }\n\n if (!isArray(value)) {\n value = [value];\n }\n\n data[name] = (data[name] || []).concat(value);\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n };\n URI.removeQuery = function(data, name, value) {\n var i, length, key;\n\n if (isArray(name)) {\n for (i = 0, length = name.length; i < length; i++) {\n data[name[i]] = undefined;\n }\n } else if (getType(name) === 'RegExp') {\n for (key in data) {\n if (name.test(key)) {\n data[key] = undefined;\n }\n }\n } else if (typeof name === 'object') {\n for (key in name) {\n if (hasOwn.call(name, key)) {\n URI.removeQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (value !== undefined) {\n if (getType(value) === 'RegExp') {\n if (!isArray(data[name]) && value.test(data[name])) {\n data[name] = undefined;\n } else {\n data[name] = filterArrayValues(data[name], value);\n }\n } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) {\n data[name] = undefined;\n } else if (isArray(data[name])) {\n data[name] = filterArrayValues(data[name], value);\n }\n } else {\n data[name] = undefined;\n }\n } else {\n throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter');\n }\n };\n URI.hasQuery = function(data, name, value, withinArray) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n if (!URI.hasQuery(data, key, name[key])) {\n return false;\n }\n }\n }\n\n return true;\n } else if (typeof name !== 'string') {\n throw new TypeError('URI.hasQuery() accepts an object, string as the name parameter');\n }\n\n switch (getType(value)) {\n case 'Undefined':\n // true if exists (but may be empty)\n return name in data; // data[name] !== undefined;\n\n case 'Boolean':\n // true if exists and non-empty\n var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);\n return value === _booly;\n\n case 'Function':\n // allow complex comparison\n return !!value(data[name], name, data);\n\n case 'Array':\n if (!isArray(data[name])) {\n return false;\n }\n\n var op = withinArray ? arrayContains : arraysEqual;\n return op(data[name], value);\n\n case 'RegExp':\n if (!isArray(data[name])) {\n return Boolean(data[name] && data[name].match(value));\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n case 'Number':\n value = String(value);\n /* falls through */\n case 'String':\n if (!isArray(data[name])) {\n return data[name] === value;\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n default:\n throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter');\n }\n };\n\n\n URI.commonPath = function(one, two) {\n var length = Math.min(one.length, two.length);\n var pos;\n\n // find first non-matching character\n for (pos = 0; pos < length; pos++) {\n if (one.charAt(pos) !== two.charAt(pos)) {\n pos--;\n break;\n }\n }\n\n if (pos < 1) {\n return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';\n }\n\n // revert to last /\n if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {\n pos = one.substring(0, pos).lastIndexOf('/');\n }\n\n return one.substring(0, pos + 1);\n };\n\n URI.withinString = function(string, callback, options) {\n options || (options = {});\n var _start = options.start || URI.findUri.start;\n var _end = options.end || URI.findUri.end;\n var _trim = options.trim || URI.findUri.trim;\n var _attributeOpen = /[a-z0-9-]=[\"']?$/i;\n\n _start.lastIndex = 0;\n while (true) {\n var match = _start.exec(string);\n if (!match) {\n break;\n }\n\n var start = match.index;\n if (options.ignoreHtml) {\n // attribut(e=[\"']?$)\n var attributeOpen = string.slice(Math.max(start - 3, 0), start);\n if (attributeOpen && _attributeOpen.test(attributeOpen)) {\n continue;\n }\n }\n\n var end = start + string.slice(start).search(_end);\n var slice = string.slice(start, end).replace(_trim, '');\n if (options.ignore && options.ignore.test(slice)) {\n continue;\n }\n\n end = start + slice.length;\n var result = callback(slice, start, end, string);\n string = string.slice(0, start) + result + string.slice(end);\n _start.lastIndex = start + result.length;\n }\n\n _start.lastIndex = 0;\n return string;\n };\n\n URI.ensureValidHostname = function(v) {\n // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)\n // they are not part of DNS and therefore ignored by URI.js\n\n if (v.match(URI.invalid_hostname_characters)) {\n // test punycode\n if (!punycode) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-] and Punycode.js is not available');\n }\n\n if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n }\n };\n\n // noConflict\n URI.noConflict = function(removeAll) {\n if (removeAll) {\n var unconflicted = {\n URI: this.noConflict()\n };\n\n if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {\n unconflicted.URITemplate = root.URITemplate.noConflict();\n }\n\n if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {\n unconflicted.IPv6 = root.IPv6.noConflict();\n }\n\n if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {\n unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict();\n }\n\n return unconflicted;\n } else if (root.URI === this) {\n root.URI = _URI;\n }\n\n return this;\n };\n\n p.build = function(deferBuild) {\n if (deferBuild === true) {\n this._deferred_build = true;\n } else if (deferBuild === undefined || this._deferred_build) {\n this._string = URI.build(this._parts);\n this._deferred_build = false;\n }\n\n return this;\n };\n\n p.clone = function() {\n return new URI(this);\n };\n\n p.valueOf = p.toString = function() {\n return this.build(false)._string;\n };\n\n\n function generateSimpleAccessor(_part){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n this._parts[_part] = v || null;\n this.build(!build);\n return this;\n }\n };\n }\n\n function generatePrefixAccessor(_part, _key){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n if (v !== null) {\n v = v + '';\n if (v.charAt(0) === _key) {\n v = v.substring(1);\n }\n }\n\n this._parts[_part] = v;\n this.build(!build);\n return this;\n }\n };\n }\n\n p.protocol = generateSimpleAccessor('protocol');\n p.username = generateSimpleAccessor('username');\n p.password = generateSimpleAccessor('password');\n p.hostname = generateSimpleAccessor('hostname');\n p.port = generateSimpleAccessor('port');\n p.query = generatePrefixAccessor('query', '?');\n p.fragment = generatePrefixAccessor('fragment', '#');\n\n p.search = function(v, build) {\n var t = this.query(v, build);\n return typeof t === 'string' && t.length ? ('?' + t) : t;\n };\n p.hash = function(v, build) {\n var t = this.fragment(v, build);\n return typeof t === 'string' && t.length ? ('#' + t) : t;\n };\n\n p.pathname = function(v, build) {\n if (v === undefined || v === true) {\n var res = this._parts.path || (this._parts.hostname ? '/' : '');\n return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res;\n } else {\n if (this._parts.urn) {\n this._parts.path = v ? URI.recodeUrnPath(v) : '';\n } else {\n this._parts.path = v ? URI.recodePath(v) : '/';\n }\n this.build(!build);\n return this;\n }\n };\n p.path = p.pathname;\n p.href = function(href, build) {\n var key;\n\n if (href === undefined) {\n return this.toString();\n }\n\n this._string = '';\n this._parts = URI._parts();\n\n var _URI = href instanceof URI;\n var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname);\n if (href.nodeName) {\n var attribute = URI.getDomAttribute(href);\n href = href[attribute] || '';\n _object = false;\n }\n\n // window.location is reported to be an object, but it's not the sort\n // of object we're looking for:\n // * location.protocol ends with a colon\n // * location.query != object.search\n // * location.hash != object.fragment\n // simply serializing the unknown object should do the trick\n // (for location, not for everything...)\n if (!_URI && _object && href.pathname !== undefined) {\n href = href.toString();\n }\n\n if (typeof href === 'string' || href instanceof String) {\n this._parts = URI.parse(String(href), this._parts);\n } else if (_URI || _object) {\n var src = _URI ? href._parts : href;\n for (key in src) {\n if (hasOwn.call(this._parts, key)) {\n this._parts[key] = src[key];\n }\n }\n } else {\n throw new TypeError('invalid input');\n }\n\n this.build(!build);\n return this;\n };\n\n // identification accessors\n p.is = function(what) {\n var ip = false;\n var ip4 = false;\n var ip6 = false;\n var name = false;\n var sld = false;\n var idn = false;\n var punycode = false;\n var relative = !this._parts.urn;\n\n if (this._parts.hostname) {\n relative = false;\n ip4 = URI.ip4_expression.test(this._parts.hostname);\n ip6 = URI.ip6_expression.test(this._parts.hostname);\n ip = ip4 || ip6;\n name = !ip;\n sld = name && SLD && SLD.has(this._parts.hostname);\n idn = name && URI.idn_expression.test(this._parts.hostname);\n punycode = name && URI.punycode_expression.test(this._parts.hostname);\n }\n\n switch (what.toLowerCase()) {\n case 'relative':\n return relative;\n\n case 'absolute':\n return !relative;\n\n // hostname identification\n case 'domain':\n case 'name':\n return name;\n\n case 'sld':\n return sld;\n\n case 'ip':\n return ip;\n\n case 'ip4':\n case 'ipv4':\n case 'inet4':\n return ip4;\n\n case 'ip6':\n case 'ipv6':\n case 'inet6':\n return ip6;\n\n case 'idn':\n return idn;\n\n case 'url':\n return !this._parts.urn;\n\n case 'urn':\n return !!this._parts.urn;\n\n case 'punycode':\n return punycode;\n }\n\n return null;\n };\n\n // component specific input validation\n var _protocol = p.protocol;\n var _port = p.port;\n var _hostname = p.hostname;\n\n p.protocol = function(v, build) {\n if (v !== undefined) {\n if (v) {\n // accept trailing ://\n v = v.replace(/:(\\/\\/)?$/, '');\n\n if (!v.match(URI.protocol_expression)) {\n throw new TypeError('Protocol \"' + v + '\" contains characters other than [A-Z0-9.+-] or doesn\\'t start with [A-Z]');\n }\n }\n }\n return _protocol.call(this, v, build);\n };\n p.scheme = p.protocol;\n p.port = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n if (v === 0) {\n v = null;\n }\n\n if (v) {\n v += '';\n if (v.charAt(0) === ':') {\n v = v.substring(1);\n }\n\n if (v.match(/[^0-9]/)) {\n throw new TypeError('Port \"' + v + '\" contains characters other than [0-9]');\n }\n }\n }\n return _port.call(this, v, build);\n };\n p.hostname = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n var x = {};\n var res = URI.parseHost(v, x);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n v = x.hostname;\n }\n return _hostname.call(this, v, build);\n };\n\n // compound accessors\n p.origin = function(v, build) {\n var parts;\n\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n var protocol = this.protocol();\n var authority = this.authority();\n if (!authority) return '';\n return (protocol ? protocol + '://' : '') + this.authority();\n } else {\n var origin = URI(v);\n this\n .protocol(origin.protocol())\n .authority(origin.authority())\n .build(!build);\n return this;\n }\n };\n p.host = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildHost(this._parts) : '';\n } else {\n var res = URI.parseHost(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.authority = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildAuthority(this._parts) : '';\n } else {\n var res = URI.parseAuthority(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.userinfo = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n if (!this._parts.username) {\n return '';\n }\n\n var t = URI.buildUserinfo(this._parts);\n return t.substring(0, t.length -1);\n } else {\n if (v[v.length-1] !== '@') {\n v += '@';\n }\n\n URI.parseUserinfo(v, this._parts);\n this.build(!build);\n return this;\n }\n };\n p.resource = function(v, build) {\n var parts;\n\n if (v === undefined) {\n return this.path() + this.search() + this.hash();\n }\n\n parts = URI.parse(v);\n this._parts.path = parts.path;\n this._parts.query = parts.query;\n this._parts.fragment = parts.fragment;\n this.build(!build);\n return this;\n };\n\n // fraction accessors\n p.subdomain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n // convenience, return \"www\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // grab domain and add another segment\n var end = this._parts.hostname.length - this.domain().length - 1;\n return this._parts.hostname.substring(0, end) || '';\n } else {\n var e = this._parts.hostname.length - this.domain().length;\n var sub = this._parts.hostname.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(sub));\n\n if (v && v.charAt(v.length - 1) !== '.') {\n v += '.';\n }\n\n if (v) {\n URI.ensureValidHostname(v);\n }\n\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.domain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // convenience, return \"example.org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // if hostname consists of 1 or 2 segments, it must be the domain\n var t = this._parts.hostname.match(/\\./g);\n if (t && t.length < 2) {\n return this._parts.hostname;\n }\n\n // grab tld and add another segment\n var end = this._parts.hostname.length - this.tld(build).length - 1;\n end = this._parts.hostname.lastIndexOf('.', end -1) + 1;\n return this._parts.hostname.substring(end) || '';\n } else {\n if (!v) {\n throw new TypeError('cannot set domain empty');\n }\n\n URI.ensureValidHostname(v);\n\n if (!this._parts.hostname || this.is('IP')) {\n this._parts.hostname = v;\n } else {\n var replace = new RegExp(escapeRegEx(this.domain()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.tld = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // return \"org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n var pos = this._parts.hostname.lastIndexOf('.');\n var tld = this._parts.hostname.substring(pos + 1);\n\n if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {\n return SLD.get(this._parts.hostname) || tld;\n }\n\n return tld;\n } else {\n var replace;\n\n if (!v) {\n throw new TypeError('cannot set TLD empty');\n } else if (v.match(/[^a-zA-Z0-9-]/)) {\n if (SLD && SLD.is(v)) {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n } else {\n throw new TypeError('TLD \"' + v + '\" contains characters other than [A-Z0-9]');\n }\n } else if (!this._parts.hostname || this.is('IP')) {\n throw new ReferenceError('cannot set TLD on non-domain host');\n } else {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.directory = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path && !this._parts.hostname) {\n return '';\n }\n\n if (this._parts.path === '/') {\n return '/';\n }\n\n var end = this._parts.path.length - this.filename().length - 1;\n var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '');\n\n return v ? URI.decodePath(res) : res;\n\n } else {\n var e = this._parts.path.length - this.filename().length;\n var directory = this._parts.path.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(directory));\n\n // fully qualifier directories begin with a slash\n if (!this.is('relative')) {\n if (!v) {\n v = '/';\n }\n\n if (v.charAt(0) !== '/') {\n v = '/' + v;\n }\n }\n\n // directories always end with a slash\n if (v && v.charAt(v.length - 1) !== '/') {\n v += '/';\n }\n\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.filename = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var pos = this._parts.path.lastIndexOf('/');\n var res = this._parts.path.substring(pos+1);\n\n return v ? URI.decodePathSegment(res) : res;\n } else {\n var mutatedDirectory = false;\n\n if (v.charAt(0) === '/') {\n v = v.substring(1);\n }\n\n if (v.match(/\\.?\\//)) {\n mutatedDirectory = true;\n }\n\n var replace = new RegExp(escapeRegEx(this.filename()) + '$');\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n\n if (mutatedDirectory) {\n this.normalizePath(build);\n } else {\n this.build(!build);\n }\n\n return this;\n }\n };\n p.suffix = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var filename = this.filename();\n var pos = filename.lastIndexOf('.');\n var s, res;\n\n if (pos === -1) {\n return '';\n }\n\n // suffix may only contain alnum characters (yup, I made this up.)\n s = filename.substring(pos+1);\n res = (/^[a-z0-9%]+$/i).test(s) ? s : '';\n return v ? URI.decodePathSegment(res) : res;\n } else {\n if (v.charAt(0) === '.') {\n v = v.substring(1);\n }\n\n var suffix = this.suffix();\n var replace;\n\n if (!suffix) {\n if (!v) {\n return this;\n }\n\n this._parts.path += '.' + URI.recodePath(v);\n } else if (!v) {\n replace = new RegExp(escapeRegEx('.' + suffix) + '$');\n } else {\n replace = new RegExp(escapeRegEx(suffix) + '$');\n }\n\n if (replace) {\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.segment = function(segment, v, build) {\n var separator = this._parts.urn ? ':' : '/';\n var path = this.path();\n var absolute = path.substring(0, 1) === '/';\n var segments = path.split(separator);\n\n if (segment !== undefined && typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (segment !== undefined && typeof segment !== 'number') {\n throw new Error('Bad segment \"' + segment + '\", must be 0-based integer');\n }\n\n if (absolute) {\n segments.shift();\n }\n\n if (segment < 0) {\n // allow negative indexes to address from the end\n segment = Math.max(segments.length + segment, 0);\n }\n\n if (v === undefined) {\n /*jshint laxbreak: true */\n return segment === undefined\n ? segments\n : segments[segment];\n /*jshint laxbreak: false */\n } else if (segment === null || segments[segment] === undefined) {\n if (isArray(v)) {\n segments = [];\n // collapse empty elements within array\n for (var i=0, l=v.length; i < l; i++) {\n if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) {\n continue;\n }\n\n if (segments.length && !segments[segments.length -1].length) {\n segments.pop();\n }\n\n segments.push(trimSlashes(v[i]));\n }\n } else if (v || typeof v === 'string') {\n v = trimSlashes(v);\n if (segments[segments.length -1] === '') {\n // empty trailing elements have to be overwritten\n // to prevent results such as /foo//bar\n segments[segments.length -1] = v;\n } else {\n segments.push(v);\n }\n }\n } else {\n if (v) {\n segments[segment] = trimSlashes(v);\n } else {\n segments.splice(segment, 1);\n }\n }\n\n if (absolute) {\n segments.unshift('');\n }\n\n return this.path(segments.join(separator), build);\n };\n p.segmentCoded = function(segment, v, build) {\n var segments, i, l;\n\n if (typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (v === undefined) {\n segments = this.segment(segment, v, build);\n if (!isArray(segments)) {\n segments = segments !== undefined ? URI.decode(segments) : undefined;\n } else {\n for (i = 0, l = segments.length; i < l; i++) {\n segments[i] = URI.decode(segments[i]);\n }\n }\n\n return segments;\n }\n\n if (!isArray(v)) {\n v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v;\n } else {\n for (i = 0, l = v.length; i < l; i++) {\n v[i] = URI.encode(v[i]);\n }\n }\n\n return this.segment(segment, v, build);\n };\n\n // mutating query string\n var q = p.query;\n p.query = function(v, build) {\n if (v === true) {\n return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n } else if (typeof v === 'function') {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n var result = v.call(this, data);\n this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else if (v !== undefined && typeof v !== 'string') {\n this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else {\n return q.call(this, v, build);\n }\n };\n p.setQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n\n if (typeof name === 'string' || name instanceof String) {\n data[name] = value !== undefined ? value : null;\n } else if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n data[key] = name[key];\n }\n }\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.addQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.addQuery(data, name, value === undefined ? null : value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.removeQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.removeQuery(data, name, value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.hasQuery = function(name, value, withinArray) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n return URI.hasQuery(data, name, value, withinArray);\n };\n p.setSearch = p.setQuery;\n p.addSearch = p.addQuery;\n p.removeSearch = p.removeQuery;\n p.hasSearch = p.hasQuery;\n\n // sanitizing URLs\n p.normalize = function() {\n if (this._parts.urn) {\n return this\n .normalizeProtocol(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n }\n\n return this\n .normalizeProtocol(false)\n .normalizeHostname(false)\n .normalizePort(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n };\n p.normalizeProtocol = function(build) {\n if (typeof this._parts.protocol === 'string') {\n this._parts.protocol = this._parts.protocol.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeHostname = function(build) {\n if (this._parts.hostname) {\n if (this.is('IDN') && punycode) {\n this._parts.hostname = punycode.toASCII(this._parts.hostname);\n } else if (this.is('IPv6') && IPv6) {\n this._parts.hostname = IPv6.best(this._parts.hostname);\n }\n\n this._parts.hostname = this._parts.hostname.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePort = function(build) {\n // remove port of it's the protocol's default\n if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {\n this._parts.port = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePath = function(build) {\n var _path = this._parts.path;\n if (!_path) {\n return this;\n }\n\n if (this._parts.urn) {\n this._parts.path = URI.recodeUrnPath(this._parts.path);\n this.build(!build);\n return this;\n }\n\n if (this._parts.path === '/') {\n return this;\n }\n\n var _was_relative;\n var _leadingParents = '';\n var _parent, _pos;\n\n // handle relative paths\n if (_path.charAt(0) !== '/') {\n _was_relative = true;\n _path = '/' + _path;\n }\n\n // handle relative files (as opposed to directories)\n if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {\n _path += '/';\n }\n\n // resolve simples\n _path = _path\n .replace(/(\\/(\\.\\/)+)|(\\/\\.$)/g, '/')\n .replace(/\\/{2,}/g, '/');\n\n // remember leading parents\n if (_was_relative) {\n _leadingParents = _path.substring(1).match(/^(\\.\\.\\/)+/) || '';\n if (_leadingParents) {\n _leadingParents = _leadingParents[0];\n }\n }\n\n // resolve parents\n while (true) {\n _parent = _path.indexOf('/..');\n if (_parent === -1) {\n // no more ../ to resolve\n break;\n } else if (_parent === 0) {\n // top level cannot be relative, skip it\n _path = _path.substring(3);\n continue;\n }\n\n _pos = _path.substring(0, _parent).lastIndexOf('/');\n if (_pos === -1) {\n _pos = _parent;\n }\n _path = _path.substring(0, _pos) + _path.substring(_parent + 3);\n }\n\n // revert to relative\n if (_was_relative && this.is('relative')) {\n _path = _leadingParents + _path.substring(1);\n }\n\n _path = URI.recodePath(_path);\n this._parts.path = _path;\n this.build(!build);\n return this;\n };\n p.normalizePathname = p.normalizePath;\n p.normalizeQuery = function(build) {\n if (typeof this._parts.query === 'string') {\n if (!this._parts.query.length) {\n this._parts.query = null;\n } else {\n this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace));\n }\n\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeFragment = function(build) {\n if (!this._parts.fragment) {\n this._parts.fragment = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeSearch = p.normalizeQuery;\n p.normalizeHash = p.normalizeFragment;\n\n p.iso8859 = function() {\n // expect unicode input, iso8859 output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = escape;\n URI.decode = decodeURIComponent;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.unicode = function() {\n // expect iso8859 input, unicode output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = strictEncodeURIComponent;\n URI.decode = unescape;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.readable = function() {\n var uri = this.clone();\n // removing username, password, because they shouldn't be displayed according to RFC 3986\n uri.username('').password('').normalize();\n var t = '';\n if (uri._parts.protocol) {\n t += uri._parts.protocol + '://';\n }\n\n if (uri._parts.hostname) {\n if (uri.is('punycode') && punycode) {\n t += punycode.toUnicode(uri._parts.hostname);\n if (uri._parts.port) {\n t += ':' + uri._parts.port;\n }\n } else {\n t += uri.host();\n }\n }\n\n if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {\n t += '/';\n }\n\n t += uri.path(true);\n if (uri._parts.query) {\n var q = '';\n for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {\n var kv = (qp[i] || '').split('=');\n q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n\n if (kv[1] !== undefined) {\n q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n }\n }\n t += '?' + q.substring(1);\n }\n\n t += URI.decodeQuery(uri.hash(), true);\n return t;\n };\n\n // resolving relative and absolute URLs\n p.absoluteTo = function(base) {\n var resolved = this.clone();\n var properties = ['protocol', 'username', 'password', 'hostname', 'port'];\n var basedir, i, p;\n\n if (this._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n if (!(base instanceof URI)) {\n base = new URI(base);\n }\n\n if (!resolved._parts.protocol) {\n resolved._parts.protocol = base._parts.protocol;\n }\n\n if (this._parts.hostname) {\n return resolved;\n }\n\n for (i = 0; (p = properties[i]); i++) {\n resolved._parts[p] = base._parts[p];\n }\n\n if (!resolved._parts.path) {\n resolved._parts.path = base._parts.path;\n if (!resolved._parts.query) {\n resolved._parts.query = base._parts.query;\n }\n } else if (resolved._parts.path.substring(-2) === '..') {\n resolved._parts.path += '/';\n }\n\n if (resolved.path().charAt(0) !== '/') {\n basedir = base.directory();\n basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : '';\n resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;\n resolved.normalizePath();\n }\n\n resolved.build();\n return resolved;\n };\n p.relativeTo = function(base) {\n var relative = this.clone().normalize();\n var relativeParts, baseParts, common, relativePath, basePath;\n\n if (relative._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n base = new URI(base).normalize();\n relativeParts = relative._parts;\n baseParts = base._parts;\n relativePath = relative.path();\n basePath = base.path();\n\n if (relativePath.charAt(0) !== '/') {\n throw new Error('URI is already relative');\n }\n\n if (basePath.charAt(0) !== '/') {\n throw new Error('Cannot calculate a URI relative to another relative URI');\n }\n\n if (relativeParts.protocol === baseParts.protocol) {\n relativeParts.protocol = null;\n }\n\n if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {\n return relative.build();\n }\n\n if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {\n return relative.build();\n }\n\n if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {\n relativeParts.hostname = null;\n relativeParts.port = null;\n } else {\n return relative.build();\n }\n\n if (relativePath === basePath) {\n relativeParts.path = '';\n return relative.build();\n }\n\n // determine common sub path\n common = URI.commonPath(relativePath, basePath);\n\n // If the paths have nothing in common, return a relative URL with the absolute path.\n if (!common) {\n return relative.build();\n }\n\n var parents = baseParts.path\n .substring(common.length)\n .replace(/[^\\/]*$/, '')\n .replace(/.*?\\//g, '../');\n\n relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './';\n\n return relative.build();\n };\n\n // comparing URIs\n p.equals = function(uri) {\n var one = this.clone();\n var two = new URI(uri);\n var one_map = {};\n var two_map = {};\n var checked = {};\n var one_query, two_query, key;\n\n one.normalize();\n two.normalize();\n\n // exact match\n if (one.toString() === two.toString()) {\n return true;\n }\n\n // extract query string\n one_query = one.query();\n two_query = two.query();\n one.query('');\n two.query('');\n\n // definitely not equal if not even non-query parts match\n if (one.toString() !== two.toString()) {\n return false;\n }\n\n // query parameters have the same length, even if they're permuted\n if (one_query.length !== two_query.length) {\n return false;\n }\n\n one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace);\n two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace);\n\n for (key in one_map) {\n if (hasOwn.call(one_map, key)) {\n if (!isArray(one_map[key])) {\n if (one_map[key] !== two_map[key]) {\n return false;\n }\n } else if (!arraysEqual(one_map[key], two_map[key])) {\n return false;\n }\n\n checked[key] = true;\n }\n }\n\n for (key in two_map) {\n if (hasOwn.call(two_map, key)) {\n if (!checked[key]) {\n // two contains a parameter not present in one\n return false;\n }\n }\n }\n\n return true;\n };\n\n // state\n p.duplicateQueryParameters = function(v) {\n this._parts.duplicateQueryParameters = !!v;\n return this;\n };\n\n p.escapeQuerySpace = function(v) {\n this._parts.escapeQuerySpace = !!v;\n return this;\n };\n\n return URI;\n}));\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar Spine = require('./spine');\nvar Locations = require('./locations');\nvar Parser = require('./parser');\nvar Navigation = require('./navigation');\nvar Rendition = require('./rendition');\nvar Continuous = require('./continuous');\nvar Paginate = require('./paginate');\nvar Unarchive = require('./unarchive');\nvar request = require('./request');\n\nfunction Book(_url, options){\n // Promises\n this.opening = new RSVP.defer();\n this.opened = this.opening.promise;\n this.isOpen = false;\n\n this.url = undefined;\n\n this.loading = {\n manifest: new RSVP.defer(),\n spine: new RSVP.defer(),\n metadata: new RSVP.defer(),\n cover: new RSVP.defer(),\n navigation: new RSVP.defer(),\n pageList: new RSVP.defer()\n };\n\n this.loaded = {\n manifest: this.loading.manifest.promise,\n spine: this.loading.spine.promise,\n metadata: this.loading.metadata.promise,\n cover: this.loading.cover.promise,\n navigation: this.loading.navigation.promise,\n pageList: this.loading.pageList.promise\n };\n\n this.ready = RSVP.hash(this.loaded);\n\n // Queue for methods used before opening\n this.isRendered = false;\n // this._q = core.queue(this);\n\n this.request = this.requestMethod.bind(this);\n\n this.spine = new Spine(this.request);\n this.locations = new Locations(this.spine, this.request);\n\n if(_url) {\n this.open(_url);\n }\n};\n\nBook.prototype.open = function(_url){\n var uri;\n var parse = new Parser();\n var epubPackage;\n var epubContainer;\n var book = this;\n var containerPath = \"META-INF/container.xml\";\n var location;\n\n if(!_url) {\n this.opening.resolve(this);\n return this.opened;\n }\n\n // Reuse parsed url or create a new uri object\n // if(typeof(_url) === \"object\") {\n // uri = _url;\n // } else {\n // uri = core.uri(_url);\n // }\n uri = URI(_url);\n this.url = _url;\n\n // Find path to the Container\n if(uri.suffix() === \"opf\") {\n // Direct link to package, no container\n this.packageUrl = _url;\n this.containerUrl = '';\n\n if(uri.origin()) {\n this.baseUrl = uri.origin() + \"/\" + uri.directory() + \"/\";\n } else if(window){\n this.baseUrl = uri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n this.baseUrl = uri.directory() + \"/\";\n }\n\n epubPackage = this.request(this.packageUrl);\n\n } else if(this.isArchivedUrl(uri)) {\n // Book is archived\n this.url = '/';\n this.containerUrl = URI(containerPath).absoluteTo(this.url).toString();\n\n epubContainer = this.unarchive(_url).\n then(function() {\n return this.request(this.containerUrl);\n }.bind(this));\n\n }\n // Find the path to the Package from the container\n else if (!uri.suffix()) {\n\n this.containerUrl = this.url + containerPath;\n\n epubContainer = this.request(this.containerUrl);\n }\n\n if (epubContainer) {\n epubPackage = epubContainer.\n then(function(containerXml){\n return parse.container(containerXml); // Container has path to content\n }).\n then(function(paths){\n var packageUri = URI(paths.packagePath);\n var absPackageUri = packageUri.absoluteTo(book.url);\n book.packageUrl = absPackageUri.toString();\n book.encoding = paths.encoding;\n\n // Set Url relative to the content\n if(packageUri.origin()) {\n book.baseUrl = packageUri.origin() + \"/\" + packageUri.directory() + \"/\";\n } else if(window && !book.isArchivedUrl(uri)){\n book.baseUrl = absPackageUri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n book.baseUrl = \"/\" + packageUri.directory() + \"/\";\n }\n\n return book.request(book.packageUrl);\n }).catch(function(error) {\n // handle errors in either of the two requests\n console.error(\"Could not load book at: \" + (this.packageUrl || this.containerPath));\n book.trigger(\"book:loadFailed\", (this.packageUrl || this.containerPath));\n book.opening.reject(error);\n });\n }\n\n\n epubPackage.then(function(packageXml) {\n // Get package information from epub opf\n book.unpack(packageXml);\n\n // Resolve promises\n book.loading.manifest.resolve(book.package.manifest);\n book.loading.metadata.resolve(book.package.metadata);\n book.loading.spine.resolve(book.spine);\n book.loading.cover.resolve(book.cover);\n\n book.isOpen = true;\n\n // Clear queue of any waiting book request\n\n // Resolve book opened promise\n book.opening.resolve(book);\n\n }).catch(function(error) {\n // handle errors in parsing the book\n console.error(error.message, error.stack);\n book.opening.reject(error);\n });\n\n return this.opened;\n};\n\nBook.prototype.unpack = function(packageXml){\n var book = this,\n parse = new Parser();\n\n book.package = parse.packageContents(packageXml); // Extract info from contents\n book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths\n\n this.spine.load(book.package);\n\n book.navigation = new Navigation(book.package, this.request);\n book.navigation.load().then(function(toc){\n book.toc = toc;\n book.loading.navigation.resolve(book.toc);\n });\n\n // //-- Set Global Layout setting based on metadata\n // MOVE TO RENDER\n // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);\n\n book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();\n};\n\n// Alias for book.spine.get\nBook.prototype.section = function(target) {\n return this.spine.get(target);\n};\n\n// Sugar to render a book\nBook.prototype.renderTo = function(element, options) {\n var renderMethod = (options && options.method) ?\n options.method :\n \"rendition\";\n var Renderer = require('./'+renderMethod);\n\n this.rendition = new Renderer(this, options);\n this.rendition.attachTo(element);\n\n return this.rendition;\n};\n\nBook.prototype.requestMethod = function(_url) {\n // Switch request methods\n if(this.archive) {\n return this.archive.request(_url);\n } else {\n return request(_url, null, this.requestCredentials, this.requestHeaders);\n }\n\n};\n\nBook.prototype.setRequestCredentials = function(_credentials) {\n this.requestCredentials = _credentials;\n};\n\nBook.prototype.setRequestHeaders = function(_headers) {\n this.requestHeaders = _headers;\n};\n\nBook.prototype.unarchive = function(bookUrl){\n\tthis.archive = new Unarchive();\n\treturn this.archive.open(bookUrl);\n};\n\n//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)\nBook.prototype.isArchivedUrl = function(bookUrl){\n var uri;\n var extension;\n\n if (bookUrl instanceof ArrayBuffer) {\n\t\treturn true;\n\t}\n\n // Reuse parsed url or create a new uri object\n // if(typeof(bookUrl) === \"object\") {\n // uri = bookUrl;\n // } else {\n // uri = core.uri(bookUrl);\n // }\n uri = URI(bookUrl);\n extension = uri.suffix();\n\n\tif(extension && (extension == \"epub\" || extension == \"zip\")){\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n//-- Returns the cover\nBook.prototype.coverUrl = function(){\n\tvar retrieved = this.loaded.cover.\n\t\tthen(function(url) {\n\t\t\tif(this.archive) {\n\t\t\t\treturn this.archive.createUrl(this.cover);\n\t\t\t}else{\n\t\t\t\treturn this.cover;\n\t\t\t}\n\t\t}.bind(this));\n\n\n\n\treturn retrieved;\n};\n\nmodule.exports = Book;\n\n//-- Enable binding events to book\nRSVP.EventTarget.mixin(Book.prototype);\n\n//-- Handle RSVP Errors\nRSVP.on('error', function(event) {\n console.error(event);\n});\n\nRSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections\n// RSVP.on('created', listener);\n// RSVP.on('chained', listener);\n// RSVP.on('fulfilled', listener);\nRSVP.on('rejected', function(event){\n console.error(event.detail.message, event.detail.stack);\n});\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Rendition = require('./rendition');\nvar View = require('./view');\n\nfunction Continuous(book, options) {\n\n\tRendition.apply(this, arguments); // call super constructor.\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\toverflow: \"auto\",\n\t\taxis: \"vertical\",\n\t\toffset: 500,\n\t\toffsetDelta: 250\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t}\n\n\n};\n\n// subclass extends superclass\nContinuous.prototype = Object.create(Rendition.prototype);\nContinuous.prototype.constructor = Continuous;\n\nContinuous.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to a percent\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n\n\tif(this.settings.infinite) {\n\t\tthis.start();\n\t}\n\n\n};\n\nContinuous.prototype.parseTarget = function(target){\n\tif(this.epubcfi.isCfiString(target)) {\n cfi = this.epubcfi.parse(target);\n spinePos = cfi.spinePos;\n section = this.book.spine.get(spinePos);\n } else {\n section = this.book.spine.get(target);\n }\n};\n\nContinuous.prototype.moveTo = function(offset){\n // var bounds = this.bounds();\n // var dist = Math.floor(offset.top / bounds.height) * bounds.height;\n return this.check(\n\t\toffset.left+this.settings.offset,\n\t\toffset.top+this.settings.offset)\n\t\t.then(function(){\n\n\t if(this.settings.axis === \"vertical\") {\n\t this.scrollBy(0, offset.top);\n\t } else {\n\t this.scrollBy(offset.left, 0);\n\t }\n\n\t }.bind(this));\n};\n\nContinuous.prototype.afterDisplayed = function(currView){\n\tvar next = currView.section.next();\n\tvar prev = currView.section.prev();\n\tvar index = this.views.indexOf(currView);\n\tvar prevView, nextView;\n\n\tif(index + 1 === this.views.length && next) {\n\t\tnextView = this.createView(next);\n\t\tthis.q.enqueue(this.append, nextView);\n\t}\n\n\tif(index === 0 && prev) {\n\t\tprevView = this.createView(prev, this.viewSettings);\n\t\tthis.q.enqueue(this.prepend, prevView);\n\t}\n\n\t// this.removeShownListeners(currView);\n\t// currView.onShown = this.afterDisplayed.bind(this);\n\tthis.trigger(\"added\", currView.section);\n\n};\n\n\n// Remove Previous Listeners if present\nContinuous.prototype.removeShownListeners = function(view){\n\n\t// view.off(\"shown\", this.afterDisplayed);\n\t// view.off(\"shown\", this.afterDisplayedAbove);\n\tview.onDisplayed = function(){};\n\n};\n\nContinuous.prototype.append = function(view){\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tthis.views.append(view);\n\n //this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.prepend = function(view){\n\t// view.on(\"shown\", this.afterDisplayedAbove.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tview.on(\"resized\", this.counter.bind(this));\n\n\tthis.views.prepend(view);\n\n // this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.counter = function(bounds){\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.scrollBy(0, bounds.heightDelta, true);\n\t} else {\n\t\tthis.scrollBy(bounds.widthDelta, 0, true);\n\t}\n\n};\n\nContinuous.prototype.check = function(_offset){\n\tvar checking = new RSVP.defer();\n\tvar container = this.bounds();\n var promises = [];\n var offset = _offset || this.settings.offset;\n\n\tthis.views.each(function(view){\n\t\tvar visible = this.isVisible(view, offset, offset, container);\n\n\t\tif(visible) {\n\n\t\t\tif(!view.displayed && !view.rendering) {\n // console.log(\"render\",view.section.index)\n\t\t\t\t\tpromises.push(this.render(view));\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif(view.displayed) {\n // console.log(\"destroy\", view.section.index)\n this.q.enqueue(view.destroy.bind(view));\n // view.destroy();\n // this.q.enqueue(this.trim);\n clearTimeout(this.trimTimeout);\n this.trimTimeout = setTimeout(function(){\n this.q.enqueue(this.trim);\n }.bind(this), 250);\n\t\t\t}\n\n\t\t}\n\n\t}.bind(this));\n\n\n if(promises.length){\n\n return RSVP.all(promises)\n .then(function(posts) {\n // Check to see if anything new is on screen after rendering\n this.q.enqueue(this.check);\n\n }.bind(this));\n\n } else {\n checking.resolve();\n\n return checking.promise;\n }\n\n};\n\nContinuous.prototype.trim = function(){\n var task = new RSVP.defer();\n var displayed = this.views.displayed();\n var first = displayed[0];\n var last = displayed[displayed.length-1];\n var firstIndex = this.views.indexOf(first);\n var lastIndex = this.views.indexOf(last);\n var above = this.views.slice(0, firstIndex);\n var below = this.views.slice(lastIndex+1);\n\n // Erase all but last above\n for (var i = 0; i < above.length-1; i++) {\n this.erase(above[i], above);\n }\n\n // Erase all except first below\n for (var j = 1; j < below.length; j++) {\n this.erase(below[j]);\n }\n\n task.resolve();\n return task.promise;\n};\n\nContinuous.prototype.erase = function(view, above){ //Trim\n\n\tvar prevTop;\n\tvar prevLeft;\n\n\tif(this.settings.height) {\n \tprevTop = this.container.scrollTop;\n\t\tprevLeft = this.container.scrollLeft;\n } else {\n \tprevTop = window.scrollY;\n\t\tprevLeft = window.scrollX;\n }\n\n\tvar bounds = view.bounds();\n\n\tthis.views.remove(view);\n\n\tif(above) {\n\n\t\tif(this.settings.axis === \"vertical\") {\n\t\t\tthis.scrollTo(0, prevTop - bounds.height, true);\n\t\t} else {\n\t\t\tthis.scrollTo(prevLeft - bounds.width, 0, true);\n\t\t}\n\t}\n\n};\n\nContinuous.prototype.start = function() {\n var scroller;\n\n this.tick = core.requestAnimationFrame;\n\n if(this.settings.height) {\n \tthis.prevScrollTop = this.container.scrollTop;\n \tthis.prevScrollLeft = this.container.scrollLeft;\n } else {\n \tthis.prevScrollTop = window.scrollY;\n\t\tthis.prevScrollLeft = window.scrollX;\n }\n\n this.scrollDeltaVert = 0;\n this.scrollDeltaHorz = 0;\n\n if(this.settings.height) {\n \tscroller = this.container;\n } else {\n \tscroller = window;\n }\n\n window.addEventListener(\"scroll\", function(e){\n if(!this.ignore) {\n this.scrolled = true;\n } else {\n this.ignore = false;\n }\n }.bind(this));\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n this.tick.call(window, this.onScroll.bind(this));\n\n this.scrolled = false;\n\n};\n\nContinuous.prototype.onScroll = function(){\n\n if(this.scrolled) {\n\n if(this.settings.height) {\n\t \tscrollTop = this.container.scrollTop;\n\t \tscrollLeft = this.container.scrollLeft;\n\t } else {\n\t \tscrollTop = window.scrollY;\n\t\t\tscrollLeft = window.scrollX;\n\t }\n\n if(!this.ignore) {\n\n\t if((this.scrollDeltaVert === 0 &&\n\t \t this.scrollDeltaHorz === 0) ||\n\t \t this.scrollDeltaVert > this.settings.offsetDelta ||\n\t \t this.scrollDeltaHorz > this.settings.offsetDelta) {\n\n\t\t\t\tthis.q.enqueue(this.check);\n\n\t\t\t\tthis.scrollDeltaVert = 0;\n\t \tthis.scrollDeltaHorz = 0;\n\n\t\t\t\tthis.trigger(\"scroll\", {\n\t\t top: scrollTop,\n\t\t left: scrollLeft\n\t\t });\n\n\t\t\t}\n\n\t\t} else {\n\t this.ignore = false;\n\t\t}\n\n this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);\n this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);\n\n\t\tthis.prevScrollTop = scrollTop;\n\t\tthis.prevScrollLeft = scrollLeft;\n\n \tclearTimeout(this.scrollTimeout);\n\t\tthis.scrollTimeout = setTimeout(function(){\n\t\t\tthis.scrollDeltaVert = 0;\n\t this.scrollDeltaHorz = 0;\n\t\t}.bind(this), 150);\n\n\n this.scrolled = false;\n }\n\n this.tick.call(window, this.onScroll.bind(this));\n\n};\n\n\n Continuous.prototype.resizeView = function(view) {\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tview.lock(\"height\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nContinuous.prototype.currentLocation = function(){\n var visible = this.visible();\n var startPage, endPage;\n\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n return this.map.page(visible[0]);\n }\n\n if(visible.length > 1) {\n\n startPage = this.map.page(visible[0]);\n endPage = this.map.page(visible[visible.length-1]);\n\n return {\n start: startPage.start,\n end: endPage.end\n };\n }\n\n};\n\n/*\nContinuous.prototype.current = function(what){\n var view, top;\n var container = this.container.getBoundingClientRect();\n var length = this.views.length - 1;\n\n if(this.settings.axis === \"horizontal\") {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n left = view.position().left;\n\n if(left < container.right) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n break;\n }\n }\n\n } else {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n top = view.bounds().top;\n if(top < container.bottom) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n\n break;\n }\n }\n\n }\n\n return this._current;\n};\n*/\n\nmodule.exports = Continuous;\n","var RSVP = require('rsvp');\n\nvar requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false;\n/*\n//-- Parse the different parts of a url, returning a object\nfunction uri(url){\n var uri = {\n protocol : '',\n host : '',\n path : '',\n origin : '',\n directory : '',\n base : '',\n filename : '',\n extension : '',\n fragment : '',\n href : url\n },\n doubleSlash = url.indexOf('://'),\n search = url.indexOf('?'),\n fragment = url.indexOf(\"#\"),\n withoutProtocol,\n dot,\n firstSlash;\n\n if(fragment != -1) {\n uri.fragment = url.slice(fragment + 1);\n url = url.slice(0, fragment);\n }\n\n if(search != -1) {\n uri.search = url.slice(search + 1);\n url = url.slice(0, search);\n href = url;\n }\n\n if(doubleSlash != -1) {\n uri.protocol = url.slice(0, doubleSlash);\n withoutProtocol = url.slice(doubleSlash+3);\n firstSlash = withoutProtocol.indexOf('/');\n\n if(firstSlash === -1) {\n uri.host = uri.path;\n uri.path = \"\";\n } else {\n uri.host = withoutProtocol.slice(0, firstSlash);\n uri.path = withoutProtocol.slice(firstSlash);\n }\n\n\n uri.origin = uri.protocol + \"://\" + uri.host;\n\n uri.directory = folder(uri.path);\n\n uri.base = uri.origin + uri.directory;\n // return origin;\n } else {\n uri.path = url;\n uri.directory = folder(url);\n uri.base = uri.directory;\n }\n\n //-- Filename\n uri.filename = url.replace(uri.base, '');\n dot = uri.filename.lastIndexOf('.');\n if(dot != -1) {\n uri.extension = uri.filename.slice(dot+1);\n }\n return uri;\n};\n\n//-- Parse out the folder, will return everything before the last slash\nfunction folder(url){\n\n var lastSlash = url.lastIndexOf('/');\n\n if(lastSlash == -1) var folder = '';\n\n folder = url.slice(0, lastSlash + 1);\n\n return folder;\n\n};\n*/\nfunction isElement(obj) {\n return !!(obj && obj.nodeType == 1);\n};\n\n// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\nfunction uuid() {\n var d = new Date().getTime();\n var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (d + Math.random()*16)%16 | 0;\n d = Math.floor(d/16);\n return (c=='x' ? r : (r&0x7|0x8)).toString(16);\n });\n return uuid;\n};\n\n// From Lodash\nfunction values(object) {\n var index = -1,\n props = Object.keys(object),\n length = props.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = object[props[index]];\n }\n return result;\n};\n\nfunction resolveUrl(base, path) {\n var url = [],\n segments = [],\n baseUri = uri(base),\n pathUri = uri(path),\n baseDirectory = baseUri.directory,\n pathDirectory = pathUri.directory,\n directories = [],\n // folders = base.split(\"/\"),\n paths;\n\n // if(uri.host) {\n // return path;\n // }\n\n if(baseDirectory[0] === \"/\") {\n baseDirectory = baseDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n baseDirectory = baseDirectory.substring(0, baseDirectory.length-1);\n }\n\n if(pathDirectory[0] === \"/\") {\n pathDirectory = pathDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n pathDirectory = pathDirectory.substring(0, pathDirectory.length-1);\n }\n\n if(baseDirectory) {\n directories = baseDirectory.split(\"/\");\n }\n\n paths = pathDirectory.split(\"/\");\n\n paths.reverse().forEach(function(part, index){\n if(part === \"..\"){\n directories.pop();\n } else if(part === directories[directories.length-1]) {\n directories.pop();\n segments.unshift(part);\n } else {\n segments.unshift(part);\n }\n });\n\n url = [baseUri.origin];\n\n if(directories.length) {\n url = url.concat(directories);\n }\n\n if(segments) {\n url = url.concat(segments);\n }\n\n url = url.concat(pathUri.filename);\n\n return url.join(\"/\");\n};\n\nfunction documentHeight() {\n return Math.max(\n document.documentElement.clientHeight,\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight\n );\n};\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n};\n\nfunction prefixed(unprefixed) {\n var vendors = [\"Webkit\", \"Moz\", \"O\", \"ms\" ],\n prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],\n upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),\n length = vendors.length;\n\n if (typeof(document.body.style[unprefixed]) != 'undefined') {\n return unprefixed;\n }\n\n for ( var i=0; i < length; i++ ) {\n if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {\n return vendors[i] + upper;\n }\n }\n\n return unprefixed;\n};\n\nfunction defaults(obj) {\n for (var i = 1, length = arguments.length; i < length; i++) {\n var source = arguments[i];\n for (var prop in source) {\n if (obj[prop] === void 0) obj[prop] = source[prop];\n }\n }\n return obj;\n};\n\nfunction extend(target) {\n var sources = [].slice.call(arguments, 1);\n sources.forEach(function (source) {\n if(!source) return;\n Object.getOwnPropertyNames(source).forEach(function(propName) {\n Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));\n });\n });\n return target;\n};\n\n// Fast quicksort insert for sorted array -- based on:\n// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers\nfunction insert(item, array, compareFunction) {\n var location = locationOf(item, array, compareFunction);\n array.splice(location, 0, item);\n\n return location;\n};\n// Returns where something would fit in\nfunction locationOf(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return pivot;\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared > 0 ? pivot : pivot + 1;\n }\n\n if(compared === 0) {\n return pivot;\n }\n if(compared === -1) {\n return locationOf(item, array, compareFunction, pivot, end);\n } else{\n return locationOf(item, array, compareFunction, start, pivot);\n }\n};\n// Returns -1 of mpt found\nfunction indexOfSorted(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return -1; // Not found\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared === 0 ? pivot : -1;\n }\n if(compared === 0) {\n return pivot; // Found\n }\n if(compared === -1) {\n return indexOfSorted(item, array, compareFunction, pivot, end);\n } else{\n return indexOfSorted(item, array, compareFunction, start, pivot);\n }\n};\n\nfunction bounds(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"width\", \"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"height\", \"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction borders(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction windowBounds() {\n\n var width = window.innerWidth;\n var height = window.innerHeight;\n\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width: width,\n height: height\n };\n\n};\n\n//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496\nfunction cleanStringForXpath(str) {\n var parts = str.match(/[^'\"]+|['\"]/g);\n parts = parts.map(function(part){\n if (part === \"'\") {\n return '\\\"\\'\\\"'; // output \"'\"\n }\n\n if (part === '\"') {\n return \"\\'\\\"\\'\"; // output '\"'\n }\n return \"\\'\" + part + \"\\'\";\n });\n return \"concat(\\'\\',\" + parts.join(\",\") + \")\";\n};\n\nfunction indexOfTextNode(textNode){\n var parent = textNode.parentNode;\n var children = parent.childNodes;\n var sib;\n var index = -1;\n for (var i = 0; i < children.length; i++) {\n sib = children[i];\n if(sib.nodeType === Node.TEXT_NODE){\n index++;\n }\n if(sib == textNode) break;\n }\n\n return index;\n};\n\nfunction isXml(ext) {\n return ['xml', 'opf', 'ncx'].indexOf(ext) > -1;\n}\n\nfunction createBlobUrl(content, mime){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob = new Blob([content], {type : mime });\n\n tempUrl = _URL.createObjectURL(blob);\n\n return tempUrl;\n};\n\nmodule.exports = {\n // 'uri': uri,\n // 'folder': folder,\n 'isElement': isElement,\n 'uuid': uuid,\n 'values': values,\n 'resolveUrl': resolveUrl,\n 'indexOfSorted': indexOfSorted,\n 'documentHeight': documentHeight,\n 'isNumber': isNumber,\n 'prefixed': prefixed,\n 'defaults': defaults,\n 'extend': extend,\n 'insert': insert,\n 'locationOf': locationOf,\n 'indexOfSorted': indexOfSorted,\n 'requestAnimationFrame': requestAnimationFrame,\n 'bounds': bounds,\n 'borders': borders,\n 'windowBounds': windowBounds,\n 'cleanStringForXpath': cleanStringForXpath,\n 'indexOfTextNode': indexOfTextNode,\n 'isXml': isXml,\n 'createBlobUrl': createBlobUrl\n};\n","var URI = require('urijs');\nvar core = require('./core');\n\n/**\n EPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html\n\n Implements:\n - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)\n - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)\n\n Does Not Implement:\n - Temporal Offset (~)\n - Spatial Offset (@)\n - Temporal-Spatial Offset (~ + @)\n - Text Location Assertion ([)\n*/\n\nfunction EpubCFI(cfiFrom, base, options){\n var type;\n this.options = {\n ignoreClass: 'annotator-hl'\n };\n\n this.str = '';\n\n this.base = {};\n this.spinePos = 0; // For compatibility\n\n this.range = false; // true || false;\n\n this.path = {};\n this.start = null;\n this.end = null;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof EpubCFI)) {\n return new EpubCFI(cfiFrom, base, options);\n }\n\n // Find options\n for (var i = 1, length = arguments.length; i < length; i++) {\n if(typeof arguments[i] === 'object' && (arguments[i].ignoreClass)) {\n core.extend(this.options, arguments[i]);\n }\n }\n\n\n /* TODO: maybe accept object that includes:\n {\n spineNodeIndex: \n index: \n idref: \n }\n }\n */\n if(typeof base === 'string') {\n this.base = this.parseComponent(base);\n } else if(typeof base === 'object' && base.steps) {\n this.base = base;\n }\n\n type = this.checkType(cfiFrom);\n\n\n if(type === 'string') {\n this.str = cfiFrom;\n return core.extend(this, this.parse(cfiFrom));\n } else if (type === 'range') {\n this.fromRange(cfiFrom);\n } else if (type === 'node') {\n this.fromNode(cfiFrom);\n } else if (type === 'EpubCFI') {\n return cfiFrom;\n } else {\n throw new TypeError('not a valid argument for EpubCFI');\n }\n\n return this;\n};\n\nEpubCFI.prototype.checkType = function(cfi) {\n // is a cfi string, should be wrapped with \"epubcfi()\"\n if (typeof cfi === 'string' &&\n cfi.indexOf(\"epubcfi(\") === 0 &&\n cfi[cfi.length-1] === \")\") {\n return 'string';\n // Is a range object\n } else if (typeof cfi === 'object' && cfi.startContainer && cfi.startOffset){\n return 'range';\n } else if (typeof cfi === 'object' && cfi.nodeType){ // || typeof cfi === 'function'\n return 'node';\n } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){\n return 'EpubCFI';\n } else {\n return false;\n }\n};\n\nEpubCFI.prototype.parse = function(cfiStr) {\n var cfi = {\n spinePos: -1,\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n var baseComponent, pathComponent, range;\n\n if(typeof cfiStr !== \"string\") {\n return {spinePos: -1};\n }\n\n if(cfiStr.indexOf(\"epubcfi(\") === 0 && cfiStr[cfiStr.length-1] === \")\") {\n // Remove intial epubcfi( and ending )\n cfiStr = cfiStr.slice(8, cfiStr.length-1);\n }\n\n baseComponent = this.getChapterComponent(cfiStr);\n\n // Make sure this is a valid cfi or return\n if(!baseComponent) {\n return {spinePos: -1};\n }\n\n cfi.base = this.parseComponent(baseComponent);\n\n pathComponent = this.getPathComponent(cfiStr);\n cfi.path = this.parseComponent(pathComponent);\n\n range = this.getRange(cfiStr);\n\n if(range) {\n cfi.range = true;\n cfi.start = this.parseComponent(range[0]);\n cfi.end = this.parseComponent(range[1]);\n }\n\n // Get spine node position\n // cfi.spineSegment = cfi.base.steps[1];\n\n // Chapter segment is always the second step\n cfi.spinePos = cfi.base.steps[1].index;\n\n return cfi;\n};\n\nEpubCFI.prototype.parseComponent = function(componentStr){\n var component = {\n steps: [],\n terminal: null\n };\n var parts = componentStr.split(':');\n var steps = parts[0].split('/');\n var terminal;\n\n if(parts.length > 1) {\n terminal = parts[1];\n component.terminal = this.parseTerminal(terminal);\n }\n\n if (steps[0] === '') {\n steps.shift(); // Ignore the first slash\n }\n\n component.steps = steps.map(function(step){\n return this.parseStep(step);\n }.bind(this));\n\n return component;\n};\n\nEpubCFI.prototype.parseStep = function(stepStr){\n var type, num, index, has_brackets, id;\n\n has_brackets = stepStr.match(/\\[(.*)\\]/);\n if(has_brackets && has_brackets[1]){\n id = has_brackets[1];\n }\n\n //-- Check if step is a text node or element\n num = parseInt(stepStr);\n\n if(isNaN(num)) {\n return;\n }\n\n if(num % 2 === 0) { // Even = is an element\n type = \"element\";\n index = num / 2 - 1;\n } else {\n type = \"text\";\n index = (num - 1 ) / 2;\n }\n\n return {\n \"type\" : type,\n 'index' : index,\n 'id' : id || null\n };\n};\n\nEpubCFI.prototype.parseTerminal = function(termialStr){\n var characterOffset, textLocationAssertion;\n var assertion = termialStr.match(/\\[(.*)\\]/);\n\n if(assertion && assertion[1]){\n characterOffset = parseInt(termialStr.split('[')[0]);\n textLocationAssertion = assertion[1];\n } else {\n characterOffset = parseInt(termialStr);\n }\n\n return {\n 'offset': characterOffset,\n 'assertion': textLocationAssertion\n };\n\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n return indirection[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n if(indirection[1]) {\n ranges = indirection[1].split(',');\n return ranges[0];\n }\n\n};\n\nEpubCFI.prototype.getRange = function(cfiStr) {\n\n var ranges = cfiStr.split(\",\");\n\n if(ranges.length === 3){\n return [\n ranges[1],\n ranges[2]\n ];\n }\n\n return false;\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n var splitStr = cfiStr.split(\":\");\n return splitStr[1] || '';\n};\n\nEpubCFI.prototype.joinSteps = function(steps) {\n return steps.map(function(part){\n var segment = '';\n\n if(part.type === 'element') {\n segment += (part.index + 1) * 2;\n }\n\n if(part.type === 'text') {\n segment += 1 + (2 * part.index); // TODO: double check that this is odd\n }\n\n if(part.id) {\n segment += \"[\" + part.id + \"]\";\n }\n\n return segment;\n\n }).join('/');\n\n};\n\nEpubCFI.prototype.segmentString = function(segment) {\n var segmentString = '/';\n\n segmentString += this.joinSteps(segment.steps);\n\n if(segment.terminal && segment.terminal.offset){\n segmentString += ':' + segment.terminal.offset;\n }\n\n if(segment.terminal && segment.terminal.assertion){\n segmentString += '[' + segment.terminal.assertion + ']';\n }\n\n return segmentString;\n};\n\nEpubCFI.prototype.toString = function() {\n var cfiString = 'epubcfi(';\n\n cfiString += this.segmentString(this.base);\n\n cfiString += '!';\n cfiString += this.segmentString(this.path);\n\n // Add Range, if present\n if(this.start) {\n cfiString += ',';\n cfiString += this.segmentString(this.start);\n }\n\n if(this.end) {\n cfiString += ',';\n cfiString += this.segmentString(this.end);\n }\n\n cfiString += \")\";\n\n return cfiString;\n};\n\nmodule.exports = EpubCFI;\n","var RSVP = require('rsvp');\n\n//-- Hooks allow for injecting functions that must all complete in order before finishing\n// They will execute in parallel but all must finish before continuing\n// Functions may return a promise if they are asycn.\n\n// this.content = new EPUBJS.Hook();\n// this.content.register(function(){});\n// this.content.trigger(args).then(function(){});\n\nfunction Hook(context){\n this.context = context || this;\n this.hooks = [];\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.register = function(){\n for(var i = 0; i < arguments.length; ++i) {\n if (typeof arguments[i] === \"function\") {\n this.hooks.push(arguments[i]);\n } else {\n // unpack array\n for(var j = 0; j < arguments[i].length; ++j) {\n this.hooks.push(arguments[i][j]);\n }\n }\n }\n};\n\n// Triggers a hook to run all functions\nHook.prototype.trigger = function(){\n var args = arguments;\n var context = this.context;\n var promises = [];\n\n this.hooks.forEach(function(task, i) {\n var executing = task.apply(context, args);\n\n if(executing && typeof executing[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n promises.push(executing);\n }\n // Otherwise Task resolves immediately, continue\n });\n\n\n return RSVP.all(promises);\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.list = function(){\n return this.hooks;\n};\n\nmodule.exports = Hook;\n","var core = require('./core');\n\nfunction Reflowable(){\n\n};\n\nReflowable.prototype.calculate = function(_width, _height, _gap, _devisor){\n\n var divisor = _devisor || 1;\n\n //-- Check the width and create even width columns\n var fullWidth = Math.floor(_width);\n var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;\n\n var section = Math.floor(width / 8);\n var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);\n\n var colWidth;\n var spreadWidth;\n var delta;\n\n //-- Double Page\n if(divisor > 1) {\n colWidth = Math.floor((width - gap) / divisor);\n } else {\n colWidth = width;\n }\n\n spreadWidth = colWidth * divisor;\n\n delta = (colWidth + gap) * divisor;\n\n\n\n this.columnAxis = core.prefixed('columnAxis');\n this.columnGap = core.prefixed('columnGap');\n this.columnWidth = core.prefixed('columnWidth');\n this.columnFill = core.prefixed('columnFill');\n\n this.width = width;\n this.height = _height;\n this.spread = spreadWidth;\n this.delta = delta;\n\n this.column = colWidth;\n this.gap = gap;\n this.divisor = divisor;\n\n};\n\nReflowable.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n var $body = view.document.body;//view.document.querySelector(\"body\");\n\n $doc.style.overflow = \"hidden\";\n\n // Must be set to the new calculated width or the columns will be off\n // $body.style.width = this.width + \"px\";\n $doc.style.width = this.width + \"px\";\n\n //-- Adjust height\n $body.style.height = this.height + \"px\";\n\n //-- Add columns\n $body.style[this.columnAxis] = \"horizontal\";\n $body.style[this.columnFill] = \"auto\";\n $body.style[this.columnGap] = this.gap+\"px\";\n $body.style[this.columnWidth] = this.column+\"px\";\n\n // Add extra padding for the gap between this and the next view\n view.iframe.style.marginRight = this.gap+\"px\";\n};\n\nReflowable.prototype.count = function(view) {\n var totalWidth = view.root().scrollWidth;\n var spreads = Math.ceil(totalWidth / this.spread);\n\n return {\n spreads : spreads,\n pages : spreads * this.divisor\n };\n};\n\nfunction Fixed(_width, _height){\n\n};\n\nFixed.prototype.calculate = function(_width, _height){\n\n};\n\nFixed.prototype.format = function(view){\n var width, height;\n\n var $doc = view.document.documentElement;\n var $viewport = documentElement.querySelector(\"[name=viewport\");\n\n /**\n * check for the viewport size\n * \n */\n if($viewport && $viewport.hasAttribute(\"content\")) {\n content = $viewport.getAttribute(\"content\");\n contents = content.split(',');\n if(contents[0]){\n width = contents[0].replace(\"width=\", '');\n }\n if(contents[1]){\n height = contents[1].replace(\"height=\", '');\n }\n }\n\n //-- Adjust width and height\n // $doc.style.width = width + \"px\" || \"auto\";\n // $doc.style.height = height + \"px\" || \"auto\";\n view.resize(width, height);\n\n //-- Scroll\n $doc.style.overflow = \"auto\";\n\n};\n\nFixed.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nfunction Scroll(){\n\n};\n\nScroll.prototype.calculate = function(_width, _height){\n this.spread = _width;\n this.column = _width;\n this.gap = 0;\n};\n\nScroll.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n\n $doc.style.width = \"auto\";\n $doc.style.height = \"auto\";\n\n};\n\nScroll.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nmodule.exports = {\n 'Reflowable': Reflowable,\n 'Fixed': Fixed,\n 'Scroll': Scroll\n};\n","var core = require('./core');\nvar Queue = require('./queue');\nvar EpubCFI = require('./epubcfi');\nvar RSVP = require('rsvp');\n\nfunction Locations(spine, request) {\n this.spine = spine;\n this.request = request;\n\n this.q = new Queue(this);\n this.epubcfi = new EpubCFI();\n\n this._locations = [];\n this.total = 0;\n\n this.break = 150;\n\n this._current = 0;\n\n};\n\n// Load all of sections in the book\nLocations.prototype.generate = function(chars) {\n\n if (chars) {\n this.break = chars;\n }\n\n this.q.pause();\n\n this.spine.each(function(section) {\n\n this.q.enqueue(this.process, section);\n\n }.bind(this));\n\n return this.q.run().then(function() {\n this.total = this._locations.length-1;\n\n if (this._currentCfi) {\n this.currentLocation = this._currentCfi;\n }\n\n return this._locations;\n // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));\n }.bind(this));\n\n};\n\nLocations.prototype.process = function(section) {\n\n return section.load(this.request)\n .then(function(contents) {\n\n var range;\n var doc = contents.ownerDocument;\n var counter = 0;\n\n this.sprint(contents, function(node) {\n var len = node.length;\n var dist;\n var pos = 0;\n\n // Start range\n if (counter == 0) {\n range = doc.createRange();\n range.setStart(node, 0);\n }\n\n dist = this.break - counter;\n\n // Node is smaller than a break\n if(dist > len){\n counter += len;\n pos = len;\n }\n\n while (pos < len) {\n counter = this.break;\n pos += this.break;\n\n // Gone over\n if(pos >= len){\n // Continue counter for next node\n counter = len - (pos - this.break);\n\n // At End\n } else {\n // End the previous range\n range.setEnd(node, pos);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi);\n counter = 0;\n\n // Start new range\n pos += 1;\n range = doc.createRange();\n range.setStart(node, pos);\n }\n }\n\n\n\n }.bind(this));\n\n // Close remaining\n if (range) {\n range.setEnd(prev, prev.length);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi)\n counter = 0;\n }\n\n }.bind(this));\n\n};\n\nLocations.prototype.sprint = function(root, func) {\n\tvar treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);\n\n\twhile ((node = treeWalker.nextNode())) {\n\t\tfunc(node);\n\t}\n\n};\n\nLocations.prototype.locationFromCfi = function(cfi){\n // Check if the location has not been set yet\n\tif(this._locations.length === 0) {\n\t\treturn -1;\n\t}\n\n return core.locationOf(cfi, this._locations, this.epubcfi.compare);\n};\n\nLocations.prototype.precentageFromCfi = function(cfi) {\n // Find closest cfi\n var loc = this.locationFromCfi(cfi);\n // Get percentage in total\n return this.precentageFromLocation(loc);\n};\n\nLocations.prototype.percentageFromLocation = function(loc) {\n if (!loc || !this.total) {\n return 0;\n }\n return (loc / this.total);\n};\n\nLocations.prototype.cfiFromLocation = function(loc){\n\tvar cfi = -1;\n\t// check that pg is an int\n\tif(typeof loc != \"number\"){\n\t\tloc = parseInt(pg);\n\t}\n\n\tif(loc >= 0 && loc < this._locations.length) {\n\t\tcfi = this._locations[loc];\n\t}\n\n\treturn cfi;\n};\n\nLocations.prototype.cfiFromPercentage = function(value){\n var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1\n\tvar loc = Math.ceil(this.total * percentage);\n\n\treturn this.cfiFromLocation(loc);\n};\n\nLocations.prototype.load = function(locations){\n\tthis._locations = JSON.parse(locations);\n this.total = this._locations.length-1;\n return this._locations;\n};\n\nLocations.prototype.save = function(json){\n\treturn JSON.stringify(this._locations);\n};\n\nLocations.prototype.getCurrent = function(json){\n\treturn this._current;\n};\n\nLocations.prototype.setCurrent = function(curr){\n var loc;\n\n if(typeof curr == \"string\"){\n this._currentCfi = curr;\n } else if (typeof curr == \"number\") {\n this._current = curr;\n } else {\n return;\n }\n\n if(this._locations.length === 0) {\n return;\n\t}\n\n if(typeof curr == \"string\"){\n loc = this.locationFromCfi(curr);\n this._current = loc;\n } else {\n loc = curr;\n }\n\n this.trigger(\"changed\", {\n percentage: this.precentageFromLocation(loc)\n });\n};\n\nObject.defineProperty(Locations.prototype, 'currentLocation', {\n get: function () {\n return this._current;\n },\n set: function (curr) {\n this.setCurrent(curr);\n }\n});\n\nRSVP.EventTarget.mixin(Locations.prototype);\n\nmodule.exports = Locations;\n","function Map(layout){\n this.layout = layout;\n};\n\nMap.prototype.section = function(view) {\n var ranges = this.findRanges(view);\n var map = this.rangeListToCfiList(view, ranges);\n\n return map;\n};\n\nMap.prototype.page = function(view, start, end) {\n var root = view.document.body;\n return this.rangePairToCfiPair(view.section, {\n start: this.findStart(root, start, end),\n end: this.findEnd(root, start, end)\n });\n};\n\nMap.prototype.walk = function(root, func) {\n //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);\n var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode: function (node) {\n if ( node.data.trim().length > 0 ) {\n return NodeFilter.FILTER_ACCEPT;\n } else {\n return NodeFilter.FILTER_REJECT;\n }\n }\n }, false);\n var node;\n var result;\n while ((node = treeWalker.nextNode())) {\n result = func(node);\n if(result) break;\n }\n\n return result;\n};\n\nMap.prototype.findRanges = function(view){\n var columns = [];\n var count = this.layout.count(view);\n var column = this.layout.column;\n var gap = this.layout.gap;\n var start, end;\n\n for (var i = 0; i < count.pages; i++) {\n start = (column + gap) * i;\n end = (column * (i+1)) + (gap * i);\n columns.push({\n start: this.findStart(view.document.body, start, end),\n end: this.findEnd(view.document.body, start, end)\n });\n }\n\n return columns;\n};\n\nMap.prototype.findStart = function(root, start, end){\n var stack = [root];\n var $el;\n var found;\n var $prev = root;\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if( left >= start && left <= end ) {\n return node;\n } else if (right > start) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n if(found) {\n return this.findTextStartRange(found, start, end);\n }\n\n }\n\n // Return last element\n return this.findTextStartRange($prev, start, end);\n};\n\nMap.prototype.findEnd = function(root, start, end){\n var stack = [root];\n var $el;\n var $prev = root;\n var found;\n\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if(left > end && $prev) {\n return $prev;\n } else if(right > end) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n\n if(found){\n return this.findTextEndRange(found, start, end);\n }\n\n }\n\n // end of chapter\n return this.findTextEndRange($prev, start, end);\n};\n\n\nMap.prototype.findTextStartRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if( pos.left >= start ) {\n return range;\n }\n\n prev = range;\n\n }\n\n return ranges[0];\n};\n\nMap.prototype.findTextEndRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if(pos.left > end && prev) {\n return prev;\n } else if(pos.right > end) {\n return range;\n }\n\n prev = range;\n\n }\n\n // Ends before limit\n return ranges[ranges.length-1];\n\n};\n\nMap.prototype.splitTextNodeIntoRanges = function(node, _splitter){\n var ranges = [];\n var textContent = node.textContent || \"\";\n var text = textContent.trim();\n var range;\n var rect;\n var list;\n var doc = node.ownerDocument;\n var splitter = _splitter || \" \";\n\n pos = text.indexOf(splitter);\n\n if(pos === -1 || node.nodeType != Node.TEXT_NODE) {\n range = doc.createRange();\n range.selectNodeContents(node);\n return [range];\n }\n\n range = doc.createRange();\n range.setStart(node, 0);\n range.setEnd(node, pos);\n ranges.push(range);\n range = false;\n\n while ( pos != -1 ) {\n\n pos = text.indexOf(splitter, pos + 1);\n if(pos > 0) {\n\n if(range) {\n range.setEnd(node, pos);\n ranges.push(range);\n }\n\n range = doc.createRange();\n range.setStart(node, pos+1);\n }\n }\n\n if(range) {\n range.setEnd(node, text.length);\n ranges.push(range);\n }\n\n return ranges;\n};\n\n\n\nMap.prototype.rangePairToCfiPair = function(section, rangePair){\n\n var startRange = rangePair.start;\n var endRange = rangePair.end;\n\n startRange.collapse(true);\n endRange.collapse(true);\n\n startCfi = section.cfiFromRange(startRange);\n endCfi = section.cfiFromRange(endRange);\n\n return {\n start: startCfi,\n end: endCfi\n };\n\n};\n\nMap.prototype.rangeListToCfiList = function(view, columns){\n var map = [];\n var rangePair, cifPair;\n\n for (var i = 0; i < columns.length; i++) {\n cifPair = this.rangePairToCfiPair(view.section, columns[i]);\n\n map.push(cifPair);\n\n }\n\n return map;\n};\n\nmodule.exports = Map;\n","var core = require('./core');\nvar Parser = require('./parser');\nvar RSVP = require('rsvp');\nvar URI = require('urijs');\n\nfunction Navigation(_package, _request){\n var navigation = this;\n var parse = new Parser();\n var request = _request || require('./request');\n\n this.package = _package;\n this.toc = [];\n this.tocByHref = {};\n this.tocById = {};\n\n if(_package.navPath) {\n this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();\n this.nav = {};\n\n this.nav.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.navUrl, 'xml').then(function(xml){\n navigation.toc = parse.nav(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n\n if(_package.ncxPath) {\n this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();\n this.ncx = {};\n\n this.ncx.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.ncxUrl, 'xml').then(function(xml){\n navigation.toc = parse.ncx(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n};\n\n// Load the navigation\nNavigation.prototype.load = function(_request) {\n var request = _request || require('./request');\n var loading, loaded;\n\n if(this.nav) {\n loading = this.nav.load();\n } else if(this.ncx) {\n loading = this.ncx.load();\n } else {\n loaded = new RSVP.defer();\n loaded.resolve([]);\n loading = loaded.promise;\n }\n\n return loading;\n\n};\n\nNavigation.prototype.loaded = function(toc) {\n var item;\n\n for (var i = 0; i < toc.length; i++) {\n item = toc[i];\n this.tocByHref[item.href] = i;\n this.tocById[item.id] = i;\n }\n\n};\n\n// Get an item from the navigation\nNavigation.prototype.get = function(target) {\n var index;\n\n if(!target) {\n return this.toc;\n }\n\n if(target.indexOf(\"#\") === 0) {\n index = this.tocById[target.substring(1)];\n } else if(target in this.tocByHref){\n index = this.tocByHref[target];\n }\n\n return this.toc[index];\n};\n\nmodule.exports = Navigation;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Continuous = require('./continuous');\nvar Map = require('./map');\nvar Layout = require('./layout');\n\nfunction Paginate(book, options) {\n\n Continuous.apply(this, arguments);\n\n this.settings = core.extend(this.settings || {}, {\n width: 600,\n height: 400,\n axis: \"horizontal\",\n forceSingle: false,\n minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)\n gap: \"auto\", //-- \"auto\" or int\n overflow: \"hidden\",\n infinite: false\n });\n\n core.extend(this.settings, options);\n\n this.isForcedSingle = this.settings.forceSingle;\n\n this.viewSettings = {\n axis: this.settings.axis\n };\n\n this.start();\n};\n\nPaginate.prototype = Object.create(Continuous.prototype);\nPaginate.prototype.constructor = Paginate;\n\n\nPaginate.prototype.determineSpreads = function(cutoff){\n if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) {\n return 1; //-- Single Page\n }else{\n return 2; //-- Double Page\n }\n};\n\nPaginate.prototype.forceSingle = function(bool){\n if(bool === false) {\n this.isForcedSingle = false;\n // this.spreads = false;\n } else {\n this.isForcedSingle = true;\n // this.spreads = this.determineSpreads(this.minSpreadWidth);\n }\n this.applyLayoutMethod();\n};\n\n/**\n* Uses the settings to determine which Layout Method is needed\n* Triggers events based on the method choosen\n* Takes: Layout settings object\n* Returns: String of appropriate for EPUBJS.Layout function\n*/\n// Paginate.prototype.determineLayout = function(settings){\n// // Default is layout: reflowable & spread: auto\n// var spreads = this.determineSpreads(this.settings.minSpreadWidth);\n// console.log(\"spreads\", spreads, this.settings.minSpreadWidth)\n// var layoutMethod = spreads ? \"ReflowableSpreads\" : \"Reflowable\";\n// var scroll = false;\n//\n// if(settings.layout === \"pre-paginated\") {\n// layoutMethod = \"Fixed\";\n// scroll = true;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"none\") {\n// layoutMethod = \"Reflowable\";\n// scroll = false;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"both\") {\n// layoutMethod = \"ReflowableSpreads\";\n// scroll = false;\n// spreads = true;\n// }\n//\n// this.spreads = spreads;\n//\n// return layoutMethod;\n// };\n\nPaginate.prototype.start = function(){\n // On display\n // this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);\n // this.layoutMethod = this.determineLayout(this.layoutSettings);\n // this.layout = new EPUBJS.Layout[this.layoutMethod]();\n //this.hooks.display.register(this.registerLayoutMethod.bind(this));\n // this.hooks.display.register(this.reportLocation);\n this.on('displayed', this.reportLocation.bind(this));\n\n // this.hooks.content.register(this.adjustImages.bind(this));\n\n this.currentPage = 0;\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n};\n\n// EPUBJS.Rendition.prototype.createView = function(section) {\n// var view = new EPUBJS.View(section, this.viewSettings);\n\n\n// return view;\n// };\n\nPaginate.prototype.applyLayoutMethod = function() {\n //var task = new RSVP.defer();\n\n // this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout = new Layout.Reflowable();\n\n this.updateLayout();\n\n // Set the look ahead offset for what is visible\n\n this.map = new Map(this.layout);\n\n // this.hooks.layout.register(this.layout.format.bind(this));\n\n //task.resolve();\n //return task.promise;\n // return layout;\n};\n\nPaginate.prototype.updateLayout = function() {\n\n this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout.calculate(\n this.stage.width,\n this.stage.height,\n this.settings.gap,\n this.spreads\n );\n\n this.settings.offset = this.layout.delta;\n\n};\n\nPaginate.prototype.moveTo = function(offset){\n var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n return this.check(0, dist+this.settings.offset).then(function(){\n this.scrollBy(dist, 0);\n }.bind(this));\n};\n\nPaginate.prototype.page = function(pg){\n\n // this.currentPage = pg;\n // this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0);\n //-- Return false if page is greater than the total\n // return false;\n};\n\nPaginate.prototype.next = function(){\n\n return this.q.enqueue(function(){\n // console.log(this.container.scrollWidth, this.container.scrollLeft + this.container.offsetWidth + this.layout.delta)\n if(this.container.scrollLeft +\n this.container.offsetWidth +\n this.layout.delta < this.container.scrollWidth) {\n this.scrollBy(this.layout.delta, 0);\n } else {\n this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n }\n this.reportLocation();\n return this.check();\n });\n\n // return this.page(this.currentPage + 1);\n};\n\nPaginate.prototype.prev = function(){\n\n return this.q.enqueue(function(){\n this.scrollBy(-this.layout.delta, 0);\n this.reportLocation();\n return this.check();\n });\n // return this.page(this.currentPage - 1);\n};\n\n// Paginate.prototype.reportLocation = function(){\n// return this.q.enqueue(function(){\n// this.location = this.currentLocation();\n// this.trigger(\"locationChanged\", this.location);\n// }.bind(this));\n// };\n\nPaginate.prototype.currentLocation = function(){\n var visible = this.visible();\n var startA, startB, endA, endB;\n var pageLeft, pageRight;\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.spread;\n\n return this.map.page(visible[0], startA, endA);\n }\n\n if(visible.length > 1) {\n\n // Left Col\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.column;\n\n // Right Col\n startB = container.left + this.layout.spread - visible[visible.length-1].position().left;\n endB = startB + this.layout.column;\n\n pageLeft = this.map.page(visible[0], startA, endA);\n pageRight = this.map.page(visible[visible.length-1], startB, endB);\n\n return {\n start: pageLeft.start,\n end: pageRight.end\n };\n }\n};\n\nPaginate.prototype.resize = function(width, height){\n // Clear the queue\n this.q.clear();\n\n this.stageSize(width, height);\n\n this.updateLayout();\n\n if(this.location) {\n this.display(this.location.start);\n }\n\n this.trigger(\"resized\", {\n width: this.stage.width,\n height: this.stage.height\n });\n\n};\n\nPaginate.prototype.onResized = function(e) {\n\n this.views.clear();\n\n clearTimeout(this.resizeTimeout);\n this.resizeTimeout = setTimeout(function(){\n this.resize();\n }.bind(this), 150);\n};\n\nPaginate.prototype.adjustImages = function(view) {\n\n view.addStylesheetRules([\n [\"img\",\n [\"max-width\", (this.layout.spread) + \"px\"],\n [\"max-height\", (this.layout.height) + \"px\"]\n ]\n ]);\n return new RSVP.Promise(function(resolve, reject){\n // Wait to apply\n setTimeout(function() {\n resolve();\n }, 1);\n });\n};\n\n// Paginate.prototype.display = function(what){\n// return this.display(what);\n// };\n\nmodule.exports = Paginate;\n","var URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction Parser(){};\n\nParser.prototype.container = function(containerXml){\n //-- \n var rootfile, fullpath, folder, encoding;\n\n if(!containerXml) {\n console.error(\"Container File Not Found\");\n return;\n }\n\n rootfile = containerXml.querySelector(\"rootfile\");\n\n if(!rootfile) {\n console.error(\"No RootFile Found\");\n return;\n }\n\n fullpath = rootfile.getAttribute('full-path');\n folder = URI(fullpath).directory();\n encoding = containerXml.xmlEncoding;\n\n //-- Now that we have the path we can parse the contents\n return {\n 'packagePath' : fullpath,\n 'basePath' : folder,\n 'encoding' : encoding\n };\n};\n\nParser.prototype.identifier = function(packageXml){\n var metadataNode;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n return this.getElementText(metadataNode, \"identifier\");\n};\n\nParser.prototype.packageContents = function(packageXml){\n var parse = this;\n var metadataNode, manifestNode, spineNode;\n var manifest, navPath, ncxPath, coverPath;\n var spineNodeIndex;\n var spine;\n var spineIndexByURL;\n var metadata;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n manifestNode = packageXml.querySelector(\"manifest\");\n if(!manifestNode) {\n console.error(\"No Manifest Found\");\n return;\n }\n\n spineNode = packageXml.querySelector(\"spine\");\n if(!spineNode) {\n console.error(\"No Spine Found\");\n return;\n }\n\n manifest = parse.manifest(manifestNode);\n navPath = parse.findNavPath(manifestNode);\n ncxPath = parse.findNcxPath(manifestNode, spineNode);\n coverPath = parse.findCoverPath(packageXml);\n\n spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);\n\n spine = parse.spine(spineNode, manifest);\n\n metadata = parse.metadata(metadataNode);\n\n\tmetadata.direction = spineNode.getAttribute(\"page-progression-direction\");\n\n return {\n 'metadata' : metadata,\n 'spine' : spine,\n 'manifest' : manifest,\n 'navPath' : navPath,\n 'ncxPath' : ncxPath,\n 'coverPath': coverPath,\n 'spineNodeIndex' : spineNodeIndex\n };\n};\n\n//-- Find TOC NAV\nParser.prototype.findNavPath = function(manifestNode){\n\t// Find item with property 'nav'\n\t// Should catch nav irregardless of order\n var node = manifestNode.querySelector(\"item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']\");\n return node ? node.getAttribute('href') : false;\n};\n\n//-- Find TOC NCX: media-type=\"application/x-dtbncx+xml\" href=\"toc.ncx\"\nParser.prototype.findNcxPath = function(manifestNode, spineNode){\n\tvar node = manifestNode.querySelector(\"item[media-type='application/x-dtbncx+xml']\");\n\tvar tocId;\n\n\t// If we can't find the toc by media-type then try to look for id of the item in the spine attributes as\n\t// according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2,\n\t// \"The item that describes the NCX must be referenced by the spine toc attribute.\"\n\tif (!node) {\n\t\ttocId = spineNode.getAttribute(\"toc\");\n\t\tif(tocId) {\n\t\t\tnode = manifestNode.querySelector(\"item[id='\" + tocId + \"']\");\n\t\t}\n\t}\n\n\treturn node ? node.getAttribute('href') : false;\n};\n\n//-- Expanded to match Readium web components\nParser.prototype.metadata = function(xml){\n var metadata = {},\n p = this;\n\n metadata.title = p.getElementText(xml, 'title');\n metadata.creator = p.getElementText(xml, 'creator');\n metadata.description = p.getElementText(xml, 'description');\n\n metadata.pubdate = p.getElementText(xml, 'date');\n\n metadata.publisher = p.getElementText(xml, 'publisher');\n\n metadata.identifier = p.getElementText(xml, \"identifier\");\n metadata.language = p.getElementText(xml, \"language\");\n metadata.rights = p.getElementText(xml, \"rights\");\n\n metadata.modified_date = p.querySelectorText(xml, \"meta[property='dcterms:modified']\");\n metadata.layout = p.querySelectorText(xml, \"meta[property='rendition:layout']\");\n metadata.orientation = p.querySelectorText(xml, \"meta[property='rendition:orientation']\");\n metadata.spread = p.querySelectorText(xml, \"meta[property='rendition:spread']\");\n // metadata.page_prog_dir = packageXml.querySelector(\"spine\").getAttribute(\"page-progression-direction\");\n\n return metadata;\n};\n\n//-- Find Cover: \n//-- Fallback for Epub 2.0\nParser.prototype.findCoverPath = function(packageXml){\n\n\tvar epubVersion = packageXml.querySelector('package').getAttribute('version');\n\n\tif (epubVersion === '2.0') {\n\t\tvar metaCover = packageXml.querySelector('meta[name=\"cover\"]');\n\t\tif (metaCover) {\n\t\t\tvar coverId = metaCover.getAttribute('content');\n\t\t\tvar cover = packageXml.querySelector(\"item[id='\" + coverId + \"']\");\n\t\t\treturn cover ? cover.getAttribute('href') : false;\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\telse {\n\t\tvar node = packageXml.querySelector(\"item[properties='cover-image']\");\n\t\treturn node ? node.getAttribute('href') : false;\n\t}\n};\n\nParser.prototype.getElementText = function(xml, tag){\n var found = xml.getElementsByTagNameNS(\"http://purl.org/dc/elements/1.1/\", tag),\n el;\n\n if(!found || found.length === 0) return '';\n\n el = found[0];\n\n if(el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n\n};\n\nParser.prototype.querySelectorText = function(xml, q){\n var el = xml.querySelector(q);\n\n if(el && el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n};\n\nParser.prototype.manifest = function(manifestXml){\n var manifest = {};\n\n //-- Turn items into an array\n var selected = manifestXml.querySelectorAll(\"item\"),\n items = Array.prototype.slice.call(selected);\n\n //-- Create an object with the id as key\n items.forEach(function(item){\n var id = item.getAttribute('id'),\n href = item.getAttribute('href') || '',\n type = item.getAttribute('media-type') || '',\n properties = item.getAttribute('properties') || '';\n\n manifest[id] = {\n 'href' : href,\n // 'url' : href,\n 'type' : type,\n 'properties' : properties.length ? properties.split(' ') : []\n };\n\n });\n\n return manifest;\n\n};\n\nParser.prototype.spine = function(spineXml, manifest){\n var spine = [];\n\n var selected = spineXml.getElementsByTagName(\"itemref\"),\n items = Array.prototype.slice.call(selected);\n\n var epubcfi = new EpubCFI();\n\n //-- Add to array to mantain ordering and cross reference with manifest\n items.forEach(function(item, index){\n var idref = item.getAttribute('idref');\n // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);\n var props = item.getAttribute('properties') || '';\n var propArray = props.length ? props.split(' ') : [];\n // var manifestProps = manifest[Id].properties;\n // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];\n\n var itemref = {\n 'idref' : idref,\n 'linear' : item.getAttribute('linear') || '',\n 'properties' : propArray,\n // 'href' : manifest[Id].href,\n // 'url' : manifest[Id].url,\n 'index' : index\n // 'cfiBase' : cfiBase\n };\n spine.push(itemref);\n });\n\n return spine;\n};\n\nParser.prototype.querySelectorByType = function(html, element, type){\n\tvar query = html.querySelector(element+'[*|type=\"'+type+'\"]');\n\t// Handle IE not supporting namespaced epub:type in querySelector\n\tif(query === null || query.length === 0) {\n\t\tquery = html.querySelectorAll(element);\n\t\tfor (var i = 0; i < query.length; i++) {\n\t\t\tif(query[i].getAttributeNS(\"http://www.idpf.org/2007/ops\", \"type\") === type) {\n\t\t\t\treturn query[i];\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn query;\n\t}\n};\n\nParser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"toc\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.navItem(navItems[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.navItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"a, span\"),\n\t\t\tsrc = content.getAttribute('href') || '',\n\t\t\ttext = content.textContent || \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.toc = function(tocXml, spineIndexByURL, bookSpine){\n\tvar navPoints = tocXml.querySelectorAll(\"navMap navPoint\");\n\tvar length = navPoints.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navPoints || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.tocItem(navPoints[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.tocItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"content\"),\n\t\t\tsrc = content.getAttribute('src'),\n\t\t\tnavLabel = item.querySelector(\"navLabel\"),\n\t\t\ttext = navLabel.textContent ? navLabel.textContent : \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"page-list\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.pageListItem(navItems[i], spineIndexByURL, bookSpine);\n\t\tlist.push(item);\n\t}\n\n\treturn list;\n};\n\nParser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\tcontent = item.querySelector(\"a\"),\n\t\thref = content.getAttribute('href') || '',\n\t\ttext = content.textContent || \"\",\n\t\tpage = parseInt(text),\n\t\tisCfi = href.indexOf(\"epubcfi\"),\n\t\tsplit,\n\t\tpackageUrl,\n\t\tcfi;\n\n\tif(isCfi != -1) {\n\t\tsplit = href.split(\"#\");\n\t\tpackageUrl = split[0];\n\t\tcfi = split.length > 1 ? split[1] : false;\n\t\treturn {\n\t\t\t\"cfi\" : cfi,\n\t\t\t\"href\" : href,\n\t\t\t\"packageUrl\" : packageUrl,\n\t\t\t\"page\" : page\n\t\t};\n\t} else {\n\t\treturn {\n\t\t\t\"href\" : href,\n\t\t\t\"page\" : page\n\t\t};\n\t}\n};\n\nmodule.exports = Parser;\n","var RSVP = require('rsvp');\nvar core = require('./core');\n\nfunction Queue(_context){\n this._q = [];\n this.context = _context;\n this.tick = core.requestAnimationFrame;\n this.running = false;\n this.paused = false;\n};\n\n// Add an item to the queue\nQueue.prototype.enqueue = function() {\n var deferred, promise;\n var queued;\n var task = [].shift.call(arguments);\n var args = arguments;\n\n // Handle single args without context\n // if(args && !Array.isArray(args)) {\n // args = [args];\n // }\n if(!task) {\n return console.error(\"No Task Provided\");\n }\n\n if(typeof task === \"function\"){\n\n deferred = new RSVP.defer();\n promise = deferred.promise;\n\n queued = {\n \"task\" : task,\n \"args\" : args,\n //\"context\" : context,\n \"deferred\" : deferred,\n \"promise\" : promise\n };\n\n } else {\n // Task is a promise\n queued = {\n \"promise\" : task\n };\n\n }\n\n this._q.push(queued);\n\n // Wait to start queue flush\n if (this.paused == false && !this.running) {\n // setTimeout(this.flush.bind(this), 0);\n // this.tick.call(window, this.run.bind(this));\n this.run();\n }\n\n return queued.promise;\n};\n\n// Run one item\nQueue.prototype.dequeue = function(){\n var inwait, task, result;\n\n if(this._q.length) {\n inwait = this._q.shift();\n task = inwait.task;\n if(task){\n // console.log(task)\n\n result = task.apply(this.context, inwait.args);\n\n if(result && typeof result[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n return result.then(function(){\n inwait.deferred.resolve.apply(this.context, arguments);\n }.bind(this));\n } else {\n // Task resolves immediately\n inwait.deferred.resolve.apply(this.context, result);\n return inwait.promise;\n }\n\n\n\n } else if(inwait.promise) {\n // Task is a promise\n return inwait.promise;\n }\n\n } else {\n inwait = new RSVP.defer();\n inwait.deferred.resolve();\n return inwait.promise;\n }\n\n};\n\n// Run All Immediately\nQueue.prototype.dump = function(){\n while(this._q.length) {\n this.dequeue();\n }\n};\n\n// Run all sequentially, at convince\n\nQueue.prototype.run = function(){\n\n if(!this.running){\n this.running = true;\n this.defered = new RSVP.defer();\n }\n\n this.tick.call(window, function() {\n\n if(this._q.length) {\n\n this.dequeue()\n .then(function(){\n this.run();\n }.bind(this));\n\n } else {\n this.defered.resolve();\n this.running = undefined;\n }\n\n }.bind(this));\n\n // Unpause\n if(this.paused == true) {\n this.paused = false;\n }\n\n return this.defered.promise;\n};\n\n// Flush all, as quickly as possible\nQueue.prototype.flush = function(){\n\n if(this.running){\n return this.running;\n }\n\n if(this._q.length) {\n this.running = this.dequeue()\n .then(function(){\n this.running = undefined;\n return this.flush();\n }.bind(this));\n\n return this.running;\n }\n\n};\n\n// Clear all items in wait\nQueue.prototype.clear = function(){\n this._q = [];\n this.running = false;\n};\n\nQueue.prototype.length = function(){\n return this._q.length;\n};\n\nQueue.prototype.pause = function(){\n this.paused = true;\n};\n\n// Create a new task from a callback\nfunction Task(task, args, context){\n\n return function(){\n var toApply = arguments || [];\n\n return new RSVP.Promise(function(resolve, reject) {\n var callback = function(value){\n resolve(value);\n };\n // Add the callback to the arguments list\n toApply.push(callback);\n\n // Apply all arguments to the functions\n task.apply(this, toApply);\n\n }.bind(this));\n\n };\n\n};\n\nmodule.exports = Queue;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar replace = require('./replacements');\nvar Hook = require('./hook');\nvar EpubCFI = require('./epubcfi');\nvar Queue = require('./queue');\nvar View = require('./view');\nvar Views = require('./views');\nvar Layout = require('./layout');\nvar Map = require('./map');\n\nfunction Rendition(book, options) {\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\thidden: false,\n\t\twidth: false,\n\t\theight: null,\n\t\tlayoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},\n\t\taxis: \"vertical\"\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tthis.viewSettings = {};\n\n\tthis.book = book;\n\n\tthis.views = null;\n\n\t//-- Adds Hook methods to the Rendition prototype\n\tthis.hooks = {};\n\tthis.hooks.display = new Hook(this);\n\tthis.hooks.serialize = new Hook(this);\n\tthis.hooks.content = new Hook(this);\n\tthis.hooks.layout = new Hook(this);\n\tthis.hooks.render = new Hook(this);\n\tthis.hooks.show = new Hook(this);\n\n\tthis.hooks.content.register(replace.links.bind(this));\n\tthis.hooks.content.register(this.passViewEvents.bind(this));\n\n\t// this.hooks.display.register(this.afterDisplay.bind(this));\n\n this.epubcfi = new EpubCFI();\n\n\tthis.q = new Queue(this);\n\n\tthis.q.enqueue(this.book.opened);\n\n\tthis.q.enqueue(this.parseLayoutProperties);\n\n\tif(this.book.archive) {\n\t\tthis.replacements();\n\t}\n};\n\n/**\n* Creates an element to render to.\n* Resizes to passed width and height or to the elements size\n*/\nRendition.prototype.initialize = function(_options){\n\tvar options = _options || {};\n\tvar height = options.height;// !== false ? options.height : \"100%\";\n\tvar width = options.width;// !== false ? options.width : \"100%\";\n\tvar hidden = options.hidden || false;\n\tvar container;\n\tvar wrapper;\n\n\tif(options.height && core.isNumber(options.height)) {\n\t\theight = options.height + \"px\";\n\t}\n\n\tif(options.width && core.isNumber(options.width)) {\n\t\twidth = options.width + \"px\";\n\t}\n\n\t// Create new container element\n\tcontainer = document.createElement(\"div\");\n\n\tcontainer.id = \"epubjs-container:\" + core.uuid();\n\tcontainer.classList.add(\"epub-container\");\n\n\t// Style Element\n\tcontainer.style.fontSize = \"0\";\n\tcontainer.style.wordSpacing = \"0\";\n\tcontainer.style.lineHeight = \"0\";\n\tcontainer.style.verticalAlign = \"top\";\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tcontainer.style.whiteSpace = \"nowrap\";\n\t}\n\n\tif(width){\n\t\tcontainer.style.width = width;\n\t}\n\n\tif(height){\n\t\tcontainer.style.height = height;\n\t}\n\n\tcontainer.style.overflow = this.settings.overflow;\n\n\treturn container;\n};\n\nRendition.wrap = function(container) {\n\tvar wrapper = document.createElement(\"div\");\n\n\twrapper.style.visibility = \"hidden\";\n\twrapper.style.overflow = \"hidden\";\n\twrapper.style.width = \"0\";\n\twrapper.style.height = \"0\";\n\n\twrapper.appendChild(container);\n\treturn wrapper;\n};\n\n// Call to attach the container to an element in the dom\n// Container must be attached before rendering can begin\nRendition.prototype.attachTo = function(_element){\n\tvar bounds;\n\n\tthis.container = this.initialize({\n\t\t\"width\" : this.settings.width,\n\t\t\"height\" : this.settings.height\n\t});\n\n\tif(core.isElement(_element)) {\n\t\tthis.element = _element;\n\t} else if (typeof _element === \"string\") {\n\t\tthis.element = document.getElementById(_element);\n\t}\n\n\tif(!this.element){\n\t\tconsole.error(\"Not an Element\");\n\t\treturn;\n\t}\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t\tthis.element.appendChild(this.wrapper);\n\t} else {\n\t\tthis.element.appendChild(this.container);\n\t}\n\n\tthis.views = new Views(this.container);\n\n\t// Attach Listeners\n\tthis.attachListeners();\n\n\t// Calculate Stage Size\n\tthis.stageSize();\n\n\t// Add Layout method\n\tthis.applyLayoutMethod();\n\n\t// Trigger Attached\n\tthis.trigger(\"attached\");\n\n\t// Start processing queue\n\t// this.q.run();\n\n};\n\nRendition.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to 100%\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n};\n\nRendition.prototype.bounds = function() {\n\treturn this.container.getBoundingClientRect();\n};\n\nRendition.prototype.display = function(target){\n\n\treturn this.q.enqueue(this._display, target);\n\n};\n\nRendition.prototype._display = function(target){\n\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\n\tvar section;\n var view;\n var offset;\n\tvar fragment;\n\tvar cfi = this.epubcfi.isCfiString(target);\n\n\tvar visible;\n\n\tsection = this.book.spine.get(target);\n\n\tif(!section){\n\t\tdisplaying.reject(new Error(\"No Section Found\"));\n\t\treturn displayed;\n\t}\n\n\t// Check to make sure the section we want isn't already shown\n\tvisible = this.views.find(section);\n\n\tif(visible) {\n\t\toffset = view.locationOf(target);\n\t\tdisplayed = this.moveTo(offset)\n\t\t\t.then(function(){\n\t\t\t\treturn this.check();\n\t\t\t});\n\t} else {\n\n\t\t// Hide all current views\n\t\tthis.views.hide();\n\n\t\t// Create a new view\n\t\t// view = new View(section, this.viewSettings);\n\t\tview = this.createView(section);\n\n\t\t// This will clear all previous views\n\t\tdisplayed = this.fill(view)\n\t\t\t.then(function(){\n\n\t\t\t\t// Parse the target fragment\n\t\t\t\tif(typeof target === \"string\" &&\n\t\t\t\t\ttarget.indexOf(\"#\") > -1) {\n\t\t\t\t\t\tfragment = target.substring(target.indexOf(\"#\")+1);\n\t\t\t\t}\n\n\t\t\t\t// Move to correct place within the section, if needed\n\t\t\t\tif(cfi || fragment) {\n\t\t\t\t\toffset = view.locationOf(target);\n\t\t\t\t\treturn this.moveTo(offset);\n\t\t\t\t}\n\n\t\t\t\tif(typeof this.check === 'function') {\n\t\t\t\t\treturn this.check();\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\treturn this.hooks.display.trigger(view);\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tthis.views.show();\n\t\t\t}.bind(this));\n\t}\n\n\tdisplayed.then(function(){\n\n\t\tthis.trigger(\"displayed\", section);\n\n\t}.bind(this));\n\n\n\treturn displayed;\n};\n\n// Takes a cfi, fragment or page?\nRendition.prototype.moveTo = function(offset){\n\tthis.scrollBy(offset.left, offset.top);\n};\n\nRendition.prototype.render = function(view, show) {\n\n\tview.create();\n\n\tview.onLayout = this.layout.format.bind(this.layout);\n\n\t// Fit to size of the container, apply padding\n\tthis.resizeView(view);\n\n\t// Render Chain\n\treturn view.render(this.book.request)\n\t\t.then(function(){\n\t\t\treturn this.hooks.content.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.layout.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn view.display();\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.render.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\tif(show !== false && this.views.hidden === false) {\n\t\t\t\tthis.q.enqueue(function(view){\n\t\t\t\t\tview.show();\n\t\t\t\t}, view);\n\t\t\t}\n\n\n\t\t\t// this.map = new Map(view, this.layout);\n\t\t\tthis.hooks.show.trigger(view, this);\n\t\t\tthis.trigger(\"rendered\", view.section);\n\n\t\t}.bind(this))\n\t\t.catch(function(e){\n\t\t\tthis.trigger(\"loaderror\", e);\n\t\t}.bind(this));\n\n};\n\n\nRendition.prototype.afterDisplayed = function(view){\n\tthis.trigger(\"added\", view.section);\n};\n\nRendition.prototype.fill = function(view){\n\n\tthis.views.clear();\n\n\tthis.views.append(view);\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\treturn this.render(view);\n};\n\nRendition.prototype.resizeView = function(view) {\n\n\tif(this.globalLayoutProperties.layout === \"pre-paginated\") {\n\t\tview.lock(\"both\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nRendition.prototype.stageSize = function(_width, _height){\n\tvar bounds;\n\tvar width = _width || this.settings.width;\n\tvar height = _height || this.settings.height;\n\n\t// If width or height are set to false, inherit them from containing element\n\tif(width === false) {\n\t\tbounds = this.element.getBoundingClientRect();\n\n\t\tif(bounds.width) {\n\t\t\twidth = bounds.width;\n\t\t\tthis.container.style.width = bounds.width + \"px\";\n\t\t}\n\t}\n\n\tif(height === false) {\n\t\tbounds = bounds || this.element.getBoundingClientRect();\n\n\t\tif(bounds.height) {\n\t\t\theight = bounds.height;\n\t\t\tthis.container.style.height = bounds.height + \"px\";\n\t\t}\n\n\t}\n\n\tif(width && !core.isNumber(width)) {\n\t\tbounds = this.container.getBoundingClientRect();\n\t\twidth = bounds.width;\n\t\t//height = bounds.height;\n\t}\n\n\tif(height && !core.isNumber(height)) {\n\t\tbounds = bounds || this.container.getBoundingClientRect();\n\t\t//width = bounds.width;\n\t\theight = bounds.height;\n\t}\n\n\n\tthis.containerStyles = window.getComputedStyle(this.container);\n\tthis.containerPadding = {\n\t\tleft: parseFloat(this.containerStyles[\"padding-left\"]) || 0,\n\t\tright: parseFloat(this.containerStyles[\"padding-right\"]) || 0,\n\t\ttop: parseFloat(this.containerStyles[\"padding-top\"]) || 0,\n\t\tbottom: parseFloat(this.containerStyles[\"padding-bottom\"]) || 0\n\t};\n\n\tthis.stage = {\n\t\twidth: width -\n\t\t\t\t\t\tthis.containerPadding.left -\n\t\t\t\t\t\tthis.containerPadding.right,\n\t\theight: height -\n\t\t\t\t\t\tthis.containerPadding.top -\n\t\t\t\t\t\tthis.containerPadding.bottom\n\t};\n\n\treturn this.stage;\n\n};\n\nRendition.prototype.applyLayoutMethod = function() {\n\n\tthis.layout = new Layout.Scroll();\n\tthis.updateLayout();\n\n\tthis.map = new Map(this.layout);\n};\n\nRendition.prototype.updateLayout = function() {\n\n\tthis.layout.calculate(this.stage.width, this.stage.height);\n\n};\n\nRendition.prototype.resize = function(width, height){\n\n\tthis.stageSize(width, height);\n\n\tthis.updateLayout();\n\n\tthis.views.each(this.resizeView.bind(this));\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nRendition.prototype.onResized = function(e) {\n\tthis.resize();\n};\n\nRendition.prototype.createView = function(section) {\n\t// Transfer the existing hooks\n\tsection.hooks.serialize.register(this.hooks.serialize.list());\n\n\treturn new View(section, this.viewSettings);\n};\n\nRendition.prototype.next = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar next;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tnext = this.views.last().section.next();\n\n\t\tif(next) {\n\t\t\tview = this.createView(next);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\nRendition.prototype.prev = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar prev;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tprev = this.views.first().section.prev();\n\t\tif(prev) {\n\t\t\tview = this.createView(prev);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\n//-- http://www.idpf.org/epub/fxl/\nRendition.prototype.parseLayoutProperties = function(_metadata){\n\tvar metadata = _metadata || this.book.package.metadata;\n\tvar layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || \"reflowable\";\n\tvar spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || \"auto\";\n\tvar orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || \"auto\";\n\tthis.globalLayoutProperties = {\n\t\tlayout : layout,\n\t\tspread : spread,\n\t\torientation : orientation\n\t};\n\treturn this.globalLayoutProperties;\n};\n\n\nRendition.prototype.current = function(){\n\tvar visible = this.visible();\n\tif(visible.length){\n\t\t// Current is the last visible view\n\t\treturn visible[visible.length-1];\n\t}\n return null;\n};\n\nRendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){\n\tvar position = view.position();\n\tvar container = _container || this.container.getBoundingClientRect();\n\n\tif(this.settings.axis === \"horizontal\" &&\n\t\tposition.right > container.left - offsetPrev &&\n\t\tposition.left < container.right + offsetNext) {\n\n\t\treturn true;\n\n } else if(this.settings.axis === \"vertical\" &&\n \tposition.bottom > container.top - offsetPrev &&\n\t\tposition.top < container.bottom + offsetNext) {\n\n\t\treturn true;\n }\n\n\treturn false;\n\n};\n\nRendition.prototype.visible = function(){\n\tvar container = this.bounds();\n\tvar displayedViews = this.views.displayed();\n var visible = [];\n var isVisible;\n var view;\n\n for (var i = 0; i < displayedViews.length; i++) {\n view = displayedViews[i];\n isVisible = this.isVisible(view, 0, 0, container);\n\n if(isVisible === true) {\n visible.push(view);\n }\n\n }\n return visible;\n\n};\n\nRendition.prototype.bounds = function(func) {\n var bounds;\n\n if(!this.settings.height) {\n bounds = core.windowBounds();\n } else {\n bounds = this.container.getBoundingClientRect();\n }\n\n return bounds;\n};\n\nRendition.prototype.destroy = function(){\n // Clear the queue\n\tthis.q.clear();\n\n\tthis.views.clear();\n\n\tclearTimeout(this.trimTimeout);\n\tif(this.settings.hidden) {\n\t\tthis.element.removeChild(this.wrapper);\n\t} else {\n\t\tthis.element.removeChild(this.container);\n\t}\n\n};\n\nRendition.prototype.reportLocation = function(){\n return this.q.enqueue(function(){\n this.location = this.currentLocation();\n this.trigger(\"locationChanged\", this.location);\n }.bind(this));\n};\n\nRendition.prototype.currentLocation = function(){\n var view;\n var start, end;\n\n if(this.views.length) {\n \tview = this.views.first();\n // start = container.left - view.position().left;\n // end = start + this.layout.spread;\n\n return this.map.page(view);\n }\n\n};\n\nRendition.prototype.scrollBy = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n\n if(x) this.container.scrollLeft += x;\n \tif(y) this.container.scrollTop += y;\n\n } else {\n \twindow.scrollBy(x,y);\n }\n // console.log(\"scrollBy\", x, y);\n this.scrolled = true;\n};\n\nRendition.prototype.scrollTo = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n \tthis.container.scrollLeft = x;\n \tthis.container.scrollTop = y;\n } else {\n \twindow.scrollTo(x,y);\n }\n // console.log(\"scrollTo\", x, y);\n this.scrolled = true;\n // if(this.container.scrollLeft != x){\n // setTimeout(function() {\n // this.scrollTo(x, y, silent);\n // }.bind(this), 10);\n // return;\n // };\n };\n\nRendition.prototype.passViewEvents = function(view){\n view.listenedEvents.forEach(function(e){\n\t\tview.on(e, this.triggerViewEvent.bind(this));\n\t}.bind(this));\n\n\tview.on(\"selected\", this.triggerSelectedEvent.bind(this));\n};\n\nRendition.prototype.triggerViewEvent = function(e){\n this.trigger(e.type, e);\n};\n\nRendition.prototype.triggerSelectedEvent = function(cfirange){\n\tconsole.log(cfirange);\n this.trigger(\"selected\", cfirange);\n};\n\nRendition.prototype.replacements = function(){\n\t// Wait for loading\n\treturn this.q.enqueue(function () {\n\t\t// Get thes books manifest\n\t\tvar manifest = this.book.package.manifest;\n\t var manifestArray = Object.keys(manifest).\n\t map(function (key){\n\t return manifest[key];\n\t });\n\n\t // Exclude HTML\n\t var items = manifestArray.\n\t filter(function (item){\n\t if (item.type != \"application/xhtml+xml\" &&\n\t item.type != \"text/html\") {\n\t return true;\n\t }\n\t });\n\n\t // Only CSS\n\t var css = items.\n\t filter(function (item){\n\t if (item.type === \"text/css\") {\n\t return true;\n\t }\n\t });\n\n\t\t// Css Urls\n\t\tvar cssUrls = css.map(function(item) {\n\t\t\treturn item.href;\n\t\t});\n\n\t\t// All Assets Urls\n\t var urls = items.\n\t map(function(item) {\n\t return item.href;\n\t }.bind(this));\n\n\t\t// Create blob urls for all the assets\n\t var processing = urls.\n\t map(function(url) {\n\t\t\t\tvar absolute = URI(url).absoluteTo(this.book.baseUrl).toString();\n\t\t\t\t// Full url from archive base\n\t return this.book.archive.createUrl(absolute);\n\t }.bind(this));\n\n\t\t// After all the urls are created\n\t return RSVP.all(processing).\n\t then(function(replacementUrls) {\n\n\t\t\t\t// Replace Asset Urls in the text of all css files\n\t\t\t\tcssUrls.forEach(function(href) {\n\t\t\t\t\tthis.replaceCss(href, urls, replacementUrls);\n\t\t }.bind(this));\n\n\t\t\t\t// Replace Asset Urls in chapters\n\t\t\t\t// by registering a hook after the sections contents has been serialized\n\t this.hooks.serialize.register(function(output, section) {\n\t\t\t\t\tthis.replaceAssets(section, urls, replacementUrls);\n\t }.bind(this));\n\n\t }.bind(this)).catch(function(reason){\n\t console.error(reason);\n\t });\n\t}.bind(this));\n};\n\nRendition.prototype.replaceCss = function(href, urls, replacementUrls){\n\t\tvar newUrl;\n\t\tvar indexInUrls;\n\n\t\t// Find the absolute url of the css file\n\t\tvar fileUri = URI(href);\n\t\tvar absolute = fileUri.absoluteTo(this.book.baseUrl).toString();\n\t\t// Get the text of the css file from the archive\n\t\tvar text = this.book.archive.getText(absolute);\n\t\t// Get asset links relative to css file\n\t\tvar relUrls = urls.\n\t\t\tmap(function(assetHref) {\n\t\t\t\tvar assetUri = URI(assetHref).absoluteTo(this.book.baseUrl);\n\t\t\t\tvar relative = assetUri.relativeTo(absolute).toString();\n\t\t\t\treturn relative;\n\t\t\t}.bind(this));\n\n\t\t// Replacements in the css text\n\t\ttext = replace.substitute(text, relUrls, replacementUrls);\n\n\t\t// Get the new url\n\t\tnewUrl = core.createBlobUrl(text, 'text/css');\n\n\t\t// switch the url in the replacementUrls\n\t\tindexInUrls = urls.indexOf(href);\n\t\tif (indexInUrls > -1) {\n\t\t\treplacementUrls[indexInUrls] = newUrl;\n\t\t}\n};\n\nRendition.prototype.replaceAssets = function(section, urls, replacementUrls){\n\tvar fileUri = URI(section.url);\n\t// Get Urls relative to current sections\n\tvar relUrls = urls.\n\t\tmap(function(href) {\n\t\t\tvar assetUri = URI(href).absoluteTo(this.book.baseUrl);\n\t\t\tvar relative = assetUri.relativeTo(fileUri).toString();\n\t\t\treturn relative;\n\t\t}.bind(this));\n\n\n\tsection.output = replace.substitute(section.output, relUrls, replacementUrls);\n};\n//-- Enable binding events to Renderer\nRSVP.EventTarget.mixin(Rendition.prototype);\n\nmodule.exports = Rendition;\n","var URI = require('urijs');\nvar core = require('./core');\n\nfunction base(doc, section){\n var base;\n var head;\n\n if(!doc){\n return;\n }\n\n head = doc.querySelector(\"head\");\n base = head.querySelector(\"base\");\n\n if(!base) {\n base = doc.createElement(\"base\");\n }\n\n base.setAttribute(\"href\", section.url);\n head.insertBefore(base, head.firstChild);\n\n}\n\nfunction links(view, renderer) {\n\n var links = view.document.querySelectorAll(\"a[href]\");\n var replaceLinks = function(link){\n var href = link.getAttribute(\"href\");\n var linkUri = URI(href);\n var absolute = linkUri.absoluteTo(view.section.url);\n var relative = absolute.relativeTo(this.book.baseUrl).toString();\n\n if(linkUri.protocol()){\n\n link.setAttribute(\"target\", \"_blank\");\n\n }else{\n /*\n if(baseDirectory) {\n\t\t\t\t// We must ensure that the file:// protocol is preserved for\n\t\t\t\t// local file links, as in certain contexts (such as under\n\t\t\t\t// Titanium), file links without the file:// protocol will not\n\t\t\t\t// work\n\t\t\t\tif (baseUri.protocol === \"file\") {\n\t\t\t\t\trelative = core.resolveUrl(baseUri.base, href);\n\t\t\t\t} else {\n\t\t\t\t\trelative = core.resolveUrl(baseDirectory, href);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trelative = href;\n\t\t\t}\n */\n\n if(linkUri.fragment()) {\n // do nothing with fragment yet\n } else {\n link.onclick = function(){\n renderer.display(relative);\n return false;\n };\n }\n\n }\n };\n\n for (var i = 0; i < links.length; i++) {\n replaceLinks(links[i]);\n }\n\n\n};\n\nfunction substitute(content, urls, replacements) {\n urls.forEach(function(url, i){\n if (url && replacements[i]) {\n content = content.replace(new RegExp(url, 'g'), replacements[i]);\n }\n });\n return content;\n}\nmodule.exports = {\n 'base': base,\n 'links': links,\n 'substitute': substitute\n};\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\n\nfunction request(url, type, withCredentials, headers) {\n var supportsURL = window.URL;\n var BLOB_RESPONSE = supportsURL ? \"blob\" : \"arraybuffer\";\n var uri;\n\n var deferred = new RSVP.defer();\n\n var xhr = new XMLHttpRequest();\n\n //-- Check from PDF.js:\n // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js\n var xhrPrototype = XMLHttpRequest.prototype;\n\n var header;\n\n if (!('overrideMimeType' in xhrPrototype)) {\n // IE10 might have response, but not overrideMimeType\n Object.defineProperty(xhrPrototype, 'overrideMimeType', {\n value: function xmlHttpRequestOverrideMimeType(mimeType) {}\n });\n }\n if(withCredentials) {\n xhr.withCredentials = true;\n }\n\n xhr.open(\"GET\", url, true);\n\n for(header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n\n xhr.onreadystatechange = handler;\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n xhr.responseType = BLOB_RESPONSE;\n }\n\n if(type == \"json\") {\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n }\n\n if(core.isXml(type)) {\n\t\txhr.responseType = \"document\";\n\t\txhr.overrideMimeType('text/xml'); // for OPF parsing\n\t}\n\n\tif(type == 'xhtml') {\n\t\txhr.responseType = \"document\";\n\t}\n\n\tif(type == 'html' || type == 'htm') {\n\t\txhr.responseType = \"document\";\n \t}\n\n if(type == \"binary\") {\n xhr.responseType = \"arraybuffer\";\n }\n\n xhr.send();\n\n function handler() {\n if (this.readyState === this.DONE) {\n if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls\n var r;\n\n if((this.responseType == '' || this.responseType == 'document')\n && this.responseXML){\n r = this.responseXML;\n } else\n if(core.isXml(type)){\n // If this.responseXML wasn't set, try to parse using a DOMParser from text\n r = new DOMParser().parseFromString(this.response, \"text/xml\");\n }else\n if(type == 'xhtml'){\n r = new DOMParser().parseFromString(this.response, \"application/xhtml+xml\");\n }else\n if(type == 'html' || type == 'htm'){\n r = new DOMParser().parseFromString(this.response, \"text/html\");\n }else\n if(type == 'json'){\n r = JSON.parse(this.response);\n }else\n if(type == 'blob'){\n\n if(supportsURL) {\n r = this.response;\n } else {\n //-- Safari doesn't support responseType blob, so create a blob from arraybuffer\n r = new Blob([this.response]);\n }\n\n }else{\n r = this.response;\n }\n\n deferred.resolve(r);\n } else {\n deferred.reject({\n status: this.status,\n message : this.response,\n stack : new Error().stack\n });\n }\n }\n }\n\n return deferred.promise;\n};\n\nmodule.exports = request;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\nvar replacements = require('./replacements');\n\nfunction Section(item, hooks){\n this.idref = item.idref;\n this.linear = item.linear;\n this.properties = item.properties;\n this.index = item.index;\n this.href = item.href;\n this.url = item.url;\n this.next = item.next;\n this.prev = item.prev;\n\n this.epubcfi = new EpubCFI();\n this.cfiBase = item.cfiBase;\n\n this.hooks = {};\n this.hooks.serialize = new Hook(this);\n this.hooks.content = new Hook(this);\n\n // Register replacements\n this.hooks.content.register(replacements.base);\n};\n\n\nSection.prototype.load = function(_request){\n var request = _request || this.request || require('./request');\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(this.contents) {\n loading.resolve(this.contents);\n } else {\n request(this.url)\n .then(function(xml){\n var base;\n var directory = URI(this.url).directory();\n\n this.document = xml;\n this.contents = xml.documentElement;\n\n return this.hooks.content.trigger(this.document, this);\n }.bind(this))\n .then(function(){\n loading.resolve(this.contents);\n }.bind(this))\n .catch(function(error){\n loading.reject(error);\n });\n }\n\n return loaded;\n};\n\nSection.prototype.base = function(_document){\n var task = new RSVP.defer();\n var base = _document.createElement(\"base\"); // TODO: check if exists\n var head;\n\n base.setAttribute(\"href\", this.url);\n\n if(_document) {\n head = _document.querySelector(\"head\");\n }\n if(head) {\n head.insertBefore(base, head.firstChild);\n task.resolve();\n } else {\n task.reject(new Error(\"No head to insert into\"));\n }\n\n\n return task.promise;\n};\n\nSection.prototype.beforeSectionLoad = function(){\n // Stub for a hook - replace me for now\n};\n\nSection.prototype.render = function(_request){\n var rendering = new RSVP.defer();\n var rendered = rendering.promise;\n this.output; // TODO: better way to return this from hooks?\n\n this.load(_request).\n then(function(contents){\n var serializer = new XMLSerializer();\n this.output = serializer.serializeToString(contents);\n return this.output;\n }.bind(this)).\n then(function(){\n return this.hooks.serialize.trigger(this.output, this);\n }.bind(this)).\n then(function(){\n rendering.resolve(this.output);\n }.bind(this))\n .catch(function(error){\n rendering.reject(error);\n });\n\n return rendered;\n};\n\nSection.prototype.find = function(_query){\n\n};\n\n/**\n* Reconciles the current chapters layout properies with\n* the global layout properities.\n* Takes: global layout settings object, chapter properties string\n* Returns: Object with layout properties\n*/\nSection.prototype.reconcileLayoutSettings = function(global){\n //-- Get the global defaults\n var settings = {\n layout : global.layout,\n spread : global.spread,\n orientation : global.orientation\n };\n\n //-- Get the chapter's display type\n this.properties.forEach(function(prop){\n var rendition = prop.replace(\"rendition:\", '');\n var split = rendition.indexOf(\"-\");\n var property, value;\n\n if(split != -1){\n property = rendition.slice(0, split);\n value = rendition.slice(split+1);\n\n settings[property] = value;\n }\n });\n return settings;\n};\n\nSection.prototype.cfiFromRange = function(_range) {\n return this.epubcfi.generateCfiFromRange(_range, this.cfiBase);\n};\n\nSection.prototype.cfiFromElement = function(el) {\n return this.epubcfi.generateCfiFromElement(el, this.cfiBase);\n};\n\nmodule.exports = Section;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Section = require('./section');\n\nfunction Spine(_request){\n this.request = _request;\n this.spineItems = [];\n this.spineByHref = {};\n this.spineById = {};\n\n};\n\nSpine.prototype.load = function(_package) {\n\n this.items = _package.spine;\n this.manifest = _package.manifest;\n this.spineNodeIndex = _package.spineNodeIndex;\n this.baseUrl = _package.baseUrl || '';\n this.length = this.items.length;\n this.epubcfi = new EpubCFI();\n\n this.items.forEach(function(item, index){\n var href, url;\n var manifestItem = this.manifest[item.idref];\n var spineItem;\n item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);\n\n if(manifestItem) {\n item.href = manifestItem.href;\n item.url = this.baseUrl + item.href;\n\n if(manifestItem.properties.length){\n item.properties.push.apply(item.properties, manifestItem.properties);\n }\n }\n\n // if(index > 0) {\n item.prev = function(){ return this.get(index-1); }.bind(this);\n // }\n\n // if(index+1 < this.items.length) {\n item.next = function(){ return this.get(index+1); }.bind(this);\n // }\n\n spineItem = new Section(item);\n this.append(spineItem);\n\n\n }.bind(this));\n\n};\n\n// book.spine.get();\n// book.spine.get(1);\n// book.spine.get(\"chap1.html\");\n// book.spine.get(\"#id1234\");\nSpine.prototype.get = function(target) {\n var index = 0;\n\n if(this.epubcfi.isCfiString(target)) {\n cfi = this.epubcfi.parse(target);\n index = cfi.spinePos;\n } else if(target && (typeof target === \"number\" || isNaN(target) === false)){\n index = target;\n } else if(target && target.indexOf(\"#\") === 0) {\n index = this.spineById[target.substring(1)];\n } else if(target) {\n // Remove fragments\n target = target.split(\"#\")[0];\n index = this.spineByHref[target];\n }\n\n return this.spineItems[index] || null;\n};\n\nSpine.prototype.append = function(section) {\n var index = this.spineItems.length;\n section.index = index;\n\n this.spineItems.push(section);\n\n this.spineByHref[section.href] = index;\n this.spineById[section.idref] = index;\n\n return index;\n};\n\nSpine.prototype.prepend = function(section) {\n var index = this.spineItems.unshift(section);\n this.spineByHref[section.href] = 0;\n this.spineById[section.idref] = 0;\n\n // Re-index\n this.spineItems.forEach(function(item, index){\n item.index = index;\n });\n\n return 0;\n};\n\nSpine.prototype.insert = function(section, index) {\n\n};\n\nSpine.prototype.remove = function(section) {\n var index = this.spineItems.indexOf(section);\n\n if(index > -1) {\n delete this.spineByHref[section.href];\n delete this.spineById[section.idref];\n\n return this.spineItems.splice(index, 1);\n }\n};\n\nSpine.prototype.each = function() {\n\treturn this.spineItems.forEach.apply(this.spineItems, arguments);\n};\n\nmodule.exports = Spine;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar request = require('./request');\nvar mime = require('../libs/mime/mime');\n\nfunction Unarchive() {\n\n this.checkRequirements();\n this.urlCache = {};\n\n}\n\nUnarchive.prototype.checkRequirements = function(callback){\n try {\n if (typeof JSZip !== 'undefined') {\n this.zip = new JSZip();\n } else {\n JSZip = require('jszip');\n this.zip = new JSZip();\n }\n } catch (e) {\n console.error(\"JSZip lib not loaded\");\n }\n};\n\nUnarchive.prototype.open = function(zipUrl){\n\tif (zipUrl instanceof ArrayBuffer) {\n return new RSVP.Promise(function(resolve, reject) {\n this.zip = new JSZip(zipUrl);\n resolve(this.zip);\n });\n\t} else {\n\t\treturn request(zipUrl, \"binary\")\n .then(function(data){\n\t\t\t this.zip = new JSZip(data);\n return this.zip;\n\t\t }.bind(this));\n\t}\n};\n\nUnarchive.prototype.request = function(url, type){\n var deferred = new RSVP.defer();\n var response;\n var r;\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n response = this.getBlob(url);\n } else {\n response = this.getText(url);\n }\n\n if (response) {\n r = this.handleResponse(response, type);\n deferred.resolve(r);\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n return deferred.promise;\n};\n\nUnarchive.prototype.handleResponse = function(response, type){\n var r;\n\n if(type == \"json\") {\n r = JSON.parse(response);\n }\n else\n if(core.isXml(type)) {\n r = new DOMParser().parseFromString(response, \"text/xml\");\n\t}\n else\n\tif(type == 'xhtml') {\n r = new DOMParser().parseFromString(response, \"application/xhtml+xml\");\n\t}\n else\n\tif(type == 'html' || type == 'htm') {\n r = new DOMParser().parseFromString(response, \"text/html\");\n \t} else {\n \t r = response;\n \t}\n\n return r;\n};\n\nUnarchive.prototype.getBlob = function(url, _mimeType){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n var mimeType;\n\n\tif(entry) {\n mimeType = _mimeType || mime.lookup(entry.name);\n return new Blob([entry.asUint8Array()], {type : mimeType});\n\t}\n};\n\nUnarchive.prototype.getText = function(url, encoding){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n\n\tif(entry) {\n return entry.asText();\n\t}\n};\n\nUnarchive.prototype.createUrl = function(url, mime){\n\tvar deferred = new RSVP.defer();\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob;\n\n\tif(url in this.urlCache) {\n\t\tdeferred.resolve(this.urlCache[url]);\n\t\treturn deferred.promise;\n\t}\n\n\tblob = this.getBlob(url);\n\n if (blob) {\n tempUrl = _URL.createObjectURL(blob);\n deferred.resolve(tempUrl);\n this.urlCache[url] = tempUrl;\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n\n\treturn deferred.promise;\n};\n\nUnarchive.prototype.revokeUrl = function(url){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar fromCache = this.urlCache[url];\n\tif(fromCache) _URL.revokeObjectURL(fromCache);\n};\n\nmodule.exports = Unarchive;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction View(section, options) {\n this.settings = options || {};\n\n this.id = \"epubjs-view:\" + core.uuid();\n this.section = section;\n this.index = section.index;\n\n this.element = document.createElement('div');\n this.element.classList.add(\"epub-view\");\n\n\n // this.element.style.minHeight = \"100px\";\n this.element.style.height = \"0px\";\n this.element.style.width = \"0px\";\n this.element.style.overflow = \"hidden\";\n\n this.added = false;\n this.displayed = false;\n this.rendered = false;\n\n //this.width = 0;\n //this.height = 0;\n\n // Blank Cfi for Parsing\n this.epubcfi = new EpubCFI();\n\n if(this.settings.axis && this.settings.axis == \"horizontal\"){\n this.element.style.display = \"inline-block\";\n } else {\n this.element.style.display = \"block\";\n }\n\n // Dom events to listen for\n this.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n\n};\n\nView.prototype.create = function() {\n\n if(this.iframe) {\n return this.iframe;\n }\n\n this.iframe = document.createElement('iframe');\n this.iframe.id = this.id;\n this.iframe.scrolling = \"no\"; // Might need to be removed: breaks ios width calculations\n this.iframe.style.overflow = \"hidden\";\n this.iframe.seamless = \"seamless\";\n // Back up if seamless isn't supported\n this.iframe.style.border = \"none\";\n\n this.resizing = true;\n\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.iframe.style.width = \"0\";\n this.iframe.style.height = \"0\";\n this._width = 0;\n this._height = 0;\n\n this.element.appendChild(this.iframe);\n this.added = true;\n\n this.elementBounds = core.bounds(this.element);\n\n // if(width || height){\n // this.resize(width, height);\n // } else if(this.width && this.height){\n // this.resize(this.width, this.height);\n // } else {\n // this.iframeBounds = core.bounds(this.iframe);\n // }\n\n // Firefox has trouble with baseURI and srcdoc\n // Disabled for now\n /*\n if(!!(\"srcdoc\" in this.iframe)) {\n this.supportsSrcdoc = true;\n } else {\n this.supportsSrcdoc = false;\n }\n */\n this.supportsSrcdoc = false;\n\n return this.iframe;\n};\n\n\nView.prototype.lock = function(what, width, height) {\n\n var elBorders = core.borders(this.element);\n var iframeBorders;\n\n if(this.iframe) {\n iframeBorders = core.borders(this.iframe);\n } else {\n iframeBorders = {width: 0, height: 0};\n }\n\n if(what == \"width\" && core.isNumber(width)){\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.resize(this.lockedWidth, width); // width keeps ratio correct\n }\n\n if(what == \"height\" && core.isNumber(height)){\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n this.resize(width, this.lockedHeight);\n }\n\n if(what === \"both\" &&\n core.isNumber(width) &&\n core.isNumber(height)){\n\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n\n this.resize(this.lockedWidth, this.lockedHeight);\n }\n\n if(this.displayed && this.iframe) {\n\n this.layout();\n this.expand();\n\n }\n\n\n\n};\n\nView.prototype.expand = function(force) {\n var width = this.lockedWidth;\n var height = this.lockedHeight;\n\n var textWidth, textHeight;\n // console.log(\"expanding a\")\n if(!this.iframe || this._expanding) return;\n\n this._expanding = true;\n\n // Expand Horizontally\n if(height && !width) {\n // Get the width of the text\n textWidth = this.textWidth();\n // Check if the textWidth has changed\n if(textWidth != this._textWidth){\n // Get the contentWidth by resizing the iframe\n // Check with a min reset of the textWidth\n width = this.contentWidth(textWidth);\n // Save the textWdith\n this._textWidth = textWidth;\n // Save the contentWidth\n this._contentWidth = width;\n } else {\n // Otherwise assume content height hasn't changed\n width = this._contentWidth;\n }\n }\n\n // Expand Vertically\n if(width && !height) {\n textHeight = this.textHeight();\n if(textHeight != this._textHeight){\n height = this.contentHeight(textHeight);\n this._textHeight = textHeight;\n this._contentHeight = height;\n } else {\n height = this._contentHeight;\n }\n }\n\n // Only Resize if dimensions have changed or\n // if Frame is still hidden, so needs reframing\n if(this._needsReframe || width != this._width || height != this._height){\n this.resize(width, height);\n }\n\n this._expanding = false;\n};\n\nView.prototype.contentWidth = function(min) {\n var prev;\n var width;\n\n // Save previous width\n prev = this.iframe.style.width;\n // Set the iframe size to min, width will only ever be greater\n // Will preserve the aspect ratio\n this.iframe.style.width = (min || 0) + \"px\";\n // Get the scroll overflow width\n width = this.document.body.scrollWidth;\n // Reset iframe size back\n this.iframe.style.width = prev;\n return width;\n};\n\nView.prototype.contentHeight = function(min) {\n var prev;\n var height;\n\n prev = this.iframe.style.height;\n this.iframe.style.height = (min || 0) + \"px\";\n height = this.document.body.scrollHeight;\n this.iframe.style.height = prev;\n return height;\n};\n\nView.prototype.textWidth = function() {\n var width;\n var range = this.document.createRange();\n\n // Select the contents of frame\n range.selectNodeContents(this.document.body);\n\n // get the width of the text content\n width = range.getBoundingClientRect().width;\n return width;\n\n};\n\nView.prototype.textHeight = function() {\n var height;\n var range = this.document.createRange();\n\n range.selectNodeContents(this.document.body);\n\n height = range.getBoundingClientRect().height;\n return height;\n};\n\nView.prototype.resize = function(width, height) {\n\n if(!this.iframe) return;\n\n if(core.isNumber(width)){\n this.iframe.style.width = width + \"px\";\n this._width = width;\n }\n\n if(core.isNumber(height)){\n this.iframe.style.height = height + \"px\";\n this._height = height;\n }\n\n this.iframeBounds = core.bounds(this.iframe);\n\n this.reframe(this.iframeBounds.width, this.iframeBounds.height);\n\n};\n\nView.prototype.reframe = function(width, height) {\n //var prevBounds;\n\n if(!this.displayed) {\n this._needsReframe = true;\n return;\n }\n\n if(core.isNumber(width)){\n this.element.style.width = width + \"px\";\n }\n\n if(core.isNumber(height)){\n this.element.style.height = height + \"px\";\n }\n\n this.prevBounds = this.elementBounds;\n\n this.elementBounds = core.bounds(this.element);\n\n this.trigger(\"resized\", {\n width: this.elementBounds.width,\n height: this.elementBounds.height,\n widthDelta: this.elementBounds.width - this.prevBounds.width,\n heightDelta: this.elementBounds.height - this.prevBounds.height,\n });\n\n};\n\nView.prototype.resized = function(e) {\n /*\n if (!this.resizing) {\n if(this.iframe) {\n // this.expand();\n }\n } else {\n this.resizing = false;\n }*/\n\n};\n\nView.prototype.render = function(_request) {\n\n // if(this.rendering){\n // return this.displayed;\n // }\n\n this.rendering = true;\n // this.displayingDefer = new RSVP.defer();\n // this.displayedPromise = this.displaying.promise;\n\n return this.section.render(_request)\n .then(function(contents){\n return this.load(contents);\n }.bind(this));\n};\n\nView.prototype.load = function(contents) {\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(!this.iframe) {\n loading.reject(new Error(\"No Iframe Available\"));\n return loaded;\n }\n\n this.iframe.onload = function(event) {\n\n this.window = this.iframe.contentWindow;\n this.document = this.iframe.contentDocument;\n this.rendering = false;\n loading.resolve(this);\n\n }.bind(this);\n\n if(this.supportsSrcdoc){\n this.iframe.srcdoc = contents;\n } else {\n\n this.document = this.iframe.contentDocument;\n\n if(!this.document) {\n loading.reject(new Error(\"No Document Available\"));\n return loaded;\n }\n\n this.document.open();\n this.document.write(contents);\n this.document.close();\n\n }\n\n return loaded;\n};\n\n\nView.prototype.layout = function(layoutFunc) {\n\n this.iframe.style.display = \"inline-block\";\n\n // Reset Body Styles\n this.document.body.style.margin = \"0\";\n //this.document.body.style.display = \"inline-block\";\n //this.document.documentElement.style.width = \"auto\";\n\n if(layoutFunc){\n layoutFunc(this);\n }\n\n this.onLayout(this);\n\n};\n\nView.prototype.onLayout = function(view) {\n // stub\n};\n\nView.prototype.listeners = function() {\n /*\n setTimeout(function(){\n this.window.addEventListener(\"resize\", this.resized.bind(this), false);\n }.bind(this), 10); // Wait to listen for resize events\n */\n\n // Wait for fonts to load to finish\n // http://dev.w3.org/csswg/css-font-loading/\n // Not implemented fully except in chrome\n\n if(this.document.fonts && this.document.fonts.status === \"loading\") {\n // console.log(\"fonts unloaded\");\n this.document.fonts.onloadingdone = function(){\n // console.log(\"loaded fonts\");\n this.expand();\n }.bind(this);\n }\n\n if(this.section.properties.indexOf(\"scripted\") > -1){\n this.observer = this.observe(this.document.body);\n }\n\n this.imageLoadListeners();\n\n this.mediaQueryListeners();\n\n // this.resizeListenters();\n\n this.addEventListeners();\n\n this.addSelectionListeners();\n};\n\nView.prototype.removeListeners = function() {\n\n this.removeEventListeners();\n\n this.removeSelectionListeners();\n};\n\nView.prototype.resizeListenters = function() {\n // Test size again\n clearTimeout(this.expanding);\n this.expanding = setTimeout(this.expand.bind(this), 350);\n};\n\n//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js\nView.prototype.mediaQueryListeners = function() {\n var sheets = this.document.styleSheets;\n var mediaChangeHandler = function(m){\n if(m.matches && !this._expanding) {\n setTimeout(this.expand.bind(this), 1);\n // this.expand();\n }\n }.bind(this);\n\n for (var i = 0; i < sheets.length; i += 1) {\n var rules = sheets[i].cssRules;\n if(!rules) return; // Stylesheets changed\n for (var j = 0; j < rules.length; j += 1) {\n //if (rules[j].constructor === CSSMediaRule) {\n if(rules[j].media){\n var mql = this.window.matchMedia(rules[j].media.mediaText);\n mql.addListener(mediaChangeHandler);\n //mql.onchange = mediaChangeHandler;\n }\n }\n }\n};\n\nView.prototype.observe = function(target) {\n var renderer = this;\n\n // create an observer instance\n var observer = new MutationObserver(function(mutations) {\n if(renderer._expanding) {\n renderer.expand();\n }\n // mutations.forEach(function(mutation) {\n // console.log(mutation);\n // });\n });\n\n // configuration of the observer:\n var config = { attributes: true, childList: true, characterData: true, subtree: true };\n\n // pass in the target node, as well as the observer options\n observer.observe(target, config);\n\n return observer;\n};\n\n// View.prototype.appendTo = function(element) {\n// this.element = element;\n// this.element.appendChild(this.iframe);\n// };\n//\n// View.prototype.prependTo = function(element) {\n// this.element = element;\n// element.insertBefore(this.iframe, element.firstChild);\n// };\n\nView.prototype.imageLoadListeners = function(target) {\n var images = this.document.body.querySelectorAll(\"img\");\n var img;\n for (var i = 0; i < images.length; i++) {\n img = images[i];\n\n if (typeof img.naturalWidth !== \"undefined\" &&\n img.naturalWidth === 0) {\n img.onload = this.expand.bind(this);\n }\n }\n};\n\nView.prototype.display = function() {\n var displayed = new RSVP.defer();\n\n this.displayed = true;\n\n this.layout();\n\n this.listeners();\n\n this.expand();\n\n this.trigger(\"displayed\", this);\n this.onDisplayed(this);\n\n displayed.resolve(this);\n\n return displayed.promise;\n};\n\nView.prototype.show = function() {\n\n this.element.style.visibility = \"visible\";\n\n if(this.iframe){\n this.iframe.style.visibility = \"visible\";\n }\n\n this.trigger(\"shown\", this);\n};\n\nView.prototype.hide = function() {\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.stopExpanding = true;\n this.trigger(\"hidden\", this);\n};\n\nView.prototype.position = function() {\n return this.element.getBoundingClientRect();\n};\n\nView.prototype.onDisplayed = function(view) {\n // Stub, override with a custom functions\n};\n\nView.prototype.bounds = function() {\n if(!this.elementBounds) {\n this.elementBounds = core.bounds(this.element);\n }\n return this.elementBounds;\n};\n\nView.prototype.destroy = function() {\n // Stop observing\n if(this.observer) {\n this.observer.disconnect();\n }\n\n if(this.displayed){\n this.removeListeners();\n\n this.stopExpanding = true;\n this.element.removeChild(this.iframe);\n this.displayed = false;\n this.iframe = null;\n\n this._textWidth = null;\n this._textHeight = null;\n this._width = null;\n this._height = null;\n }\n // this.element.style.height = \"0px\";\n // this.element.style.width = \"0px\";\n};\n\nView.prototype.root = function() {\n if(!this.document) return null;\n return this.document.documentElement;\n};\n\nView.prototype.locationOf = function(target) {\n var parentPos = this.iframe.getBoundingClientRect();\n var targetPos = {\"left\": 0, \"top\": 0};\n\n if(!this.document) return;\n\n if(this.epubcfi.isCfiString(target)) {\n cfi = this.epubcfi.parse(target);\n\n if(typeof document.evaluate === 'undefined') {\n marker = this.epubcfi.addMarker(cfi, this.document);\n if(marker) {\n // Must Clean up Marker before going to page\n this.epubcfi.removeMarker(marker, this.document);\n\n targetPos = marker.getBoundingClientRect();\n }\n } else {\n range = this.epubcfi.generateRangeFromCfi(cfi, this.document);\n if(range) {\n targetPos = range.getBoundingClientRect();\n }\n }\n } else if(typeof target === \"string\" &&\n target.indexOf(\"#\") > -1) {\n\n id = target.substring(target.indexOf(\"#\")+1);\n el = this.document.getElementById(id);\n\n if(el) {\n targetPos = el.getBoundingClientRect();\n }\n }\n\n return {\n \"left\": window.scrollX + parentPos.left + targetPos.left,\n \"top\": window.scrollY + parentPos.top + targetPos.top\n };\n};\n\nView.prototype.addCss = function(src) {\n return new RSVP.Promise(function(resolve, reject){\n var $stylesheet;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $stylesheet = this.document.createElement('link');\n $stylesheet.type = 'text/css';\n $stylesheet.rel = \"stylesheet\";\n $stylesheet.href = src;\n $stylesheet.onload = $stylesheet.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n // Let apply\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($stylesheet);\n\n }.bind(this));\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule\nView.prototype.addStylesheetRules = function(rules) {\n var styleEl;\n var styleSheet;\n\n if(!this.document) return;\n\n styleEl = this.document.createElement('style');\n\n // Append style element to head\n this.document.head.appendChild(styleEl);\n\n // Grab style sheet\n styleSheet = styleEl.sheet;\n\n for (var i = 0, rl = rules.length; i < rl; i++) {\n var j = 1, rule = rules[i], selector = rules[i][0], propStr = '';\n // If the second argument of a rule is an array of arrays, correct our variables.\n if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {\n rule = rule[1];\n j = 0;\n }\n\n for (var pl = rule.length; j < pl; j++) {\n var prop = rule[j];\n propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\\n';\n }\n\n // Insert CSS Rule\n styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);\n }\n};\n\nView.prototype.addScript = function(src) {\n\n return new RSVP.Promise(function(resolve, reject){\n var $script;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $script = this.document.createElement('script');\n $script.type = 'text/javascript';\n $script.async = true;\n $script.src = src;\n $script.onload = $script.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($script);\n\n }.bind(this));\n};\n\nView.prototype.addEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);\n }, this);\n\n};\n\nView.prototype.removeEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.removeEventListener(eventName, this.triggerEvent, false);\n }, this);\n\n};\n\n// Pass browser events\nView.prototype.triggerEvent = function(e){\n this.trigger(e.type, e);\n};\n\nView.prototype.addSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.addEventListener(\"selectionchange\", this.onSelectionChange.bind(this), false);\n};\n\nView.prototype.removeSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.removeEventListener(\"selectionchange\", this.onSelectionChange, false);\n};\n\nView.prototype.onSelectionChange = function(e){\n if (this.selectionEndTimeout) {\n clearTimeout(this.selectionEndTimeout);\n }\n this.selectionEndTimeout = setTimeout(function() {\n var selection = this.window.getSelection();\n this.triggerSelectedEvent(selection);\n }.bind(this), 500);\n};\n\nView.prototype.triggerSelectedEvent = function(selection){\n\tvar range = selection.getRangeAt(0);\n\tconsole.log(range);\n\tvar cfirange = this.section.cfiFromRange(range);\n this.trigger(\"selected\", cfirange);\n};\n\nRSVP.EventTarget.mixin(View.prototype);\n\nmodule.exports = View;\n","function Views(container) {\n this.container = container;\n this._views = [];\n this.length = 0;\n this.hidden = false;\n};\n\nViews.prototype.first = function() {\n\treturn this._views[0];\n};\n\nViews.prototype.last = function() {\n\treturn this._views[this._views.length-1];\n};\n\nViews.prototype.each = function() {\n\treturn this._views.forEach.apply(this._views, arguments);\n};\n\nViews.prototype.indexOf = function(view) {\n\treturn this._views.indexOf(view);\n};\n\nViews.prototype.slice = function() {\n\treturn this._views.slice.apply(this._views, arguments);\n};\n\nViews.prototype.get = function(i) {\n\treturn this._views[i];\n};\n\nViews.prototype.append = function(view){\n\tthis._views.push(view);\n\tthis.container.appendChild(view.element);\n this.length++;\n return view;\n};\n\nViews.prototype.prepend = function(view){\n\tthis._views.unshift(view);\n\tthis.container.insertBefore(view.element, this.container.firstChild);\n this.length++;\n return view;\n};\n\nViews.prototype.insert = function(view, index) {\n\tthis._views.splice(index, 0, view);\n\n\tif(index < this.container.children.length){\n\t\tthis.container.insertBefore(view.element, this.container.children[index]);\n\t} else {\n\t\tthis.container.appendChild(view.element);\n\t}\n this.length++;\n return view;\n};\n\nViews.prototype.remove = function(view) {\n\tvar index = this._views.indexOf(view);\n\n\tif(index > -1) {\n\t\tthis._views.splice(index, 1);\n\t}\n\n\n\tthis.destroy(view);\n\n this.length--;\n};\n\nViews.prototype.destroy = function(view) {\n\tview.off(\"resized\");\n\n\tif(view.displayed){\n\t\tview.destroy();\n\t}\n\n\tthis.container.removeChild(view.element);\n\tview = null;\n};\n\n// Iterators\n\nViews.prototype.clear = function(){\n\t// Remove all views\n var view;\n var len = this.length;\n\n if(!this.length) return;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tthis.destroy(view);\n }\n\n this._views = [];\n this.length = 0;\n};\n\nViews.prototype.find = function(section){\n\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tif(view.displayed && view.section.index == section.index) {\n\t\t\treturn view;\n\t\t}\n }\n\n};\n\nViews.prototype.displayed = function(){\n var displayed = [];\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n displayed.push(view);\n }\n }\n return displayed;\n};\n\nViews.prototype.show = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.show();\n }\n }\n this.hidden = false;\n};\n\nViews.prototype.hide = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.hide();\n }\n }\n this.hidden = true;\n};\n\nmodule.exports = Views;\n","if (typeof EPUBJS === 'undefined') {\n\t(typeof window !== 'undefined' ? window : global).EPUBJS = {};\n}\n\nEPUBJS.VERSION = \"0.3.0\";\n\nvar Book = require('./book');\n\nfunction ePub(_url) {\n\treturn new Book(_url);\n};\n\nmodule.exports = ePub;\n"]} \ No newline at end of file +{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","libs/mime/mime.js","node_modules/browserify/lib/_empty.js","node_modules/browserify/node_modules/process/browser.js","node_modules/rsvp/dist/rsvp.js","node_modules/urijs/src/URI.js","src/book.js","src/continuous.js","src/core.js","src/epubcfi.js","src/hook.js","src/layout.js","src/locations.js","src/map.js","src/navigation.js","src/paginate.js","src/parser.js","src/queue.js","src/rendition.js","src/replacements.js","src/request.js","src/section.js","src/spine.js","src/unarchive.js","src/view.js","src/views.js","src/epub.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3KA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7jDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9cA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"epub.js","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n setTimeout(drainQueue, 0);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n","/*!\n * @overview RSVP - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors\n * @license Licensed under MIT license\n * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE\n * @version 3.1.0\n */\n\n(function() {\n \"use strict\";\n function lib$rsvp$utils$$objectOrFunction(x) {\n return typeof x === 'function' || (typeof x === 'object' && x !== null);\n }\n\n function lib$rsvp$utils$$isFunction(x) {\n return typeof x === 'function';\n }\n\n function lib$rsvp$utils$$isMaybeThenable(x) {\n return typeof x === 'object' && x !== null;\n }\n\n var lib$rsvp$utils$$_isArray;\n if (!Array.isArray) {\n lib$rsvp$utils$$_isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n } else {\n lib$rsvp$utils$$_isArray = Array.isArray;\n }\n\n var lib$rsvp$utils$$isArray = lib$rsvp$utils$$_isArray;\n\n var lib$rsvp$utils$$now = Date.now || function() { return new Date().getTime(); };\n\n function lib$rsvp$utils$$F() { }\n\n var lib$rsvp$utils$$o_create = (Object.create || function (o) {\n if (arguments.length > 1) {\n throw new Error('Second argument not supported');\n }\n if (typeof o !== 'object') {\n throw new TypeError('Argument must be an object');\n }\n lib$rsvp$utils$$F.prototype = o;\n return new lib$rsvp$utils$$F();\n });\n function lib$rsvp$events$$indexOf(callbacks, callback) {\n for (var i=0, l=callbacks.length; i 0.5) {\n throw new Error();\n }\n return new Author();\n }\n\n try {\n return findAuthor(); // succeed or fail\n } catch(error) {\n return findOtherAuther();\n } finally {\n // always runs\n // doesn't affect the return value\n }\n ```\n\n Asynchronous example:\n\n ```js\n findAuthor().catch(function(reason){\n return findOtherAuther();\n }).finally(function(){\n // author was either found, or not\n });\n ```\n\n @method finally\n @param {Function} callback\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'finally': function(callback, label) {\n var promise = this;\n var constructor = promise.constructor;\n\n return promise.then(function(value) {\n return constructor.resolve(callback()).then(function(){\n return value;\n });\n }, function(reason) {\n return constructor.resolve(callback()).then(function(){\n throw reason;\n });\n }, label);\n }\n };\n\n function lib$rsvp$all$settled$$AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);\n }\n\n lib$rsvp$all$settled$$AllSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$all$settled$$AllSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$all$settled$$AllSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n lib$rsvp$all$settled$$AllSettled.prototype._validationError = function() {\n return new Error('allSettled must be called with an array');\n };\n\n function lib$rsvp$all$settled$$allSettled(entries, label) {\n return new lib$rsvp$all$settled$$AllSettled(lib$rsvp$promise$$default, entries, label).promise;\n }\n var lib$rsvp$all$settled$$default = lib$rsvp$all$settled$$allSettled;\n function lib$rsvp$all$$all(array, label) {\n return lib$rsvp$promise$$default.all(array, label);\n }\n var lib$rsvp$all$$default = lib$rsvp$all$$all;\n var lib$rsvp$asap$$len = 0;\n var lib$rsvp$asap$$toString = {}.toString;\n var lib$rsvp$asap$$vertxNext;\n function lib$rsvp$asap$$asap(callback, arg) {\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len] = callback;\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len + 1] = arg;\n lib$rsvp$asap$$len += 2;\n if (lib$rsvp$asap$$len === 2) {\n // If len is 1, that means that we need to schedule an async flush.\n // If additional callbacks are queued before the queue is flushed, they\n // will be processed by this flush that we are scheduling.\n lib$rsvp$asap$$scheduleFlush();\n }\n }\n\n var lib$rsvp$asap$$default = lib$rsvp$asap$$asap;\n\n var lib$rsvp$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;\n var lib$rsvp$asap$$browserGlobal = lib$rsvp$asap$$browserWindow || {};\n var lib$rsvp$asap$$BrowserMutationObserver = lib$rsvp$asap$$browserGlobal.MutationObserver || lib$rsvp$asap$$browserGlobal.WebKitMutationObserver;\n var lib$rsvp$asap$$isNode = typeof self === 'undefined' &&\n typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';\n\n // test for web worker but not in IE10\n var lib$rsvp$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&\n typeof importScripts !== 'undefined' &&\n typeof MessageChannel !== 'undefined';\n\n // node\n function lib$rsvp$asap$$useNextTick() {\n var nextTick = process.nextTick;\n // node version 0.10.x displays a deprecation warning when nextTick is used recursively\n // setImmediate should be used instead instead\n var version = process.versions.node.match(/^(?:(\\d+)\\.)?(?:(\\d+)\\.)?(\\*|\\d+)$/);\n if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {\n nextTick = setImmediate;\n }\n return function() {\n nextTick(lib$rsvp$asap$$flush);\n };\n }\n\n // vertx\n function lib$rsvp$asap$$useVertxTimer() {\n return function() {\n lib$rsvp$asap$$vertxNext(lib$rsvp$asap$$flush);\n };\n }\n\n function lib$rsvp$asap$$useMutationObserver() {\n var iterations = 0;\n var observer = new lib$rsvp$asap$$BrowserMutationObserver(lib$rsvp$asap$$flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function() {\n node.data = (iterations = ++iterations % 2);\n };\n }\n\n // web worker\n function lib$rsvp$asap$$useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = lib$rsvp$asap$$flush;\n return function () {\n channel.port2.postMessage(0);\n };\n }\n\n function lib$rsvp$asap$$useSetTimeout() {\n return function() {\n setTimeout(lib$rsvp$asap$$flush, 1);\n };\n }\n\n var lib$rsvp$asap$$queue = new Array(1000);\n function lib$rsvp$asap$$flush() {\n for (var i = 0; i < lib$rsvp$asap$$len; i+=2) {\n var callback = lib$rsvp$asap$$queue[i];\n var arg = lib$rsvp$asap$$queue[i+1];\n\n callback(arg);\n\n lib$rsvp$asap$$queue[i] = undefined;\n lib$rsvp$asap$$queue[i+1] = undefined;\n }\n\n lib$rsvp$asap$$len = 0;\n }\n\n function lib$rsvp$asap$$attemptVertex() {\n try {\n var r = require;\n var vertx = r('vertx');\n lib$rsvp$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return lib$rsvp$asap$$useVertxTimer();\n } catch(e) {\n return lib$rsvp$asap$$useSetTimeout();\n }\n }\n\n var lib$rsvp$asap$$scheduleFlush;\n // Decide what async method to use to triggering processing of queued callbacks:\n if (lib$rsvp$asap$$isNode) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useNextTick();\n } else if (lib$rsvp$asap$$BrowserMutationObserver) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMutationObserver();\n } else if (lib$rsvp$asap$$isWorker) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMessageChannel();\n } else if (lib$rsvp$asap$$browserWindow === undefined && typeof require === 'function') {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$attemptVertex();\n } else {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useSetTimeout();\n }\n function lib$rsvp$defer$$defer(label) {\n var deferred = {};\n\n deferred['promise'] = new lib$rsvp$promise$$default(function(resolve, reject) {\n deferred['resolve'] = resolve;\n deferred['reject'] = reject;\n }, label);\n\n return deferred;\n }\n var lib$rsvp$defer$$default = lib$rsvp$defer$$defer;\n function lib$rsvp$filter$$filter(promises, filterFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(filterFn)) {\n throw new TypeError(\"You must pass a function as filter's second argument.\");\n }\n\n var length = values.length;\n var filtered = new Array(length);\n\n for (var i = 0; i < length; i++) {\n filtered[i] = filterFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(filtered, label).then(function(filtered) {\n var results = new Array(length);\n var newLength = 0;\n\n for (var i = 0; i < length; i++) {\n if (filtered[i]) {\n results[newLength] = values[i];\n newLength++;\n }\n }\n\n results.length = newLength;\n\n return results;\n });\n });\n }\n var lib$rsvp$filter$$default = lib$rsvp$filter$$filter;\n\n function lib$rsvp$promise$hash$$PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n }\n\n var lib$rsvp$promise$hash$$default = lib$rsvp$promise$hash$$PromiseHash;\n\n lib$rsvp$promise$hash$$PromiseHash.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$promise$hash$$PromiseHash.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$promise$hash$$PromiseHash.prototype._init = function() {\n this._result = {};\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validateInput = function(input) {\n return input && typeof input === 'object';\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validationError = function() {\n return new Error('Promise.hash must be called with an object');\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._enumerate = function() {\n var enumerator = this;\n var promise = enumerator.promise;\n var input = enumerator._input;\n var results = [];\n\n for (var key in input) {\n if (promise._state === lib$rsvp$$internal$$PENDING && Object.prototype.hasOwnProperty.call(input, key)) {\n results.push({\n position: key,\n entry: input[key]\n });\n }\n }\n\n var length = results.length;\n enumerator._remaining = length;\n var result;\n\n for (var i = 0; promise._state === lib$rsvp$$internal$$PENDING && i < length; i++) {\n result = results[i];\n enumerator._eachEntry(result.entry, result.position);\n }\n };\n\n function lib$rsvp$hash$settled$$HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n }\n\n lib$rsvp$hash$settled$$HashSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$promise$hash$$default.prototype);\n lib$rsvp$hash$settled$$HashSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$hash$settled$$HashSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n\n lib$rsvp$hash$settled$$HashSettled.prototype._validationError = function() {\n return new Error('hashSettled must be called with an object');\n };\n\n function lib$rsvp$hash$settled$$hashSettled(object, label) {\n return new lib$rsvp$hash$settled$$HashSettled(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$settled$$default = lib$rsvp$hash$settled$$hashSettled;\n function lib$rsvp$hash$$hash(object, label) {\n return new lib$rsvp$promise$hash$$default(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$$default = lib$rsvp$hash$$hash;\n function lib$rsvp$map$$map(promises, mapFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(mapFn)) {\n throw new TypeError(\"You must pass a function as map's second argument.\");\n }\n\n var length = values.length;\n var results = new Array(length);\n\n for (var i = 0; i < length; i++) {\n results[i] = mapFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(results, label);\n });\n }\n var lib$rsvp$map$$default = lib$rsvp$map$$map;\n\n function lib$rsvp$node$$Result() {\n this.value = undefined;\n }\n\n var lib$rsvp$node$$ERROR = new lib$rsvp$node$$Result();\n var lib$rsvp$node$$GET_THEN_ERROR = new lib$rsvp$node$$Result();\n\n function lib$rsvp$node$$getThen(obj) {\n try {\n return obj.then;\n } catch(error) {\n lib$rsvp$node$$ERROR.value= error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n\n function lib$rsvp$node$$tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch(error) {\n lib$rsvp$node$$ERROR.value = error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n function lib$rsvp$node$$makeObject(_, argumentNames) {\n var obj = {};\n var name;\n var i;\n var length = _.length;\n var args = new Array(length);\n\n for (var x = 0; x < length; x++) {\n args[x] = _[x];\n }\n\n for (i = 0; i < argumentNames.length; i++) {\n name = argumentNames[i];\n obj[name] = args[i + 1];\n }\n\n return obj;\n }\n\n function lib$rsvp$node$$arrayResult(_) {\n var length = _.length;\n var args = new Array(length - 1);\n\n for (var i = 1; i < length; i++) {\n args[i - 1] = _[i];\n }\n\n return args;\n }\n\n function lib$rsvp$node$$wrapThenable(then, promise) {\n return {\n then: function(onFulFillment, onRejection) {\n return then.call(promise, onFulFillment, onRejection);\n }\n };\n }\n\n function lib$rsvp$node$$denodeify(nodeFunc, options) {\n var fn = function() {\n var self = this;\n var l = arguments.length;\n var args = new Array(l + 1);\n var arg;\n var promiseInput = false;\n\n for (var i = 0; i < l; ++i) {\n arg = arguments[i];\n\n if (!promiseInput) {\n // TODO: clean this up\n promiseInput = lib$rsvp$node$$needsPromiseInput(arg);\n if (promiseInput === lib$rsvp$node$$GET_THEN_ERROR) {\n var p = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n lib$rsvp$$internal$$reject(p, lib$rsvp$node$$GET_THEN_ERROR.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = lib$rsvp$node$$wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n\n args[l] = function(err, val) {\n if (err)\n lib$rsvp$$internal$$reject(promise, err);\n else if (options === undefined)\n lib$rsvp$$internal$$resolve(promise, val);\n else if (options === true)\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$arrayResult(arguments));\n else if (lib$rsvp$utils$$isArray(options))\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$makeObject(arguments, options));\n else\n lib$rsvp$$internal$$resolve(promise, val);\n };\n\n if (promiseInput) {\n return lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n }\n\n var lib$rsvp$node$$default = lib$rsvp$node$$denodeify;\n\n function lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self) {\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n }\n\n function lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self){\n return lib$rsvp$promise$$default.all(args).then(function(args){\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n });\n }\n\n function lib$rsvp$node$$needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === lib$rsvp$promise$$default) {\n return true;\n } else {\n return lib$rsvp$node$$getThen(arg);\n }\n } else {\n return false;\n }\n }\n var lib$rsvp$platform$$platform;\n\n /* global self */\n if (typeof self === 'object') {\n lib$rsvp$platform$$platform = self;\n\n /* global global */\n } else if (typeof global === 'object') {\n lib$rsvp$platform$$platform = global;\n } else {\n throw new Error('no global: `self` or `global` found');\n }\n\n var lib$rsvp$platform$$default = lib$rsvp$platform$$platform;\n function lib$rsvp$race$$race(array, label) {\n return lib$rsvp$promise$$default.race(array, label);\n }\n var lib$rsvp$race$$default = lib$rsvp$race$$race;\n function lib$rsvp$reject$$reject(reason, label) {\n return lib$rsvp$promise$$default.reject(reason, label);\n }\n var lib$rsvp$reject$$default = lib$rsvp$reject$$reject;\n function lib$rsvp$resolve$$resolve(value, label) {\n return lib$rsvp$promise$$default.resolve(value, label);\n }\n var lib$rsvp$resolve$$default = lib$rsvp$resolve$$resolve;\n function lib$rsvp$rethrow$$rethrow(reason) {\n setTimeout(function() {\n throw reason;\n });\n throw reason;\n }\n var lib$rsvp$rethrow$$default = lib$rsvp$rethrow$$rethrow;\n\n // defaults\n lib$rsvp$config$$config.async = lib$rsvp$asap$$default;\n lib$rsvp$config$$config.after = function(cb) {\n setTimeout(cb, 0);\n };\n var lib$rsvp$$cast = lib$rsvp$resolve$$default;\n function lib$rsvp$$async(callback, arg) {\n lib$rsvp$config$$config.async(callback, arg);\n }\n\n function lib$rsvp$$on() {\n lib$rsvp$config$$config['on'].apply(lib$rsvp$config$$config, arguments);\n }\n\n function lib$rsvp$$off() {\n lib$rsvp$config$$config['off'].apply(lib$rsvp$config$$config, arguments);\n }\n\n // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`\n if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {\n var lib$rsvp$$callbacks = window['__PROMISE_INSTRUMENTATION__'];\n lib$rsvp$config$$configure('instrument', true);\n for (var lib$rsvp$$eventName in lib$rsvp$$callbacks) {\n if (lib$rsvp$$callbacks.hasOwnProperty(lib$rsvp$$eventName)) {\n lib$rsvp$$on(lib$rsvp$$eventName, lib$rsvp$$callbacks[lib$rsvp$$eventName]);\n }\n }\n }\n\n var lib$rsvp$umd$$RSVP = {\n 'race': lib$rsvp$race$$default,\n 'Promise': lib$rsvp$promise$$default,\n 'allSettled': lib$rsvp$all$settled$$default,\n 'hash': lib$rsvp$hash$$default,\n 'hashSettled': lib$rsvp$hash$settled$$default,\n 'denodeify': lib$rsvp$node$$default,\n 'on': lib$rsvp$$on,\n 'off': lib$rsvp$$off,\n 'map': lib$rsvp$map$$default,\n 'filter': lib$rsvp$filter$$default,\n 'resolve': lib$rsvp$resolve$$default,\n 'reject': lib$rsvp$reject$$default,\n 'all': lib$rsvp$all$$default,\n 'rethrow': lib$rsvp$rethrow$$default,\n 'defer': lib$rsvp$defer$$default,\n 'EventTarget': lib$rsvp$events$$default,\n 'configure': lib$rsvp$config$$configure,\n 'async': lib$rsvp$$async\n };\n\n /* global define:true module:true window: true */\n if (typeof define === 'function' && define['amd']) {\n define(function() { return lib$rsvp$umd$$RSVP; });\n } else if (typeof module !== 'undefined' && module['exports']) {\n module['exports'] = lib$rsvp$umd$$RSVP;\n } else if (typeof lib$rsvp$platform$$default !== 'undefined') {\n lib$rsvp$platform$$default['RSVP'] = lib$rsvp$umd$$RSVP;\n }\n}).call(this);\n\n","/*!\n * URI.js - Mutating URLs\n *\n * Version: 1.17.0\n *\n * Author: Rodney Rehm\n * Web: http://medialize.github.io/URI.js/\n *\n * Licensed under\n * MIT License http://www.opensource.org/licenses/mit-license\n * GPL v3 http://opensource.org/licenses/GPL-3.0\n *\n */\n(function (root, factory) {\n 'use strict';\n // https://github.com/umdjs/umd/blob/master/returnExports.js\n if (typeof exports === 'object') {\n // Node\n module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(['./punycode', './IPv6', './SecondLevelDomains'], factory);\n } else {\n // Browser globals (root is window)\n root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root);\n }\n}(this, function (punycode, IPv6, SLD, root) {\n 'use strict';\n /*global location, escape, unescape */\n // FIXME: v2.0.0 renamce non-camelCase properties to uppercase\n /*jshint camelcase: false */\n\n // save current URI variable, if any\n var _URI = root && root.URI;\n\n function URI(url, base) {\n var _urlSupplied = arguments.length >= 1;\n var _baseSupplied = arguments.length >= 2;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof URI)) {\n if (_urlSupplied) {\n if (_baseSupplied) {\n return new URI(url, base);\n }\n\n return new URI(url);\n }\n\n return new URI();\n }\n\n if (url === undefined) {\n if (_urlSupplied) {\n throw new TypeError('undefined is not a valid argument for URI');\n }\n\n if (typeof location !== 'undefined') {\n url = location.href + '';\n } else {\n url = '';\n }\n }\n\n this.href(url);\n\n // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor\n if (base !== undefined) {\n return this.absoluteTo(base);\n }\n\n return this;\n }\n\n URI.version = '1.17.0';\n\n var p = URI.prototype;\n var hasOwn = Object.prototype.hasOwnProperty;\n\n function escapeRegEx(string) {\n // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963\n return string.replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n }\n\n function getType(value) {\n // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value\n if (value === undefined) {\n return 'Undefined';\n }\n\n return String(Object.prototype.toString.call(value)).slice(8, -1);\n }\n\n function isArray(obj) {\n return getType(obj) === 'Array';\n }\n\n function filterArrayValues(data, value) {\n var lookup = {};\n var i, length;\n\n if (getType(value) === 'RegExp') {\n lookup = null;\n } else if (isArray(value)) {\n for (i = 0, length = value.length; i < length; i++) {\n lookup[value[i]] = true;\n }\n } else {\n lookup[value] = true;\n }\n\n for (i = 0, length = data.length; i < length; i++) {\n /*jshint laxbreak: true */\n var _match = lookup && lookup[data[i]] !== undefined\n || !lookup && value.test(data[i]);\n /*jshint laxbreak: false */\n if (_match) {\n data.splice(i, 1);\n length--;\n i--;\n }\n }\n\n return data;\n }\n\n function arrayContains(list, value) {\n var i, length;\n\n // value may be string, number, array, regexp\n if (isArray(value)) {\n // Note: this can be optimized to O(n) (instead of current O(m * n))\n for (i = 0, length = value.length; i < length; i++) {\n if (!arrayContains(list, value[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n var _type = getType(value);\n for (i = 0, length = list.length; i < length; i++) {\n if (_type === 'RegExp') {\n if (typeof list[i] === 'string' && list[i].match(value)) {\n return true;\n }\n } else if (list[i] === value) {\n return true;\n }\n }\n\n return false;\n }\n\n function arraysEqual(one, two) {\n if (!isArray(one) || !isArray(two)) {\n return false;\n }\n\n // arrays can't be equal if they have different amount of content\n if (one.length !== two.length) {\n return false;\n }\n\n one.sort();\n two.sort();\n\n for (var i = 0, l = one.length; i < l; i++) {\n if (one[i] !== two[i]) {\n return false;\n }\n }\n\n return true;\n }\n\n function trimSlashes(text) {\n var trim_expression = /^\\/+|\\/+$/g;\n return text.replace(trim_expression, '');\n }\n\n URI._parts = function() {\n return {\n protocol: null,\n username: null,\n password: null,\n hostname: null,\n urn: null,\n port: null,\n path: null,\n query: null,\n fragment: null,\n // state\n duplicateQueryParameters: URI.duplicateQueryParameters,\n escapeQuerySpace: URI.escapeQuerySpace\n };\n };\n // state: allow duplicate query parameters (a=1&a=1)\n URI.duplicateQueryParameters = false;\n // state: replaces + with %20 (space in query strings)\n URI.escapeQuerySpace = true;\n // static properties\n URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i;\n URI.idn_expression = /[^a-z0-9\\.-]/i;\n URI.punycode_expression = /(xn--)/i;\n // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?\n URI.ip4_expression = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n // credits to Rich Brown\n // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096\n // specification: http://www.ietf.org/rfc/rfc4291.txt\n URI.ip6_expression = /^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$/;\n // expression used is \"gruber revised\" (@gruber v2) determined to be the\n // best solution in a regex-golf we did a couple of ages ago at\n // * http://mathiasbynens.be/demo/url-regex\n // * http://rodneyrehm.de/t/url-regex.html\n URI.find_uri_expression = /\\b((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))/ig;\n URI.findUri = {\n // valid \"scheme://\" or \"www.\"\n start: /\\b(?:([a-z][a-z0-9.+-]*:\\/\\/)|www\\.)/gi,\n // everything up to the next whitespace\n end: /[\\s\\r\\n]|$/,\n // trim trailing punctuation captured by end RegExp\n trim: /[`!()\\[\\]{};:'\".,<>?«»“”„‘’]+$/\n };\n // http://www.iana.org/assignments/uri-schemes.html\n // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports\n URI.defaultPorts = {\n http: '80',\n https: '443',\n ftp: '21',\n gopher: '70',\n ws: '80',\n wss: '443'\n };\n // allowed hostname characters according to RFC 3986\n // ALPHA DIGIT \"-\" \".\" \"_\" \"~\" \"!\" \"$\" \"&\" \"'\" \"(\" \")\" \"*\" \"+\" \",\" \";\" \"=\" %encoded\n // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . -\n URI.invalid_hostname_characters = /[^a-zA-Z0-9\\.-]/;\n // map DOM Elements to their URI attribute\n URI.domAttributes = {\n 'a': 'href',\n 'blockquote': 'cite',\n 'link': 'href',\n 'base': 'href',\n 'script': 'src',\n 'form': 'action',\n 'img': 'src',\n 'area': 'href',\n 'iframe': 'src',\n 'embed': 'src',\n 'source': 'src',\n 'track': 'src',\n 'input': 'src', // but only if type=\"image\"\n 'audio': 'src',\n 'video': 'src'\n };\n URI.getDomAttribute = function(node) {\n if (!node || !node.nodeName) {\n return undefined;\n }\n\n var nodeName = node.nodeName.toLowerCase();\n // should only expose src for type=\"image\"\n if (nodeName === 'input' && node.type !== 'image') {\n return undefined;\n }\n\n return URI.domAttributes[nodeName];\n };\n\n function escapeForDumbFirefox36(value) {\n // https://github.com/medialize/URI.js/issues/91\n return escape(value);\n }\n\n // encoding / decoding according to RFC3986\n function strictEncodeURIComponent(string) {\n // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent\n return encodeURIComponent(string)\n .replace(/[!'()*]/g, escapeForDumbFirefox36)\n .replace(/\\*/g, '%2A');\n }\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n URI.iso8859 = function() {\n URI.encode = escape;\n URI.decode = unescape;\n };\n URI.unicode = function() {\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n };\n URI.characters = {\n pathname: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,\n map: {\n // -._~!'()*\n '%24': '$',\n '%26': '&',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%3A': ':',\n '%40': '@'\n }\n },\n decode: {\n expression: /[\\/\\?#]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23'\n }\n }\n },\n reserved: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,\n map: {\n // gen-delims\n '%3A': ':',\n '%2F': '/',\n '%3F': '?',\n '%23': '#',\n '%5B': '[',\n '%5D': ']',\n '%40': '@',\n // sub-delims\n '%21': '!',\n '%24': '$',\n '%26': '&',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '='\n }\n }\n },\n urnpath: {\n // The characters under `encode` are the characters called out by RFC 2141 as being acceptable\n // for usage in a URN. RFC2141 also calls out \"-\", \".\", and \"_\" as acceptable characters, but\n // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also\n // note that the colon character is not featured in the encoding map; this is because URI.js\n // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it\n // should not appear unencoded in a segment itself.\n // See also the note above about RFC3986 and capitalalized hex digits.\n encode: {\n expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,\n map: {\n '%21': '!',\n '%24': '$',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%40': '@'\n }\n },\n // These characters are the characters called out by RFC2141 as \"reserved\" characters that\n // should never appear in a URN, plus the colon character (see note above).\n decode: {\n expression: /[\\/\\?#:]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23',\n ':': '%3A'\n }\n }\n }\n };\n URI.encodeQuery = function(string, escapeQuerySpace) {\n var escaped = URI.encode(string + '');\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped;\n };\n URI.decodeQuery = function(string, escapeQuerySpace) {\n string += '';\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n try {\n return URI.decode(escapeQuerySpace ? string.replace(/\\+/g, '%20') : string);\n } catch(e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n // generate encode/decode path functions\n var _parts = {'encode':'encode', 'decode':'decode'};\n var _part;\n var generateAccessor = function(_group, _part) {\n return function(string) {\n try {\n return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {\n return URI.characters[_group][_part].map[c];\n });\n } catch (e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n };\n\n for (_part in _parts) {\n URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);\n URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]);\n }\n\n var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) {\n return function(string) {\n // Why pass in names of functions, rather than the function objects themselves? The\n // definitions of some functions (but in particular, URI.decode) will occasionally change due\n // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure\n // that the functions we use here are \"fresh\".\n var actualCodingFunc;\n if (!_innerCodingFuncName) {\n actualCodingFunc = URI[_codingFuncName];\n } else {\n actualCodingFunc = function(string) {\n return URI[_codingFuncName](URI[_innerCodingFuncName](string));\n };\n }\n\n var segments = (string + '').split(_sep);\n\n for (var i = 0, length = segments.length; i < length; i++) {\n segments[i] = actualCodingFunc(segments[i]);\n }\n\n return segments.join(_sep);\n };\n };\n\n // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.\n URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment');\n URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment');\n URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode');\n URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode');\n\n URI.encodeReserved = generateAccessor('reserved', 'encode');\n\n URI.parse = function(string, parts) {\n var pos;\n if (!parts) {\n parts = {};\n }\n // [protocol\"://\"[username[\":\"password]\"@\"]hostname[\":\"port]\"/\"?][path][\"?\"querystring][\"#\"fragment]\n\n // extract fragment\n pos = string.indexOf('#');\n if (pos > -1) {\n // escaping?\n parts.fragment = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract query\n pos = string.indexOf('?');\n if (pos > -1) {\n // escaping?\n parts.query = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract protocol\n if (string.substring(0, 2) === '//') {\n // relative-scheme\n parts.protocol = null;\n string = string.substring(2);\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n pos = string.indexOf(':');\n if (pos > -1) {\n parts.protocol = string.substring(0, pos) || null;\n if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {\n // : may be within the path\n parts.protocol = undefined;\n } else if (string.substring(pos + 1, pos + 3) === '//') {\n string = string.substring(pos + 3);\n\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n string = string.substring(pos + 1);\n parts.urn = true;\n }\n }\n }\n\n // what's left must be the path\n parts.path = string;\n\n // and we're done\n return parts;\n };\n URI.parseHost = function(string, parts) {\n // Copy chrome, IE, opera backslash-handling behavior.\n // Back slashes before the query string get converted to forward slashes\n // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124\n // See: https://code.google.com/p/chromium/issues/detail?id=25916\n // https://github.com/medialize/URI.js/pull/233\n string = string.replace(/\\\\/g, '/');\n\n // extract host:port\n var pos = string.indexOf('/');\n var bracketPos;\n var t;\n\n if (pos === -1) {\n pos = string.length;\n }\n\n if (string.charAt(0) === '[') {\n // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6\n // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts\n // IPv6+port in the format [2001:db8::1]:80 (for the time being)\n bracketPos = string.indexOf(']');\n parts.hostname = string.substring(1, bracketPos) || null;\n parts.port = string.substring(bracketPos + 2, pos) || null;\n if (parts.port === '/') {\n parts.port = null;\n }\n } else {\n var firstColon = string.indexOf(':');\n var firstSlash = string.indexOf('/');\n var nextColon = string.indexOf(':', firstColon + 1);\n if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {\n // IPv6 host contains multiple colons - but no port\n // this notation is actually not allowed by RFC 3986, but we're a liberal parser\n parts.hostname = string.substring(0, pos) || null;\n parts.port = null;\n } else {\n t = string.substring(0, pos).split(':');\n parts.hostname = t[0] || null;\n parts.port = t[1] || null;\n }\n }\n\n if (parts.hostname && string.substring(pos).charAt(0) !== '/') {\n pos++;\n string = '/' + string;\n }\n\n return string.substring(pos) || '/';\n };\n URI.parseAuthority = function(string, parts) {\n string = URI.parseUserinfo(string, parts);\n return URI.parseHost(string, parts);\n };\n URI.parseUserinfo = function(string, parts) {\n // extract username:password\n var firstSlash = string.indexOf('/');\n var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1);\n var t;\n\n // authority@ must come before /path\n if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {\n t = string.substring(0, pos).split(':');\n parts.username = t[0] ? URI.decode(t[0]) : null;\n t.shift();\n parts.password = t[0] ? URI.decode(t.join(':')) : null;\n string = string.substring(pos + 1);\n } else {\n parts.username = null;\n parts.password = null;\n }\n\n return string;\n };\n URI.parseQuery = function(string, escapeQuerySpace) {\n if (!string) {\n return {};\n }\n\n // throw out the funky business - \"?\"[name\"=\"value\"&\"]+\n string = string.replace(/&+/g, '&').replace(/^\\?*&*|&+$/g, '');\n\n if (!string) {\n return {};\n }\n\n var items = {};\n var splits = string.split('&');\n var length = splits.length;\n var v, name, value;\n\n for (var i = 0; i < length; i++) {\n v = splits[i].split('=');\n name = URI.decodeQuery(v.shift(), escapeQuerySpace);\n // no \"=\" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters\n value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;\n\n if (hasOwn.call(items, name)) {\n if (typeof items[name] === 'string' || items[name] === null) {\n items[name] = [items[name]];\n }\n\n items[name].push(value);\n } else {\n items[name] = value;\n }\n }\n\n return items;\n };\n\n URI.build = function(parts) {\n var t = '';\n\n if (parts.protocol) {\n t += parts.protocol + ':';\n }\n\n if (!parts.urn && (t || parts.hostname)) {\n t += '//';\n }\n\n t += (URI.buildAuthority(parts) || '');\n\n if (typeof parts.path === 'string') {\n if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {\n t += '/';\n }\n\n t += parts.path;\n }\n\n if (typeof parts.query === 'string' && parts.query) {\n t += '?' + parts.query;\n }\n\n if (typeof parts.fragment === 'string' && parts.fragment) {\n t += '#' + parts.fragment;\n }\n return t;\n };\n URI.buildHost = function(parts) {\n var t = '';\n\n if (!parts.hostname) {\n return '';\n } else if (URI.ip6_expression.test(parts.hostname)) {\n t += '[' + parts.hostname + ']';\n } else {\n t += parts.hostname;\n }\n\n if (parts.port) {\n t += ':' + parts.port;\n }\n\n return t;\n };\n URI.buildAuthority = function(parts) {\n return URI.buildUserinfo(parts) + URI.buildHost(parts);\n };\n URI.buildUserinfo = function(parts) {\n var t = '';\n\n if (parts.username) {\n t += URI.encode(parts.username);\n\n if (parts.password) {\n t += ':' + URI.encode(parts.password);\n }\n\n t += '@';\n }\n\n return t;\n };\n URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {\n // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html\n // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed\n // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!\n // URI.js treats the query string as being application/x-www-form-urlencoded\n // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type\n\n var t = '';\n var unique, key, i, length;\n for (key in data) {\n if (hasOwn.call(data, key) && key) {\n if (isArray(data[key])) {\n unique = {};\n for (i = 0, length = data[key].length; i < length; i++) {\n if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace);\n if (duplicateQueryParameters !== true) {\n unique[data[key][i] + ''] = true;\n }\n }\n }\n } else if (data[key] !== undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace);\n }\n }\n }\n\n return t.substring(1);\n };\n URI.buildQueryParameter = function(name, value, escapeQuerySpace) {\n // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded\n // don't append \"=\" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization\n return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '');\n };\n\n URI.addQuery = function(data, name, value) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n URI.addQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (data[name] === undefined) {\n data[name] = value;\n return;\n } else if (typeof data[name] === 'string') {\n data[name] = [data[name]];\n }\n\n if (!isArray(value)) {\n value = [value];\n }\n\n data[name] = (data[name] || []).concat(value);\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n };\n URI.removeQuery = function(data, name, value) {\n var i, length, key;\n\n if (isArray(name)) {\n for (i = 0, length = name.length; i < length; i++) {\n data[name[i]] = undefined;\n }\n } else if (getType(name) === 'RegExp') {\n for (key in data) {\n if (name.test(key)) {\n data[key] = undefined;\n }\n }\n } else if (typeof name === 'object') {\n for (key in name) {\n if (hasOwn.call(name, key)) {\n URI.removeQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (value !== undefined) {\n if (getType(value) === 'RegExp') {\n if (!isArray(data[name]) && value.test(data[name])) {\n data[name] = undefined;\n } else {\n data[name] = filterArrayValues(data[name], value);\n }\n } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) {\n data[name] = undefined;\n } else if (isArray(data[name])) {\n data[name] = filterArrayValues(data[name], value);\n }\n } else {\n data[name] = undefined;\n }\n } else {\n throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter');\n }\n };\n URI.hasQuery = function(data, name, value, withinArray) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n if (!URI.hasQuery(data, key, name[key])) {\n return false;\n }\n }\n }\n\n return true;\n } else if (typeof name !== 'string') {\n throw new TypeError('URI.hasQuery() accepts an object, string as the name parameter');\n }\n\n switch (getType(value)) {\n case 'Undefined':\n // true if exists (but may be empty)\n return name in data; // data[name] !== undefined;\n\n case 'Boolean':\n // true if exists and non-empty\n var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);\n return value === _booly;\n\n case 'Function':\n // allow complex comparison\n return !!value(data[name], name, data);\n\n case 'Array':\n if (!isArray(data[name])) {\n return false;\n }\n\n var op = withinArray ? arrayContains : arraysEqual;\n return op(data[name], value);\n\n case 'RegExp':\n if (!isArray(data[name])) {\n return Boolean(data[name] && data[name].match(value));\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n case 'Number':\n value = String(value);\n /* falls through */\n case 'String':\n if (!isArray(data[name])) {\n return data[name] === value;\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n default:\n throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter');\n }\n };\n\n\n URI.commonPath = function(one, two) {\n var length = Math.min(one.length, two.length);\n var pos;\n\n // find first non-matching character\n for (pos = 0; pos < length; pos++) {\n if (one.charAt(pos) !== two.charAt(pos)) {\n pos--;\n break;\n }\n }\n\n if (pos < 1) {\n return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';\n }\n\n // revert to last /\n if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {\n pos = one.substring(0, pos).lastIndexOf('/');\n }\n\n return one.substring(0, pos + 1);\n };\n\n URI.withinString = function(string, callback, options) {\n options || (options = {});\n var _start = options.start || URI.findUri.start;\n var _end = options.end || URI.findUri.end;\n var _trim = options.trim || URI.findUri.trim;\n var _attributeOpen = /[a-z0-9-]=[\"']?$/i;\n\n _start.lastIndex = 0;\n while (true) {\n var match = _start.exec(string);\n if (!match) {\n break;\n }\n\n var start = match.index;\n if (options.ignoreHtml) {\n // attribut(e=[\"']?$)\n var attributeOpen = string.slice(Math.max(start - 3, 0), start);\n if (attributeOpen && _attributeOpen.test(attributeOpen)) {\n continue;\n }\n }\n\n var end = start + string.slice(start).search(_end);\n var slice = string.slice(start, end).replace(_trim, '');\n if (options.ignore && options.ignore.test(slice)) {\n continue;\n }\n\n end = start + slice.length;\n var result = callback(slice, start, end, string);\n string = string.slice(0, start) + result + string.slice(end);\n _start.lastIndex = start + result.length;\n }\n\n _start.lastIndex = 0;\n return string;\n };\n\n URI.ensureValidHostname = function(v) {\n // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)\n // they are not part of DNS and therefore ignored by URI.js\n\n if (v.match(URI.invalid_hostname_characters)) {\n // test punycode\n if (!punycode) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-] and Punycode.js is not available');\n }\n\n if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n }\n };\n\n // noConflict\n URI.noConflict = function(removeAll) {\n if (removeAll) {\n var unconflicted = {\n URI: this.noConflict()\n };\n\n if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {\n unconflicted.URITemplate = root.URITemplate.noConflict();\n }\n\n if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {\n unconflicted.IPv6 = root.IPv6.noConflict();\n }\n\n if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {\n unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict();\n }\n\n return unconflicted;\n } else if (root.URI === this) {\n root.URI = _URI;\n }\n\n return this;\n };\n\n p.build = function(deferBuild) {\n if (deferBuild === true) {\n this._deferred_build = true;\n } else if (deferBuild === undefined || this._deferred_build) {\n this._string = URI.build(this._parts);\n this._deferred_build = false;\n }\n\n return this;\n };\n\n p.clone = function() {\n return new URI(this);\n };\n\n p.valueOf = p.toString = function() {\n return this.build(false)._string;\n };\n\n\n function generateSimpleAccessor(_part){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n this._parts[_part] = v || null;\n this.build(!build);\n return this;\n }\n };\n }\n\n function generatePrefixAccessor(_part, _key){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n if (v !== null) {\n v = v + '';\n if (v.charAt(0) === _key) {\n v = v.substring(1);\n }\n }\n\n this._parts[_part] = v;\n this.build(!build);\n return this;\n }\n };\n }\n\n p.protocol = generateSimpleAccessor('protocol');\n p.username = generateSimpleAccessor('username');\n p.password = generateSimpleAccessor('password');\n p.hostname = generateSimpleAccessor('hostname');\n p.port = generateSimpleAccessor('port');\n p.query = generatePrefixAccessor('query', '?');\n p.fragment = generatePrefixAccessor('fragment', '#');\n\n p.search = function(v, build) {\n var t = this.query(v, build);\n return typeof t === 'string' && t.length ? ('?' + t) : t;\n };\n p.hash = function(v, build) {\n var t = this.fragment(v, build);\n return typeof t === 'string' && t.length ? ('#' + t) : t;\n };\n\n p.pathname = function(v, build) {\n if (v === undefined || v === true) {\n var res = this._parts.path || (this._parts.hostname ? '/' : '');\n return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res;\n } else {\n if (this._parts.urn) {\n this._parts.path = v ? URI.recodeUrnPath(v) : '';\n } else {\n this._parts.path = v ? URI.recodePath(v) : '/';\n }\n this.build(!build);\n return this;\n }\n };\n p.path = p.pathname;\n p.href = function(href, build) {\n var key;\n\n if (href === undefined) {\n return this.toString();\n }\n\n this._string = '';\n this._parts = URI._parts();\n\n var _URI = href instanceof URI;\n var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname);\n if (href.nodeName) {\n var attribute = URI.getDomAttribute(href);\n href = href[attribute] || '';\n _object = false;\n }\n\n // window.location is reported to be an object, but it's not the sort\n // of object we're looking for:\n // * location.protocol ends with a colon\n // * location.query != object.search\n // * location.hash != object.fragment\n // simply serializing the unknown object should do the trick\n // (for location, not for everything...)\n if (!_URI && _object && href.pathname !== undefined) {\n href = href.toString();\n }\n\n if (typeof href === 'string' || href instanceof String) {\n this._parts = URI.parse(String(href), this._parts);\n } else if (_URI || _object) {\n var src = _URI ? href._parts : href;\n for (key in src) {\n if (hasOwn.call(this._parts, key)) {\n this._parts[key] = src[key];\n }\n }\n } else {\n throw new TypeError('invalid input');\n }\n\n this.build(!build);\n return this;\n };\n\n // identification accessors\n p.is = function(what) {\n var ip = false;\n var ip4 = false;\n var ip6 = false;\n var name = false;\n var sld = false;\n var idn = false;\n var punycode = false;\n var relative = !this._parts.urn;\n\n if (this._parts.hostname) {\n relative = false;\n ip4 = URI.ip4_expression.test(this._parts.hostname);\n ip6 = URI.ip6_expression.test(this._parts.hostname);\n ip = ip4 || ip6;\n name = !ip;\n sld = name && SLD && SLD.has(this._parts.hostname);\n idn = name && URI.idn_expression.test(this._parts.hostname);\n punycode = name && URI.punycode_expression.test(this._parts.hostname);\n }\n\n switch (what.toLowerCase()) {\n case 'relative':\n return relative;\n\n case 'absolute':\n return !relative;\n\n // hostname identification\n case 'domain':\n case 'name':\n return name;\n\n case 'sld':\n return sld;\n\n case 'ip':\n return ip;\n\n case 'ip4':\n case 'ipv4':\n case 'inet4':\n return ip4;\n\n case 'ip6':\n case 'ipv6':\n case 'inet6':\n return ip6;\n\n case 'idn':\n return idn;\n\n case 'url':\n return !this._parts.urn;\n\n case 'urn':\n return !!this._parts.urn;\n\n case 'punycode':\n return punycode;\n }\n\n return null;\n };\n\n // component specific input validation\n var _protocol = p.protocol;\n var _port = p.port;\n var _hostname = p.hostname;\n\n p.protocol = function(v, build) {\n if (v !== undefined) {\n if (v) {\n // accept trailing ://\n v = v.replace(/:(\\/\\/)?$/, '');\n\n if (!v.match(URI.protocol_expression)) {\n throw new TypeError('Protocol \"' + v + '\" contains characters other than [A-Z0-9.+-] or doesn\\'t start with [A-Z]');\n }\n }\n }\n return _protocol.call(this, v, build);\n };\n p.scheme = p.protocol;\n p.port = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n if (v === 0) {\n v = null;\n }\n\n if (v) {\n v += '';\n if (v.charAt(0) === ':') {\n v = v.substring(1);\n }\n\n if (v.match(/[^0-9]/)) {\n throw new TypeError('Port \"' + v + '\" contains characters other than [0-9]');\n }\n }\n }\n return _port.call(this, v, build);\n };\n p.hostname = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n var x = {};\n var res = URI.parseHost(v, x);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n v = x.hostname;\n }\n return _hostname.call(this, v, build);\n };\n\n // compound accessors\n p.origin = function(v, build) {\n var parts;\n\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n var protocol = this.protocol();\n var authority = this.authority();\n if (!authority) return '';\n return (protocol ? protocol + '://' : '') + this.authority();\n } else {\n var origin = URI(v);\n this\n .protocol(origin.protocol())\n .authority(origin.authority())\n .build(!build);\n return this;\n }\n };\n p.host = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildHost(this._parts) : '';\n } else {\n var res = URI.parseHost(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.authority = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildAuthority(this._parts) : '';\n } else {\n var res = URI.parseAuthority(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.userinfo = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n if (!this._parts.username) {\n return '';\n }\n\n var t = URI.buildUserinfo(this._parts);\n return t.substring(0, t.length -1);\n } else {\n if (v[v.length-1] !== '@') {\n v += '@';\n }\n\n URI.parseUserinfo(v, this._parts);\n this.build(!build);\n return this;\n }\n };\n p.resource = function(v, build) {\n var parts;\n\n if (v === undefined) {\n return this.path() + this.search() + this.hash();\n }\n\n parts = URI.parse(v);\n this._parts.path = parts.path;\n this._parts.query = parts.query;\n this._parts.fragment = parts.fragment;\n this.build(!build);\n return this;\n };\n\n // fraction accessors\n p.subdomain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n // convenience, return \"www\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // grab domain and add another segment\n var end = this._parts.hostname.length - this.domain().length - 1;\n return this._parts.hostname.substring(0, end) || '';\n } else {\n var e = this._parts.hostname.length - this.domain().length;\n var sub = this._parts.hostname.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(sub));\n\n if (v && v.charAt(v.length - 1) !== '.') {\n v += '.';\n }\n\n if (v) {\n URI.ensureValidHostname(v);\n }\n\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.domain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // convenience, return \"example.org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // if hostname consists of 1 or 2 segments, it must be the domain\n var t = this._parts.hostname.match(/\\./g);\n if (t && t.length < 2) {\n return this._parts.hostname;\n }\n\n // grab tld and add another segment\n var end = this._parts.hostname.length - this.tld(build).length - 1;\n end = this._parts.hostname.lastIndexOf('.', end -1) + 1;\n return this._parts.hostname.substring(end) || '';\n } else {\n if (!v) {\n throw new TypeError('cannot set domain empty');\n }\n\n URI.ensureValidHostname(v);\n\n if (!this._parts.hostname || this.is('IP')) {\n this._parts.hostname = v;\n } else {\n var replace = new RegExp(escapeRegEx(this.domain()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.tld = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // return \"org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n var pos = this._parts.hostname.lastIndexOf('.');\n var tld = this._parts.hostname.substring(pos + 1);\n\n if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {\n return SLD.get(this._parts.hostname) || tld;\n }\n\n return tld;\n } else {\n var replace;\n\n if (!v) {\n throw new TypeError('cannot set TLD empty');\n } else if (v.match(/[^a-zA-Z0-9-]/)) {\n if (SLD && SLD.is(v)) {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n } else {\n throw new TypeError('TLD \"' + v + '\" contains characters other than [A-Z0-9]');\n }\n } else if (!this._parts.hostname || this.is('IP')) {\n throw new ReferenceError('cannot set TLD on non-domain host');\n } else {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.directory = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path && !this._parts.hostname) {\n return '';\n }\n\n if (this._parts.path === '/') {\n return '/';\n }\n\n var end = this._parts.path.length - this.filename().length - 1;\n var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '');\n\n return v ? URI.decodePath(res) : res;\n\n } else {\n var e = this._parts.path.length - this.filename().length;\n var directory = this._parts.path.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(directory));\n\n // fully qualifier directories begin with a slash\n if (!this.is('relative')) {\n if (!v) {\n v = '/';\n }\n\n if (v.charAt(0) !== '/') {\n v = '/' + v;\n }\n }\n\n // directories always end with a slash\n if (v && v.charAt(v.length - 1) !== '/') {\n v += '/';\n }\n\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.filename = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var pos = this._parts.path.lastIndexOf('/');\n var res = this._parts.path.substring(pos+1);\n\n return v ? URI.decodePathSegment(res) : res;\n } else {\n var mutatedDirectory = false;\n\n if (v.charAt(0) === '/') {\n v = v.substring(1);\n }\n\n if (v.match(/\\.?\\//)) {\n mutatedDirectory = true;\n }\n\n var replace = new RegExp(escapeRegEx(this.filename()) + '$');\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n\n if (mutatedDirectory) {\n this.normalizePath(build);\n } else {\n this.build(!build);\n }\n\n return this;\n }\n };\n p.suffix = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var filename = this.filename();\n var pos = filename.lastIndexOf('.');\n var s, res;\n\n if (pos === -1) {\n return '';\n }\n\n // suffix may only contain alnum characters (yup, I made this up.)\n s = filename.substring(pos+1);\n res = (/^[a-z0-9%]+$/i).test(s) ? s : '';\n return v ? URI.decodePathSegment(res) : res;\n } else {\n if (v.charAt(0) === '.') {\n v = v.substring(1);\n }\n\n var suffix = this.suffix();\n var replace;\n\n if (!suffix) {\n if (!v) {\n return this;\n }\n\n this._parts.path += '.' + URI.recodePath(v);\n } else if (!v) {\n replace = new RegExp(escapeRegEx('.' + suffix) + '$');\n } else {\n replace = new RegExp(escapeRegEx(suffix) + '$');\n }\n\n if (replace) {\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.segment = function(segment, v, build) {\n var separator = this._parts.urn ? ':' : '/';\n var path = this.path();\n var absolute = path.substring(0, 1) === '/';\n var segments = path.split(separator);\n\n if (segment !== undefined && typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (segment !== undefined && typeof segment !== 'number') {\n throw new Error('Bad segment \"' + segment + '\", must be 0-based integer');\n }\n\n if (absolute) {\n segments.shift();\n }\n\n if (segment < 0) {\n // allow negative indexes to address from the end\n segment = Math.max(segments.length + segment, 0);\n }\n\n if (v === undefined) {\n /*jshint laxbreak: true */\n return segment === undefined\n ? segments\n : segments[segment];\n /*jshint laxbreak: false */\n } else if (segment === null || segments[segment] === undefined) {\n if (isArray(v)) {\n segments = [];\n // collapse empty elements within array\n for (var i=0, l=v.length; i < l; i++) {\n if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) {\n continue;\n }\n\n if (segments.length && !segments[segments.length -1].length) {\n segments.pop();\n }\n\n segments.push(trimSlashes(v[i]));\n }\n } else if (v || typeof v === 'string') {\n v = trimSlashes(v);\n if (segments[segments.length -1] === '') {\n // empty trailing elements have to be overwritten\n // to prevent results such as /foo//bar\n segments[segments.length -1] = v;\n } else {\n segments.push(v);\n }\n }\n } else {\n if (v) {\n segments[segment] = trimSlashes(v);\n } else {\n segments.splice(segment, 1);\n }\n }\n\n if (absolute) {\n segments.unshift('');\n }\n\n return this.path(segments.join(separator), build);\n };\n p.segmentCoded = function(segment, v, build) {\n var segments, i, l;\n\n if (typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (v === undefined) {\n segments = this.segment(segment, v, build);\n if (!isArray(segments)) {\n segments = segments !== undefined ? URI.decode(segments) : undefined;\n } else {\n for (i = 0, l = segments.length; i < l; i++) {\n segments[i] = URI.decode(segments[i]);\n }\n }\n\n return segments;\n }\n\n if (!isArray(v)) {\n v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v;\n } else {\n for (i = 0, l = v.length; i < l; i++) {\n v[i] = URI.encode(v[i]);\n }\n }\n\n return this.segment(segment, v, build);\n };\n\n // mutating query string\n var q = p.query;\n p.query = function(v, build) {\n if (v === true) {\n return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n } else if (typeof v === 'function') {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n var result = v.call(this, data);\n this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else if (v !== undefined && typeof v !== 'string') {\n this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else {\n return q.call(this, v, build);\n }\n };\n p.setQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n\n if (typeof name === 'string' || name instanceof String) {\n data[name] = value !== undefined ? value : null;\n } else if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n data[key] = name[key];\n }\n }\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.addQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.addQuery(data, name, value === undefined ? null : value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.removeQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.removeQuery(data, name, value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.hasQuery = function(name, value, withinArray) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n return URI.hasQuery(data, name, value, withinArray);\n };\n p.setSearch = p.setQuery;\n p.addSearch = p.addQuery;\n p.removeSearch = p.removeQuery;\n p.hasSearch = p.hasQuery;\n\n // sanitizing URLs\n p.normalize = function() {\n if (this._parts.urn) {\n return this\n .normalizeProtocol(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n }\n\n return this\n .normalizeProtocol(false)\n .normalizeHostname(false)\n .normalizePort(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n };\n p.normalizeProtocol = function(build) {\n if (typeof this._parts.protocol === 'string') {\n this._parts.protocol = this._parts.protocol.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeHostname = function(build) {\n if (this._parts.hostname) {\n if (this.is('IDN') && punycode) {\n this._parts.hostname = punycode.toASCII(this._parts.hostname);\n } else if (this.is('IPv6') && IPv6) {\n this._parts.hostname = IPv6.best(this._parts.hostname);\n }\n\n this._parts.hostname = this._parts.hostname.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePort = function(build) {\n // remove port of it's the protocol's default\n if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {\n this._parts.port = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePath = function(build) {\n var _path = this._parts.path;\n if (!_path) {\n return this;\n }\n\n if (this._parts.urn) {\n this._parts.path = URI.recodeUrnPath(this._parts.path);\n this.build(!build);\n return this;\n }\n\n if (this._parts.path === '/') {\n return this;\n }\n\n var _was_relative;\n var _leadingParents = '';\n var _parent, _pos;\n\n // handle relative paths\n if (_path.charAt(0) !== '/') {\n _was_relative = true;\n _path = '/' + _path;\n }\n\n // handle relative files (as opposed to directories)\n if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {\n _path += '/';\n }\n\n // resolve simples\n _path = _path\n .replace(/(\\/(\\.\\/)+)|(\\/\\.$)/g, '/')\n .replace(/\\/{2,}/g, '/');\n\n // remember leading parents\n if (_was_relative) {\n _leadingParents = _path.substring(1).match(/^(\\.\\.\\/)+/) || '';\n if (_leadingParents) {\n _leadingParents = _leadingParents[0];\n }\n }\n\n // resolve parents\n while (true) {\n _parent = _path.indexOf('/..');\n if (_parent === -1) {\n // no more ../ to resolve\n break;\n } else if (_parent === 0) {\n // top level cannot be relative, skip it\n _path = _path.substring(3);\n continue;\n }\n\n _pos = _path.substring(0, _parent).lastIndexOf('/');\n if (_pos === -1) {\n _pos = _parent;\n }\n _path = _path.substring(0, _pos) + _path.substring(_parent + 3);\n }\n\n // revert to relative\n if (_was_relative && this.is('relative')) {\n _path = _leadingParents + _path.substring(1);\n }\n\n _path = URI.recodePath(_path);\n this._parts.path = _path;\n this.build(!build);\n return this;\n };\n p.normalizePathname = p.normalizePath;\n p.normalizeQuery = function(build) {\n if (typeof this._parts.query === 'string') {\n if (!this._parts.query.length) {\n this._parts.query = null;\n } else {\n this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace));\n }\n\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeFragment = function(build) {\n if (!this._parts.fragment) {\n this._parts.fragment = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeSearch = p.normalizeQuery;\n p.normalizeHash = p.normalizeFragment;\n\n p.iso8859 = function() {\n // expect unicode input, iso8859 output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = escape;\n URI.decode = decodeURIComponent;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.unicode = function() {\n // expect iso8859 input, unicode output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = strictEncodeURIComponent;\n URI.decode = unescape;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.readable = function() {\n var uri = this.clone();\n // removing username, password, because they shouldn't be displayed according to RFC 3986\n uri.username('').password('').normalize();\n var t = '';\n if (uri._parts.protocol) {\n t += uri._parts.protocol + '://';\n }\n\n if (uri._parts.hostname) {\n if (uri.is('punycode') && punycode) {\n t += punycode.toUnicode(uri._parts.hostname);\n if (uri._parts.port) {\n t += ':' + uri._parts.port;\n }\n } else {\n t += uri.host();\n }\n }\n\n if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {\n t += '/';\n }\n\n t += uri.path(true);\n if (uri._parts.query) {\n var q = '';\n for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {\n var kv = (qp[i] || '').split('=');\n q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n\n if (kv[1] !== undefined) {\n q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n }\n }\n t += '?' + q.substring(1);\n }\n\n t += URI.decodeQuery(uri.hash(), true);\n return t;\n };\n\n // resolving relative and absolute URLs\n p.absoluteTo = function(base) {\n var resolved = this.clone();\n var properties = ['protocol', 'username', 'password', 'hostname', 'port'];\n var basedir, i, p;\n\n if (this._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n if (!(base instanceof URI)) {\n base = new URI(base);\n }\n\n if (!resolved._parts.protocol) {\n resolved._parts.protocol = base._parts.protocol;\n }\n\n if (this._parts.hostname) {\n return resolved;\n }\n\n for (i = 0; (p = properties[i]); i++) {\n resolved._parts[p] = base._parts[p];\n }\n\n if (!resolved._parts.path) {\n resolved._parts.path = base._parts.path;\n if (!resolved._parts.query) {\n resolved._parts.query = base._parts.query;\n }\n } else if (resolved._parts.path.substring(-2) === '..') {\n resolved._parts.path += '/';\n }\n\n if (resolved.path().charAt(0) !== '/') {\n basedir = base.directory();\n basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : '';\n resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;\n resolved.normalizePath();\n }\n\n resolved.build();\n return resolved;\n };\n p.relativeTo = function(base) {\n var relative = this.clone().normalize();\n var relativeParts, baseParts, common, relativePath, basePath;\n\n if (relative._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n base = new URI(base).normalize();\n relativeParts = relative._parts;\n baseParts = base._parts;\n relativePath = relative.path();\n basePath = base.path();\n\n if (relativePath.charAt(0) !== '/') {\n throw new Error('URI is already relative');\n }\n\n if (basePath.charAt(0) !== '/') {\n throw new Error('Cannot calculate a URI relative to another relative URI');\n }\n\n if (relativeParts.protocol === baseParts.protocol) {\n relativeParts.protocol = null;\n }\n\n if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {\n return relative.build();\n }\n\n if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {\n return relative.build();\n }\n\n if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {\n relativeParts.hostname = null;\n relativeParts.port = null;\n } else {\n return relative.build();\n }\n\n if (relativePath === basePath) {\n relativeParts.path = '';\n return relative.build();\n }\n\n // determine common sub path\n common = URI.commonPath(relativePath, basePath);\n\n // If the paths have nothing in common, return a relative URL with the absolute path.\n if (!common) {\n return relative.build();\n }\n\n var parents = baseParts.path\n .substring(common.length)\n .replace(/[^\\/]*$/, '')\n .replace(/.*?\\//g, '../');\n\n relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './';\n\n return relative.build();\n };\n\n // comparing URIs\n p.equals = function(uri) {\n var one = this.clone();\n var two = new URI(uri);\n var one_map = {};\n var two_map = {};\n var checked = {};\n var one_query, two_query, key;\n\n one.normalize();\n two.normalize();\n\n // exact match\n if (one.toString() === two.toString()) {\n return true;\n }\n\n // extract query string\n one_query = one.query();\n two_query = two.query();\n one.query('');\n two.query('');\n\n // definitely not equal if not even non-query parts match\n if (one.toString() !== two.toString()) {\n return false;\n }\n\n // query parameters have the same length, even if they're permuted\n if (one_query.length !== two_query.length) {\n return false;\n }\n\n one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace);\n two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace);\n\n for (key in one_map) {\n if (hasOwn.call(one_map, key)) {\n if (!isArray(one_map[key])) {\n if (one_map[key] !== two_map[key]) {\n return false;\n }\n } else if (!arraysEqual(one_map[key], two_map[key])) {\n return false;\n }\n\n checked[key] = true;\n }\n }\n\n for (key in two_map) {\n if (hasOwn.call(two_map, key)) {\n if (!checked[key]) {\n // two contains a parameter not present in one\n return false;\n }\n }\n }\n\n return true;\n };\n\n // state\n p.duplicateQueryParameters = function(v) {\n this._parts.duplicateQueryParameters = !!v;\n return this;\n };\n\n p.escapeQuerySpace = function(v) {\n this._parts.escapeQuerySpace = !!v;\n return this;\n };\n\n return URI;\n}));\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar Spine = require('./spine');\nvar Locations = require('./locations');\nvar Parser = require('./parser');\nvar Navigation = require('./navigation');\nvar Rendition = require('./rendition');\nvar Continuous = require('./continuous');\nvar Paginate = require('./paginate');\nvar Unarchive = require('./unarchive');\nvar request = require('./request');\n\nfunction Book(_url, options){\n // Promises\n this.opening = new RSVP.defer();\n this.opened = this.opening.promise;\n this.isOpen = false;\n\n this.url = undefined;\n\n this.loading = {\n manifest: new RSVP.defer(),\n spine: new RSVP.defer(),\n metadata: new RSVP.defer(),\n cover: new RSVP.defer(),\n navigation: new RSVP.defer(),\n pageList: new RSVP.defer()\n };\n\n this.loaded = {\n manifest: this.loading.manifest.promise,\n spine: this.loading.spine.promise,\n metadata: this.loading.metadata.promise,\n cover: this.loading.cover.promise,\n navigation: this.loading.navigation.promise,\n pageList: this.loading.pageList.promise\n };\n\n this.ready = RSVP.hash(this.loaded);\n\n // Queue for methods used before opening\n this.isRendered = false;\n // this._q = core.queue(this);\n\n this.request = this.requestMethod.bind(this);\n\n this.spine = new Spine(this.request);\n this.locations = new Locations(this.spine, this.request);\n\n if(_url) {\n this.open(_url);\n }\n};\n\nBook.prototype.open = function(_url){\n var uri;\n var parse = new Parser();\n var epubPackage;\n var epubContainer;\n var book = this;\n var containerPath = \"META-INF/container.xml\";\n var location;\n\n if(!_url) {\n this.opening.resolve(this);\n return this.opened;\n }\n\n // Reuse parsed url or create a new uri object\n // if(typeof(_url) === \"object\") {\n // uri = _url;\n // } else {\n // uri = core.uri(_url);\n // }\n uri = URI(_url);\n this.url = _url;\n\n // Find path to the Container\n if(uri.suffix() === \"opf\") {\n // Direct link to package, no container\n this.packageUrl = _url;\n this.containerUrl = '';\n\n if(uri.origin()) {\n this.baseUrl = uri.origin() + \"/\" + uri.directory() + \"/\";\n } else if(window){\n this.baseUrl = uri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n this.baseUrl = uri.directory() + \"/\";\n }\n\n epubPackage = this.request(this.packageUrl);\n\n } else if(this.isArchivedUrl(uri)) {\n // Book is archived\n this.url = '/';\n this.containerUrl = URI(containerPath).absoluteTo(this.url).toString();\n\n epubContainer = this.unarchive(_url).\n then(function() {\n return this.request(this.containerUrl);\n }.bind(this));\n\n }\n // Find the path to the Package from the container\n else if (!uri.suffix()) {\n\n this.containerUrl = this.url + containerPath;\n\n epubContainer = this.request(this.containerUrl);\n }\n\n if (epubContainer) {\n epubPackage = epubContainer.\n then(function(containerXml){\n return parse.container(containerXml); // Container has path to content\n }).\n then(function(paths){\n var packageUri = URI(paths.packagePath);\n var absPackageUri = packageUri.absoluteTo(book.url);\n book.packageUrl = absPackageUri.toString();\n book.encoding = paths.encoding;\n\n // Set Url relative to the content\n if(packageUri.origin()) {\n book.baseUrl = packageUri.origin() + \"/\" + packageUri.directory() + \"/\";\n } else if(window && !book.isArchivedUrl(uri)){\n book.baseUrl = absPackageUri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n book.baseUrl = \"/\" + packageUri.directory() + \"/\";\n }\n\n return book.request(book.packageUrl);\n }).catch(function(error) {\n // handle errors in either of the two requests\n console.error(\"Could not load book at: \" + (this.packageUrl || this.containerPath));\n book.trigger(\"book:loadFailed\", (this.packageUrl || this.containerPath));\n book.opening.reject(error);\n });\n }\n\n\n epubPackage.then(function(packageXml) {\n // Get package information from epub opf\n book.unpack(packageXml);\n\n // Resolve promises\n book.loading.manifest.resolve(book.package.manifest);\n book.loading.metadata.resolve(book.package.metadata);\n book.loading.spine.resolve(book.spine);\n book.loading.cover.resolve(book.cover);\n\n book.isOpen = true;\n\n // Clear queue of any waiting book request\n\n // Resolve book opened promise\n book.opening.resolve(book);\n\n }).catch(function(error) {\n // handle errors in parsing the book\n console.error(error.message, error.stack);\n book.opening.reject(error);\n });\n\n return this.opened;\n};\n\nBook.prototype.unpack = function(packageXml){\n var book = this,\n parse = new Parser();\n\n book.package = parse.packageContents(packageXml); // Extract info from contents\n book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths\n\n this.spine.load(book.package);\n\n book.navigation = new Navigation(book.package, this.request);\n book.navigation.load().then(function(toc){\n book.toc = toc;\n book.loading.navigation.resolve(book.toc);\n });\n\n // //-- Set Global Layout setting based on metadata\n // MOVE TO RENDER\n // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);\n\n book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();\n};\n\n// Alias for book.spine.get\nBook.prototype.section = function(target) {\n return this.spine.get(target);\n};\n\n// Sugar to render a book\nBook.prototype.renderTo = function(element, options) {\n var renderMethod = (options && options.method) ?\n options.method :\n \"rendition\";\n var Renderer = require('./'+renderMethod);\n\n this.rendition = new Renderer(this, options);\n this.rendition.attachTo(element);\n\n return this.rendition;\n};\n\nBook.prototype.requestMethod = function(_url) {\n // Switch request methods\n if(this.archive) {\n return this.archive.request(_url);\n } else {\n return request(_url, null, this.requestCredentials, this.requestHeaders);\n }\n\n};\n\nBook.prototype.setRequestCredentials = function(_credentials) {\n this.requestCredentials = _credentials;\n};\n\nBook.prototype.setRequestHeaders = function(_headers) {\n this.requestHeaders = _headers;\n};\n\nBook.prototype.unarchive = function(bookUrl){\n\tthis.archive = new Unarchive();\n\treturn this.archive.open(bookUrl);\n};\n\n//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)\nBook.prototype.isArchivedUrl = function(bookUrl){\n var uri;\n var extension;\n\n if (bookUrl instanceof ArrayBuffer) {\n\t\treturn true;\n\t}\n\n // Reuse parsed url or create a new uri object\n // if(typeof(bookUrl) === \"object\") {\n // uri = bookUrl;\n // } else {\n // uri = core.uri(bookUrl);\n // }\n uri = URI(bookUrl);\n extension = uri.suffix();\n\n\tif(extension && (extension == \"epub\" || extension == \"zip\")){\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n//-- Returns the cover\nBook.prototype.coverUrl = function(){\n\tvar retrieved = this.loaded.cover.\n\t\tthen(function(url) {\n\t\t\tif(this.archive) {\n\t\t\t\treturn this.archive.createUrl(this.cover);\n\t\t\t}else{\n\t\t\t\treturn this.cover;\n\t\t\t}\n\t\t}.bind(this));\n\n\n\n\treturn retrieved;\n};\n\nmodule.exports = Book;\n\n//-- Enable binding events to book\nRSVP.EventTarget.mixin(Book.prototype);\n\n//-- Handle RSVP Errors\nRSVP.on('error', function(event) {\n console.error(event);\n});\n\nRSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections\n// RSVP.on('created', listener);\n// RSVP.on('chained', listener);\n// RSVP.on('fulfilled', listener);\nRSVP.on('rejected', function(event){\n console.error(event.detail.message, event.detail.stack);\n});\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Rendition = require('./rendition');\nvar View = require('./view');\n\nfunction Continuous(book, options) {\n\n\tRendition.apply(this, arguments); // call super constructor.\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\toverflow: \"auto\",\n\t\taxis: \"vertical\",\n\t\toffset: 500,\n\t\toffsetDelta: 250\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t}\n\n\n};\n\n// subclass extends superclass\nContinuous.prototype = Object.create(Rendition.prototype);\nContinuous.prototype.constructor = Continuous;\n\nContinuous.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to a percent\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n\n\tif(this.settings.infinite) {\n\t\tthis.start();\n\t}\n\n\n};\n\nContinuous.prototype.parseTarget = function(target){\n\tif(this.epubcfi.isCfiString(target)) {\n cfi = this.epubcfi.parse(target);\n spinePos = cfi.spinePos;\n section = this.book.spine.get(spinePos);\n } else {\n section = this.book.spine.get(target);\n }\n};\n\nContinuous.prototype.moveTo = function(offset){\n // var bounds = this.bounds();\n // var dist = Math.floor(offset.top / bounds.height) * bounds.height;\n return this.check(\n\t\toffset.left+this.settings.offset,\n\t\toffset.top+this.settings.offset)\n\t\t.then(function(){\n\n\t if(this.settings.axis === \"vertical\") {\n\t this.scrollBy(0, offset.top);\n\t } else {\n\t this.scrollBy(offset.left, 0);\n\t }\n\n\t }.bind(this));\n};\n\nContinuous.prototype.afterDisplayed = function(currView){\n\tvar next = currView.section.next();\n\tvar prev = currView.section.prev();\n\tvar index = this.views.indexOf(currView);\n\tvar prevView, nextView;\n\n\tif(index + 1 === this.views.length && next) {\n\t\tnextView = this.createView(next);\n\t\tthis.q.enqueue(this.append, nextView);\n\t}\n\n\tif(index === 0 && prev) {\n\t\tprevView = this.createView(prev, this.viewSettings);\n\t\tthis.q.enqueue(this.prepend, prevView);\n\t}\n\n\t// this.removeShownListeners(currView);\n\t// currView.onShown = this.afterDisplayed.bind(this);\n\tthis.trigger(\"added\", currView.section);\n\n};\n\n\n// Remove Previous Listeners if present\nContinuous.prototype.removeShownListeners = function(view){\n\n\t// view.off(\"shown\", this.afterDisplayed);\n\t// view.off(\"shown\", this.afterDisplayedAbove);\n\tview.onDisplayed = function(){};\n\n};\n\nContinuous.prototype.append = function(view){\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tthis.views.append(view);\n\n //this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.prepend = function(view){\n\t// view.on(\"shown\", this.afterDisplayedAbove.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tview.on(\"resized\", this.counter.bind(this));\n\n\tthis.views.prepend(view);\n\n // this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.counter = function(bounds){\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.scrollBy(0, bounds.heightDelta, true);\n\t} else {\n\t\tthis.scrollBy(bounds.widthDelta, 0, true);\n\t}\n\n};\n\nContinuous.prototype.check = function(_offset){\n\tvar checking = new RSVP.defer();\n\tvar container = this.bounds();\n var promises = [];\n var offset = _offset || this.settings.offset;\n\n\tthis.views.each(function(view){\n\t\tvar visible = this.isVisible(view, offset, offset, container);\n\n\t\tif(visible) {\n\n\t\t\tif(!view.displayed && !view.rendering) {\n // console.log(\"render\",view.section.index)\n\t\t\t\t\tpromises.push(this.render(view));\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif(view.displayed) {\n // console.log(\"destroy\", view.section.index)\n this.q.enqueue(view.destroy.bind(view));\n // view.destroy();\n // this.q.enqueue(this.trim);\n clearTimeout(this.trimTimeout);\n this.trimTimeout = setTimeout(function(){\n this.q.enqueue(this.trim);\n }.bind(this), 250);\n\t\t\t}\n\n\t\t}\n\n\t}.bind(this));\n\n\n if(promises.length){\n\n return RSVP.all(promises)\n .then(function(posts) {\n // Check to see if anything new is on screen after rendering\n this.q.enqueue(this.check);\n\n }.bind(this));\n\n } else {\n checking.resolve();\n\n return checking.promise;\n }\n\n};\n\nContinuous.prototype.trim = function(){\n var task = new RSVP.defer();\n var displayed = this.views.displayed();\n var first = displayed[0];\n var last = displayed[displayed.length-1];\n var firstIndex = this.views.indexOf(first);\n var lastIndex = this.views.indexOf(last);\n var above = this.views.slice(0, firstIndex);\n var below = this.views.slice(lastIndex+1);\n\n // Erase all but last above\n for (var i = 0; i < above.length-1; i++) {\n this.erase(above[i], above);\n }\n\n // Erase all except first below\n for (var j = 1; j < below.length; j++) {\n this.erase(below[j]);\n }\n\n task.resolve();\n return task.promise;\n};\n\nContinuous.prototype.erase = function(view, above){ //Trim\n\n\tvar prevTop;\n\tvar prevLeft;\n\n\tif(this.settings.height) {\n \tprevTop = this.container.scrollTop;\n\t\tprevLeft = this.container.scrollLeft;\n } else {\n \tprevTop = window.scrollY;\n\t\tprevLeft = window.scrollX;\n }\n\n\tvar bounds = view.bounds();\n\n\tthis.views.remove(view);\n\n\tif(above) {\n\n\t\tif(this.settings.axis === \"vertical\") {\n\t\t\tthis.scrollTo(0, prevTop - bounds.height, true);\n\t\t} else {\n\t\t\tthis.scrollTo(prevLeft - bounds.width, 0, true);\n\t\t}\n\t}\n\n};\n\nContinuous.prototype.start = function() {\n var scroller;\n\n this.tick = core.requestAnimationFrame;\n\n if(this.settings.height) {\n \tthis.prevScrollTop = this.container.scrollTop;\n \tthis.prevScrollLeft = this.container.scrollLeft;\n } else {\n \tthis.prevScrollTop = window.scrollY;\n\t\tthis.prevScrollLeft = window.scrollX;\n }\n\n this.scrollDeltaVert = 0;\n this.scrollDeltaHorz = 0;\n\n if(this.settings.height) {\n \tscroller = this.container;\n } else {\n \tscroller = window;\n }\n\n window.addEventListener(\"scroll\", function(e){\n if(!this.ignore) {\n this.scrolled = true;\n } else {\n this.ignore = false;\n }\n }.bind(this));\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n this.tick.call(window, this.onScroll.bind(this));\n\n this.scrolled = false;\n\n};\n\nContinuous.prototype.onScroll = function(){\n\n if(this.scrolled) {\n\n if(this.settings.height) {\n\t \tscrollTop = this.container.scrollTop;\n\t \tscrollLeft = this.container.scrollLeft;\n\t } else {\n\t \tscrollTop = window.scrollY;\n\t\t\tscrollLeft = window.scrollX;\n\t }\n\n if(!this.ignore) {\n\n\t if((this.scrollDeltaVert === 0 &&\n\t \t this.scrollDeltaHorz === 0) ||\n\t \t this.scrollDeltaVert > this.settings.offsetDelta ||\n\t \t this.scrollDeltaHorz > this.settings.offsetDelta) {\n\n\t\t\t\tthis.q.enqueue(this.check);\n\n\t\t\t\tthis.scrollDeltaVert = 0;\n\t \tthis.scrollDeltaHorz = 0;\n\n\t\t\t\tthis.trigger(\"scroll\", {\n\t\t top: scrollTop,\n\t\t left: scrollLeft\n\t\t });\n\n\t\t\t}\n\n\t\t} else {\n\t this.ignore = false;\n\t\t}\n\n this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);\n this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);\n\n\t\tthis.prevScrollTop = scrollTop;\n\t\tthis.prevScrollLeft = scrollLeft;\n\n \tclearTimeout(this.scrollTimeout);\n\t\tthis.scrollTimeout = setTimeout(function(){\n\t\t\tthis.scrollDeltaVert = 0;\n\t this.scrollDeltaHorz = 0;\n\t\t}.bind(this), 150);\n\n\n this.scrolled = false;\n }\n\n this.tick.call(window, this.onScroll.bind(this));\n\n};\n\n\n Continuous.prototype.resizeView = function(view) {\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tview.lock(\"height\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nContinuous.prototype.currentLocation = function(){\n var visible = this.visible();\n var startPage, endPage;\n\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n return this.map.page(visible[0]);\n }\n\n if(visible.length > 1) {\n\n startPage = this.map.page(visible[0]);\n endPage = this.map.page(visible[visible.length-1]);\n\n return {\n start: startPage.start,\n end: endPage.end\n };\n }\n\n};\n\n/*\nContinuous.prototype.current = function(what){\n var view, top;\n var container = this.container.getBoundingClientRect();\n var length = this.views.length - 1;\n\n if(this.settings.axis === \"horizontal\") {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n left = view.position().left;\n\n if(left < container.right) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n break;\n }\n }\n\n } else {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n top = view.bounds().top;\n if(top < container.bottom) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n\n break;\n }\n }\n\n }\n\n return this._current;\n};\n*/\n\nmodule.exports = Continuous;\n","var RSVP = require('rsvp');\n\nvar requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false;\n/*\n//-- Parse the different parts of a url, returning a object\nfunction uri(url){\n var uri = {\n protocol : '',\n host : '',\n path : '',\n origin : '',\n directory : '',\n base : '',\n filename : '',\n extension : '',\n fragment : '',\n href : url\n },\n doubleSlash = url.indexOf('://'),\n search = url.indexOf('?'),\n fragment = url.indexOf(\"#\"),\n withoutProtocol,\n dot,\n firstSlash;\n\n if(fragment != -1) {\n uri.fragment = url.slice(fragment + 1);\n url = url.slice(0, fragment);\n }\n\n if(search != -1) {\n uri.search = url.slice(search + 1);\n url = url.slice(0, search);\n href = url;\n }\n\n if(doubleSlash != -1) {\n uri.protocol = url.slice(0, doubleSlash);\n withoutProtocol = url.slice(doubleSlash+3);\n firstSlash = withoutProtocol.indexOf('/');\n\n if(firstSlash === -1) {\n uri.host = uri.path;\n uri.path = \"\";\n } else {\n uri.host = withoutProtocol.slice(0, firstSlash);\n uri.path = withoutProtocol.slice(firstSlash);\n }\n\n\n uri.origin = uri.protocol + \"://\" + uri.host;\n\n uri.directory = folder(uri.path);\n\n uri.base = uri.origin + uri.directory;\n // return origin;\n } else {\n uri.path = url;\n uri.directory = folder(url);\n uri.base = uri.directory;\n }\n\n //-- Filename\n uri.filename = url.replace(uri.base, '');\n dot = uri.filename.lastIndexOf('.');\n if(dot != -1) {\n uri.extension = uri.filename.slice(dot+1);\n }\n return uri;\n};\n\n//-- Parse out the folder, will return everything before the last slash\nfunction folder(url){\n\n var lastSlash = url.lastIndexOf('/');\n\n if(lastSlash == -1) var folder = '';\n\n folder = url.slice(0, lastSlash + 1);\n\n return folder;\n\n};\n*/\nfunction isElement(obj) {\n return !!(obj && obj.nodeType == 1);\n};\n\n// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\nfunction uuid() {\n var d = new Date().getTime();\n var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (d + Math.random()*16)%16 | 0;\n d = Math.floor(d/16);\n return (c=='x' ? r : (r&0x7|0x8)).toString(16);\n });\n return uuid;\n};\n\n// From Lodash\nfunction values(object) {\n var index = -1,\n props = Object.keys(object),\n length = props.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = object[props[index]];\n }\n return result;\n};\n\nfunction resolveUrl(base, path) {\n var url = [],\n segments = [],\n baseUri = uri(base),\n pathUri = uri(path),\n baseDirectory = baseUri.directory,\n pathDirectory = pathUri.directory,\n directories = [],\n // folders = base.split(\"/\"),\n paths;\n\n // if(uri.host) {\n // return path;\n // }\n\n if(baseDirectory[0] === \"/\") {\n baseDirectory = baseDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n baseDirectory = baseDirectory.substring(0, baseDirectory.length-1);\n }\n\n if(pathDirectory[0] === \"/\") {\n pathDirectory = pathDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n pathDirectory = pathDirectory.substring(0, pathDirectory.length-1);\n }\n\n if(baseDirectory) {\n directories = baseDirectory.split(\"/\");\n }\n\n paths = pathDirectory.split(\"/\");\n\n paths.reverse().forEach(function(part, index){\n if(part === \"..\"){\n directories.pop();\n } else if(part === directories[directories.length-1]) {\n directories.pop();\n segments.unshift(part);\n } else {\n segments.unshift(part);\n }\n });\n\n url = [baseUri.origin];\n\n if(directories.length) {\n url = url.concat(directories);\n }\n\n if(segments) {\n url = url.concat(segments);\n }\n\n url = url.concat(pathUri.filename);\n\n return url.join(\"/\");\n};\n\nfunction documentHeight() {\n return Math.max(\n document.documentElement.clientHeight,\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight\n );\n};\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n};\n\nfunction prefixed(unprefixed) {\n var vendors = [\"Webkit\", \"Moz\", \"O\", \"ms\" ],\n prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],\n upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),\n length = vendors.length;\n\n if (typeof(document.body.style[unprefixed]) != 'undefined') {\n return unprefixed;\n }\n\n for ( var i=0; i < length; i++ ) {\n if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {\n return vendors[i] + upper;\n }\n }\n\n return unprefixed;\n};\n\nfunction defaults(obj) {\n for (var i = 1, length = arguments.length; i < length; i++) {\n var source = arguments[i];\n for (var prop in source) {\n if (obj[prop] === void 0) obj[prop] = source[prop];\n }\n }\n return obj;\n};\n\nfunction extend(target) {\n var sources = [].slice.call(arguments, 1);\n sources.forEach(function (source) {\n if(!source) return;\n Object.getOwnPropertyNames(source).forEach(function(propName) {\n Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));\n });\n });\n return target;\n};\n\n// Fast quicksort insert for sorted array -- based on:\n// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers\nfunction insert(item, array, compareFunction) {\n var location = locationOf(item, array, compareFunction);\n array.splice(location, 0, item);\n\n return location;\n};\n// Returns where something would fit in\nfunction locationOf(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return pivot;\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared > 0 ? pivot : pivot + 1;\n }\n\n if(compared === 0) {\n return pivot;\n }\n if(compared === -1) {\n return locationOf(item, array, compareFunction, pivot, end);\n } else{\n return locationOf(item, array, compareFunction, start, pivot);\n }\n};\n// Returns -1 of mpt found\nfunction indexOfSorted(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return -1; // Not found\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared === 0 ? pivot : -1;\n }\n if(compared === 0) {\n return pivot; // Found\n }\n if(compared === -1) {\n return indexOfSorted(item, array, compareFunction, pivot, end);\n } else{\n return indexOfSorted(item, array, compareFunction, start, pivot);\n }\n};\n\nfunction bounds(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"width\", \"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"height\", \"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction borders(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction windowBounds() {\n\n var width = window.innerWidth;\n var height = window.innerHeight;\n\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width: width,\n height: height\n };\n\n};\n\n//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496\nfunction cleanStringForXpath(str) {\n var parts = str.match(/[^'\"]+|['\"]/g);\n parts = parts.map(function(part){\n if (part === \"'\") {\n return '\\\"\\'\\\"'; // output \"'\"\n }\n\n if (part === '\"') {\n return \"\\'\\\"\\'\"; // output '\"'\n }\n return \"\\'\" + part + \"\\'\";\n });\n return \"concat(\\'\\',\" + parts.join(\",\") + \")\";\n};\n\nfunction indexOfTextNode(textNode){\n var parent = textNode.parentNode;\n var children = parent.childNodes;\n var sib;\n var index = -1;\n for (var i = 0; i < children.length; i++) {\n sib = children[i];\n if(sib.nodeType === Node.TEXT_NODE){\n index++;\n }\n if(sib == textNode) break;\n }\n\n return index;\n};\n\nfunction isXml(ext) {\n return ['xml', 'opf', 'ncx'].indexOf(ext) > -1;\n}\n\nfunction createBlobUrl(content, mime){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob = new Blob([content], {type : mime });\n\n tempUrl = _URL.createObjectURL(blob);\n\n return tempUrl;\n};\n\nmodule.exports = {\n // 'uri': uri,\n // 'folder': folder,\n 'isElement': isElement,\n 'uuid': uuid,\n 'values': values,\n 'resolveUrl': resolveUrl,\n 'indexOfSorted': indexOfSorted,\n 'documentHeight': documentHeight,\n 'isNumber': isNumber,\n 'prefixed': prefixed,\n 'defaults': defaults,\n 'extend': extend,\n 'insert': insert,\n 'locationOf': locationOf,\n 'indexOfSorted': indexOfSorted,\n 'requestAnimationFrame': requestAnimationFrame,\n 'bounds': bounds,\n 'borders': borders,\n 'windowBounds': windowBounds,\n 'cleanStringForXpath': cleanStringForXpath,\n 'indexOfTextNode': indexOfTextNode,\n 'isXml': isXml,\n 'createBlobUrl': createBlobUrl\n};\n","var URI = require('urijs');\nvar core = require('./core');\n\n/**\n EPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html\n\n Implements:\n - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)\n - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)\n\n Does Not Implement:\n - Temporal Offset (~)\n - Spatial Offset (@)\n - Temporal-Spatial Offset (~ + @)\n - Text Location Assertion ([)\n*/\n\nfunction EpubCFI(cfiFrom, base, options){\n var type;\n this.options = {\n ignoreClass: 'annotator-hl'\n };\n\n this.str = '';\n\n this.base = {};\n this.spinePos = 0; // For compatibility\n\n this.range = false; // true || false;\n\n this.path = {};\n this.start = null;\n this.end = null;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof EpubCFI)) {\n return new EpubCFI(cfiFrom, base, options);\n }\n\n // Find options\n for (var i = 1, length = arguments.length; i < length; i++) {\n if(typeof arguments[i] === 'object' && (arguments[i].ignoreClass)) {\n core.extend(this.options, arguments[i]);\n }\n }\n\n\n /* TODO: maybe accept object that includes:\n {\n spineNodeIndex: \n index: \n idref: \n }\n }\n */\n if(typeof base === 'string') {\n this.base = this.parseComponent(base);\n } else if(typeof base === 'object' && base.steps) {\n this.base = base;\n }\n\n type = this.checkType(cfiFrom);\n\n\n if(type === 'string') {\n this.str = cfiFrom;\n return core.extend(this, this.parse(cfiFrom));\n } else if (type === 'range') {\n this.fromRange(cfiFrom);\n } else if (type === 'node') {\n this.fromNode(cfiFrom);\n } else if (type === 'EpubCFI') {\n return cfiFrom;\n } else if (!cfiFrom) {\n return this;\n } else {\n throw new TypeError('not a valid argument for EpubCFI');\n }\n\n};\n\nEpubCFI.prototype.checkType = function(cfi) {\n // is a cfi string, should be wrapped with \"epubcfi()\"\n if (typeof cfi === 'string' &&\n cfi.indexOf(\"epubcfi(\") === 0 &&\n cfi[cfi.length-1] === \")\") {\n return 'string';\n // Is a range object\n} else if (typeof cfi === 'object' && cfi instanceof window.Range){\n return 'range';\n } else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function'\n return 'node';\n } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){\n return 'EpubCFI';\n } else {\n return false;\n }\n};\n\nEpubCFI.prototype.parse = function(cfiStr) {\n var cfi = {\n spinePos: -1,\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n var baseComponent, pathComponent, range;\n\n if(typeof cfiStr !== \"string\") {\n return {spinePos: -1};\n }\n\n if(cfiStr.indexOf(\"epubcfi(\") === 0 && cfiStr[cfiStr.length-1] === \")\") {\n // Remove intial epubcfi( and ending )\n cfiStr = cfiStr.slice(8, cfiStr.length-1);\n }\n\n baseComponent = this.getChapterComponent(cfiStr);\n\n // Make sure this is a valid cfi or return\n if(!baseComponent) {\n return {spinePos: -1};\n }\n\n cfi.base = this.parseComponent(baseComponent);\n\n pathComponent = this.getPathComponent(cfiStr);\n cfi.path = this.parseComponent(pathComponent);\n\n range = this.getRange(cfiStr);\n\n if(range) {\n cfi.range = true;\n cfi.start = this.parseComponent(range[0]);\n cfi.end = this.parseComponent(range[1]);\n }\n\n // Get spine node position\n // cfi.spineSegment = cfi.base.steps[1];\n\n // Chapter segment is always the second step\n cfi.spinePos = cfi.base.steps[1].index;\n\n return cfi;\n};\n\nEpubCFI.prototype.parseComponent = function(componentStr){\n var component = {\n steps: [],\n terminal: null\n };\n var parts = componentStr.split(':');\n var steps = parts[0].split('/');\n var terminal;\n\n if(parts.length > 1) {\n terminal = parts[1];\n component.terminal = this.parseTerminal(terminal);\n }\n\n if (steps[0] === '') {\n steps.shift(); // Ignore the first slash\n }\n\n component.steps = steps.map(function(step){\n return this.parseStep(step);\n }.bind(this));\n\n return component;\n};\n\nEpubCFI.prototype.parseStep = function(stepStr){\n var type, num, index, has_brackets, id;\n\n has_brackets = stepStr.match(/\\[(.*)\\]/);\n if(has_brackets && has_brackets[1]){\n id = has_brackets[1];\n }\n\n //-- Check if step is a text node or element\n num = parseInt(stepStr);\n\n if(isNaN(num)) {\n return;\n }\n\n if(num % 2 === 0) { // Even = is an element\n type = \"element\";\n index = num / 2 - 1;\n } else {\n type = \"text\";\n index = (num - 1 ) / 2;\n }\n\n return {\n \"type\" : type,\n 'index' : index,\n 'id' : id || null\n };\n};\n\nEpubCFI.prototype.parseTerminal = function(termialStr){\n var characterOffset, textLocationAssertion;\n var assertion = termialStr.match(/\\[(.*)\\]/);\n\n if(assertion && assertion[1]){\n characterOffset = parseInt(termialStr.split('[')[0]);\n textLocationAssertion = assertion[1];\n } else {\n characterOffset = parseInt(termialStr);\n }\n\n return {\n 'offset': characterOffset,\n 'assertion': textLocationAssertion\n };\n\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n return indirection[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n if(indirection[1]) {\n ranges = indirection[1].split(',');\n return ranges[0];\n }\n\n};\n\nEpubCFI.prototype.getRange = function(cfiStr) {\n\n var ranges = cfiStr.split(\",\");\n\n if(ranges.length === 3){\n return [\n ranges[1],\n ranges[2]\n ];\n }\n\n return false;\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n var splitStr = cfiStr.split(\":\");\n return splitStr[1] || '';\n};\n\nEpubCFI.prototype.joinSteps = function(steps) {\n return steps.map(function(part){\n var segment = '';\n\n if(part.type === 'element') {\n segment += (part.index + 1) * 2;\n }\n\n if(part.type === 'text') {\n segment += 1 + (2 * part.index); // TODO: double check that this is odd\n }\n\n if(part.id) {\n segment += \"[\" + part.id + \"]\";\n }\n\n return segment;\n\n }).join('/');\n\n};\n\nEpubCFI.prototype.segmentString = function(segment) {\n var segmentString = '/';\n\n segmentString += this.joinSteps(segment.steps);\n\n if(segment.terminal && segment.terminal.offset){\n segmentString += ':' + segment.terminal.offset;\n }\n\n if(segment.terminal && segment.terminal.assertion){\n segmentString += '[' + segment.terminal.assertion + ']';\n }\n\n return segmentString;\n};\n\nEpubCFI.prototype.toString = function() {\n var cfiString = 'epubcfi(';\n\n cfiString += this.segmentString(this.base);\n\n cfiString += '!';\n cfiString += this.segmentString(this.path);\n\n // Add Range, if present\n if(this.start) {\n cfiString += ',';\n cfiString += this.segmentString(this.start);\n }\n\n if(this.end) {\n cfiString += ',';\n cfiString += this.segmentString(this.end);\n }\n\n cfiString += \")\";\n\n return cfiString;\n};\n\nEpubCFI.prototype.compare = function(cfiOne, cfiTwo) {\n if(typeof cfiOne === 'string') {\n cfiOne = new EpubCFI(cfiOne);\n }\n if(typeof cfiTwo === 'string') {\n cfiTwo = new EpubCFI(cfiTwo);\n }\n // Compare Spine Positions\n if(cfiOne.spinePos > cfiTwo.spinePos) {\n return 1;\n }\n if(cfiOne.spinePos < cfiTwo.spinePos) {\n return -1;\n }\n\n\n // Compare Each Step in the First item\n for (var i = 0; i < cfiOne.path.steps.length; i++) {\n if(!cfiTwo.path.steps[i]) {\n return 1;\n }\n if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {\n return 1;\n }\n if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {\n return -1;\n }\n // Otherwise continue checking\n }\n\n // All steps in First present in Second\n if(cfiOne.path.steps.length < cfiTwo.path.steps.length) {\n return -1;\n }\n\n // Compare the charecter offset of the text node\n if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {\n return 1;\n }\n if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {\n return -1;\n }\n\n // TODO: compare ranges\n\n // CFI's are equal\n return 0;\n};\n\nmodule.exports = EpubCFI;\n","var RSVP = require('rsvp');\n\n//-- Hooks allow for injecting functions that must all complete in order before finishing\n// They will execute in parallel but all must finish before continuing\n// Functions may return a promise if they are asycn.\n\n// this.content = new EPUBJS.Hook();\n// this.content.register(function(){});\n// this.content.trigger(args).then(function(){});\n\nfunction Hook(context){\n this.context = context || this;\n this.hooks = [];\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.register = function(){\n for(var i = 0; i < arguments.length; ++i) {\n if (typeof arguments[i] === \"function\") {\n this.hooks.push(arguments[i]);\n } else {\n // unpack array\n for(var j = 0; j < arguments[i].length; ++j) {\n this.hooks.push(arguments[i][j]);\n }\n }\n }\n};\n\n// Triggers a hook to run all functions\nHook.prototype.trigger = function(){\n var args = arguments;\n var context = this.context;\n var promises = [];\n\n this.hooks.forEach(function(task, i) {\n var executing = task.apply(context, args);\n\n if(executing && typeof executing[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n promises.push(executing);\n }\n // Otherwise Task resolves immediately, continue\n });\n\n\n return RSVP.all(promises);\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.list = function(){\n return this.hooks;\n};\n\nmodule.exports = Hook;\n","var core = require('./core');\n\nfunction Reflowable(){\n\n};\n\nReflowable.prototype.calculate = function(_width, _height, _gap, _devisor){\n\n var divisor = _devisor || 1;\n\n //-- Check the width and create even width columns\n var fullWidth = Math.floor(_width);\n var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;\n\n var section = Math.floor(width / 8);\n var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);\n\n var colWidth;\n var spreadWidth;\n var delta;\n\n //-- Double Page\n if(divisor > 1) {\n colWidth = Math.floor((width - gap) / divisor);\n } else {\n colWidth = width;\n }\n\n spreadWidth = colWidth * divisor;\n\n delta = (colWidth + gap) * divisor;\n\n\n\n this.columnAxis = core.prefixed('columnAxis');\n this.columnGap = core.prefixed('columnGap');\n this.columnWidth = core.prefixed('columnWidth');\n this.columnFill = core.prefixed('columnFill');\n\n this.width = width;\n this.height = _height;\n this.spread = spreadWidth;\n this.delta = delta;\n\n this.column = colWidth;\n this.gap = gap;\n this.divisor = divisor;\n\n};\n\nReflowable.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n var $body = view.document.body;//view.document.querySelector(\"body\");\n\n $doc.style.overflow = \"hidden\";\n\n // Must be set to the new calculated width or the columns will be off\n // $body.style.width = this.width + \"px\";\n $doc.style.width = this.width + \"px\";\n\n //-- Adjust height\n $body.style.height = this.height + \"px\";\n\n //-- Add columns\n $body.style[this.columnAxis] = \"horizontal\";\n $body.style[this.columnFill] = \"auto\";\n $body.style[this.columnGap] = this.gap+\"px\";\n $body.style[this.columnWidth] = this.column+\"px\";\n\n // Add extra padding for the gap between this and the next view\n view.iframe.style.marginRight = this.gap+\"px\";\n};\n\nReflowable.prototype.count = function(view) {\n var totalWidth = view.root().scrollWidth;\n var spreads = Math.ceil(totalWidth / this.spread);\n\n return {\n spreads : spreads,\n pages : spreads * this.divisor\n };\n};\n\nfunction Fixed(_width, _height){\n\n};\n\nFixed.prototype.calculate = function(_width, _height){\n\n};\n\nFixed.prototype.format = function(view){\n var width, height;\n\n var $doc = view.document.documentElement;\n var $viewport = documentElement.querySelector(\"[name=viewport\");\n\n /**\n * check for the viewport size\n * \n */\n if($viewport && $viewport.hasAttribute(\"content\")) {\n content = $viewport.getAttribute(\"content\");\n contents = content.split(',');\n if(contents[0]){\n width = contents[0].replace(\"width=\", '');\n }\n if(contents[1]){\n height = contents[1].replace(\"height=\", '');\n }\n }\n\n //-- Adjust width and height\n // $doc.style.width = width + \"px\" || \"auto\";\n // $doc.style.height = height + \"px\" || \"auto\";\n view.resize(width, height);\n\n //-- Scroll\n $doc.style.overflow = \"auto\";\n\n};\n\nFixed.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nfunction Scroll(){\n\n};\n\nScroll.prototype.calculate = function(_width, _height){\n this.spread = _width;\n this.column = _width;\n this.gap = 0;\n};\n\nScroll.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n\n $doc.style.width = \"auto\";\n $doc.style.height = \"auto\";\n\n};\n\nScroll.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nmodule.exports = {\n 'Reflowable': Reflowable,\n 'Fixed': Fixed,\n 'Scroll': Scroll\n};\n","var core = require('./core');\nvar Queue = require('./queue');\nvar EpubCFI = require('./epubcfi');\nvar RSVP = require('rsvp');\n\nfunction Locations(spine, request) {\n this.spine = spine;\n this.request = request;\n\n this.q = new Queue(this);\n this.epubcfi = new EpubCFI();\n\n this._locations = [];\n this.total = 0;\n\n this.break = 150;\n\n this._current = 0;\n\n};\n\n// Load all of sections in the book\nLocations.prototype.generate = function(chars) {\n\n if (chars) {\n this.break = chars;\n }\n\n this.q.pause();\n\n this.spine.each(function(section) {\n\n this.q.enqueue(this.process, section);\n\n }.bind(this));\n\n return this.q.run().then(function() {\n this.total = this._locations.length-1;\n\n if (this._currentCfi) {\n this.currentLocation = this._currentCfi;\n }\n\n return this._locations;\n // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));\n }.bind(this));\n\n};\n\nLocations.prototype.process = function(section) {\n\n return section.load(this.request)\n .then(function(contents) {\n\n var range;\n var doc = contents.ownerDocument;\n var counter = 0;\n\n this.sprint(contents, function(node) {\n var len = node.length;\n var dist;\n var pos = 0;\n\n // Start range\n if (counter == 0) {\n range = doc.createRange();\n range.setStart(node, 0);\n }\n\n dist = this.break - counter;\n\n // Node is smaller than a break\n if(dist > len){\n counter += len;\n pos = len;\n }\n\n while (pos < len) {\n counter = this.break;\n pos += this.break;\n\n // Gone over\n if(pos >= len){\n // Continue counter for next node\n counter = len - (pos - this.break);\n\n // At End\n } else {\n // End the previous range\n range.setEnd(node, pos);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi);\n counter = 0;\n\n // Start new range\n pos += 1;\n range = doc.createRange();\n range.setStart(node, pos);\n }\n }\n\n\n\n }.bind(this));\n\n // Close remaining\n if (range) {\n range.setEnd(prev, prev.length);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi)\n counter = 0;\n }\n\n }.bind(this));\n\n};\n\nLocations.prototype.sprint = function(root, func) {\n\tvar treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);\n\n\twhile ((node = treeWalker.nextNode())) {\n\t\tfunc(node);\n\t}\n\n};\n\nLocations.prototype.locationFromCfi = function(cfi){\n // Check if the location has not been set yet\n\tif(this._locations.length === 0) {\n\t\treturn -1;\n\t}\n\n return core.locationOf(cfi, this._locations, this.epubcfi.compare);\n};\n\nLocations.prototype.precentageFromCfi = function(cfi) {\n // Find closest cfi\n var loc = this.locationFromCfi(cfi);\n // Get percentage in total\n return this.precentageFromLocation(loc);\n};\n\nLocations.prototype.percentageFromLocation = function(loc) {\n if (!loc || !this.total) {\n return 0;\n }\n return (loc / this.total);\n};\n\nLocations.prototype.cfiFromLocation = function(loc){\n\tvar cfi = -1;\n\t// check that pg is an int\n\tif(typeof loc != \"number\"){\n\t\tloc = parseInt(pg);\n\t}\n\n\tif(loc >= 0 && loc < this._locations.length) {\n\t\tcfi = this._locations[loc];\n\t}\n\n\treturn cfi;\n};\n\nLocations.prototype.cfiFromPercentage = function(value){\n var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1\n\tvar loc = Math.ceil(this.total * percentage);\n\n\treturn this.cfiFromLocation(loc);\n};\n\nLocations.prototype.load = function(locations){\n\tthis._locations = JSON.parse(locations);\n this.total = this._locations.length-1;\n return this._locations;\n};\n\nLocations.prototype.save = function(json){\n\treturn JSON.stringify(this._locations);\n};\n\nLocations.prototype.getCurrent = function(json){\n\treturn this._current;\n};\n\nLocations.prototype.setCurrent = function(curr){\n var loc;\n\n if(typeof curr == \"string\"){\n this._currentCfi = curr;\n } else if (typeof curr == \"number\") {\n this._current = curr;\n } else {\n return;\n }\n\n if(this._locations.length === 0) {\n return;\n\t}\n\n if(typeof curr == \"string\"){\n loc = this.locationFromCfi(curr);\n this._current = loc;\n } else {\n loc = curr;\n }\n\n this.trigger(\"changed\", {\n percentage: this.precentageFromLocation(loc)\n });\n};\n\nObject.defineProperty(Locations.prototype, 'currentLocation', {\n get: function () {\n return this._current;\n },\n set: function (curr) {\n this.setCurrent(curr);\n }\n});\n\nRSVP.EventTarget.mixin(Locations.prototype);\n\nmodule.exports = Locations;\n","function Map(layout){\n this.layout = layout;\n};\n\nMap.prototype.section = function(view) {\n var ranges = this.findRanges(view);\n var map = this.rangeListToCfiList(view, ranges);\n\n return map;\n};\n\nMap.prototype.page = function(view, start, end) {\n var root = view.document.body;\n return this.rangePairToCfiPair(view.section, {\n start: this.findStart(root, start, end),\n end: this.findEnd(root, start, end)\n });\n};\n\nMap.prototype.walk = function(root, func) {\n //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);\n var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode: function (node) {\n if ( node.data.trim().length > 0 ) {\n return NodeFilter.FILTER_ACCEPT;\n } else {\n return NodeFilter.FILTER_REJECT;\n }\n }\n }, false);\n var node;\n var result;\n while ((node = treeWalker.nextNode())) {\n result = func(node);\n if(result) break;\n }\n\n return result;\n};\n\nMap.prototype.findRanges = function(view){\n var columns = [];\n var count = this.layout.count(view);\n var column = this.layout.column;\n var gap = this.layout.gap;\n var start, end;\n\n for (var i = 0; i < count.pages; i++) {\n start = (column + gap) * i;\n end = (column * (i+1)) + (gap * i);\n columns.push({\n start: this.findStart(view.document.body, start, end),\n end: this.findEnd(view.document.body, start, end)\n });\n }\n\n return columns;\n};\n\nMap.prototype.findStart = function(root, start, end){\n var stack = [root];\n var $el;\n var found;\n var $prev = root;\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if( left >= start && left <= end ) {\n return node;\n } else if (right > start) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n if(found) {\n return this.findTextStartRange(found, start, end);\n }\n\n }\n\n // Return last element\n return this.findTextStartRange($prev, start, end);\n};\n\nMap.prototype.findEnd = function(root, start, end){\n var stack = [root];\n var $el;\n var $prev = root;\n var found;\n\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if(left > end && $prev) {\n return $prev;\n } else if(right > end) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n\n if(found){\n return this.findTextEndRange(found, start, end);\n }\n\n }\n\n // end of chapter\n return this.findTextEndRange($prev, start, end);\n};\n\n\nMap.prototype.findTextStartRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if( pos.left >= start ) {\n return range;\n }\n\n prev = range;\n\n }\n\n return ranges[0];\n};\n\nMap.prototype.findTextEndRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if(pos.left > end && prev) {\n return prev;\n } else if(pos.right > end) {\n return range;\n }\n\n prev = range;\n\n }\n\n // Ends before limit\n return ranges[ranges.length-1];\n\n};\n\nMap.prototype.splitTextNodeIntoRanges = function(node, _splitter){\n var ranges = [];\n var textContent = node.textContent || \"\";\n var text = textContent.trim();\n var range;\n var rect;\n var list;\n var doc = node.ownerDocument;\n var splitter = _splitter || \" \";\n\n pos = text.indexOf(splitter);\n\n if(pos === -1 || node.nodeType != Node.TEXT_NODE) {\n range = doc.createRange();\n range.selectNodeContents(node);\n return [range];\n }\n\n range = doc.createRange();\n range.setStart(node, 0);\n range.setEnd(node, pos);\n ranges.push(range);\n range = false;\n\n while ( pos != -1 ) {\n\n pos = text.indexOf(splitter, pos + 1);\n if(pos > 0) {\n\n if(range) {\n range.setEnd(node, pos);\n ranges.push(range);\n }\n\n range = doc.createRange();\n range.setStart(node, pos+1);\n }\n }\n\n if(range) {\n range.setEnd(node, text.length);\n ranges.push(range);\n }\n\n return ranges;\n};\n\n\n\nMap.prototype.rangePairToCfiPair = function(section, rangePair){\n\n var startRange = rangePair.start;\n var endRange = rangePair.end;\n\n startRange.collapse(true);\n endRange.collapse(true);\n\n startCfi = section.cfiFromRange(startRange);\n endCfi = section.cfiFromRange(endRange);\n\n return {\n start: startCfi,\n end: endCfi\n };\n\n};\n\nMap.prototype.rangeListToCfiList = function(view, columns){\n var map = [];\n var rangePair, cifPair;\n\n for (var i = 0; i < columns.length; i++) {\n cifPair = this.rangePairToCfiPair(view.section, columns[i]);\n\n map.push(cifPair);\n\n }\n\n return map;\n};\n\nmodule.exports = Map;\n","var core = require('./core');\nvar Parser = require('./parser');\nvar RSVP = require('rsvp');\nvar URI = require('urijs');\n\nfunction Navigation(_package, _request){\n var navigation = this;\n var parse = new Parser();\n var request = _request || require('./request');\n\n this.package = _package;\n this.toc = [];\n this.tocByHref = {};\n this.tocById = {};\n\n if(_package.navPath) {\n this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();\n this.nav = {};\n\n this.nav.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.navUrl, 'xml').then(function(xml){\n navigation.toc = parse.nav(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n\n if(_package.ncxPath) {\n this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();\n this.ncx = {};\n\n this.ncx.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.ncxUrl, 'xml').then(function(xml){\n navigation.toc = parse.ncx(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n};\n\n// Load the navigation\nNavigation.prototype.load = function(_request) {\n var request = _request || require('./request');\n var loading, loaded;\n\n if(this.nav) {\n loading = this.nav.load();\n } else if(this.ncx) {\n loading = this.ncx.load();\n } else {\n loaded = new RSVP.defer();\n loaded.resolve([]);\n loading = loaded.promise;\n }\n\n return loading;\n\n};\n\nNavigation.prototype.loaded = function(toc) {\n var item;\n\n for (var i = 0; i < toc.length; i++) {\n item = toc[i];\n this.tocByHref[item.href] = i;\n this.tocById[item.id] = i;\n }\n\n};\n\n// Get an item from the navigation\nNavigation.prototype.get = function(target) {\n var index;\n\n if(!target) {\n return this.toc;\n }\n\n if(target.indexOf(\"#\") === 0) {\n index = this.tocById[target.substring(1)];\n } else if(target in this.tocByHref){\n index = this.tocByHref[target];\n }\n\n return this.toc[index];\n};\n\nmodule.exports = Navigation;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Continuous = require('./continuous');\nvar Map = require('./map');\nvar Layout = require('./layout');\n\nfunction Paginate(book, options) {\n\n Continuous.apply(this, arguments);\n\n this.settings = core.extend(this.settings || {}, {\n width: 600,\n height: 400,\n axis: \"horizontal\",\n forceSingle: false,\n minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)\n gap: \"auto\", //-- \"auto\" or int\n overflow: \"hidden\",\n infinite: false\n });\n\n core.extend(this.settings, options);\n\n this.isForcedSingle = this.settings.forceSingle;\n\n this.viewSettings = {\n axis: this.settings.axis\n };\n\n this.start();\n};\n\nPaginate.prototype = Object.create(Continuous.prototype);\nPaginate.prototype.constructor = Paginate;\n\n\nPaginate.prototype.determineSpreads = function(cutoff){\n if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) {\n return 1; //-- Single Page\n }else{\n return 2; //-- Double Page\n }\n};\n\nPaginate.prototype.forceSingle = function(bool){\n if(bool === false) {\n this.isForcedSingle = false;\n // this.spreads = false;\n } else {\n this.isForcedSingle = true;\n // this.spreads = this.determineSpreads(this.minSpreadWidth);\n }\n this.applyLayoutMethod();\n};\n\n/**\n* Uses the settings to determine which Layout Method is needed\n* Triggers events based on the method choosen\n* Takes: Layout settings object\n* Returns: String of appropriate for EPUBJS.Layout function\n*/\n// Paginate.prototype.determineLayout = function(settings){\n// // Default is layout: reflowable & spread: auto\n// var spreads = this.determineSpreads(this.settings.minSpreadWidth);\n// console.log(\"spreads\", spreads, this.settings.minSpreadWidth)\n// var layoutMethod = spreads ? \"ReflowableSpreads\" : \"Reflowable\";\n// var scroll = false;\n//\n// if(settings.layout === \"pre-paginated\") {\n// layoutMethod = \"Fixed\";\n// scroll = true;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"none\") {\n// layoutMethod = \"Reflowable\";\n// scroll = false;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"both\") {\n// layoutMethod = \"ReflowableSpreads\";\n// scroll = false;\n// spreads = true;\n// }\n//\n// this.spreads = spreads;\n//\n// return layoutMethod;\n// };\n\nPaginate.prototype.start = function(){\n // On display\n // this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);\n // this.layoutMethod = this.determineLayout(this.layoutSettings);\n // this.layout = new EPUBJS.Layout[this.layoutMethod]();\n //this.hooks.display.register(this.registerLayoutMethod.bind(this));\n // this.hooks.display.register(this.reportLocation);\n this.on('displayed', this.reportLocation.bind(this));\n\n // this.hooks.content.register(this.adjustImages.bind(this));\n\n this.currentPage = 0;\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n};\n\n// EPUBJS.Rendition.prototype.createView = function(section) {\n// var view = new EPUBJS.View(section, this.viewSettings);\n\n\n// return view;\n// };\n\nPaginate.prototype.applyLayoutMethod = function() {\n //var task = new RSVP.defer();\n\n // this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout = new Layout.Reflowable();\n\n this.updateLayout();\n\n // Set the look ahead offset for what is visible\n\n this.map = new Map(this.layout);\n\n // this.hooks.layout.register(this.layout.format.bind(this));\n\n //task.resolve();\n //return task.promise;\n // return layout;\n};\n\nPaginate.prototype.updateLayout = function() {\n\n this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout.calculate(\n this.stage.width,\n this.stage.height,\n this.settings.gap,\n this.spreads\n );\n\n this.settings.offset = this.layout.delta;\n\n};\n\nPaginate.prototype.moveTo = function(offset){\n var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n return this.check(0, dist+this.settings.offset).then(function(){\n this.scrollBy(dist, 0);\n }.bind(this));\n};\n\nPaginate.prototype.page = function(pg){\n\n // this.currentPage = pg;\n // this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0);\n //-- Return false if page is greater than the total\n // return false;\n};\n\nPaginate.prototype.next = function(){\n\n return this.q.enqueue(function(){\n // console.log(this.container.scrollWidth, this.container.scrollLeft + this.container.offsetWidth + this.layout.delta)\n if(this.container.scrollLeft +\n this.container.offsetWidth +\n this.layout.delta < this.container.scrollWidth) {\n this.scrollBy(this.layout.delta, 0);\n } else {\n this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n }\n this.reportLocation();\n return this.check();\n });\n\n // return this.page(this.currentPage + 1);\n};\n\nPaginate.prototype.prev = function(){\n\n return this.q.enqueue(function(){\n this.scrollBy(-this.layout.delta, 0);\n this.reportLocation();\n return this.check();\n });\n // return this.page(this.currentPage - 1);\n};\n\n// Paginate.prototype.reportLocation = function(){\n// return this.q.enqueue(function(){\n// this.location = this.currentLocation();\n// this.trigger(\"locationChanged\", this.location);\n// }.bind(this));\n// };\n\nPaginate.prototype.currentLocation = function(){\n var visible = this.visible();\n var startA, startB, endA, endB;\n var pageLeft, pageRight;\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.spread;\n\n return this.map.page(visible[0], startA, endA);\n }\n\n if(visible.length > 1) {\n\n // Left Col\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.column;\n\n // Right Col\n startB = container.left + this.layout.spread - visible[visible.length-1].position().left;\n endB = startB + this.layout.column;\n\n pageLeft = this.map.page(visible[0], startA, endA);\n pageRight = this.map.page(visible[visible.length-1], startB, endB);\n\n return {\n start: pageLeft.start,\n end: pageRight.end\n };\n }\n};\n\nPaginate.prototype.resize = function(width, height){\n // Clear the queue\n this.q.clear();\n\n this.stageSize(width, height);\n\n this.updateLayout();\n\n if(this.location) {\n this.display(this.location.start);\n }\n\n this.trigger(\"resized\", {\n width: this.stage.width,\n height: this.stage.height\n });\n\n};\n\nPaginate.prototype.onResized = function(e) {\n\n this.views.clear();\n\n clearTimeout(this.resizeTimeout);\n this.resizeTimeout = setTimeout(function(){\n this.resize();\n }.bind(this), 150);\n};\n\nPaginate.prototype.adjustImages = function(view) {\n\n view.addStylesheetRules([\n [\"img\",\n [\"max-width\", (this.layout.spread) + \"px\"],\n [\"max-height\", (this.layout.height) + \"px\"]\n ]\n ]);\n return new RSVP.Promise(function(resolve, reject){\n // Wait to apply\n setTimeout(function() {\n resolve();\n }, 1);\n });\n};\n\n// Paginate.prototype.display = function(what){\n// return this.display(what);\n// };\n\nmodule.exports = Paginate;\n","var URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction Parser(){};\n\nParser.prototype.container = function(containerXml){\n //-- \n var rootfile, fullpath, folder, encoding;\n\n if(!containerXml) {\n console.error(\"Container File Not Found\");\n return;\n }\n\n rootfile = containerXml.querySelector(\"rootfile\");\n\n if(!rootfile) {\n console.error(\"No RootFile Found\");\n return;\n }\n\n fullpath = rootfile.getAttribute('full-path');\n folder = URI(fullpath).directory();\n encoding = containerXml.xmlEncoding;\n\n //-- Now that we have the path we can parse the contents\n return {\n 'packagePath' : fullpath,\n 'basePath' : folder,\n 'encoding' : encoding\n };\n};\n\nParser.prototype.identifier = function(packageXml){\n var metadataNode;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n return this.getElementText(metadataNode, \"identifier\");\n};\n\nParser.prototype.packageContents = function(packageXml){\n var parse = this;\n var metadataNode, manifestNode, spineNode;\n var manifest, navPath, ncxPath, coverPath;\n var spineNodeIndex;\n var spine;\n var spineIndexByURL;\n var metadata;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n manifestNode = packageXml.querySelector(\"manifest\");\n if(!manifestNode) {\n console.error(\"No Manifest Found\");\n return;\n }\n\n spineNode = packageXml.querySelector(\"spine\");\n if(!spineNode) {\n console.error(\"No Spine Found\");\n return;\n }\n\n manifest = parse.manifest(manifestNode);\n navPath = parse.findNavPath(manifestNode);\n ncxPath = parse.findNcxPath(manifestNode, spineNode);\n coverPath = parse.findCoverPath(packageXml);\n\n spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);\n\n spine = parse.spine(spineNode, manifest);\n\n metadata = parse.metadata(metadataNode);\n\n\tmetadata.direction = spineNode.getAttribute(\"page-progression-direction\");\n\n return {\n 'metadata' : metadata,\n 'spine' : spine,\n 'manifest' : manifest,\n 'navPath' : navPath,\n 'ncxPath' : ncxPath,\n 'coverPath': coverPath,\n 'spineNodeIndex' : spineNodeIndex\n };\n};\n\n//-- Find TOC NAV\nParser.prototype.findNavPath = function(manifestNode){\n\t// Find item with property 'nav'\n\t// Should catch nav irregardless of order\n var node = manifestNode.querySelector(\"item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']\");\n return node ? node.getAttribute('href') : false;\n};\n\n//-- Find TOC NCX: media-type=\"application/x-dtbncx+xml\" href=\"toc.ncx\"\nParser.prototype.findNcxPath = function(manifestNode, spineNode){\n\tvar node = manifestNode.querySelector(\"item[media-type='application/x-dtbncx+xml']\");\n\tvar tocId;\n\n\t// If we can't find the toc by media-type then try to look for id of the item in the spine attributes as\n\t// according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2,\n\t// \"The item that describes the NCX must be referenced by the spine toc attribute.\"\n\tif (!node) {\n\t\ttocId = spineNode.getAttribute(\"toc\");\n\t\tif(tocId) {\n\t\t\tnode = manifestNode.querySelector(\"item[id='\" + tocId + \"']\");\n\t\t}\n\t}\n\n\treturn node ? node.getAttribute('href') : false;\n};\n\n//-- Expanded to match Readium web components\nParser.prototype.metadata = function(xml){\n var metadata = {},\n p = this;\n\n metadata.title = p.getElementText(xml, 'title');\n metadata.creator = p.getElementText(xml, 'creator');\n metadata.description = p.getElementText(xml, 'description');\n\n metadata.pubdate = p.getElementText(xml, 'date');\n\n metadata.publisher = p.getElementText(xml, 'publisher');\n\n metadata.identifier = p.getElementText(xml, \"identifier\");\n metadata.language = p.getElementText(xml, \"language\");\n metadata.rights = p.getElementText(xml, \"rights\");\n\n metadata.modified_date = p.querySelectorText(xml, \"meta[property='dcterms:modified']\");\n metadata.layout = p.querySelectorText(xml, \"meta[property='rendition:layout']\");\n metadata.orientation = p.querySelectorText(xml, \"meta[property='rendition:orientation']\");\n metadata.spread = p.querySelectorText(xml, \"meta[property='rendition:spread']\");\n // metadata.page_prog_dir = packageXml.querySelector(\"spine\").getAttribute(\"page-progression-direction\");\n\n return metadata;\n};\n\n//-- Find Cover: \n//-- Fallback for Epub 2.0\nParser.prototype.findCoverPath = function(packageXml){\n\n\tvar epubVersion = packageXml.querySelector('package').getAttribute('version');\n\n\tif (epubVersion === '2.0') {\n\t\tvar metaCover = packageXml.querySelector('meta[name=\"cover\"]');\n\t\tif (metaCover) {\n\t\t\tvar coverId = metaCover.getAttribute('content');\n\t\t\tvar cover = packageXml.querySelector(\"item[id='\" + coverId + \"']\");\n\t\t\treturn cover ? cover.getAttribute('href') : false;\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\telse {\n\t\tvar node = packageXml.querySelector(\"item[properties='cover-image']\");\n\t\treturn node ? node.getAttribute('href') : false;\n\t}\n};\n\nParser.prototype.getElementText = function(xml, tag){\n var found = xml.getElementsByTagNameNS(\"http://purl.org/dc/elements/1.1/\", tag),\n el;\n\n if(!found || found.length === 0) return '';\n\n el = found[0];\n\n if(el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n\n};\n\nParser.prototype.querySelectorText = function(xml, q){\n var el = xml.querySelector(q);\n\n if(el && el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n};\n\nParser.prototype.manifest = function(manifestXml){\n var manifest = {};\n\n //-- Turn items into an array\n var selected = manifestXml.querySelectorAll(\"item\"),\n items = Array.prototype.slice.call(selected);\n\n //-- Create an object with the id as key\n items.forEach(function(item){\n var id = item.getAttribute('id'),\n href = item.getAttribute('href') || '',\n type = item.getAttribute('media-type') || '',\n properties = item.getAttribute('properties') || '';\n\n manifest[id] = {\n 'href' : href,\n // 'url' : href,\n 'type' : type,\n 'properties' : properties.length ? properties.split(' ') : []\n };\n\n });\n\n return manifest;\n\n};\n\nParser.prototype.spine = function(spineXml, manifest){\n var spine = [];\n\n var selected = spineXml.getElementsByTagName(\"itemref\"),\n items = Array.prototype.slice.call(selected);\n\n var epubcfi = new EpubCFI();\n\n //-- Add to array to mantain ordering and cross reference with manifest\n items.forEach(function(item, index){\n var idref = item.getAttribute('idref');\n // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);\n var props = item.getAttribute('properties') || '';\n var propArray = props.length ? props.split(' ') : [];\n // var manifestProps = manifest[Id].properties;\n // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];\n\n var itemref = {\n 'idref' : idref,\n 'linear' : item.getAttribute('linear') || '',\n 'properties' : propArray,\n // 'href' : manifest[Id].href,\n // 'url' : manifest[Id].url,\n 'index' : index\n // 'cfiBase' : cfiBase\n };\n spine.push(itemref);\n });\n\n return spine;\n};\n\nParser.prototype.querySelectorByType = function(html, element, type){\n\tvar query = html.querySelector(element+'[*|type=\"'+type+'\"]');\n\t// Handle IE not supporting namespaced epub:type in querySelector\n\tif(query === null || query.length === 0) {\n\t\tquery = html.querySelectorAll(element);\n\t\tfor (var i = 0; i < query.length; i++) {\n\t\t\tif(query[i].getAttributeNS(\"http://www.idpf.org/2007/ops\", \"type\") === type) {\n\t\t\t\treturn query[i];\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn query;\n\t}\n};\n\nParser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"toc\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.navItem(navItems[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.navItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"a, span\"),\n\t\t\tsrc = content.getAttribute('href') || '',\n\t\t\ttext = content.textContent || \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.toc = function(tocXml, spineIndexByURL, bookSpine){\n\tvar navPoints = tocXml.querySelectorAll(\"navMap navPoint\");\n\tvar length = navPoints.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navPoints || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.tocItem(navPoints[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.tocItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"content\"),\n\t\t\tsrc = content.getAttribute('src'),\n\t\t\tnavLabel = item.querySelector(\"navLabel\"),\n\t\t\ttext = navLabel.textContent ? navLabel.textContent : \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"page-list\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.pageListItem(navItems[i], spineIndexByURL, bookSpine);\n\t\tlist.push(item);\n\t}\n\n\treturn list;\n};\n\nParser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\tcontent = item.querySelector(\"a\"),\n\t\thref = content.getAttribute('href') || '',\n\t\ttext = content.textContent || \"\",\n\t\tpage = parseInt(text),\n\t\tisCfi = href.indexOf(\"epubcfi\"),\n\t\tsplit,\n\t\tpackageUrl,\n\t\tcfi;\n\n\tif(isCfi != -1) {\n\t\tsplit = href.split(\"#\");\n\t\tpackageUrl = split[0];\n\t\tcfi = split.length > 1 ? split[1] : false;\n\t\treturn {\n\t\t\t\"cfi\" : cfi,\n\t\t\t\"href\" : href,\n\t\t\t\"packageUrl\" : packageUrl,\n\t\t\t\"page\" : page\n\t\t};\n\t} else {\n\t\treturn {\n\t\t\t\"href\" : href,\n\t\t\t\"page\" : page\n\t\t};\n\t}\n};\n\nmodule.exports = Parser;\n","var RSVP = require('rsvp');\nvar core = require('./core');\n\nfunction Queue(_context){\n this._q = [];\n this.context = _context;\n this.tick = core.requestAnimationFrame;\n this.running = false;\n this.paused = false;\n};\n\n// Add an item to the queue\nQueue.prototype.enqueue = function() {\n var deferred, promise;\n var queued;\n var task = [].shift.call(arguments);\n var args = arguments;\n\n // Handle single args without context\n // if(args && !Array.isArray(args)) {\n // args = [args];\n // }\n if(!task) {\n return console.error(\"No Task Provided\");\n }\n\n if(typeof task === \"function\"){\n\n deferred = new RSVP.defer();\n promise = deferred.promise;\n\n queued = {\n \"task\" : task,\n \"args\" : args,\n //\"context\" : context,\n \"deferred\" : deferred,\n \"promise\" : promise\n };\n\n } else {\n // Task is a promise\n queued = {\n \"promise\" : task\n };\n\n }\n\n this._q.push(queued);\n\n // Wait to start queue flush\n if (this.paused == false && !this.running) {\n // setTimeout(this.flush.bind(this), 0);\n // this.tick.call(window, this.run.bind(this));\n this.run();\n }\n\n return queued.promise;\n};\n\n// Run one item\nQueue.prototype.dequeue = function(){\n var inwait, task, result;\n\n if(this._q.length) {\n inwait = this._q.shift();\n task = inwait.task;\n if(task){\n // console.log(task)\n\n result = task.apply(this.context, inwait.args);\n\n if(result && typeof result[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n return result.then(function(){\n inwait.deferred.resolve.apply(this.context, arguments);\n }.bind(this));\n } else {\n // Task resolves immediately\n inwait.deferred.resolve.apply(this.context, result);\n return inwait.promise;\n }\n\n\n\n } else if(inwait.promise) {\n // Task is a promise\n return inwait.promise;\n }\n\n } else {\n inwait = new RSVP.defer();\n inwait.deferred.resolve();\n return inwait.promise;\n }\n\n};\n\n// Run All Immediately\nQueue.prototype.dump = function(){\n while(this._q.length) {\n this.dequeue();\n }\n};\n\n// Run all sequentially, at convince\n\nQueue.prototype.run = function(){\n\n if(!this.running){\n this.running = true;\n this.defered = new RSVP.defer();\n }\n\n this.tick.call(window, function() {\n\n if(this._q.length) {\n\n this.dequeue()\n .then(function(){\n this.run();\n }.bind(this));\n\n } else {\n this.defered.resolve();\n this.running = undefined;\n }\n\n }.bind(this));\n\n // Unpause\n if(this.paused == true) {\n this.paused = false;\n }\n\n return this.defered.promise;\n};\n\n// Flush all, as quickly as possible\nQueue.prototype.flush = function(){\n\n if(this.running){\n return this.running;\n }\n\n if(this._q.length) {\n this.running = this.dequeue()\n .then(function(){\n this.running = undefined;\n return this.flush();\n }.bind(this));\n\n return this.running;\n }\n\n};\n\n// Clear all items in wait\nQueue.prototype.clear = function(){\n this._q = [];\n this.running = false;\n};\n\nQueue.prototype.length = function(){\n return this._q.length;\n};\n\nQueue.prototype.pause = function(){\n this.paused = true;\n};\n\n// Create a new task from a callback\nfunction Task(task, args, context){\n\n return function(){\n var toApply = arguments || [];\n\n return new RSVP.Promise(function(resolve, reject) {\n var callback = function(value){\n resolve(value);\n };\n // Add the callback to the arguments list\n toApply.push(callback);\n\n // Apply all arguments to the functions\n task.apply(this, toApply);\n\n }.bind(this));\n\n };\n\n};\n\nmodule.exports = Queue;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar replace = require('./replacements');\nvar Hook = require('./hook');\nvar EpubCFI = require('./epubcfi');\nvar Queue = require('./queue');\nvar View = require('./view');\nvar Views = require('./views');\nvar Layout = require('./layout');\nvar Map = require('./map');\n\nfunction Rendition(book, options) {\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\thidden: false,\n\t\twidth: false,\n\t\theight: null,\n\t\tlayoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},\n\t\taxis: \"vertical\"\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tthis.viewSettings = {};\n\n\tthis.book = book;\n\n\tthis.views = null;\n\n\t//-- Adds Hook methods to the Rendition prototype\n\tthis.hooks = {};\n\tthis.hooks.display = new Hook(this);\n\tthis.hooks.serialize = new Hook(this);\n\tthis.hooks.content = new Hook(this);\n\tthis.hooks.layout = new Hook(this);\n\tthis.hooks.render = new Hook(this);\n\tthis.hooks.show = new Hook(this);\n\n\tthis.hooks.content.register(replace.links.bind(this));\n\tthis.hooks.content.register(this.passViewEvents.bind(this));\n\n\t// this.hooks.display.register(this.afterDisplay.bind(this));\n\n this.epubcfi = new EpubCFI();\n\n\tthis.q = new Queue(this);\n\n\tthis.q.enqueue(this.book.opened);\n\n\tthis.q.enqueue(this.parseLayoutProperties);\n\n\tif(this.book.archive) {\n\t\tthis.replacements();\n\t}\n};\n\n/**\n* Creates an element to render to.\n* Resizes to passed width and height or to the elements size\n*/\nRendition.prototype.initialize = function(_options){\n\tvar options = _options || {};\n\tvar height = options.height;// !== false ? options.height : \"100%\";\n\tvar width = options.width;// !== false ? options.width : \"100%\";\n\tvar hidden = options.hidden || false;\n\tvar container;\n\tvar wrapper;\n\n\tif(options.height && core.isNumber(options.height)) {\n\t\theight = options.height + \"px\";\n\t}\n\n\tif(options.width && core.isNumber(options.width)) {\n\t\twidth = options.width + \"px\";\n\t}\n\n\t// Create new container element\n\tcontainer = document.createElement(\"div\");\n\n\tcontainer.id = \"epubjs-container:\" + core.uuid();\n\tcontainer.classList.add(\"epub-container\");\n\n\t// Style Element\n\tcontainer.style.fontSize = \"0\";\n\tcontainer.style.wordSpacing = \"0\";\n\tcontainer.style.lineHeight = \"0\";\n\tcontainer.style.verticalAlign = \"top\";\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tcontainer.style.whiteSpace = \"nowrap\";\n\t}\n\n\tif(width){\n\t\tcontainer.style.width = width;\n\t}\n\n\tif(height){\n\t\tcontainer.style.height = height;\n\t}\n\n\tcontainer.style.overflow = this.settings.overflow;\n\n\treturn container;\n};\n\nRendition.wrap = function(container) {\n\tvar wrapper = document.createElement(\"div\");\n\n\twrapper.style.visibility = \"hidden\";\n\twrapper.style.overflow = \"hidden\";\n\twrapper.style.width = \"0\";\n\twrapper.style.height = \"0\";\n\n\twrapper.appendChild(container);\n\treturn wrapper;\n};\n\n// Call to attach the container to an element in the dom\n// Container must be attached before rendering can begin\nRendition.prototype.attachTo = function(_element){\n\tvar bounds;\n\n\tthis.container = this.initialize({\n\t\t\"width\" : this.settings.width,\n\t\t\"height\" : this.settings.height\n\t});\n\n\tif(core.isElement(_element)) {\n\t\tthis.element = _element;\n\t} else if (typeof _element === \"string\") {\n\t\tthis.element = document.getElementById(_element);\n\t}\n\n\tif(!this.element){\n\t\tconsole.error(\"Not an Element\");\n\t\treturn;\n\t}\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t\tthis.element.appendChild(this.wrapper);\n\t} else {\n\t\tthis.element.appendChild(this.container);\n\t}\n\n\tthis.views = new Views(this.container);\n\n\t// Attach Listeners\n\tthis.attachListeners();\n\n\t// Calculate Stage Size\n\tthis.stageSize();\n\n\t// Add Layout method\n\tthis.applyLayoutMethod();\n\n\t// Trigger Attached\n\tthis.trigger(\"attached\");\n\n\t// Start processing queue\n\t// this.q.run();\n\n};\n\nRendition.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to 100%\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n};\n\nRendition.prototype.bounds = function() {\n\treturn this.container.getBoundingClientRect();\n};\n\nRendition.prototype.display = function(target){\n\n\treturn this.q.enqueue(this._display, target);\n\n};\n\nRendition.prototype._display = function(target){\n\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\n\tvar section;\n var view;\n var offset;\n\tvar fragment;\n\tvar cfi = this.epubcfi.isCfiString(target);\n\n\tvar visible;\n\n\tsection = this.book.spine.get(target);\n\n\tif(!section){\n\t\tdisplaying.reject(new Error(\"No Section Found\"));\n\t\treturn displayed;\n\t}\n\n\t// Check to make sure the section we want isn't already shown\n\tvisible = this.views.find(section);\n\n\tif(visible) {\n\t\toffset = view.locationOf(target);\n\t\tdisplayed = this.moveTo(offset)\n\t\t\t.then(function(){\n\t\t\t\treturn this.check();\n\t\t\t});\n\t} else {\n\n\t\t// Hide all current views\n\t\tthis.views.hide();\n\n\t\t// Create a new view\n\t\t// view = new View(section, this.viewSettings);\n\t\tview = this.createView(section);\n\n\t\t// This will clear all previous views\n\t\tdisplayed = this.fill(view)\n\t\t\t.then(function(){\n\n\t\t\t\t// Parse the target fragment\n\t\t\t\tif(typeof target === \"string\" &&\n\t\t\t\t\ttarget.indexOf(\"#\") > -1) {\n\t\t\t\t\t\tfragment = target.substring(target.indexOf(\"#\")+1);\n\t\t\t\t}\n\n\t\t\t\t// Move to correct place within the section, if needed\n\t\t\t\tif(cfi || fragment) {\n\t\t\t\t\toffset = view.locationOf(target);\n\t\t\t\t\treturn this.moveTo(offset);\n\t\t\t\t}\n\n\t\t\t\tif(typeof this.check === 'function') {\n\t\t\t\t\treturn this.check();\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\treturn this.hooks.display.trigger(view);\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tthis.views.show();\n\t\t\t}.bind(this));\n\t}\n\n\tdisplayed.then(function(){\n\n\t\tthis.trigger(\"displayed\", section);\n\n\t}.bind(this));\n\n\n\treturn displayed;\n};\n\n// Takes a cfi, fragment or page?\nRendition.prototype.moveTo = function(offset){\n\tthis.scrollBy(offset.left, offset.top);\n};\n\nRendition.prototype.render = function(view, show) {\n\n\tview.create();\n\n\tview.onLayout = this.layout.format.bind(this.layout);\n\n\t// Fit to size of the container, apply padding\n\tthis.resizeView(view);\n\n\t// Render Chain\n\treturn view.render(this.book.request)\n\t\t.then(function(){\n\t\t\treturn this.hooks.content.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.layout.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn view.display();\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.render.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\tif(show !== false && this.views.hidden === false) {\n\t\t\t\tthis.q.enqueue(function(view){\n\t\t\t\t\tview.show();\n\t\t\t\t}, view);\n\t\t\t}\n\n\n\t\t\t// this.map = new Map(view, this.layout);\n\t\t\tthis.hooks.show.trigger(view, this);\n\t\t\tthis.trigger(\"rendered\", view.section);\n\n\t\t}.bind(this))\n\t\t.catch(function(e){\n\t\t\tthis.trigger(\"loaderror\", e);\n\t\t}.bind(this));\n\n};\n\n\nRendition.prototype.afterDisplayed = function(view){\n\tthis.trigger(\"added\", view.section);\n};\n\nRendition.prototype.fill = function(view){\n\n\tthis.views.clear();\n\n\tthis.views.append(view);\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\treturn this.render(view);\n};\n\nRendition.prototype.resizeView = function(view) {\n\n\tif(this.globalLayoutProperties.layout === \"pre-paginated\") {\n\t\tview.lock(\"both\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nRendition.prototype.stageSize = function(_width, _height){\n\tvar bounds;\n\tvar width = _width || this.settings.width;\n\tvar height = _height || this.settings.height;\n\n\t// If width or height are set to false, inherit them from containing element\n\tif(width === false) {\n\t\tbounds = this.element.getBoundingClientRect();\n\n\t\tif(bounds.width) {\n\t\t\twidth = bounds.width;\n\t\t\tthis.container.style.width = bounds.width + \"px\";\n\t\t}\n\t}\n\n\tif(height === false) {\n\t\tbounds = bounds || this.element.getBoundingClientRect();\n\n\t\tif(bounds.height) {\n\t\t\theight = bounds.height;\n\t\t\tthis.container.style.height = bounds.height + \"px\";\n\t\t}\n\n\t}\n\n\tif(width && !core.isNumber(width)) {\n\t\tbounds = this.container.getBoundingClientRect();\n\t\twidth = bounds.width;\n\t\t//height = bounds.height;\n\t}\n\n\tif(height && !core.isNumber(height)) {\n\t\tbounds = bounds || this.container.getBoundingClientRect();\n\t\t//width = bounds.width;\n\t\theight = bounds.height;\n\t}\n\n\n\tthis.containerStyles = window.getComputedStyle(this.container);\n\tthis.containerPadding = {\n\t\tleft: parseFloat(this.containerStyles[\"padding-left\"]) || 0,\n\t\tright: parseFloat(this.containerStyles[\"padding-right\"]) || 0,\n\t\ttop: parseFloat(this.containerStyles[\"padding-top\"]) || 0,\n\t\tbottom: parseFloat(this.containerStyles[\"padding-bottom\"]) || 0\n\t};\n\n\tthis.stage = {\n\t\twidth: width -\n\t\t\t\t\t\tthis.containerPadding.left -\n\t\t\t\t\t\tthis.containerPadding.right,\n\t\theight: height -\n\t\t\t\t\t\tthis.containerPadding.top -\n\t\t\t\t\t\tthis.containerPadding.bottom\n\t};\n\n\treturn this.stage;\n\n};\n\nRendition.prototype.applyLayoutMethod = function() {\n\n\tthis.layout = new Layout.Scroll();\n\tthis.updateLayout();\n\n\tthis.map = new Map(this.layout);\n};\n\nRendition.prototype.updateLayout = function() {\n\n\tthis.layout.calculate(this.stage.width, this.stage.height);\n\n};\n\nRendition.prototype.resize = function(width, height){\n\n\tthis.stageSize(width, height);\n\n\tthis.updateLayout();\n\n\tthis.views.each(this.resizeView.bind(this));\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nRendition.prototype.onResized = function(e) {\n\tthis.resize();\n};\n\nRendition.prototype.createView = function(section) {\n\t// Transfer the existing hooks\n\tsection.hooks.serialize.register(this.hooks.serialize.list());\n\n\treturn new View(section, this.viewSettings);\n};\n\nRendition.prototype.next = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar next;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tnext = this.views.last().section.next();\n\n\t\tif(next) {\n\t\t\tview = this.createView(next);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\nRendition.prototype.prev = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar prev;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tprev = this.views.first().section.prev();\n\t\tif(prev) {\n\t\t\tview = this.createView(prev);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\n//-- http://www.idpf.org/epub/fxl/\nRendition.prototype.parseLayoutProperties = function(_metadata){\n\tvar metadata = _metadata || this.book.package.metadata;\n\tvar layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || \"reflowable\";\n\tvar spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || \"auto\";\n\tvar orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || \"auto\";\n\tthis.globalLayoutProperties = {\n\t\tlayout : layout,\n\t\tspread : spread,\n\t\torientation : orientation\n\t};\n\treturn this.globalLayoutProperties;\n};\n\n\nRendition.prototype.current = function(){\n\tvar visible = this.visible();\n\tif(visible.length){\n\t\t// Current is the last visible view\n\t\treturn visible[visible.length-1];\n\t}\n return null;\n};\n\nRendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){\n\tvar position = view.position();\n\tvar container = _container || this.container.getBoundingClientRect();\n\n\tif(this.settings.axis === \"horizontal\" &&\n\t\tposition.right > container.left - offsetPrev &&\n\t\tposition.left < container.right + offsetNext) {\n\n\t\treturn true;\n\n } else if(this.settings.axis === \"vertical\" &&\n \tposition.bottom > container.top - offsetPrev &&\n\t\tposition.top < container.bottom + offsetNext) {\n\n\t\treturn true;\n }\n\n\treturn false;\n\n};\n\nRendition.prototype.visible = function(){\n\tvar container = this.bounds();\n\tvar displayedViews = this.views.displayed();\n var visible = [];\n var isVisible;\n var view;\n\n for (var i = 0; i < displayedViews.length; i++) {\n view = displayedViews[i];\n isVisible = this.isVisible(view, 0, 0, container);\n\n if(isVisible === true) {\n visible.push(view);\n }\n\n }\n return visible;\n\n};\n\nRendition.prototype.bounds = function(func) {\n var bounds;\n\n if(!this.settings.height) {\n bounds = core.windowBounds();\n } else {\n bounds = this.container.getBoundingClientRect();\n }\n\n return bounds;\n};\n\nRendition.prototype.destroy = function(){\n // Clear the queue\n\tthis.q.clear();\n\n\tthis.views.clear();\n\n\tclearTimeout(this.trimTimeout);\n\tif(this.settings.hidden) {\n\t\tthis.element.removeChild(this.wrapper);\n\t} else {\n\t\tthis.element.removeChild(this.container);\n\t}\n\n};\n\nRendition.prototype.reportLocation = function(){\n return this.q.enqueue(function(){\n this.location = this.currentLocation();\n this.trigger(\"locationChanged\", this.location);\n }.bind(this));\n};\n\nRendition.prototype.currentLocation = function(){\n var view;\n var start, end;\n\n if(this.views.length) {\n \tview = this.views.first();\n // start = container.left - view.position().left;\n // end = start + this.layout.spread;\n\n return this.map.page(view);\n }\n\n};\n\nRendition.prototype.scrollBy = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n\n if(x) this.container.scrollLeft += x;\n \tif(y) this.container.scrollTop += y;\n\n } else {\n \twindow.scrollBy(x,y);\n }\n // console.log(\"scrollBy\", x, y);\n this.scrolled = true;\n};\n\nRendition.prototype.scrollTo = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n \tthis.container.scrollLeft = x;\n \tthis.container.scrollTop = y;\n } else {\n \twindow.scrollTo(x,y);\n }\n // console.log(\"scrollTo\", x, y);\n this.scrolled = true;\n // if(this.container.scrollLeft != x){\n // setTimeout(function() {\n // this.scrollTo(x, y, silent);\n // }.bind(this), 10);\n // return;\n // };\n };\n\nRendition.prototype.passViewEvents = function(view){\n view.listenedEvents.forEach(function(e){\n\t\tview.on(e, this.triggerViewEvent.bind(this));\n\t}.bind(this));\n\n\tview.on(\"selected\", this.triggerSelectedEvent.bind(this));\n};\n\nRendition.prototype.triggerViewEvent = function(e){\n this.trigger(e.type, e);\n};\n\nRendition.prototype.triggerSelectedEvent = function(cfirange){\n\tconsole.log(cfirange);\n this.trigger(\"selected\", cfirange);\n};\n\nRendition.prototype.replacements = function(){\n\t// Wait for loading\n\treturn this.q.enqueue(function () {\n\t\t// Get thes books manifest\n\t\tvar manifest = this.book.package.manifest;\n\t var manifestArray = Object.keys(manifest).\n\t map(function (key){\n\t return manifest[key];\n\t });\n\n\t // Exclude HTML\n\t var items = manifestArray.\n\t filter(function (item){\n\t if (item.type != \"application/xhtml+xml\" &&\n\t item.type != \"text/html\") {\n\t return true;\n\t }\n\t });\n\n\t // Only CSS\n\t var css = items.\n\t filter(function (item){\n\t if (item.type === \"text/css\") {\n\t return true;\n\t }\n\t });\n\n\t\t// Css Urls\n\t\tvar cssUrls = css.map(function(item) {\n\t\t\treturn item.href;\n\t\t});\n\n\t\t// All Assets Urls\n\t var urls = items.\n\t map(function(item) {\n\t return item.href;\n\t }.bind(this));\n\n\t\t// Create blob urls for all the assets\n\t var processing = urls.\n\t map(function(url) {\n\t\t\t\tvar absolute = URI(url).absoluteTo(this.book.baseUrl).toString();\n\t\t\t\t// Full url from archive base\n\t return this.book.archive.createUrl(absolute);\n\t }.bind(this));\n\n\t\t// After all the urls are created\n\t return RSVP.all(processing).\n\t then(function(replacementUrls) {\n\n\t\t\t\t// Replace Asset Urls in the text of all css files\n\t\t\t\tcssUrls.forEach(function(href) {\n\t\t\t\t\tthis.replaceCss(href, urls, replacementUrls);\n\t\t }.bind(this));\n\n\t\t\t\t// Replace Asset Urls in chapters\n\t\t\t\t// by registering a hook after the sections contents has been serialized\n\t this.hooks.serialize.register(function(output, section) {\n\t\t\t\t\tthis.replaceAssets(section, urls, replacementUrls);\n\t }.bind(this));\n\n\t }.bind(this)).catch(function(reason){\n\t console.error(reason);\n\t });\n\t}.bind(this));\n};\n\nRendition.prototype.replaceCss = function(href, urls, replacementUrls){\n\t\tvar newUrl;\n\t\tvar indexInUrls;\n\n\t\t// Find the absolute url of the css file\n\t\tvar fileUri = URI(href);\n\t\tvar absolute = fileUri.absoluteTo(this.book.baseUrl).toString();\n\t\t// Get the text of the css file from the archive\n\t\tvar text = this.book.archive.getText(absolute);\n\t\t// Get asset links relative to css file\n\t\tvar relUrls = urls.\n\t\t\tmap(function(assetHref) {\n\t\t\t\tvar assetUri = URI(assetHref).absoluteTo(this.book.baseUrl);\n\t\t\t\tvar relative = assetUri.relativeTo(absolute).toString();\n\t\t\t\treturn relative;\n\t\t\t}.bind(this));\n\n\t\t// Replacements in the css text\n\t\ttext = replace.substitute(text, relUrls, replacementUrls);\n\n\t\t// Get the new url\n\t\tnewUrl = core.createBlobUrl(text, 'text/css');\n\n\t\t// switch the url in the replacementUrls\n\t\tindexInUrls = urls.indexOf(href);\n\t\tif (indexInUrls > -1) {\n\t\t\treplacementUrls[indexInUrls] = newUrl;\n\t\t}\n};\n\nRendition.prototype.replaceAssets = function(section, urls, replacementUrls){\n\tvar fileUri = URI(section.url);\n\t// Get Urls relative to current sections\n\tvar relUrls = urls.\n\t\tmap(function(href) {\n\t\t\tvar assetUri = URI(href).absoluteTo(this.book.baseUrl);\n\t\t\tvar relative = assetUri.relativeTo(fileUri).toString();\n\t\t\treturn relative;\n\t\t}.bind(this));\n\n\n\tsection.output = replace.substitute(section.output, relUrls, replacementUrls);\n};\n//-- Enable binding events to Renderer\nRSVP.EventTarget.mixin(Rendition.prototype);\n\nmodule.exports = Rendition;\n","var URI = require('urijs');\nvar core = require('./core');\n\nfunction base(doc, section){\n var base;\n var head;\n\n if(!doc){\n return;\n }\n\n head = doc.querySelector(\"head\");\n base = head.querySelector(\"base\");\n\n if(!base) {\n base = doc.createElement(\"base\");\n }\n\n base.setAttribute(\"href\", section.url);\n head.insertBefore(base, head.firstChild);\n\n}\n\nfunction links(view, renderer) {\n\n var links = view.document.querySelectorAll(\"a[href]\");\n var replaceLinks = function(link){\n var href = link.getAttribute(\"href\");\n var linkUri = URI(href);\n var absolute = linkUri.absoluteTo(view.section.url);\n var relative = absolute.relativeTo(this.book.baseUrl).toString();\n\n if(linkUri.protocol()){\n\n link.setAttribute(\"target\", \"_blank\");\n\n }else{\n /*\n if(baseDirectory) {\n\t\t\t\t// We must ensure that the file:// protocol is preserved for\n\t\t\t\t// local file links, as in certain contexts (such as under\n\t\t\t\t// Titanium), file links without the file:// protocol will not\n\t\t\t\t// work\n\t\t\t\tif (baseUri.protocol === \"file\") {\n\t\t\t\t\trelative = core.resolveUrl(baseUri.base, href);\n\t\t\t\t} else {\n\t\t\t\t\trelative = core.resolveUrl(baseDirectory, href);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trelative = href;\n\t\t\t}\n */\n\n if(linkUri.fragment()) {\n // do nothing with fragment yet\n } else {\n link.onclick = function(){\n renderer.display(relative);\n return false;\n };\n }\n\n }\n };\n\n for (var i = 0; i < links.length; i++) {\n replaceLinks(links[i]);\n }\n\n\n};\n\nfunction substitute(content, urls, replacements) {\n urls.forEach(function(url, i){\n if (url && replacements[i]) {\n content = content.replace(new RegExp(url, 'g'), replacements[i]);\n }\n });\n return content;\n}\nmodule.exports = {\n 'base': base,\n 'links': links,\n 'substitute': substitute\n};\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\n\nfunction request(url, type, withCredentials, headers) {\n var supportsURL = window.URL;\n var BLOB_RESPONSE = supportsURL ? \"blob\" : \"arraybuffer\";\n var uri;\n\n var deferred = new RSVP.defer();\n\n var xhr = new XMLHttpRequest();\n\n //-- Check from PDF.js:\n // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js\n var xhrPrototype = XMLHttpRequest.prototype;\n\n var header;\n\n if (!('overrideMimeType' in xhrPrototype)) {\n // IE10 might have response, but not overrideMimeType\n Object.defineProperty(xhrPrototype, 'overrideMimeType', {\n value: function xmlHttpRequestOverrideMimeType(mimeType) {}\n });\n }\n if(withCredentials) {\n xhr.withCredentials = true;\n }\n\n xhr.open(\"GET\", url, true);\n\n for(header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n\n xhr.onreadystatechange = handler;\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n xhr.responseType = BLOB_RESPONSE;\n }\n\n if(type == \"json\") {\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n }\n\n if(core.isXml(type)) {\n\t\txhr.responseType = \"document\";\n\t\txhr.overrideMimeType('text/xml'); // for OPF parsing\n\t}\n\n\tif(type == 'xhtml') {\n\t\txhr.responseType = \"document\";\n\t}\n\n\tif(type == 'html' || type == 'htm') {\n\t\txhr.responseType = \"document\";\n \t}\n\n if(type == \"binary\") {\n xhr.responseType = \"arraybuffer\";\n }\n\n xhr.send();\n\n function handler() {\n if (this.readyState === this.DONE) {\n if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls\n var r;\n\n if((this.responseType == '' || this.responseType == 'document')\n && this.responseXML){\n r = this.responseXML;\n } else\n if(core.isXml(type)){\n // If this.responseXML wasn't set, try to parse using a DOMParser from text\n r = new DOMParser().parseFromString(this.response, \"text/xml\");\n }else\n if(type == 'xhtml'){\n r = new DOMParser().parseFromString(this.response, \"application/xhtml+xml\");\n }else\n if(type == 'html' || type == 'htm'){\n r = new DOMParser().parseFromString(this.response, \"text/html\");\n }else\n if(type == 'json'){\n r = JSON.parse(this.response);\n }else\n if(type == 'blob'){\n\n if(supportsURL) {\n r = this.response;\n } else {\n //-- Safari doesn't support responseType blob, so create a blob from arraybuffer\n r = new Blob([this.response]);\n }\n\n }else{\n r = this.response;\n }\n\n deferred.resolve(r);\n } else {\n deferred.reject({\n status: this.status,\n message : this.response,\n stack : new Error().stack\n });\n }\n }\n }\n\n return deferred.promise;\n};\n\nmodule.exports = request;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\nvar replacements = require('./replacements');\n\nfunction Section(item, hooks){\n this.idref = item.idref;\n this.linear = item.linear;\n this.properties = item.properties;\n this.index = item.index;\n this.href = item.href;\n this.url = item.url;\n this.next = item.next;\n this.prev = item.prev;\n\n this.epubcfi = new EpubCFI();\n this.cfiBase = item.cfiBase;\n\n this.hooks = {};\n this.hooks.serialize = new Hook(this);\n this.hooks.content = new Hook(this);\n\n // Register replacements\n this.hooks.content.register(replacements.base);\n};\n\n\nSection.prototype.load = function(_request){\n var request = _request || this.request || require('./request');\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(this.contents) {\n loading.resolve(this.contents);\n } else {\n request(this.url)\n .then(function(xml){\n var base;\n var directory = URI(this.url).directory();\n\n this.document = xml;\n this.contents = xml.documentElement;\n\n return this.hooks.content.trigger(this.document, this);\n }.bind(this))\n .then(function(){\n loading.resolve(this.contents);\n }.bind(this))\n .catch(function(error){\n loading.reject(error);\n });\n }\n\n return loaded;\n};\n\nSection.prototype.base = function(_document){\n var task = new RSVP.defer();\n var base = _document.createElement(\"base\"); // TODO: check if exists\n var head;\n\n base.setAttribute(\"href\", this.url);\n\n if(_document) {\n head = _document.querySelector(\"head\");\n }\n if(head) {\n head.insertBefore(base, head.firstChild);\n task.resolve();\n } else {\n task.reject(new Error(\"No head to insert into\"));\n }\n\n\n return task.promise;\n};\n\nSection.prototype.beforeSectionLoad = function(){\n // Stub for a hook - replace me for now\n};\n\nSection.prototype.render = function(_request){\n var rendering = new RSVP.defer();\n var rendered = rendering.promise;\n this.output; // TODO: better way to return this from hooks?\n\n this.load(_request).\n then(function(contents){\n var serializer = new XMLSerializer();\n this.output = serializer.serializeToString(contents);\n return this.output;\n }.bind(this)).\n then(function(){\n return this.hooks.serialize.trigger(this.output, this);\n }.bind(this)).\n then(function(){\n rendering.resolve(this.output);\n }.bind(this))\n .catch(function(error){\n rendering.reject(error);\n });\n\n return rendered;\n};\n\nSection.prototype.find = function(_query){\n\n};\n\n/**\n* Reconciles the current chapters layout properies with\n* the global layout properities.\n* Takes: global layout settings object, chapter properties string\n* Returns: Object with layout properties\n*/\nSection.prototype.reconcileLayoutSettings = function(global){\n //-- Get the global defaults\n var settings = {\n layout : global.layout,\n spread : global.spread,\n orientation : global.orientation\n };\n\n //-- Get the chapter's display type\n this.properties.forEach(function(prop){\n var rendition = prop.replace(\"rendition:\", '');\n var split = rendition.indexOf(\"-\");\n var property, value;\n\n if(split != -1){\n property = rendition.slice(0, split);\n value = rendition.slice(split+1);\n\n settings[property] = value;\n }\n });\n return settings;\n};\n\nSection.prototype.cfiFromRange = function(_range) {\n return this.epubcfi.generateCfiFromRange(_range, this.cfiBase);\n};\n\nSection.prototype.cfiFromElement = function(el) {\n return this.epubcfi.generateCfiFromElement(el, this.cfiBase);\n};\n\nmodule.exports = Section;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Section = require('./section');\n\nfunction Spine(_request){\n this.request = _request;\n this.spineItems = [];\n this.spineByHref = {};\n this.spineById = {};\n\n};\n\nSpine.prototype.load = function(_package) {\n\n this.items = _package.spine;\n this.manifest = _package.manifest;\n this.spineNodeIndex = _package.spineNodeIndex;\n this.baseUrl = _package.baseUrl || '';\n this.length = this.items.length;\n this.epubcfi = new EpubCFI();\n\n this.items.forEach(function(item, index){\n var href, url;\n var manifestItem = this.manifest[item.idref];\n var spineItem;\n item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);\n\n if(manifestItem) {\n item.href = manifestItem.href;\n item.url = this.baseUrl + item.href;\n\n if(manifestItem.properties.length){\n item.properties.push.apply(item.properties, manifestItem.properties);\n }\n }\n\n // if(index > 0) {\n item.prev = function(){ return this.get(index-1); }.bind(this);\n // }\n\n // if(index+1 < this.items.length) {\n item.next = function(){ return this.get(index+1); }.bind(this);\n // }\n\n spineItem = new Section(item);\n this.append(spineItem);\n\n\n }.bind(this));\n\n};\n\n// book.spine.get();\n// book.spine.get(1);\n// book.spine.get(\"chap1.html\");\n// book.spine.get(\"#id1234\");\nSpine.prototype.get = function(target) {\n var index = 0;\n\n if(this.epubcfi.isCfiString(target)) {\n cfi = this.epubcfi.parse(target);\n index = cfi.spinePos;\n } else if(target && (typeof target === \"number\" || isNaN(target) === false)){\n index = target;\n } else if(target && target.indexOf(\"#\") === 0) {\n index = this.spineById[target.substring(1)];\n } else if(target) {\n // Remove fragments\n target = target.split(\"#\")[0];\n index = this.spineByHref[target];\n }\n\n return this.spineItems[index] || null;\n};\n\nSpine.prototype.append = function(section) {\n var index = this.spineItems.length;\n section.index = index;\n\n this.spineItems.push(section);\n\n this.spineByHref[section.href] = index;\n this.spineById[section.idref] = index;\n\n return index;\n};\n\nSpine.prototype.prepend = function(section) {\n var index = this.spineItems.unshift(section);\n this.spineByHref[section.href] = 0;\n this.spineById[section.idref] = 0;\n\n // Re-index\n this.spineItems.forEach(function(item, index){\n item.index = index;\n });\n\n return 0;\n};\n\nSpine.prototype.insert = function(section, index) {\n\n};\n\nSpine.prototype.remove = function(section) {\n var index = this.spineItems.indexOf(section);\n\n if(index > -1) {\n delete this.spineByHref[section.href];\n delete this.spineById[section.idref];\n\n return this.spineItems.splice(index, 1);\n }\n};\n\nSpine.prototype.each = function() {\n\treturn this.spineItems.forEach.apply(this.spineItems, arguments);\n};\n\nmodule.exports = Spine;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar request = require('./request');\nvar mime = require('../libs/mime/mime');\n\nfunction Unarchive() {\n\n this.checkRequirements();\n this.urlCache = {};\n\n}\n\nUnarchive.prototype.checkRequirements = function(callback){\n try {\n if (typeof JSZip !== 'undefined') {\n this.zip = new JSZip();\n } else {\n JSZip = require('jszip');\n this.zip = new JSZip();\n }\n } catch (e) {\n console.error(\"JSZip lib not loaded\");\n }\n};\n\nUnarchive.prototype.open = function(zipUrl){\n\tif (zipUrl instanceof ArrayBuffer) {\n return new RSVP.Promise(function(resolve, reject) {\n this.zip = new JSZip(zipUrl);\n resolve(this.zip);\n });\n\t} else {\n\t\treturn request(zipUrl, \"binary\")\n .then(function(data){\n\t\t\t this.zip = new JSZip(data);\n return this.zip;\n\t\t }.bind(this));\n\t}\n};\n\nUnarchive.prototype.request = function(url, type){\n var deferred = new RSVP.defer();\n var response;\n var r;\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n response = this.getBlob(url);\n } else {\n response = this.getText(url);\n }\n\n if (response) {\n r = this.handleResponse(response, type);\n deferred.resolve(r);\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n return deferred.promise;\n};\n\nUnarchive.prototype.handleResponse = function(response, type){\n var r;\n\n if(type == \"json\") {\n r = JSON.parse(response);\n }\n else\n if(core.isXml(type)) {\n r = new DOMParser().parseFromString(response, \"text/xml\");\n\t}\n else\n\tif(type == 'xhtml') {\n r = new DOMParser().parseFromString(response, \"application/xhtml+xml\");\n\t}\n else\n\tif(type == 'html' || type == 'htm') {\n r = new DOMParser().parseFromString(response, \"text/html\");\n \t} else {\n \t r = response;\n \t}\n\n return r;\n};\n\nUnarchive.prototype.getBlob = function(url, _mimeType){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n var mimeType;\n\n\tif(entry) {\n mimeType = _mimeType || mime.lookup(entry.name);\n return new Blob([entry.asUint8Array()], {type : mimeType});\n\t}\n};\n\nUnarchive.prototype.getText = function(url, encoding){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n\n\tif(entry) {\n return entry.asText();\n\t}\n};\n\nUnarchive.prototype.createUrl = function(url, mime){\n\tvar deferred = new RSVP.defer();\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob;\n\n\tif(url in this.urlCache) {\n\t\tdeferred.resolve(this.urlCache[url]);\n\t\treturn deferred.promise;\n\t}\n\n\tblob = this.getBlob(url);\n\n if (blob) {\n tempUrl = _URL.createObjectURL(blob);\n deferred.resolve(tempUrl);\n this.urlCache[url] = tempUrl;\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n\n\treturn deferred.promise;\n};\n\nUnarchive.prototype.revokeUrl = function(url){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar fromCache = this.urlCache[url];\n\tif(fromCache) _URL.revokeObjectURL(fromCache);\n};\n\nmodule.exports = Unarchive;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction View(section, options) {\n this.settings = options || {};\n\n this.id = \"epubjs-view:\" + core.uuid();\n this.section = section;\n this.index = section.index;\n\n this.element = document.createElement('div');\n this.element.classList.add(\"epub-view\");\n\n\n // this.element.style.minHeight = \"100px\";\n this.element.style.height = \"0px\";\n this.element.style.width = \"0px\";\n this.element.style.overflow = \"hidden\";\n\n this.added = false;\n this.displayed = false;\n this.rendered = false;\n\n //this.width = 0;\n //this.height = 0;\n\n // Blank Cfi for Parsing\n this.epubcfi = new EpubCFI();\n\n if(this.settings.axis && this.settings.axis == \"horizontal\"){\n this.element.style.display = \"inline-block\";\n } else {\n this.element.style.display = \"block\";\n }\n\n // Dom events to listen for\n this.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n\n};\n\nView.prototype.create = function() {\n\n if(this.iframe) {\n return this.iframe;\n }\n\n this.iframe = document.createElement('iframe');\n this.iframe.id = this.id;\n this.iframe.scrolling = \"no\"; // Might need to be removed: breaks ios width calculations\n this.iframe.style.overflow = \"hidden\";\n this.iframe.seamless = \"seamless\";\n // Back up if seamless isn't supported\n this.iframe.style.border = \"none\";\n\n this.resizing = true;\n\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.iframe.style.width = \"0\";\n this.iframe.style.height = \"0\";\n this._width = 0;\n this._height = 0;\n\n this.element.appendChild(this.iframe);\n this.added = true;\n\n this.elementBounds = core.bounds(this.element);\n\n // if(width || height){\n // this.resize(width, height);\n // } else if(this.width && this.height){\n // this.resize(this.width, this.height);\n // } else {\n // this.iframeBounds = core.bounds(this.iframe);\n // }\n\n // Firefox has trouble with baseURI and srcdoc\n // Disabled for now\n /*\n if(!!(\"srcdoc\" in this.iframe)) {\n this.supportsSrcdoc = true;\n } else {\n this.supportsSrcdoc = false;\n }\n */\n this.supportsSrcdoc = false;\n\n return this.iframe;\n};\n\n\nView.prototype.lock = function(what, width, height) {\n\n var elBorders = core.borders(this.element);\n var iframeBorders;\n\n if(this.iframe) {\n iframeBorders = core.borders(this.iframe);\n } else {\n iframeBorders = {width: 0, height: 0};\n }\n\n if(what == \"width\" && core.isNumber(width)){\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.resize(this.lockedWidth, width); // width keeps ratio correct\n }\n\n if(what == \"height\" && core.isNumber(height)){\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n this.resize(width, this.lockedHeight);\n }\n\n if(what === \"both\" &&\n core.isNumber(width) &&\n core.isNumber(height)){\n\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n\n this.resize(this.lockedWidth, this.lockedHeight);\n }\n\n if(this.displayed && this.iframe) {\n\n this.layout();\n this.expand();\n\n }\n\n\n\n};\n\nView.prototype.expand = function(force) {\n var width = this.lockedWidth;\n var height = this.lockedHeight;\n\n var textWidth, textHeight;\n // console.log(\"expanding a\")\n if(!this.iframe || this._expanding) return;\n\n this._expanding = true;\n\n // Expand Horizontally\n if(height && !width) {\n // Get the width of the text\n textWidth = this.textWidth();\n // Check if the textWidth has changed\n if(textWidth != this._textWidth){\n // Get the contentWidth by resizing the iframe\n // Check with a min reset of the textWidth\n width = this.contentWidth(textWidth);\n // Save the textWdith\n this._textWidth = textWidth;\n // Save the contentWidth\n this._contentWidth = width;\n } else {\n // Otherwise assume content height hasn't changed\n width = this._contentWidth;\n }\n }\n\n // Expand Vertically\n if(width && !height) {\n textHeight = this.textHeight();\n if(textHeight != this._textHeight){\n height = this.contentHeight(textHeight);\n this._textHeight = textHeight;\n this._contentHeight = height;\n } else {\n height = this._contentHeight;\n }\n }\n\n // Only Resize if dimensions have changed or\n // if Frame is still hidden, so needs reframing\n if(this._needsReframe || width != this._width || height != this._height){\n this.resize(width, height);\n }\n\n this._expanding = false;\n};\n\nView.prototype.contentWidth = function(min) {\n var prev;\n var width;\n\n // Save previous width\n prev = this.iframe.style.width;\n // Set the iframe size to min, width will only ever be greater\n // Will preserve the aspect ratio\n this.iframe.style.width = (min || 0) + \"px\";\n // Get the scroll overflow width\n width = this.document.body.scrollWidth;\n // Reset iframe size back\n this.iframe.style.width = prev;\n return width;\n};\n\nView.prototype.contentHeight = function(min) {\n var prev;\n var height;\n\n prev = this.iframe.style.height;\n this.iframe.style.height = (min || 0) + \"px\";\n height = this.document.body.scrollHeight;\n this.iframe.style.height = prev;\n return height;\n};\n\nView.prototype.textWidth = function() {\n var width;\n var range = this.document.createRange();\n\n // Select the contents of frame\n range.selectNodeContents(this.document.body);\n\n // get the width of the text content\n width = range.getBoundingClientRect().width;\n return width;\n\n};\n\nView.prototype.textHeight = function() {\n var height;\n var range = this.document.createRange();\n\n range.selectNodeContents(this.document.body);\n\n height = range.getBoundingClientRect().height;\n return height;\n};\n\nView.prototype.resize = function(width, height) {\n\n if(!this.iframe) return;\n\n if(core.isNumber(width)){\n this.iframe.style.width = width + \"px\";\n this._width = width;\n }\n\n if(core.isNumber(height)){\n this.iframe.style.height = height + \"px\";\n this._height = height;\n }\n\n this.iframeBounds = core.bounds(this.iframe);\n\n this.reframe(this.iframeBounds.width, this.iframeBounds.height);\n\n};\n\nView.prototype.reframe = function(width, height) {\n //var prevBounds;\n\n if(!this.displayed) {\n this._needsReframe = true;\n return;\n }\n\n if(core.isNumber(width)){\n this.element.style.width = width + \"px\";\n }\n\n if(core.isNumber(height)){\n this.element.style.height = height + \"px\";\n }\n\n this.prevBounds = this.elementBounds;\n\n this.elementBounds = core.bounds(this.element);\n\n this.trigger(\"resized\", {\n width: this.elementBounds.width,\n height: this.elementBounds.height,\n widthDelta: this.elementBounds.width - this.prevBounds.width,\n heightDelta: this.elementBounds.height - this.prevBounds.height,\n });\n\n};\n\nView.prototype.resized = function(e) {\n /*\n if (!this.resizing) {\n if(this.iframe) {\n // this.expand();\n }\n } else {\n this.resizing = false;\n }*/\n\n};\n\nView.prototype.render = function(_request) {\n\n // if(this.rendering){\n // return this.displayed;\n // }\n\n this.rendering = true;\n // this.displayingDefer = new RSVP.defer();\n // this.displayedPromise = this.displaying.promise;\n\n return this.section.render(_request)\n .then(function(contents){\n return this.load(contents);\n }.bind(this));\n};\n\nView.prototype.load = function(contents) {\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(!this.iframe) {\n loading.reject(new Error(\"No Iframe Available\"));\n return loaded;\n }\n\n this.iframe.onload = function(event) {\n\n this.window = this.iframe.contentWindow;\n this.document = this.iframe.contentDocument;\n this.rendering = false;\n loading.resolve(this);\n\n }.bind(this);\n\n if(this.supportsSrcdoc){\n this.iframe.srcdoc = contents;\n } else {\n\n this.document = this.iframe.contentDocument;\n\n if(!this.document) {\n loading.reject(new Error(\"No Document Available\"));\n return loaded;\n }\n\n this.document.open();\n this.document.write(contents);\n this.document.close();\n\n }\n\n return loaded;\n};\n\n\nView.prototype.layout = function(layoutFunc) {\n\n this.iframe.style.display = \"inline-block\";\n\n // Reset Body Styles\n this.document.body.style.margin = \"0\";\n //this.document.body.style.display = \"inline-block\";\n //this.document.documentElement.style.width = \"auto\";\n\n if(layoutFunc){\n layoutFunc(this);\n }\n\n this.onLayout(this);\n\n};\n\nView.prototype.onLayout = function(view) {\n // stub\n};\n\nView.prototype.listeners = function() {\n /*\n setTimeout(function(){\n this.window.addEventListener(\"resize\", this.resized.bind(this), false);\n }.bind(this), 10); // Wait to listen for resize events\n */\n\n // Wait for fonts to load to finish\n // http://dev.w3.org/csswg/css-font-loading/\n // Not implemented fully except in chrome\n\n if(this.document.fonts && this.document.fonts.status === \"loading\") {\n // console.log(\"fonts unloaded\");\n this.document.fonts.onloadingdone = function(){\n // console.log(\"loaded fonts\");\n this.expand();\n }.bind(this);\n }\n\n if(this.section.properties.indexOf(\"scripted\") > -1){\n this.observer = this.observe(this.document.body);\n }\n\n this.imageLoadListeners();\n\n this.mediaQueryListeners();\n\n // this.resizeListenters();\n\n this.addEventListeners();\n\n this.addSelectionListeners();\n};\n\nView.prototype.removeListeners = function() {\n\n this.removeEventListeners();\n\n this.removeSelectionListeners();\n};\n\nView.prototype.resizeListenters = function() {\n // Test size again\n clearTimeout(this.expanding);\n this.expanding = setTimeout(this.expand.bind(this), 350);\n};\n\n//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js\nView.prototype.mediaQueryListeners = function() {\n var sheets = this.document.styleSheets;\n var mediaChangeHandler = function(m){\n if(m.matches && !this._expanding) {\n setTimeout(this.expand.bind(this), 1);\n // this.expand();\n }\n }.bind(this);\n\n for (var i = 0; i < sheets.length; i += 1) {\n var rules = sheets[i].cssRules;\n if(!rules) return; // Stylesheets changed\n for (var j = 0; j < rules.length; j += 1) {\n //if (rules[j].constructor === CSSMediaRule) {\n if(rules[j].media){\n var mql = this.window.matchMedia(rules[j].media.mediaText);\n mql.addListener(mediaChangeHandler);\n //mql.onchange = mediaChangeHandler;\n }\n }\n }\n};\n\nView.prototype.observe = function(target) {\n var renderer = this;\n\n // create an observer instance\n var observer = new MutationObserver(function(mutations) {\n if(renderer._expanding) {\n renderer.expand();\n }\n // mutations.forEach(function(mutation) {\n // console.log(mutation);\n // });\n });\n\n // configuration of the observer:\n var config = { attributes: true, childList: true, characterData: true, subtree: true };\n\n // pass in the target node, as well as the observer options\n observer.observe(target, config);\n\n return observer;\n};\n\n// View.prototype.appendTo = function(element) {\n// this.element = element;\n// this.element.appendChild(this.iframe);\n// };\n//\n// View.prototype.prependTo = function(element) {\n// this.element = element;\n// element.insertBefore(this.iframe, element.firstChild);\n// };\n\nView.prototype.imageLoadListeners = function(target) {\n var images = this.document.body.querySelectorAll(\"img\");\n var img;\n for (var i = 0; i < images.length; i++) {\n img = images[i];\n\n if (typeof img.naturalWidth !== \"undefined\" &&\n img.naturalWidth === 0) {\n img.onload = this.expand.bind(this);\n }\n }\n};\n\nView.prototype.display = function() {\n var displayed = new RSVP.defer();\n\n this.displayed = true;\n\n this.layout();\n\n this.listeners();\n\n this.expand();\n\n this.trigger(\"displayed\", this);\n this.onDisplayed(this);\n\n displayed.resolve(this);\n\n return displayed.promise;\n};\n\nView.prototype.show = function() {\n\n this.element.style.visibility = \"visible\";\n\n if(this.iframe){\n this.iframe.style.visibility = \"visible\";\n }\n\n this.trigger(\"shown\", this);\n};\n\nView.prototype.hide = function() {\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.stopExpanding = true;\n this.trigger(\"hidden\", this);\n};\n\nView.prototype.position = function() {\n return this.element.getBoundingClientRect();\n};\n\nView.prototype.onDisplayed = function(view) {\n // Stub, override with a custom functions\n};\n\nView.prototype.bounds = function() {\n if(!this.elementBounds) {\n this.elementBounds = core.bounds(this.element);\n }\n return this.elementBounds;\n};\n\nView.prototype.destroy = function() {\n // Stop observing\n if(this.observer) {\n this.observer.disconnect();\n }\n\n if(this.displayed){\n this.removeListeners();\n\n this.stopExpanding = true;\n this.element.removeChild(this.iframe);\n this.displayed = false;\n this.iframe = null;\n\n this._textWidth = null;\n this._textHeight = null;\n this._width = null;\n this._height = null;\n }\n // this.element.style.height = \"0px\";\n // this.element.style.width = \"0px\";\n};\n\nView.prototype.root = function() {\n if(!this.document) return null;\n return this.document.documentElement;\n};\n\nView.prototype.locationOf = function(target) {\n var parentPos = this.iframe.getBoundingClientRect();\n var targetPos = {\"left\": 0, \"top\": 0};\n\n if(!this.document) return;\n\n if(this.epubcfi.isCfiString(target)) {\n cfi = this.epubcfi.parse(target);\n\n if(typeof document.evaluate === 'undefined') {\n marker = this.epubcfi.addMarker(cfi, this.document);\n if(marker) {\n // Must Clean up Marker before going to page\n this.epubcfi.removeMarker(marker, this.document);\n\n targetPos = marker.getBoundingClientRect();\n }\n } else {\n range = this.epubcfi.generateRangeFromCfi(cfi, this.document);\n if(range) {\n targetPos = range.getBoundingClientRect();\n }\n }\n } else if(typeof target === \"string\" &&\n target.indexOf(\"#\") > -1) {\n\n id = target.substring(target.indexOf(\"#\")+1);\n el = this.document.getElementById(id);\n\n if(el) {\n targetPos = el.getBoundingClientRect();\n }\n }\n\n return {\n \"left\": window.scrollX + parentPos.left + targetPos.left,\n \"top\": window.scrollY + parentPos.top + targetPos.top\n };\n};\n\nView.prototype.addCss = function(src) {\n return new RSVP.Promise(function(resolve, reject){\n var $stylesheet;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $stylesheet = this.document.createElement('link');\n $stylesheet.type = 'text/css';\n $stylesheet.rel = \"stylesheet\";\n $stylesheet.href = src;\n $stylesheet.onload = $stylesheet.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n // Let apply\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($stylesheet);\n\n }.bind(this));\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule\nView.prototype.addStylesheetRules = function(rules) {\n var styleEl;\n var styleSheet;\n\n if(!this.document) return;\n\n styleEl = this.document.createElement('style');\n\n // Append style element to head\n this.document.head.appendChild(styleEl);\n\n // Grab style sheet\n styleSheet = styleEl.sheet;\n\n for (var i = 0, rl = rules.length; i < rl; i++) {\n var j = 1, rule = rules[i], selector = rules[i][0], propStr = '';\n // If the second argument of a rule is an array of arrays, correct our variables.\n if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {\n rule = rule[1];\n j = 0;\n }\n\n for (var pl = rule.length; j < pl; j++) {\n var prop = rule[j];\n propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\\n';\n }\n\n // Insert CSS Rule\n styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);\n }\n};\n\nView.prototype.addScript = function(src) {\n\n return new RSVP.Promise(function(resolve, reject){\n var $script;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $script = this.document.createElement('script');\n $script.type = 'text/javascript';\n $script.async = true;\n $script.src = src;\n $script.onload = $script.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($script);\n\n }.bind(this));\n};\n\nView.prototype.addEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);\n }, this);\n\n};\n\nView.prototype.removeEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.removeEventListener(eventName, this.triggerEvent, false);\n }, this);\n\n};\n\n// Pass browser events\nView.prototype.triggerEvent = function(e){\n this.trigger(e.type, e);\n};\n\nView.prototype.addSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.addEventListener(\"selectionchange\", this.onSelectionChange.bind(this), false);\n};\n\nView.prototype.removeSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.removeEventListener(\"selectionchange\", this.onSelectionChange, false);\n};\n\nView.prototype.onSelectionChange = function(e){\n if (this.selectionEndTimeout) {\n clearTimeout(this.selectionEndTimeout);\n }\n this.selectionEndTimeout = setTimeout(function() {\n var selection = this.window.getSelection();\n this.triggerSelectedEvent(selection);\n }.bind(this), 500);\n};\n\nView.prototype.triggerSelectedEvent = function(selection){\n\tvar range = selection.getRangeAt(0);\n\tconsole.log(range);\n\tvar cfirange = this.section.cfiFromRange(range);\n this.trigger(\"selected\", cfirange);\n};\n\nRSVP.EventTarget.mixin(View.prototype);\n\nmodule.exports = View;\n","function Views(container) {\n this.container = container;\n this._views = [];\n this.length = 0;\n this.hidden = false;\n};\n\nViews.prototype.first = function() {\n\treturn this._views[0];\n};\n\nViews.prototype.last = function() {\n\treturn this._views[this._views.length-1];\n};\n\nViews.prototype.each = function() {\n\treturn this._views.forEach.apply(this._views, arguments);\n};\n\nViews.prototype.indexOf = function(view) {\n\treturn this._views.indexOf(view);\n};\n\nViews.prototype.slice = function() {\n\treturn this._views.slice.apply(this._views, arguments);\n};\n\nViews.prototype.get = function(i) {\n\treturn this._views[i];\n};\n\nViews.prototype.append = function(view){\n\tthis._views.push(view);\n\tthis.container.appendChild(view.element);\n this.length++;\n return view;\n};\n\nViews.prototype.prepend = function(view){\n\tthis._views.unshift(view);\n\tthis.container.insertBefore(view.element, this.container.firstChild);\n this.length++;\n return view;\n};\n\nViews.prototype.insert = function(view, index) {\n\tthis._views.splice(index, 0, view);\n\n\tif(index < this.container.children.length){\n\t\tthis.container.insertBefore(view.element, this.container.children[index]);\n\t} else {\n\t\tthis.container.appendChild(view.element);\n\t}\n this.length++;\n return view;\n};\n\nViews.prototype.remove = function(view) {\n\tvar index = this._views.indexOf(view);\n\n\tif(index > -1) {\n\t\tthis._views.splice(index, 1);\n\t}\n\n\n\tthis.destroy(view);\n\n this.length--;\n};\n\nViews.prototype.destroy = function(view) {\n\tview.off(\"resized\");\n\n\tif(view.displayed){\n\t\tview.destroy();\n\t}\n\n\tthis.container.removeChild(view.element);\n\tview = null;\n};\n\n// Iterators\n\nViews.prototype.clear = function(){\n\t// Remove all views\n var view;\n var len = this.length;\n\n if(!this.length) return;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tthis.destroy(view);\n }\n\n this._views = [];\n this.length = 0;\n};\n\nViews.prototype.find = function(section){\n\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tif(view.displayed && view.section.index == section.index) {\n\t\t\treturn view;\n\t\t}\n }\n\n};\n\nViews.prototype.displayed = function(){\n var displayed = [];\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n displayed.push(view);\n }\n }\n return displayed;\n};\n\nViews.prototype.show = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.show();\n }\n }\n this.hidden = false;\n};\n\nViews.prototype.hide = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.hide();\n }\n }\n this.hidden = true;\n};\n\nmodule.exports = Views;\n","if (typeof EPUBJS === 'undefined') {\n\t(typeof window !== 'undefined' ? window : global).EPUBJS = {};\n}\n\nEPUBJS.VERSION = \"0.3.0\";\n\nvar Book = require('./book');\n\nfunction ePub(_url) {\n\treturn new Book(_url);\n};\n\nmodule.exports = ePub;\n"]} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index fad4ac1..2584766 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -18,7 +18,7 @@ var sourcemaps = require('gulp-sourcemaps'); var size = require('gulp-size'); var URI = require('urijs'); - +var mochify = require('mochify'); // https://github.com/mishoo/UglifyJS2/pull/265 // uglify.AST_Node.warn_function = function() {}; @@ -60,8 +60,12 @@ gulp.task('serve', function() { server(); }); -gulp.task('test', function() { - +gulp.task('test', function(cb) { + mochify('./test/*.js', { + reporter: 'spec', + watch: true + }) + .bundle(); }); // Default diff --git a/src/epubcfi.js b/src/epubcfi.js index 12ee3ea..c4605e3 100644 --- a/src/epubcfi.js +++ b/src/epubcfi.js @@ -71,11 +71,12 @@ function EpubCFI(cfiFrom, base, options){ this.fromNode(cfiFrom); } else if (type === 'EpubCFI') { return cfiFrom; + } else if (!cfiFrom) { + return this; } else { throw new TypeError('not a valid argument for EpubCFI'); } - return this; }; EpubCFI.prototype.checkType = function(cfi) { @@ -85,9 +86,9 @@ EpubCFI.prototype.checkType = function(cfi) { cfi[cfi.length-1] === ")") { return 'string'; // Is a range object - } else if (typeof cfi === 'object' && cfi.startContainer && cfi.startOffset){ +} else if (typeof cfi === 'object' && cfi instanceof window.Range){ return 'range'; - } else if (typeof cfi === 'object' && cfi.nodeType){ // || typeof cfi === 'function' + } else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function' return 'node'; } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){ return 'EpubCFI'; @@ -317,4 +318,53 @@ EpubCFI.prototype.toString = function() { return cfiString; }; +EpubCFI.prototype.compare = function(cfiOne, cfiTwo) { + if(typeof cfiOne === 'string') { + cfiOne = new EpubCFI(cfiOne); + } + if(typeof cfiTwo === 'string') { + cfiTwo = new 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.path.steps.length; i++) { + if(!cfiTwo.path.steps[i]) { + return 1; + } + if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) { + return 1; + } + if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) { + return -1; + } + // Otherwise continue checking + } + + // All steps in First present in Second + if(cfiOne.path.steps.length < cfiTwo.path.steps.length) { + return -1; + } + + // Compare the charecter offset of the text node + if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) { + return 1; + } + if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) { + return -1; + } + + // TODO: compare ranges + + // CFI's are equal + return 0; +}; + module.exports = EpubCFI; diff --git a/test/epubcfi.js b/test/epubcfi.js index 9eff9c9..7a59b45 100644 --- a/test/epubcfi.js +++ b/test/epubcfi.js @@ -4,34 +4,47 @@ var assert = require('assert'); describe('EpubCFI', function() { var EpubCFI = require('../src/epubcfi.js'); - describe('EpubCFI()', function() { + it('parse a cfi on init', function() { + var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)"); + + assert.equal( cfi.spinePos, 0, "spinePos is parsed as the first item" ); + }); + + it('parse a cfi and ignore the base if present', function() { + var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)", "/6/6[end]"); + + assert.equal( cfi.spinePos, 0, "base is ignored and spinePos is parsed as the first item" ); + }); + + describe('#parse()', function() { + var cfi = new EpubCFI(); it('parse a cfi on init', function() { - var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)"); + var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)"); - assert.equal( cfi.spinePos, 0, "spinePos is parsed as the first item" ); + assert.equal( parsed.spinePos, 0, "spinePos is parsed as the first item" ); }); it('parse a cfi and ignore the base if present', function() { - var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)", "/6/6[end]"); + var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)", "/6/6[end]"); - assert.equal( cfi.spinePos, 0, "base is ignored and spinePos is parsed as the first item" ); + assert.equal( parsed.spinePos, 0, "base is ignored and spinePos is parsed as the first item" ); }); it('parse a cfi with a charecter offset', function() { - var cfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)"); + var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)"); - assert.equal( cfi.path.terminal.offset, 3, "Path has a terminal offset of 3" ); + assert.equal( parsed.path.terminal.offset, 3, "Path has a terminal offset of 3" ); }); it('parse a cfi with a range', function() { - var cfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)"); + var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)"); - assert.equal( cfi.range, true, "Range is true" ); - assert.equal( cfi.start.steps.length, 2, "Start steps are present" ); - assert.equal( cfi.end.steps.length, 1, "End steps are present" ); - assert.equal( cfi.start.terminal.offset, 1, "Start has a terminal offset of 1" ); - assert.equal( cfi.end.terminal.offset, 4, "End has a terminal offset of 4" ); + assert.equal( parsed.range, true, "Range is true" ); + assert.equal( parsed.start.steps.length, 2, "Start steps are present" ); + assert.equal( parsed.end.steps.length, 1, "End steps are present" ); + assert.equal( parsed.start.terminal.offset, 1, "Start has a terminal offset of 1" ); + assert.equal( parsed.end.terminal.offset, 4, "End has a terminal offset of 4" ); }); @@ -47,4 +60,76 @@ describe('EpubCFI', function() { }); }); + describe('#checkType()', function() { + it('determine the type of a cfi string', function() { + var cfi = new EpubCFI(); + + assert.equal( cfi.checkType('epubcfi(/6/2[cover]!/6)'), 'string' ); + assert.equal( cfi.checkType('/6/2[cover]!/6'), false ); + + }); + + it('determine the type of a cfi', function() { + var ogcfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)"); + var cfi = new EpubCFI(); + + assert.equal( cfi.checkType(ogcfi), 'EpubCFI' ); + + }); + + it('determine the type of a node', function() { + var cfi = new EpubCFI(); + var el = document.createElement('div'); + + assert.equal( cfi.checkType(el), 'node' ); + + }); + + it('determine the type of a range', function() { + var cfi = new EpubCFI(); + var range = document.createRange(); + + assert.equal( cfi.checkType(range), 'range' ); + + }); + + }); + + describe('#compare()', function() { + it('compare CFIs', function() { + var epubcfi = new EpubCFI(); + + // Spines + assert.equal(epubcfi.compare("epubcfi(/6/4[cover]!/4)", "epubcfi(/6/2[cover]!/4)"), 1, "First spine is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/4[cover]!/4)", "epubcfi(/6/6[cover]!/4)"), -1, "Second spine is greater"); + + // First is deeper + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/8/2)", "epubcfi(/6/2[cover]!/6)"), 1, "First Element is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/2)", "epubcfi(/6/2[cover]!/6)"), -1, "Second Element is greater"); + + // Second is deeper + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/8/2)", "epubcfi(/6/2[cover]!/6/4/2/2)"), 1, "First Element is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/4)", "epubcfi(/6/2[cover]!/6/4/2/2)"), -1, "Second Element is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/6)", "epubcfi(/6/2[cover]!/4/6/8/1:0)"), -1, "Second"); + + // Same Depth + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/6/8)", "epubcfi(/6/2[cover]!/6/2)"), 1, "First Element is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/20)", "epubcfi(/6/2[cover]!/6/10)"), -1, "Second Element is greater"); + + // Text nodes + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/5)", "epubcfi(/6/2[cover]!/4/3)"), 1, "First TextNode is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/7)", "epubcfi(/6/2[cover]!/4/13)"), -1, "Second TextNode is greater"); + + // Char offset + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/5:1)", "epubcfi(/6/2[cover]!/4/5:0)"), 1, "First Char Offset is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/5:2)", "epubcfi(/6/2[cover]!/4/5:30)"), -1, "Second Char Offset is greater"); + + // Normal example + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/5:1)", "epubcfi(/6/2[cover]!/4/6/15:2)"), 1, "First Element is greater"); + assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/1:0)", "epubcfi(/6/2[cover]!/4/8/1:0)"), 0, "All Equal"); + + }); + }); + + });