diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 4f3760c..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "books"] - path = books - url = https://github.com/futurepress/books.git diff --git a/.jshintrc b/.jshintrc index aacee1a..c2b6f01 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,16 +1,11 @@ { - // Environments "browser": true, "devel": true, "worker": true, - // Enforcing - //"maxlen": 80, - //"quotmark": "single", "trailing": true, "strict": false, - - // Relaxing + "boss": true, "funcscope": true, "globalstrict": true, @@ -19,8 +14,8 @@ "nonstandard": true, "sub": true, "validthis": true, - - "globals": { + + "globals": { "_": false, "define" : false, "module" : false diff --git a/.npmignore b/.npmignore index 99c53ca..497933f 100644 --- a/.npmignore +++ b/.npmignore @@ -1 +1,2 @@ books +test diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..baa0031 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/dist/epub.js b/dist/epub.js index 1055064..ab317db 100644 --- a/dist/epub.js +++ b/dist/epub.js @@ -1,12999 +1,14008 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ePub = f()}})(function(){var define,module,exports;return (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 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 -} - -function byteLength (b64) { - // base64 is 4/3 + up to two characters of the original data - return b64.length * 3 / 4 - placeHoldersCount(b64) -} - -function toByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - var len = b64.length - placeHolders = placeHoldersCount(b64) - - arr = new Arr(len * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? len - 4 : len - - var L = 0 - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] - arr[L++] = (tmp >> 16) & 0xFF - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } - - if (placeHolders === 2) { - tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[L++] = tmp & 0xFF - } else if (placeHolders === 1) { - tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var output = '' - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - output += lookup[tmp >> 2] - output += lookup[(tmp << 4) & 0x3F] - output += '==' - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) - output += lookup[tmp >> 10] - output += lookup[(tmp >> 4) & 0x3F] - output += lookup[(tmp << 2) & 0x3F] - output += '=' - } - - parts.push(output) - - return parts.join('') -} - -},{}],3:[function(require,module,exports){ - -},{}],4:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],5:[function(require,module,exports){ -(function (process,global){ -/*! - * @overview RSVP - a tiny implementation of Promises/A+. - * @copyright Copyright (c) 2016 Yehuda Katz, Tom Dale, Stefan Penner and contributors - * @license Licensed under MIT license - * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE - * @version 3.3.2 - */ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.RSVP = global.RSVP || {}))); -}(this, (function (exports) { 'use strict'; - -function indexOf(callbacks, callback) { - for (var i = 0, l = callbacks.length; i < l; i++) { - if (callbacks[i] === callback) { - return i; - } - } - - return -1; -} - -function callbacksFor(object) { - var callbacks = object._promiseCallbacks; - - if (!callbacks) { - callbacks = object._promiseCallbacks = {}; - } - - return callbacks; -} - -/** - @class RSVP.EventTarget -*/ -var EventTarget = { - - /** - `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For - Example: - ```javascript - let object = {}; - RSVP.EventTarget.mixin(object); - object.on('finished', function(event) { - // handle event - }); - object.trigger('finished', { detail: value }); - ``` - `EventTarget.mixin` also works with prototypes: - ```javascript - let Person = function() {}; - RSVP.EventTarget.mixin(Person.prototype); - let yehuda = new Person(); - let tom = new Person(); - yehuda.on('poke', function(event) { - console.log('Yehuda says OW'); - }); - tom.on('poke', function(event) { - console.log('Tom says OW'); - }); - yehuda.trigger('poke'); - tom.trigger('poke'); - ``` - @method mixin - @for RSVP.EventTarget - @private - @param {Object} object object to extend with EventTarget methods - */ - mixin: function mixin(object) { - object['on'] = this['on']; - object['off'] = this['off']; - object['trigger'] = this['trigger']; - object._promiseCallbacks = undefined; - return object; - }, - - /** - Registers a callback to be executed when `eventName` is triggered - ```javascript - object.on('event', function(eventInfo){ - // handle the event - }); - object.trigger('event'); - ``` - @method on - @for RSVP.EventTarget - @private - @param {String} eventName name of the event to listen for - @param {Function} callback function to be called when the event is triggered. - */ - on: function on(eventName, callback) { - if (typeof callback !== 'function') { - throw new TypeError('Callback must be a function'); - } - - var allCallbacks = callbacksFor(this), - callbacks = undefined; - - callbacks = allCallbacks[eventName]; - - if (!callbacks) { - callbacks = allCallbacks[eventName] = []; - } - - if (indexOf(callbacks, callback) === -1) { - callbacks.push(callback); - } - }, - - /** - You can use `off` to stop firing a particular callback for an event: - ```javascript - function doStuff() { // do stuff! } - object.on('stuff', doStuff); - object.trigger('stuff'); // doStuff will be called - // Unregister ONLY the doStuff callback - object.off('stuff', doStuff); - object.trigger('stuff'); // doStuff will NOT be called - ``` - If you don't pass a `callback` argument to `off`, ALL callbacks for the - event will not be executed when the event fires. For example: - ```javascript - let callback1 = function(){}; - let callback2 = function(){}; - object.on('stuff', callback1); - object.on('stuff', callback2); - object.trigger('stuff'); // callback1 and callback2 will be executed. - object.off('stuff'); - object.trigger('stuff'); // callback1 and callback2 will not be executed! - ``` - @method off - @for RSVP.EventTarget - @private - @param {String} eventName event to stop listening to - @param {Function} callback optional argument. If given, only the function - given will be removed from the event's callback queue. If no `callback` - argument is given, all callbacks will be removed from the event's callback - queue. - */ - off: function off(eventName, callback) { - var allCallbacks = callbacksFor(this), - callbacks = undefined, - index = undefined; - - if (!callback) { - allCallbacks[eventName] = []; - return; - } - - callbacks = allCallbacks[eventName]; - - index = indexOf(callbacks, callback); - - if (index !== -1) { - callbacks.splice(index, 1); - } - }, - - /** - Use `trigger` to fire custom events. For example: - ```javascript - object.on('foo', function(){ - console.log('foo event happened!'); - }); - object.trigger('foo'); - // 'foo event happened!' logged to the console - ``` - You can also pass a value as a second argument to `trigger` that will be - passed as an argument to all event listeners for the event: - ```javascript - object.on('foo', function(value){ - console.log(value.name); - }); - object.trigger('foo', { name: 'bar' }); - // 'bar' logged to the console - ``` - @method trigger - @for RSVP.EventTarget - @private - @param {String} eventName name of the event to be triggered - @param {*} options optional value to be passed to any event handlers for - the given `eventName` - */ - trigger: function trigger(eventName, options, label) { - var allCallbacks = callbacksFor(this), - callbacks = undefined, - callback = undefined; - - if (callbacks = allCallbacks[eventName]) { - // Don't cache the callbacks.length since it may grow - for (var i = 0; i < callbacks.length; i++) { - callback = callbacks[i]; - - callback(options, label); - } - } - } -}; - -var config = { - instrument: false -}; - -EventTarget['mixin'](config); - -function configure(name, value) { - if (name === 'onerror') { - // handle for legacy users that expect the actual - // error to be passed to their function added via - // `RSVP.configure('onerror', someFunctionHere);` - config['on']('error', value); - return; - } - - if (arguments.length === 2) { - config[name] = value; - } else { - return config[name]; - } -} - -function objectOrFunction(x) { - return typeof x === 'function' || typeof x === 'object' && x !== null; -} - -function isFunction(x) { - return typeof x === 'function'; -} - -function isMaybeThenable(x) { - return typeof x === 'object' && x !== null; -} - -var _isArray = undefined; -if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; -} else { - _isArray = Array.isArray; -} - -var isArray = _isArray; - -// Date.now is not available in browsers < IE9 -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility -var now = Date.now || function () { - return new Date().getTime(); -}; - -function F() {} - -var o_create = Object.create || function (o) { - if (arguments.length > 1) { - throw new Error('Second argument not supported'); - } - if (typeof o !== 'object') { - throw new TypeError('Argument must be an object'); - } - F.prototype = o; - return new F(); -}; - -var queue = []; - -function scheduleFlush() { - setTimeout(function () { - for (var i = 0; i < queue.length; i++) { - var entry = queue[i]; - - var payload = entry.payload; - - payload.guid = payload.key + payload.id; - payload.childGuid = payload.key + payload.childId; - if (payload.error) { - payload.stack = payload.error.stack; - } - - config['trigger'](entry.name, entry.payload); - } - queue.length = 0; - }, 50); -} -function instrument(eventName, promise, child) { - if (1 === queue.push({ - name: eventName, - payload: { - key: promise._guidKey, - id: promise._id, - eventName: eventName, - detail: promise._result, - childId: child && child._id, - label: promise._label, - timeStamp: now(), - error: config["instrument-with-stack"] ? new Error(promise._label) : null - } })) { - scheduleFlush(); - } -} - -/** - `RSVP.Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: - - ```javascript - let promise = new RSVP.Promise(function(resolve, reject){ - resolve(1); - }); - - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - let promise = RSVP.Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {*} object value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` -*/ -function resolve$1(object, label) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor(noop, label); - resolve(promise, object); - return promise; -} - -function withOwnPromise() { - return new TypeError('A promises callback cannot return that same promise.'); -} - -function noop() {} - -var PENDING = void 0; -var FULFILLED = 1; -var REJECTED = 2; - -var GET_THEN_ERROR = new ErrorObject(); - -function getThen(promise) { - try { - return promise.then; - } catch (error) { - GET_THEN_ERROR.error = error; - return GET_THEN_ERROR; - } -} - -function tryThen(then, value, fulfillmentHandler, rejectionHandler) { - try { - then.call(value, fulfillmentHandler, rejectionHandler); - } catch (e) { - return e; - } -} - -function handleForeignThenable(promise, thenable, then) { - config.async(function (promise) { - var sealed = false; - var error = tryThen(then, thenable, function (value) { - if (sealed) { - return; - } - sealed = true; - if (thenable !== value) { - resolve(promise, value, undefined); - } else { - fulfill(promise, value); - } - }, function (reason) { - if (sealed) { - return; - } - sealed = true; - - reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - reject(promise, error); - } - }, promise); -} - -function handleOwnThenable(promise, thenable) { - if (thenable._state === FULFILLED) { - fulfill(promise, thenable._result); - } else if (thenable._state === REJECTED) { - thenable._onError = null; - reject(promise, thenable._result); - } else { - subscribe(thenable, undefined, function (value) { - if (thenable !== value) { - resolve(promise, value, undefined); - } else { - fulfill(promise, value); - } - }, function (reason) { - return reject(promise, reason); - }); - } -} - -function handleMaybeThenable(promise, maybeThenable, then$$) { - if (maybeThenable.constructor === promise.constructor && then$$ === then && promise.constructor.resolve === resolve$1) { - handleOwnThenable(promise, maybeThenable); - } else { - if (then$$ === GET_THEN_ERROR) { - reject(promise, GET_THEN_ERROR.error); - } else if (then$$ === undefined) { - fulfill(promise, maybeThenable); - } else if (isFunction(then$$)) { - handleForeignThenable(promise, maybeThenable, then$$); - } else { - fulfill(promise, maybeThenable); - } - } -} - -function resolve(promise, value) { - if (promise === value) { - fulfill(promise, value); - } else if (objectOrFunction(value)) { - handleMaybeThenable(promise, value, getThen(value)); - } else { - fulfill(promise, value); - } -} - -function publishRejection(promise) { - if (promise._onError) { - promise._onError(promise._result); - } - - publish(promise); -} - -function fulfill(promise, value) { - if (promise._state !== PENDING) { - return; - } - - promise._result = value; - promise._state = FULFILLED; - - if (promise._subscribers.length === 0) { - if (config.instrument) { - instrument('fulfilled', promise); - } - } else { - config.async(publish, promise); - } -} - -function reject(promise, reason) { - if (promise._state !== PENDING) { - return; - } - promise._state = REJECTED; - promise._result = reason; - config.async(publishRejection, promise); -} - -function subscribe(parent, child, onFulfillment, onRejection) { - var subscribers = parent._subscribers; - var length = subscribers.length; - - parent._onError = null; - - subscribers[length] = child; - subscribers[length + FULFILLED] = onFulfillment; - subscribers[length + REJECTED] = onRejection; - - if (length === 0 && parent._state) { - config.async(publish, parent); - } -} - -function publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; - - if (config.instrument) { - instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); - } - - if (subscribers.length === 0) { - return; - } - - var child = undefined, - callback = undefined, - detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - invokeCallback(settled, child, callback, detail); - } else { - callback(detail); - } - } - - promise._subscribers.length = 0; -} - -function ErrorObject() { - this.error = null; -} - -var TRY_CATCH_ERROR = new ErrorObject(); - -function tryCatch(callback, detail) { - try { - return callback(detail); - } catch (e) { - TRY_CATCH_ERROR.error = e; - return TRY_CATCH_ERROR; - } -} - -function invokeCallback(settled, promise, callback, detail) { - var hasCallback = isFunction(callback), - value = undefined, - error = undefined, - succeeded = undefined, - failed = undefined; - - if (hasCallback) { - value = tryCatch(callback, detail); - - if (value === TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value = null; - } else { - succeeded = true; - } - - if (promise === value) { - reject(promise, withOwnPromise()); - return; - } - } else { - value = detail; - succeeded = true; - } - - if (promise._state !== PENDING) { - // noop - } else if (hasCallback && succeeded) { - resolve(promise, value); - } else if (failed) { - reject(promise, error); - } else if (settled === FULFILLED) { - fulfill(promise, value); - } else if (settled === REJECTED) { - reject(promise, value); - } -} - -function initializePromise(promise, resolver) { - var resolved = false; - try { - resolver(function (value) { - if (resolved) { - return; - } - resolved = true; - resolve(promise, value); - }, function (reason) { - if (resolved) { - return; - } - resolved = true; - reject(promise, reason); - }); - } catch (e) { - reject(promise, e); - } -} - -function then(onFulfillment, onRejection, label) { - var _arguments = arguments; - - var parent = this; - var state = parent._state; - - if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { - config.instrument && instrument('chained', parent, parent); - return parent; - } - - parent._onError = null; - - var child = new parent.constructor(noop, label); - var result = parent._result; - - config.instrument && instrument('chained', parent, child); - - if (state) { - (function () { - var callback = _arguments[state - 1]; - config.async(function () { - return invokeCallback(state, child, callback, result); - }); - })(); - } else { - subscribe(parent, child, onFulfillment, onRejection); - } - - return child; -} - -function makeSettledResult(state, position, value) { - if (state === FULFILLED) { - return { - state: 'fulfilled', - value: value - }; - } else { - return { - state: 'rejected', - reason: value - }; - } -} - -function Enumerator(Constructor, input, abortOnReject, label) { - this._instanceConstructor = Constructor; - this.promise = new Constructor(noop, label); - this._abortOnReject = abortOnReject; - - if (this._validateInput(input)) { - this._input = input; - this.length = input.length; - this._remaining = input.length; - - this._init(); - - if (this.length === 0) { - fulfill(this.promise, this._result); - } else { - this.length = this.length || 0; - this._enumerate(); - if (this._remaining === 0) { - fulfill(this.promise, this._result); - } - } - } else { - reject(this.promise, this._validationError()); - } -} - -Enumerator.prototype._validateInput = function (input) { - return isArray(input); -}; - -Enumerator.prototype._validationError = function () { - return new Error('Array Methods must be provided an Array'); -}; - -Enumerator.prototype._init = function () { - this._result = new Array(this.length); -}; - -Enumerator.prototype._enumerate = function () { - var length = this.length; - var promise = this.promise; - var input = this._input; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - this._eachEntry(input[i], i); - } -}; - -Enumerator.prototype._settleMaybeThenable = function (entry, i) { - var c = this._instanceConstructor; - var resolve = c.resolve; - - if (resolve === resolve$1) { - var then$$ = getThen(entry); - - if (then$$ === then && entry._state !== PENDING) { - entry._onError = null; - this._settledAt(entry._state, i, entry._result); - } else if (typeof then$$ !== 'function') { - this._remaining--; - this._result[i] = this._makeResult(FULFILLED, i, entry); - } else if (c === Promise) { - var promise = new c(noop); - handleMaybeThenable(promise, entry, then$$); - this._willSettleAt(promise, i); - } else { - this._willSettleAt(new c(function (resolve) { - return resolve(entry); - }), i); - } - } else { - this._willSettleAt(resolve(entry), i); - } -}; - -Enumerator.prototype._eachEntry = function (entry, i) { - if (isMaybeThenable(entry)) { - this._settleMaybeThenable(entry, i); - } else { - this._remaining--; - this._result[i] = this._makeResult(FULFILLED, i, entry); - } -}; - -Enumerator.prototype._settledAt = function (state, i, value) { - var promise = this.promise; - - if (promise._state === PENDING) { - this._remaining--; - - if (this._abortOnReject && state === REJECTED) { - reject(promise, value); - } else { - this._result[i] = this._makeResult(state, i, value); - } - } - - if (this._remaining === 0) { - fulfill(promise, this._result); - } -}; - -Enumerator.prototype._makeResult = function (state, i, value) { - return value; -}; - -Enumerator.prototype._willSettleAt = function (promise, i) { - var enumerator = this; - - subscribe(promise, undefined, function (value) { - return enumerator._settledAt(FULFILLED, i, value); - }, function (reason) { - return enumerator._settledAt(REJECTED, i, reason); - }); -}; - -/** - `RSVP.Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. - - Example: - - ```javascript - let promise1 = RSVP.resolve(1); - let promise2 = RSVP.resolve(2); - let promise3 = RSVP.resolve(3); - let promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` - - If any of the `promises` given to `RSVP.all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: - - Example: - - ```javascript - let promise1 = RSVP.resolve(1); - let promise2 = RSVP.reject(new Error("2")); - let promise3 = RSVP.reject(new Error("3")); - let promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` - - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static -*/ -function all(entries, label) { - return new Enumerator(this, entries, true, /* abort on reject */label).promise; -} - -/** - `RSVP.Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. - - Example: - - ```javascript - let promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - let promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` - - `RSVP.Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: - - ```javascript - let promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - let promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` - - An example real-world use case is implementing timeouts: - - ```javascript - RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) - ``` - - @method race - @static - @param {Array} entries array of promises to observe - @param {String} label optional string for describing the promise returned. - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. -*/ -function race(entries, label) { - /*jshint validthis:true */ - var Constructor = this; - - var promise = new Constructor(noop, label); - - if (!isArray(entries)) { - reject(promise, new TypeError('You must pass an array to race.')); - return promise; - } - - for (var i = 0; promise._state === PENDING && i < entries.length; i++) { - subscribe(Constructor.resolve(entries[i]), undefined, function (value) { - return resolve(promise, value); - }, function (reason) { - return reject(promise, reason); - }); - } - - return promise; -} - -/** - `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - let promise = new RSVP.Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - let promise = RSVP.Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {*} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. -*/ -function reject$1(reason, label) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(noop, label); - reject(promise, reason); - return promise; -} - -var guidKey = 'rsvp_' + now() + '-'; -var counter = 0; - -function needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); -} - -function needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); -} - -/** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise’s eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - let promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - let xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; - }); - } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class RSVP.Promise - @param {function} resolver - @param {String} label optional string for labeling the promise. - Useful for tooling. - @constructor -*/ -function Promise(resolver, label) { - this._id = counter++; - this._label = label; - this._state = undefined; - this._result = undefined; - this._subscribers = []; - - config.instrument && instrument('created', this); - - if (noop !== resolver) { - typeof resolver !== 'function' && needsResolver(); - this instanceof Promise ? initializePromise(this, resolver) : needsNew(); - } -} - -Promise.cast = resolve$1; // deprecated -Promise.all = all; -Promise.race = race; -Promise.resolve = resolve$1; -Promise.reject = reject$1; - -Promise.prototype = { - constructor: Promise, - - _guidKey: guidKey, - - _onError: function _onError(reason) { - var promise = this; - config.after(function () { - if (promise._onError) { - config['trigger']('error', reason, promise._label); - } - }); - }, - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - - Chaining - -------- - - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we\'re unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we\'re unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - - Assimilation - ------------ - - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - - If the assimliated promise rejects, then the downstream promise will also reject. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - - Simple Example - -------------- - - Synchronous Example - - ```javascript - let result; - - try { - result = findResult(); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success - } - }); - ``` - - Promise Example; - - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` - - Advanced Example - -------------- - - Synchronous Example - - ```javascript - let author, books; - - try { - author = findAuthor(); - books = findBooksByAuthor(author); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - - function foundBooks(books) { - - } - - function failure(reason) { - - } - - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { - try { - findBoooksByAuthor(author, function(books, err) { - if (err) { - failure(err); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } - } - }); - } catch(error) { - failure(err); - } - // success - } - }); - ``` - - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfillment - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - then: then, - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - - ```js - function findAuthor(){ - throw new Error('couldn\'t find that author'); - } - - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - - @method catch - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - 'catch': function _catch(onRejection, label) { - return this.then(undefined, onRejection, label); - }, - - /** - `finally` will be invoked regardless of the promise's fate just as native - try/catch/finally behaves - - Synchronous example: - - ```js - findAuthor() { - if (Math.random() > 0.5) { - throw new Error(); - } - return new Author(); - } - - try { - return findAuthor(); // succeed or fail - } catch(error) { - return findOtherAuther(); - } finally { - // always runs - // doesn't affect the return value - } - ``` - - Asynchronous example: - - ```js - findAuthor().catch(function(reason){ - return findOtherAuther(); - }).finally(function(){ - // author was either found, or not - }); - ``` - - @method finally - @param {Function} callback - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - 'finally': function _finally(callback, label) { - var promise = this; - var constructor = promise.constructor; - - return promise.then(function (value) { - return constructor.resolve(callback()).then(function () { - return value; - }); - }, function (reason) { - return constructor.resolve(callback()).then(function () { - throw reason; - }); - }, label); - } -}; - -function Result() { - this.value = undefined; -} - -var ERROR = new Result(); -var GET_THEN_ERROR$1 = new Result(); - -function getThen$1(obj) { - try { - return obj.then; - } catch (error) { - ERROR.value = error; - return ERROR; - } -} - -function tryApply(f, s, a) { - try { - f.apply(s, a); - } catch (error) { - ERROR.value = error; - return ERROR; - } -} - -function makeObject(_, argumentNames) { - var obj = {}; - var length = _.length; - var args = new Array(length); - - for (var x = 0; x < length; x++) { - args[x] = _[x]; - } - - for (var i = 0; i < argumentNames.length; i++) { - var _name = argumentNames[i]; - obj[_name] = args[i + 1]; - } - - return obj; -} - -function arrayResult(_) { - var length = _.length; - var args = new Array(length - 1); - - for (var i = 1; i < length; i++) { - args[i - 1] = _[i]; - } - - return args; -} - -function wrapThenable(_then, promise) { - return { - then: function then(onFulFillment, onRejection) { - return _then.call(promise, onFulFillment, onRejection); - } - }; -} - -/** - `RSVP.denodeify` takes a 'node-style' function and returns a function that - will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the - browser when you'd prefer to use promises over using callbacks. For example, - `denodeify` transforms the following: - - ```javascript - let fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) return handleError(err); - handleData(data); - }); - ``` - - into: - - ```javascript - let fs = require('fs'); - let readFile = RSVP.denodeify(fs.readFile); - - readFile('myfile.txt').then(handleData, handleError); - ``` - - If the node function has multiple success parameters, then `denodeify` - just returns the first one: - - ```javascript - let request = RSVP.denodeify(require('request')); - - request('http://example.com').then(function(res) { - // ... - }); - ``` - - However, if you need all success parameters, setting `denodeify`'s - second parameter to `true` causes it to return all success parameters - as an array: - - ```javascript - let request = RSVP.denodeify(require('request'), true); - - request('http://example.com').then(function(result) { - // result[0] -> res - // result[1] -> body - }); - ``` - - Or if you pass it an array with names it returns the parameters as a hash: - - ```javascript - let request = RSVP.denodeify(require('request'), ['res', 'body']); - - request('http://example.com').then(function(result) { - // result.res - // result.body - }); - ``` - - Sometimes you need to retain the `this`: - - ```javascript - let app = require('express')(); - let render = RSVP.denodeify(app.render.bind(app)); - ``` - - The denodified function inherits from the original function. It works in all - environments, except IE 10 and below. Consequently all properties of the original - function are available to you. However, any properties you change on the - denodeified function won't be changed on the original function. Example: - - ```javascript - let request = RSVP.denodeify(require('request')), - cookieJar = request.jar(); // <- Inheritance is used here - - request('http://example.com', {jar: cookieJar}).then(function(res) { - // cookieJar.cookies holds now the cookies returned by example.com - }); - ``` - - Using `denodeify` makes it easier to compose asynchronous operations instead - of using callbacks. For example, instead of: - - ```javascript - let fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) { ... } // Handle error - fs.writeFile('myfile2.txt', data, function(err){ - if (err) { ... } // Handle error - console.log('done') - }); - }); - ``` - - you can chain the operations together using `then` from the returned promise: - - ```javascript - let fs = require('fs'); - let readFile = RSVP.denodeify(fs.readFile); - let writeFile = RSVP.denodeify(fs.writeFile); - - readFile('myfile.txt').then(function(data){ - return writeFile('myfile2.txt', data); - }).then(function(){ - console.log('done') - }).catch(function(error){ - // Handle error - }); - ``` - - @method denodeify - @static - @for RSVP - @param {Function} nodeFunc a 'node-style' function that takes a callback as - its last argument. The callback expects an error to be passed as its first - argument (if an error occurred, otherwise null), and the value from the - operation as its second argument ('function(err, value){ }'). - @param {Boolean|Array} [options] An optional paramter that if set - to `true` causes the promise to fulfill with the callback's success arguments - as an array. This is useful if the node function has multiple success - paramters. If you set this paramter to an array with names, the promise will - fulfill with a hash with these names as keys and the success parameters as - values. - @return {Function} a function that wraps `nodeFunc` to return an - `RSVP.Promise` - @static -*/ -function denodeify(nodeFunc, options) { - var fn = function fn() { - var self = this; - var l = arguments.length; - var args = new Array(l + 1); - var promiseInput = false; - - for (var i = 0; i < l; ++i) { - var arg = arguments[i]; - - if (!promiseInput) { - // TODO: clean this up - promiseInput = needsPromiseInput(arg); - if (promiseInput === GET_THEN_ERROR$1) { - var p = new Promise(noop); - reject(p, GET_THEN_ERROR$1.value); - return p; - } else if (promiseInput && promiseInput !== true) { - arg = wrapThenable(promiseInput, arg); - } - } - args[i] = arg; - } - - var promise = new Promise(noop); - - args[l] = function (err, val) { - if (err) reject(promise, err);else if (options === undefined) resolve(promise, val);else if (options === true) resolve(promise, arrayResult(arguments));else if (isArray(options)) resolve(promise, makeObject(arguments, options));else resolve(promise, val); - }; - - if (promiseInput) { - return handlePromiseInput(promise, args, nodeFunc, self); - } else { - return handleValueInput(promise, args, nodeFunc, self); - } - }; - - fn.__proto__ = nodeFunc; - - return fn; -} - -function handleValueInput(promise, args, nodeFunc, self) { - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); - } - return promise; -} - -function handlePromiseInput(promise, args, nodeFunc, self) { - return Promise.all(args).then(function (args) { - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); - } - return promise; - }); -} - -function needsPromiseInput(arg) { - if (arg && typeof arg === 'object') { - if (arg.constructor === Promise) { - return true; - } else { - return getThen$1(arg); - } - } else { - return false; - } -} - -/** - This is a convenient alias for `RSVP.Promise.all`. - - @method all - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. -*/ -function all$1(array, label) { - return Promise.all(array, label); -} - -function AllSettled(Constructor, entries, label) { - this._superConstructor(Constructor, entries, false, /* don't abort on reject */label); -} - -AllSettled.prototype = o_create(Enumerator.prototype); -AllSettled.prototype._superConstructor = Enumerator; -AllSettled.prototype._makeResult = makeSettledResult; -AllSettled.prototype._validationError = function () { - return new Error('allSettled must be called with an array'); -}; - -/** - `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing - a fail-fast method, it waits until all the promises have returned and - shows you all the results. This is useful if you want to handle multiple - promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled. The return promise is fulfilled with an array of the states of - the promises passed into the `promises` array argument. - - Each state object will either indicate fulfillment or rejection, and - provide the corresponding value or reason. The states will take one of - the following formats: - - ```javascript - { state: 'fulfilled', value: value } - or - { state: 'rejected', reason: reason } - ``` - - Example: - - ```javascript - let promise1 = RSVP.Promise.resolve(1); - let promise2 = RSVP.Promise.reject(new Error('2')); - let promise3 = RSVP.Promise.reject(new Error('3')); - let promises = [ promise1, promise2, promise3 ]; - - RSVP.allSettled(promises).then(function(array){ - // array == [ - // { state: 'fulfilled', value: 1 }, - // { state: 'rejected', reason: Error }, - // { state: 'rejected', reason: Error } - // ] - // Note that for the second item, reason.message will be '2', and for the - // third item, reason.message will be '3'. - }, function(error) { - // Not run. (This block would only be called if allSettled had failed, - // for instance if passed an incorrect argument type.) - }); - ``` - - @method allSettled - @static - @for RSVP - @param {Array} entries - @param {String} label - optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with an array of the settled - states of the constituent promises. -*/ -function allSettled(entries, label) { - return new AllSettled(Promise, entries, label).promise; -} - -/** - This is a convenient alias for `RSVP.Promise.race`. - - @method race - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. - */ -function race$1(array, label) { - return Promise.race(array, label); -} - -function PromiseHash(Constructor, object, label) { - this._superConstructor(Constructor, object, true, label); -} - -PromiseHash.prototype = o_create(Enumerator.prototype); -PromiseHash.prototype._superConstructor = Enumerator; -PromiseHash.prototype._init = function () { - this._result = {}; -}; - -PromiseHash.prototype._validateInput = function (input) { - return input && typeof input === 'object'; -}; - -PromiseHash.prototype._validationError = function () { - return new Error('Promise.hash must be called with an object'); -}; - -PromiseHash.prototype._enumerate = function () { - var enumerator = this; - var promise = enumerator.promise; - var input = enumerator._input; - var results = []; - - for (var key in input) { - if (promise._state === PENDING && Object.prototype.hasOwnProperty.call(input, key)) { - results.push({ - position: key, - entry: input[key] - }); - } - } - - var length = results.length; - enumerator._remaining = length; - var result = undefined; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - result = results[i]; - enumerator._eachEntry(result.entry, result.position); - } -}; - -/** - `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array - for its `promises` argument. - - Returns a promise that is fulfilled when all the given promises have been - fulfilled, or rejected if any of them become rejected. The returned promise - is fulfilled with a hash that has the same key names as the `promises` object - argument. If any of the values in the object are not promises, they will - simply be copied over to the fulfilled object. - - Example: - - ```javascript - let promises = { - myPromise: RSVP.resolve(1), - yourPromise: RSVP.resolve(2), - theirPromise: RSVP.resolve(3), - notAPromise: 4 - }; - - RSVP.hash(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: 1, - // yourPromise: 2, - // theirPromise: 3, - // notAPromise: 4 - // } - }); - ```` - - If any of the `promises` given to `RSVP.hash` are rejected, the first promise - that is rejected will be given as the reason to the rejection handler. - - Example: - - ```javascript - let promises = { - myPromise: RSVP.resolve(1), - rejectedPromise: RSVP.reject(new Error('rejectedPromise')), - anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')), - }; - - RSVP.hash(promises).then(function(hash){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === 'rejectedPromise' - }); - ``` - - An important note: `RSVP.hash` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hash` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.resolve('Example'); - } - - MyConstructor.prototype = { - protoProperty: RSVP.resolve('Proto Property') - }; - - let myObject = new MyConstructor(); - - RSVP.hash(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: 'Example' - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hash - @static - @for RSVP - @param {Object} object - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all properties of `promises` - have been fulfilled, or rejected if any of them become rejected. -*/ -function hash(object, label) { - return new PromiseHash(Promise, object, label).promise; -} - -function HashSettled(Constructor, object, label) { - this._superConstructor(Constructor, object, false, label); -} - -HashSettled.prototype = o_create(PromiseHash.prototype); -HashSettled.prototype._superConstructor = Enumerator; -HashSettled.prototype._makeResult = makeSettledResult; - -HashSettled.prototype._validationError = function () { - return new Error('hashSettled must be called with an object'); -}; - -/** - `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object - instead of an array for its `promises` argument. - - Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method, - but like `RSVP.allSettled`, `hashSettled` waits until all the - constituent promises have returned and then shows you all the results - with their states and values/reasons. This is useful if you want to - handle multiple promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled, or rejected if the passed parameters are invalid. - - The returned promise is fulfilled with a hash that has the same key names as - the `promises` object argument. If any of the values in the object are not - promises, they will be copied over to the fulfilled object and marked with state - 'fulfilled'. - - Example: - - ```javascript - let promises = { - myPromise: RSVP.Promise.resolve(1), - yourPromise: RSVP.Promise.resolve(2), - theirPromise: RSVP.Promise.resolve(3), - notAPromise: 4 - }; - - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // yourPromise: { state: 'fulfilled', value: 2 }, - // theirPromise: { state: 'fulfilled', value: 3 }, - // notAPromise: { state: 'fulfilled', value: 4 } - // } - }); - ``` - - If any of the `promises` given to `RSVP.hash` are rejected, the state will - be set to 'rejected' and the reason for rejection provided. - - Example: - - ```javascript - let promises = { - myPromise: RSVP.Promise.resolve(1), - rejectedPromise: RSVP.Promise.reject(new Error('rejection')), - anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')), - }; - - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // rejectedPromise: { state: 'rejected', reason: Error }, - // anotherRejectedPromise: { state: 'rejected', reason: Error }, - // } - // Note that for rejectedPromise, reason.message == 'rejection', - // and for anotherRejectedPromise, reason.message == 'more rejection'. - }); - ``` - - An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.Promise.resolve('Example'); - } - - MyConstructor.prototype = { - protoProperty: RSVP.Promise.resolve('Proto Property') - }; - - let myObject = new MyConstructor(); - - RSVP.hashSettled(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: { state: 'fulfilled', value: 'Example' } - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hashSettled - @for RSVP - @param {Object} object - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when when all properties of `promises` - have been settled. - @static -*/ -function hashSettled(object, label) { - return new HashSettled(Promise, object, label).promise; -} - -function rethrow(reason) { - setTimeout(function () { - throw reason; - }); - throw reason; -} - -/** - `RSVP.defer` returns an object similar to jQuery's `$.Deferred`. - `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s - interface. New code should use the `RSVP.Promise` constructor instead. - - The object returned from `RSVP.defer` is a plain object with three properties: - - * promise - an `RSVP.Promise`. - * reject - a function that causes the `promise` property on this object to - become rejected - * resolve - a function that causes the `promise` property on this object to - become fulfilled. - - Example: - - ```javascript - let deferred = RSVP.defer(); - - deferred.resolve("Success!"); - - deferred.promise.then(function(value){ - // value here is "Success!" - }); - ``` - - @method defer - @static - @for RSVP - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Object} - */ -function defer(label) { - var deferred = { resolve: undefined, reject: undefined }; - - deferred.promise = new Promise(function (resolve, reject) { - deferred.resolve = resolve; - deferred.reject = reject; - }, label); - - return deferred; -} - -/** - `RSVP.map` is similar to JavaScript's native `map` method, except that it - waits for all promises to become fulfilled before running the `mapFn` on - each item in given to `promises`. `RSVP.map` returns a promise that will - become fulfilled with the result of running `mapFn` on the values the promises - become fulfilled with. - - For example: - - ```javascript - - let promise1 = RSVP.resolve(1); - let promise2 = RSVP.resolve(2); - let promise3 = RSVP.resolve(3); - let promises = [ promise1, promise2, promise3 ]; - - let mapFn = function(item){ - return item + 1; - }; - - RSVP.map(promises, mapFn).then(function(result){ - // result is [ 2, 3, 4 ] - }); - ``` - - If any of the `promises` given to `RSVP.map` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - let promise1 = RSVP.resolve(1); - let promise2 = RSVP.reject(new Error('2')); - let promise3 = RSVP.reject(new Error('3')); - let promises = [ promise1, promise2, promise3 ]; - - let mapFn = function(item){ - return item + 1; - }; - - RSVP.map(promises, mapFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.map` will also wait if a promise is returned from `mapFn`. For example, - say you want to get all comments from a set of blog posts, but you need - the blog posts first because they contain a url to those comments. - - ```javscript - - let mapFn = function(blogPost){ - // getComments does some ajax and returns an RSVP.Promise that is fulfilled - // with some comments data - return getComments(blogPost.comments_url); - }; - - // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled - // with some blog post data - RSVP.map(getBlogPosts(), mapFn).then(function(comments){ - // comments is the result of asking the server for the comments - // of all blog posts returned from getBlogPosts() - }); - ``` - - @method map - @static - @for RSVP - @param {Array} promises - @param {Function} mapFn function to be called on each fulfilled promise. - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with the result of calling - `mapFn` on each fulfilled promise or value when they become fulfilled. - The promise will be rejected if any of the given `promises` become rejected. - @static -*/ -function map(promises, mapFn, label) { - return Promise.all(promises, label).then(function (values) { - if (!isFunction(mapFn)) { - throw new TypeError("You must pass a function as map's second argument."); - } - - var length = values.length; - var results = new Array(length); - - for (var i = 0; i < length; i++) { - results[i] = mapFn(values[i]); - } - - return Promise.all(results, label); - }); -} - -/** - This is a convenient alias for `RSVP.Promise.resolve`. - - @method resolve - @static - @for RSVP - @param {*} value value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` -*/ -function resolve$2(value, label) { - return Promise.resolve(value, label); -} - -/** - This is a convenient alias for `RSVP.Promise.reject`. - - @method reject - @static - @for RSVP - @param {*} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. -*/ -function reject$2(reason, label) { - return Promise.reject(reason, label); -} - -/** - `RSVP.filter` is similar to JavaScript's native `filter` method, except that it - waits for all promises to become fulfilled before running the `filterFn` on - each item in given to `promises`. `RSVP.filter` returns a promise that will - become fulfilled with the result of running `filterFn` on the values the - promises become fulfilled with. - - For example: - - ```javascript - - let promise1 = RSVP.resolve(1); - let promise2 = RSVP.resolve(2); - let promise3 = RSVP.resolve(3); - - let promises = [promise1, promise2, promise3]; - - let filterFn = function(item){ - return item > 1; - }; - - RSVP.filter(promises, filterFn).then(function(result){ - // result is [ 2, 3 ] - }); - ``` - - If any of the `promises` given to `RSVP.filter` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - let promise1 = RSVP.resolve(1); - let promise2 = RSVP.reject(new Error('2')); - let promise3 = RSVP.reject(new Error('3')); - let promises = [ promise1, promise2, promise3 ]; - - let filterFn = function(item){ - return item > 1; - }; - - RSVP.filter(promises, filterFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.filter` will also wait for any promises returned from `filterFn`. - For instance, you may want to fetch a list of users then return a subset - of those users based on some asynchronous operation: - - ```javascript - - let alice = { name: 'alice' }; - let bob = { name: 'bob' }; - let users = [ alice, bob ]; - - let promises = users.map(function(user){ - return RSVP.resolve(user); - }); - - let filterFn = function(user){ - // Here, Alice has permissions to create a blog post, but Bob does not. - return getPrivilegesForUser(user).then(function(privs){ - return privs.can_create_blog_post === true; - }); - }; - RSVP.filter(promises, filterFn).then(function(users){ - // true, because the server told us only Alice can create a blog post. - users.length === 1; - // false, because Alice is the only user present in `users` - users[0] === bob; - }); - ``` - - @method filter - @static - @for RSVP - @param {Array} promises - @param {Function} filterFn - function to be called on each resolved value to - filter the final results. - @param {String} label optional string describing the promise. Useful for - tooling. - @return {Promise} -*/ - -function resolveAll(promises, label) { - return Promise.all(promises, label); -} - -function resolveSingle(promise, label) { - return Promise.resolve(promise, label).then(function (promises) { - return resolveAll(promises, label); - }); -} -function filter(promises, filterFn, label) { - var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label); - return promise.then(function (values) { - if (!isFunction(filterFn)) { - throw new TypeError("You must pass a function as filter's second argument."); - } - - var length = values.length; - var filtered = new Array(length); - - for (var i = 0; i < length; i++) { - filtered[i] = filterFn(values[i]); - } - - return resolveAll(filtered, label).then(function (filtered) { - var results = new Array(length); - var newLength = 0; - - for (var i = 0; i < length; i++) { - if (filtered[i]) { - results[newLength] = values[i]; - newLength++; - } - } - - results.length = newLength; - - return results; - }); - }); -} - -var len = 0; -var vertxNext = undefined; -function asap(callback, arg) { - queue$1[len] = callback; - queue$1[len + 1] = arg; - len += 2; - if (len === 2) { - // If len is 1, that means that we need to schedule an async flush. - // If additional callbacks are queued before the queue is flushed, they - // will be processed by this flush that we are scheduling. - scheduleFlush$1(); - } -} - -var browserWindow = typeof window !== 'undefined' ? window : undefined; -var browserGlobal = browserWindow || {}; -var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; -var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; - -// test for web worker but not in IE10 -var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; - -// node -function useNextTick() { - var nextTick = process.nextTick; - // node version 0.10.x displays a deprecation warning when nextTick is used recursively - // setImmediate should be used instead instead - var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/); - if (Array.isArray(version) && version[1] === '0' && version[2] === '10') { - nextTick = setImmediate; - } - return function () { - return nextTick(flush); - }; -} - -// vertx -function useVertxTimer() { - return function () { - return vertxNext(flush); - }; -} - -function useMutationObserver() { - var iterations = 0; - var observer = new BrowserMutationObserver(flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); - - return function () { - return node.data = iterations = ++iterations % 2; - }; -} - -// web worker -function useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - return function () { - return channel.port2.postMessage(0); - }; -} - -function useSetTimeout() { - return function () { - return setTimeout(flush, 1); - }; -} - -var queue$1 = new Array(1000); - -function flush() { - for (var i = 0; i < len; i += 2) { - var callback = queue$1[i]; - var arg = queue$1[i + 1]; - - callback(arg); - - queue$1[i] = undefined; - queue$1[i + 1] = undefined; - } - - len = 0; -} - -function attemptVertex() { - try { - var r = require; - var vertx = r('vertx'); - vertxNext = vertx.runOnLoop || vertx.runOnContext; - return useVertxTimer(); - } catch (e) { - return useSetTimeout(); - } -} - -var scheduleFlush$1 = undefined; -// Decide what async method to use to triggering processing of queued callbacks: -if (isNode) { - scheduleFlush$1 = useNextTick(); -} else if (BrowserMutationObserver) { - scheduleFlush$1 = useMutationObserver(); -} else if (isWorker) { - scheduleFlush$1 = useMessageChannel(); -} else if (browserWindow === undefined && typeof require === 'function') { - scheduleFlush$1 = attemptVertex(); -} else { - scheduleFlush$1 = useSetTimeout(); -} - -var platform = undefined; - -/* global self */ -if (typeof self === 'object') { - platform = self; - - /* global global */ -} else if (typeof global === 'object') { - platform = global; - } else { - throw new Error('no global: `self` or `global` found'); - } - -var _async$filter; - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -// defaults - -// the default export here is for backwards compat: -// https://github.com/tildeio/rsvp.js/issues/434 -config.async = asap; -config.after = function (cb) { - return setTimeout(cb, 0); -}; -var cast = resolve$2; - -var async = function async(callback, arg) { - return config.async(callback, arg); -}; - -function on() { - config['on'].apply(config, arguments); -} - -function off() { - config['off'].apply(config, arguments); -} - -// Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` -if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { - var callbacks = window['__PROMISE_INSTRUMENTATION__']; - configure('instrument', true); - for (var eventName in callbacks) { - if (callbacks.hasOwnProperty(eventName)) { - on(eventName, callbacks[eventName]); - } - } -}var rsvp = (_async$filter = { - cast: cast, - Promise: Promise, - EventTarget: EventTarget, - all: all$1, - allSettled: allSettled, - race: race$1, - hash: hash, - hashSettled: hashSettled, - rethrow: rethrow, - defer: defer, - denodeify: denodeify, - configure: configure, - on: on, - off: off, - resolve: resolve$2, - reject: reject$2, - map: map -}, _defineProperty(_async$filter, 'async', async), _defineProperty(_async$filter, 'filter', // babel seems to error if async isn't a computed prop here... -filter), _async$filter); - -exports['default'] = rsvp; -exports.cast = cast; -exports.Promise = Promise; -exports.EventTarget = EventTarget; -exports.all = all$1; -exports.allSettled = allSettled; -exports.race = race$1; -exports.hash = hash; -exports.hashSettled = hashSettled; -exports.rethrow = rethrow; -exports.defer = defer; -exports.denodeify = denodeify; -exports.configure = configure; -exports.on = on; -exports.off = off; -exports.resolve = resolve$2; -exports.reject = reject$2; -exports.map = map; -exports.async = async; -exports.filter = filter; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{"_process":4}],6:[function(require,module,exports){ -/*! - * URI.js - Mutating URLs - * Second Level Domain (SLD) Support - * - * Version: 1.18.1 - * - * Author: Rodney Rehm - * Web: http://medialize.github.io/URI.js/ - * - * Licensed under - * MIT License http://www.opensource.org/licenses/mit-license - * - */ - -(function (root, factory) { - 'use strict'; - // https://github.com/umdjs/umd/blob/master/returnExports.js - if (typeof exports === 'object') { - // Node - module.exports = factory(); - } else if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(factory); - } else { - // Browser globals (root is window) - root.SecondLevelDomains = factory(root); - } -}(this, function (root) { - 'use strict'; - - // save current SecondLevelDomains variable, if any - var _SecondLevelDomains = root && root.SecondLevelDomains; - - var SLD = { - // list of known Second Level Domains - // converted list of SLDs from https://github.com/gavingmiller/second-level-domains - // ---- - // publicsuffix.org is more current and actually used by a couple of browsers internally. - // downside is it also contains domains like "dyndns.org" - which is fine for the security - // issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js - // ---- - list: { - 'ac':' com gov mil net org ', - 'ae':' ac co gov mil name net org pro sch ', - 'af':' com edu gov net org ', - 'al':' com edu gov mil net org ', - 'ao':' co ed gv it og pb ', - 'ar':' com edu gob gov int mil net org tur ', - 'at':' ac co gv or ', - 'au':' asn com csiro edu gov id net org ', - 'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ', - 'bb':' biz co com edu gov info net org store tv ', - 'bh':' biz cc com edu gov info net org ', - 'bn':' com edu gov net org ', - 'bo':' com edu gob gov int mil net org tv ', - 'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ', - 'bs':' com edu gov net org ', - 'bz':' du et om ov rg ', - 'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ', - 'ck':' biz co edu gen gov info net org ', - 'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ', - 'co':' com edu gov mil net nom org ', - 'cr':' ac c co ed fi go or sa ', - 'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ', - 'do':' art com edu gob gov mil net org sld web ', - 'dz':' art asso com edu gov net org pol ', - 'ec':' com edu fin gov info med mil net org pro ', - 'eg':' com edu eun gov mil name net org sci ', - 'er':' com edu gov ind mil net org rochest w ', - 'es':' com edu gob nom org ', - 'et':' biz com edu gov info name net org ', - 'fj':' ac biz com info mil name net org pro ', - 'fk':' ac co gov net nom org ', - 'fr':' asso com f gouv nom prd presse tm ', - 'gg':' co net org ', - 'gh':' com edu gov mil org ', - 'gn':' ac com gov net org ', - 'gr':' com edu gov mil net org ', - 'gt':' com edu gob ind mil net org ', - 'gu':' com edu gov net org ', - 'hk':' com edu gov idv net org ', - 'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ', - 'id':' ac co go mil net or sch web ', - 'il':' ac co gov idf k12 muni net org ', - 'in':' ac co edu ernet firm gen gov i ind mil net nic org res ', - 'iq':' com edu gov i mil net org ', - 'ir':' ac co dnssec gov i id net org sch ', - 'it':' edu gov ', - 'je':' co net org ', - 'jo':' com edu gov mil name net org sch ', - 'jp':' ac ad co ed go gr lg ne or ', - 'ke':' ac co go info me mobi ne or sc ', - 'kh':' com edu gov mil net org per ', - 'ki':' biz com de edu gov info mob net org tel ', - 'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ', - 'kn':' edu gov net org ', - 'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ', - 'kw':' com edu gov net org ', - 'ky':' com edu gov net org ', - 'kz':' com edu gov mil net org ', - 'lb':' com edu gov net org ', - 'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ', - 'lr':' com edu gov net org ', - 'lv':' asn com conf edu gov id mil net org ', - 'ly':' com edu gov id med net org plc sch ', - 'ma':' ac co gov m net org press ', - 'mc':' asso tm ', - 'me':' ac co edu gov its net org priv ', - 'mg':' com edu gov mil nom org prd tm ', - 'mk':' com edu gov inf name net org pro ', - 'ml':' com edu gov net org presse ', - 'mn':' edu gov org ', - 'mo':' com edu gov net org ', - 'mt':' com edu gov net org ', - 'mv':' aero biz com coop edu gov info int mil museum name net org pro ', - 'mw':' ac co com coop edu gov int museum net org ', - 'mx':' com edu gob net org ', - 'my':' com edu gov mil name net org sch ', - 'nf':' arts com firm info net other per rec store web ', - 'ng':' biz com edu gov mil mobi name net org sch ', - 'ni':' ac co com edu gob mil net nom org ', - 'np':' com edu gov mil net org ', - 'nr':' biz com edu gov info net org ', - 'om':' ac biz co com edu gov med mil museum net org pro sch ', - 'pe':' com edu gob mil net nom org sld ', - 'ph':' com edu gov i mil net ngo org ', - 'pk':' biz com edu fam gob gok gon gop gos gov net org web ', - 'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ', - 'pr':' ac biz com edu est gov info isla name net org pro prof ', - 'ps':' com edu gov net org plo sec ', - 'pw':' belau co ed go ne or ', - 'ro':' arts com firm info nom nt org rec store tm www ', - 'rs':' ac co edu gov in org ', - 'sb':' com edu gov net org ', - 'sc':' com edu gov net org ', - 'sh':' co com edu gov net nom org ', - 'sl':' com edu gov net org ', - 'st':' co com consulado edu embaixada gov mil net org principe saotome store ', - 'sv':' com edu gob org red ', - 'sz':' ac co org ', - 'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ', - 'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ', - 'tw':' club com ebiz edu game gov idv mil net org ', - 'mu':' ac co com gov net or org ', - 'mz':' ac co edu gov org ', - 'na':' co com ', - 'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ', - 'pa':' abo ac com edu gob ing med net nom org sld ', - 'pt':' com edu gov int net nome org publ ', - 'py':' com edu gov mil net org ', - 'qa':' com edu gov mil net org ', - 're':' asso com nom ', - 'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ', - 'rw':' ac co com edu gouv gov int mil net ', - 'sa':' com edu gov med net org pub sch ', - 'sd':' com edu gov info med net org tv ', - 'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ', - 'sg':' com edu gov idn net org per ', - 'sn':' art com edu gouv org perso univ ', - 'sy':' com edu gov mil net news org ', - 'th':' ac co go in mi net or ', - 'tj':' ac biz co com edu go gov info int mil name net nic org test web ', - 'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ', - 'tz':' ac co go ne or ', - 'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ', - 'ug':' ac co go ne or org sc ', - 'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ', - 'us':' dni fed isa kids nsn ', - 'uy':' com edu gub mil net org ', - 've':' co com edu gob info mil net org web ', - 'vi':' co com k12 net org ', - 'vn':' ac biz com edu gov health info int name net org pro ', - 'ye':' co com gov ltd me net org plc ', - 'yu':' ac co edu gov org ', - 'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ', - 'zm':' ac co com edu gov net org sch ' - }, - // gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost - // in both performance and memory footprint. No initialization required. - // http://jsperf.com/uri-js-sld-regex-vs-binary-search/4 - // Following methods use lastIndexOf() rather than array.split() in order - // to avoid any memory allocations. - has: function(domain) { - var tldOffset = domain.lastIndexOf('.'); - if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { - return false; - } - var sldOffset = domain.lastIndexOf('.', tldOffset-1); - if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) { - return false; - } - var sldList = SLD.list[domain.slice(tldOffset+1)]; - if (!sldList) { - return false; - } - return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0; - }, - is: function(domain) { - var tldOffset = domain.lastIndexOf('.'); - if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { - return false; - } - var sldOffset = domain.lastIndexOf('.', tldOffset-1); - if (sldOffset >= 0) { - return false; - } - var sldList = SLD.list[domain.slice(tldOffset+1)]; - if (!sldList) { - return false; - } - return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0; - }, - get: function(domain) { - var tldOffset = domain.lastIndexOf('.'); - if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { - return null; - } - var sldOffset = domain.lastIndexOf('.', tldOffset-1); - if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) { - return null; - } - var sldList = SLD.list[domain.slice(tldOffset+1)]; - if (!sldList) { - return null; - } - if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) { - return null; - } - return domain.slice(sldOffset+1); - }, - noConflict: function(){ - if (root.SecondLevelDomains === this) { - root.SecondLevelDomains = _SecondLevelDomains; - } - return this; - } - }; - - return SLD; -})); - -},{}],7:[function(require,module,exports){ -/*! - * URI.js - Mutating URLs - * - * Version: 1.18.1 - * - * Author: Rodney Rehm - * Web: http://medialize.github.io/URI.js/ - * - * Licensed under - * MIT License http://www.opensource.org/licenses/mit-license - * - */ -(function (root, factory) { - 'use strict'; - // https://github.com/umdjs/umd/blob/master/returnExports.js - if (typeof exports === 'object') { - // Node - module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains')); - } else if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['./punycode', './IPv6', './SecondLevelDomains'], factory); - } else { - // Browser globals (root is window) - root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root); - } -}(this, function (punycode, IPv6, SLD, root) { - 'use strict'; - /*global location, escape, unescape */ - // FIXME: v2.0.0 renamce non-camelCase properties to uppercase - /*jshint camelcase: false */ - - // save current URI variable, if any - var _URI = root && root.URI; - - function URI(url, base) { - var _urlSupplied = arguments.length >= 1; - var _baseSupplied = arguments.length >= 2; - - // Allow instantiation without the 'new' keyword - if (!(this instanceof URI)) { - if (_urlSupplied) { - if (_baseSupplied) { - return new URI(url, base); - } - - return new URI(url); - } - - return new URI(); - } - - if (url === undefined) { - if (_urlSupplied) { - throw new TypeError('undefined is not a valid argument for URI'); - } - - if (typeof location !== 'undefined') { - url = location.href + ''; - } else { - url = ''; - } - } - - this.href(url); - - // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor - if (base !== undefined) { - return this.absoluteTo(base); - } - - return this; - } - - URI.version = '1.18.1'; - - var p = URI.prototype; - var hasOwn = Object.prototype.hasOwnProperty; - - function escapeRegEx(string) { - // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 - return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); - } - - function getType(value) { - // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value - if (value === undefined) { - return 'Undefined'; - } - - return String(Object.prototype.toString.call(value)).slice(8, -1); - } - - function isArray(obj) { - return getType(obj) === 'Array'; - } - - function filterArrayValues(data, value) { - var lookup = {}; - var i, length; - - if (getType(value) === 'RegExp') { - lookup = null; - } else if (isArray(value)) { - for (i = 0, length = value.length; i < length; i++) { - lookup[value[i]] = true; - } - } else { - lookup[value] = true; - } - - for (i = 0, length = data.length; i < length; i++) { - /*jshint laxbreak: true */ - var _match = lookup && lookup[data[i]] !== undefined - || !lookup && value.test(data[i]); - /*jshint laxbreak: false */ - if (_match) { - data.splice(i, 1); - length--; - i--; - } - } - - return data; - } - - function arrayContains(list, value) { - var i, length; - - // value may be string, number, array, regexp - if (isArray(value)) { - // Note: this can be optimized to O(n) (instead of current O(m * n)) - for (i = 0, length = value.length; i < length; i++) { - if (!arrayContains(list, value[i])) { - return false; - } - } - - return true; - } - - var _type = getType(value); - for (i = 0, length = list.length; i < length; i++) { - if (_type === 'RegExp') { - if (typeof list[i] === 'string' && list[i].match(value)) { - return true; - } - } else if (list[i] === value) { - return true; - } - } - - return false; - } - - function arraysEqual(one, two) { - if (!isArray(one) || !isArray(two)) { - return false; - } - - // arrays can't be equal if they have different amount of content - if (one.length !== two.length) { - return false; - } - - one.sort(); - two.sort(); - - for (var i = 0, l = one.length; i < l; i++) { - if (one[i] !== two[i]) { - return false; - } - } - - return true; - } - - function trimSlashes(text) { - var trim_expression = /^\/+|\/+$/g; - return text.replace(trim_expression, ''); - } - - URI._parts = function() { - return { - protocol: null, - username: null, - password: null, - hostname: null, - urn: null, - port: null, - path: null, - query: null, - fragment: null, - // state - duplicateQueryParameters: URI.duplicateQueryParameters, - escapeQuerySpace: URI.escapeQuerySpace - }; - }; - // state: allow duplicate query parameters (a=1&a=1) - URI.duplicateQueryParameters = false; - // state: replaces + with %20 (space in query strings) - URI.escapeQuerySpace = true; - // static properties - URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i; - URI.idn_expression = /[^a-z0-9\.-]/i; - URI.punycode_expression = /(xn--)/i; - // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care? - URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; - // credits to Rich Brown - // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 - // specification: http://www.ietf.org/rfc/rfc4291.txt - 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*$/; - // expression used is "gruber revised" (@gruber v2) determined to be the - // best solution in a regex-golf we did a couple of ages ago at - // * http://mathiasbynens.be/demo/url-regex - // * http://rodneyrehm.de/t/url-regex.html - 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; - URI.findUri = { - // valid "scheme://" or "www." - start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi, - // everything up to the next whitespace - end: /[\s\r\n]|$/, - // trim trailing punctuation captured by end RegExp - trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/ - }; - // http://www.iana.org/assignments/uri-schemes.html - // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports - URI.defaultPorts = { - http: '80', - https: '443', - ftp: '21', - gopher: '70', - ws: '80', - wss: '443' - }; - // allowed hostname characters according to RFC 3986 - // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded - // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - - URI.invalid_hostname_characters = /[^a-zA-Z0-9\.-]/; - // map DOM Elements to their URI attribute - URI.domAttributes = { - 'a': 'href', - 'blockquote': 'cite', - 'link': 'href', - 'base': 'href', - 'script': 'src', - 'form': 'action', - 'img': 'src', - 'area': 'href', - 'iframe': 'src', - 'embed': 'src', - 'source': 'src', - 'track': 'src', - 'input': 'src', // but only if type="image" - 'audio': 'src', - 'video': 'src' - }; - URI.getDomAttribute = function(node) { - if (!node || !node.nodeName) { - return undefined; - } - - var nodeName = node.nodeName.toLowerCase(); - // should only expose src for type="image" - if (nodeName === 'input' && node.type !== 'image') { - return undefined; - } - - return URI.domAttributes[nodeName]; - }; - - function escapeForDumbFirefox36(value) { - // https://github.com/medialize/URI.js/issues/91 - return escape(value); - } - - // encoding / decoding according to RFC3986 - function strictEncodeURIComponent(string) { - // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent - return encodeURIComponent(string) - .replace(/[!'()*]/g, escapeForDumbFirefox36) - .replace(/\*/g, '%2A'); - } - URI.encode = strictEncodeURIComponent; - URI.decode = decodeURIComponent; - URI.iso8859 = function() { - URI.encode = escape; - URI.decode = unescape; - }; - URI.unicode = function() { - URI.encode = strictEncodeURIComponent; - URI.decode = decodeURIComponent; - }; - URI.characters = { - pathname: { - encode: { - // RFC3986 2.1: For consistency, URI producers and normalizers should - // use uppercase hexadecimal digits for all percent-encodings. - expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig, - map: { - // -._~!'()* - '%24': '$', - '%26': '&', - '%2B': '+', - '%2C': ',', - '%3B': ';', - '%3D': '=', - '%3A': ':', - '%40': '@' - } - }, - decode: { - expression: /[\/\?#]/g, - map: { - '/': '%2F', - '?': '%3F', - '#': '%23' - } - } - }, - reserved: { - encode: { - // RFC3986 2.1: For consistency, URI producers and normalizers should - // use uppercase hexadecimal digits for all percent-encodings. - expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig, - map: { - // gen-delims - '%3A': ':', - '%2F': '/', - '%3F': '?', - '%23': '#', - '%5B': '[', - '%5D': ']', - '%40': '@', - // sub-delims - '%21': '!', - '%24': '$', - '%26': '&', - '%27': '\'', - '%28': '(', - '%29': ')', - '%2A': '*', - '%2B': '+', - '%2C': ',', - '%3B': ';', - '%3D': '=' - } - } - }, - urnpath: { - // The characters under `encode` are the characters called out by RFC 2141 as being acceptable - // for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but - // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also - // note that the colon character is not featured in the encoding map; this is because URI.js - // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it - // should not appear unencoded in a segment itself. - // See also the note above about RFC3986 and capitalalized hex digits. - encode: { - expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig, - map: { - '%21': '!', - '%24': '$', - '%27': '\'', - '%28': '(', - '%29': ')', - '%2A': '*', - '%2B': '+', - '%2C': ',', - '%3B': ';', - '%3D': '=', - '%40': '@' - } - }, - // These characters are the characters called out by RFC2141 as "reserved" characters that - // should never appear in a URN, plus the colon character (see note above). - decode: { - expression: /[\/\?#:]/g, - map: { - '/': '%2F', - '?': '%3F', - '#': '%23', - ':': '%3A' - } - } - } - }; - URI.encodeQuery = function(string, escapeQuerySpace) { - var escaped = URI.encode(string + ''); - if (escapeQuerySpace === undefined) { - escapeQuerySpace = URI.escapeQuerySpace; - } - - return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped; - }; - URI.decodeQuery = function(string, escapeQuerySpace) { - string += ''; - if (escapeQuerySpace === undefined) { - escapeQuerySpace = URI.escapeQuerySpace; - } - - try { - return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string); - } catch(e) { - // we're not going to mess with weird encodings, - // give up and return the undecoded original string - // see https://github.com/medialize/URI.js/issues/87 - // see https://github.com/medialize/URI.js/issues/92 - return string; - } - }; - // generate encode/decode path functions - var _parts = {'encode':'encode', 'decode':'decode'}; - var _part; - var generateAccessor = function(_group, _part) { - return function(string) { - try { - return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) { - return URI.characters[_group][_part].map[c]; - }); - } catch (e) { - // we're not going to mess with weird encodings, - // give up and return the undecoded original string - // see https://github.com/medialize/URI.js/issues/87 - // see https://github.com/medialize/URI.js/issues/92 - return string; - } - }; - }; - - for (_part in _parts) { - URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]); - URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]); - } - - var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) { - return function(string) { - // Why pass in names of functions, rather than the function objects themselves? The - // definitions of some functions (but in particular, URI.decode) will occasionally change due - // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure - // that the functions we use here are "fresh". - var actualCodingFunc; - if (!_innerCodingFuncName) { - actualCodingFunc = URI[_codingFuncName]; - } else { - actualCodingFunc = function(string) { - return URI[_codingFuncName](URI[_innerCodingFuncName](string)); - }; - } - - var segments = (string + '').split(_sep); - - for (var i = 0, length = segments.length; i < length; i++) { - segments[i] = actualCodingFunc(segments[i]); - } - - return segments.join(_sep); - }; - }; - - // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions. - URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment'); - URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment'); - URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode'); - URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode'); - - URI.encodeReserved = generateAccessor('reserved', 'encode'); - - URI.parse = function(string, parts) { - var pos; - if (!parts) { - parts = {}; - } - // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] - - // extract fragment - pos = string.indexOf('#'); - if (pos > -1) { - // escaping? - parts.fragment = string.substring(pos + 1) || null; - string = string.substring(0, pos); - } - - // extract query - pos = string.indexOf('?'); - if (pos > -1) { - // escaping? - parts.query = string.substring(pos + 1) || null; - string = string.substring(0, pos); - } - - // extract protocol - if (string.substring(0, 2) === '//') { - // relative-scheme - parts.protocol = null; - string = string.substring(2); - // extract "user:pass@host:port" - string = URI.parseAuthority(string, parts); - } else { - pos = string.indexOf(':'); - if (pos > -1) { - parts.protocol = string.substring(0, pos) || null; - if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) { - // : may be within the path - parts.protocol = undefined; - } else if (string.substring(pos + 1, pos + 3) === '//') { - string = string.substring(pos + 3); - - // extract "user:pass@host:port" - string = URI.parseAuthority(string, parts); - } else { - string = string.substring(pos + 1); - parts.urn = true; - } - } - } - - // what's left must be the path - parts.path = string; - - // and we're done - return parts; - }; - URI.parseHost = function(string, parts) { - // Copy chrome, IE, opera backslash-handling behavior. - // Back slashes before the query string get converted to forward slashes - // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 - // See: https://code.google.com/p/chromium/issues/detail?id=25916 - // https://github.com/medialize/URI.js/pull/233 - string = string.replace(/\\/g, '/'); - - // extract host:port - var pos = string.indexOf('/'); - var bracketPos; - var t; - - if (pos === -1) { - pos = string.length; - } - - if (string.charAt(0) === '[') { - // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 - // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts - // IPv6+port in the format [2001:db8::1]:80 (for the time being) - bracketPos = string.indexOf(']'); - parts.hostname = string.substring(1, bracketPos) || null; - parts.port = string.substring(bracketPos + 2, pos) || null; - if (parts.port === '/') { - parts.port = null; - } - } else { - var firstColon = string.indexOf(':'); - var firstSlash = string.indexOf('/'); - var nextColon = string.indexOf(':', firstColon + 1); - if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) { - // IPv6 host contains multiple colons - but no port - // this notation is actually not allowed by RFC 3986, but we're a liberal parser - parts.hostname = string.substring(0, pos) || null; - parts.port = null; - } else { - t = string.substring(0, pos).split(':'); - parts.hostname = t[0] || null; - parts.port = t[1] || null; - } - } - - if (parts.hostname && string.substring(pos).charAt(0) !== '/') { - pos++; - string = '/' + string; - } - - return string.substring(pos) || '/'; - }; - URI.parseAuthority = function(string, parts) { - string = URI.parseUserinfo(string, parts); - return URI.parseHost(string, parts); - }; - URI.parseUserinfo = function(string, parts) { - // extract username:password - var firstSlash = string.indexOf('/'); - var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); - var t; - - // authority@ must come before /path - if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { - t = string.substring(0, pos).split(':'); - parts.username = t[0] ? URI.decode(t[0]) : null; - t.shift(); - parts.password = t[0] ? URI.decode(t.join(':')) : null; - string = string.substring(pos + 1); - } else { - parts.username = null; - parts.password = null; - } - - return string; - }; - URI.parseQuery = function(string, escapeQuerySpace) { - if (!string) { - return {}; - } - - // throw out the funky business - "?"[name"="value"&"]+ - string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, ''); - - if (!string) { - return {}; - } - - var items = {}; - var splits = string.split('&'); - var length = splits.length; - var v, name, value; - - for (var i = 0; i < length; i++) { - v = splits[i].split('='); - name = URI.decodeQuery(v.shift(), escapeQuerySpace); - // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters - value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null; - - if (hasOwn.call(items, name)) { - if (typeof items[name] === 'string' || items[name] === null) { - items[name] = [items[name]]; - } - - items[name].push(value); - } else { - items[name] = value; - } - } - - return items; - }; - - URI.build = function(parts) { - var t = ''; - - if (parts.protocol) { - t += parts.protocol + ':'; - } - - if (!parts.urn && (t || parts.hostname)) { - t += '//'; - } - - t += (URI.buildAuthority(parts) || ''); - - if (typeof parts.path === 'string') { - if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') { - t += '/'; - } - - t += parts.path; - } - - if (typeof parts.query === 'string' && parts.query) { - t += '?' + parts.query; - } - - if (typeof parts.fragment === 'string' && parts.fragment) { - t += '#' + parts.fragment; - } - return t; - }; - URI.buildHost = function(parts) { - var t = ''; - - if (!parts.hostname) { - return ''; - } else if (URI.ip6_expression.test(parts.hostname)) { - t += '[' + parts.hostname + ']'; - } else { - t += parts.hostname; - } - - if (parts.port) { - t += ':' + parts.port; - } - - return t; - }; - URI.buildAuthority = function(parts) { - return URI.buildUserinfo(parts) + URI.buildHost(parts); - }; - URI.buildUserinfo = function(parts) { - var t = ''; - - if (parts.username) { - t += URI.encode(parts.username); - } - - if (parts.password) { - t += ':' + URI.encode(parts.password); - } - - if (t) { - t += '@'; - } - - return t; - }; - URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) { - // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html - // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed - // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax! - // URI.js treats the query string as being application/x-www-form-urlencoded - // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type - - var t = ''; - var unique, key, i, length; - for (key in data) { - if (hasOwn.call(data, key) && key) { - if (isArray(data[key])) { - unique = {}; - for (i = 0, length = data[key].length; i < length; i++) { - if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) { - t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace); - if (duplicateQueryParameters !== true) { - unique[data[key][i] + ''] = true; - } - } - } - } else if (data[key] !== undefined) { - t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace); - } - } - } - - return t.substring(1); - }; - URI.buildQueryParameter = function(name, value, escapeQuerySpace) { - // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded - // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization - return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : ''); - }; - - URI.addQuery = function(data, name, value) { - if (typeof name === 'object') { - for (var key in name) { - if (hasOwn.call(name, key)) { - URI.addQuery(data, key, name[key]); - } - } - } else if (typeof name === 'string') { - if (data[name] === undefined) { - data[name] = value; - return; - } else if (typeof data[name] === 'string') { - data[name] = [data[name]]; - } - - if (!isArray(value)) { - value = [value]; - } - - data[name] = (data[name] || []).concat(value); - } else { - throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); - } - }; - URI.removeQuery = function(data, name, value) { - var i, length, key; - - if (isArray(name)) { - for (i = 0, length = name.length; i < length; i++) { - data[name[i]] = undefined; - } - } else if (getType(name) === 'RegExp') { - for (key in data) { - if (name.test(key)) { - data[key] = undefined; - } - } - } else if (typeof name === 'object') { - for (key in name) { - if (hasOwn.call(name, key)) { - URI.removeQuery(data, key, name[key]); - } - } - } else if (typeof name === 'string') { - if (value !== undefined) { - if (getType(value) === 'RegExp') { - if (!isArray(data[name]) && value.test(data[name])) { - data[name] = undefined; - } else { - data[name] = filterArrayValues(data[name], value); - } - } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) { - data[name] = undefined; - } else if (isArray(data[name])) { - data[name] = filterArrayValues(data[name], value); - } - } else { - data[name] = undefined; - } - } else { - throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter'); - } - }; - URI.hasQuery = function(data, name, value, withinArray) { - switch (getType(name)) { - case 'String': - // Nothing to do here - break; - - case 'RegExp': - for (var key in data) { - if (hasOwn.call(data, key)) { - if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) { - return true; - } - } - } - - return false; - - case 'Object': - for (var _key in name) { - if (hasOwn.call(name, _key)) { - if (!URI.hasQuery(data, _key, name[_key])) { - return false; - } - } - } - - return true; - - default: - throw new TypeError('URI.hasQuery() accepts a string, regular expression or object as the name parameter'); - } - - switch (getType(value)) { - case 'Undefined': - // true if exists (but may be empty) - return name in data; // data[name] !== undefined; - - case 'Boolean': - // true if exists and non-empty - var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]); - return value === _booly; - - case 'Function': - // allow complex comparison - return !!value(data[name], name, data); - - case 'Array': - if (!isArray(data[name])) { - return false; - } - - var op = withinArray ? arrayContains : arraysEqual; - return op(data[name], value); - - case 'RegExp': - if (!isArray(data[name])) { - return Boolean(data[name] && data[name].match(value)); - } - - if (!withinArray) { - return false; - } - - return arrayContains(data[name], value); - - case 'Number': - value = String(value); - /* falls through */ - case 'String': - if (!isArray(data[name])) { - return data[name] === value; - } - - if (!withinArray) { - return false; - } - - return arrayContains(data[name], value); - - default: - throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter'); - } - }; - - - URI.joinPaths = function() { - var input = []; - var segments = []; - var nonEmptySegments = 0; - - for (var i = 0; i < arguments.length; i++) { - var url = new URI(arguments[i]); - input.push(url); - var _segments = url.segment(); - for (var s = 0; s < _segments.length; s++) { - if (typeof _segments[s] === 'string') { - segments.push(_segments[s]); - } - - if (_segments[s]) { - nonEmptySegments++; - } - } - } - - if (!segments.length || !nonEmptySegments) { - return new URI(''); - } - - var uri = new URI('').segment(segments); - - if (input[0].path() === '' || input[0].path().slice(0, 1) === '/') { - uri.path('/' + uri.path()); - } - - return uri.normalize(); - }; - - URI.commonPath = function(one, two) { - var length = Math.min(one.length, two.length); - var pos; - - // find first non-matching character - for (pos = 0; pos < length; pos++) { - if (one.charAt(pos) !== two.charAt(pos)) { - pos--; - break; - } - } - - if (pos < 1) { - return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : ''; - } - - // revert to last / - if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') { - pos = one.substring(0, pos).lastIndexOf('/'); - } - - return one.substring(0, pos + 1); - }; - - URI.withinString = function(string, callback, options) { - options || (options = {}); - var _start = options.start || URI.findUri.start; - var _end = options.end || URI.findUri.end; - var _trim = options.trim || URI.findUri.trim; - var _attributeOpen = /[a-z0-9-]=["']?$/i; - - _start.lastIndex = 0; - while (true) { - var match = _start.exec(string); - if (!match) { - break; - } - - var start = match.index; - if (options.ignoreHtml) { - // attribut(e=["']?$) - var attributeOpen = string.slice(Math.max(start - 3, 0), start); - if (attributeOpen && _attributeOpen.test(attributeOpen)) { - continue; - } - } - - var end = start + string.slice(start).search(_end); - var slice = string.slice(start, end).replace(_trim, ''); - if (options.ignore && options.ignore.test(slice)) { - continue; - } - - end = start + slice.length; - var result = callback(slice, start, end, string); - string = string.slice(0, start) + result + string.slice(end); - _start.lastIndex = start + result.length; - } - - _start.lastIndex = 0; - return string; - }; - - URI.ensureValidHostname = function(v) { - // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986) - // they are not part of DNS and therefore ignored by URI.js - - if (v.match(URI.invalid_hostname_characters)) { - // test punycode - if (!punycode) { - throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-] and Punycode.js is not available'); - } - - if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) { - throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); - } - } - }; - - // noConflict - URI.noConflict = function(removeAll) { - if (removeAll) { - var unconflicted = { - URI: this.noConflict() - }; - - if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') { - unconflicted.URITemplate = root.URITemplate.noConflict(); - } - - if (root.IPv6 && typeof root.IPv6.noConflict === 'function') { - unconflicted.IPv6 = root.IPv6.noConflict(); - } - - if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') { - unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict(); - } - - return unconflicted; - } else if (root.URI === this) { - root.URI = _URI; - } - - return this; - }; - - p.build = function(deferBuild) { - if (deferBuild === true) { - this._deferred_build = true; - } else if (deferBuild === undefined || this._deferred_build) { - this._string = URI.build(this._parts); - this._deferred_build = false; - } - - return this; - }; - - p.clone = function() { - return new URI(this); - }; - - p.valueOf = p.toString = function() { - return this.build(false)._string; - }; - - - function generateSimpleAccessor(_part){ - return function(v, build) { - if (v === undefined) { - return this._parts[_part] || ''; - } else { - this._parts[_part] = v || null; - this.build(!build); - return this; - } - }; - } - - function generatePrefixAccessor(_part, _key){ - return function(v, build) { - if (v === undefined) { - return this._parts[_part] || ''; - } else { - if (v !== null) { - v = v + ''; - if (v.charAt(0) === _key) { - v = v.substring(1); - } - } - - this._parts[_part] = v; - this.build(!build); - return this; - } - }; - } - - p.protocol = generateSimpleAccessor('protocol'); - p.username = generateSimpleAccessor('username'); - p.password = generateSimpleAccessor('password'); - p.hostname = generateSimpleAccessor('hostname'); - p.port = generateSimpleAccessor('port'); - p.query = generatePrefixAccessor('query', '?'); - p.fragment = generatePrefixAccessor('fragment', '#'); - - p.search = function(v, build) { - var t = this.query(v, build); - return typeof t === 'string' && t.length ? ('?' + t) : t; - }; - p.hash = function(v, build) { - var t = this.fragment(v, build); - return typeof t === 'string' && t.length ? ('#' + t) : t; - }; - - p.pathname = function(v, build) { - if (v === undefined || v === true) { - var res = this._parts.path || (this._parts.hostname ? '/' : ''); - return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res; - } else { - if (this._parts.urn) { - this._parts.path = v ? URI.recodeUrnPath(v) : ''; - } else { - this._parts.path = v ? URI.recodePath(v) : '/'; - } - this.build(!build); - return this; - } - }; - p.path = p.pathname; - p.href = function(href, build) { - var key; - - if (href === undefined) { - return this.toString(); - } - - this._string = ''; - this._parts = URI._parts(); - - var _URI = href instanceof URI; - var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname); - if (href.nodeName) { - var attribute = URI.getDomAttribute(href); - href = href[attribute] || ''; - _object = false; - } - - // window.location is reported to be an object, but it's not the sort - // of object we're looking for: - // * location.protocol ends with a colon - // * location.query != object.search - // * location.hash != object.fragment - // simply serializing the unknown object should do the trick - // (for location, not for everything...) - if (!_URI && _object && href.pathname !== undefined) { - href = href.toString(); - } - - if (typeof href === 'string' || href instanceof String) { - this._parts = URI.parse(String(href), this._parts); - } else if (_URI || _object) { - var src = _URI ? href._parts : href; - for (key in src) { - if (hasOwn.call(this._parts, key)) { - this._parts[key] = src[key]; - } - } - } else { - throw new TypeError('invalid input'); - } - - this.build(!build); - return this; - }; - - // identification accessors - p.is = function(what) { - var ip = false; - var ip4 = false; - var ip6 = false; - var name = false; - var sld = false; - var idn = false; - var punycode = false; - var relative = !this._parts.urn; - - if (this._parts.hostname) { - relative = false; - ip4 = URI.ip4_expression.test(this._parts.hostname); - ip6 = URI.ip6_expression.test(this._parts.hostname); - ip = ip4 || ip6; - name = !ip; - sld = name && SLD && SLD.has(this._parts.hostname); - idn = name && URI.idn_expression.test(this._parts.hostname); - punycode = name && URI.punycode_expression.test(this._parts.hostname); - } - - switch (what.toLowerCase()) { - case 'relative': - return relative; - - case 'absolute': - return !relative; - - // hostname identification - case 'domain': - case 'name': - return name; - - case 'sld': - return sld; - - case 'ip': - return ip; - - case 'ip4': - case 'ipv4': - case 'inet4': - return ip4; - - case 'ip6': - case 'ipv6': - case 'inet6': - return ip6; - - case 'idn': - return idn; - - case 'url': - return !this._parts.urn; - - case 'urn': - return !!this._parts.urn; - - case 'punycode': - return punycode; - } - - return null; - }; - - // component specific input validation - var _protocol = p.protocol; - var _port = p.port; - var _hostname = p.hostname; - - p.protocol = function(v, build) { - if (v !== undefined) { - if (v) { - // accept trailing :// - v = v.replace(/:(\/\/)?$/, ''); - - if (!v.match(URI.protocol_expression)) { - throw new TypeError('Protocol "' + v + '" contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]'); - } - } - } - return _protocol.call(this, v, build); - }; - p.scheme = p.protocol; - p.port = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v !== undefined) { - if (v === 0) { - v = null; - } - - if (v) { - v += ''; - if (v.charAt(0) === ':') { - v = v.substring(1); - } - - if (v.match(/[^0-9]/)) { - throw new TypeError('Port "' + v + '" contains characters other than [0-9]'); - } - } - } - return _port.call(this, v, build); - }; - p.hostname = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v !== undefined) { - var x = {}; - var res = URI.parseHost(v, x); - if (res !== '/') { - throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); - } - - v = x.hostname; - } - return _hostname.call(this, v, build); - }; - - // compound accessors - p.origin = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined) { - var protocol = this.protocol(); - var authority = this.authority(); - if (!authority) { - return ''; - } - - return (protocol ? protocol + '://' : '') + this.authority(); - } else { - var origin = URI(v); - this - .protocol(origin.protocol()) - .authority(origin.authority()) - .build(!build); - return this; - } - }; - p.host = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined) { - return this._parts.hostname ? URI.buildHost(this._parts) : ''; - } else { - var res = URI.parseHost(v, this._parts); - if (res !== '/') { - throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); - } - - this.build(!build); - return this; - } - }; - p.authority = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined) { - return this._parts.hostname ? URI.buildAuthority(this._parts) : ''; - } else { - var res = URI.parseAuthority(v, this._parts); - if (res !== '/') { - throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); - } - - this.build(!build); - return this; - } - }; - p.userinfo = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined) { - var t = URI.buildUserinfo(this._parts); - return t ? t.substring(0, t.length -1) : t; - } else { - if (v[v.length-1] !== '@') { - v += '@'; - } - - URI.parseUserinfo(v, this._parts); - this.build(!build); - return this; - } - }; - p.resource = function(v, build) { - var parts; - - if (v === undefined) { - return this.path() + this.search() + this.hash(); - } - - parts = URI.parse(v); - this._parts.path = parts.path; - this._parts.query = parts.query; - this._parts.fragment = parts.fragment; - this.build(!build); - return this; - }; - - // fraction accessors - p.subdomain = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - // convenience, return "www" from "www.example.org" - if (v === undefined) { - if (!this._parts.hostname || this.is('IP')) { - return ''; - } - - // grab domain and add another segment - var end = this._parts.hostname.length - this.domain().length - 1; - return this._parts.hostname.substring(0, end) || ''; - } else { - var e = this._parts.hostname.length - this.domain().length; - var sub = this._parts.hostname.substring(0, e); - var replace = new RegExp('^' + escapeRegEx(sub)); - - if (v && v.charAt(v.length - 1) !== '.') { - v += '.'; - } - - if (v) { - URI.ensureValidHostname(v); - } - - this._parts.hostname = this._parts.hostname.replace(replace, v); - this.build(!build); - return this; - } - }; - p.domain = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (typeof v === 'boolean') { - build = v; - v = undefined; - } - - // convenience, return "example.org" from "www.example.org" - if (v === undefined) { - if (!this._parts.hostname || this.is('IP')) { - return ''; - } - - // if hostname consists of 1 or 2 segments, it must be the domain - var t = this._parts.hostname.match(/\./g); - if (t && t.length < 2) { - return this._parts.hostname; - } - - // grab tld and add another segment - var end = this._parts.hostname.length - this.tld(build).length - 1; - end = this._parts.hostname.lastIndexOf('.', end -1) + 1; - return this._parts.hostname.substring(end) || ''; - } else { - if (!v) { - throw new TypeError('cannot set domain empty'); - } - - URI.ensureValidHostname(v); - - if (!this._parts.hostname || this.is('IP')) { - this._parts.hostname = v; - } else { - var replace = new RegExp(escapeRegEx(this.domain()) + '$'); - this._parts.hostname = this._parts.hostname.replace(replace, v); - } - - this.build(!build); - return this; - } - }; - p.tld = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (typeof v === 'boolean') { - build = v; - v = undefined; - } - - // return "org" from "www.example.org" - if (v === undefined) { - if (!this._parts.hostname || this.is('IP')) { - return ''; - } - - var pos = this._parts.hostname.lastIndexOf('.'); - var tld = this._parts.hostname.substring(pos + 1); - - if (build !== true && SLD && SLD.list[tld.toLowerCase()]) { - return SLD.get(this._parts.hostname) || tld; - } - - return tld; - } else { - var replace; - - if (!v) { - throw new TypeError('cannot set TLD empty'); - } else if (v.match(/[^a-zA-Z0-9-]/)) { - if (SLD && SLD.is(v)) { - replace = new RegExp(escapeRegEx(this.tld()) + '$'); - this._parts.hostname = this._parts.hostname.replace(replace, v); - } else { - throw new TypeError('TLD "' + v + '" contains characters other than [A-Z0-9]'); - } - } else if (!this._parts.hostname || this.is('IP')) { - throw new ReferenceError('cannot set TLD on non-domain host'); - } else { - replace = new RegExp(escapeRegEx(this.tld()) + '$'); - this._parts.hostname = this._parts.hostname.replace(replace, v); - } - - this.build(!build); - return this; - } - }; - p.directory = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined || v === true) { - if (!this._parts.path && !this._parts.hostname) { - return ''; - } - - if (this._parts.path === '/') { - return '/'; - } - - var end = this._parts.path.length - this.filename().length - 1; - var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : ''); - - return v ? URI.decodePath(res) : res; - - } else { - var e = this._parts.path.length - this.filename().length; - var directory = this._parts.path.substring(0, e); - var replace = new RegExp('^' + escapeRegEx(directory)); - - // fully qualifier directories begin with a slash - if (!this.is('relative')) { - if (!v) { - v = '/'; - } - - if (v.charAt(0) !== '/') { - v = '/' + v; - } - } - - // directories always end with a slash - if (v && v.charAt(v.length - 1) !== '/') { - v += '/'; - } - - v = URI.recodePath(v); - this._parts.path = this._parts.path.replace(replace, v); - this.build(!build); - return this; - } - }; - p.filename = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined || v === true) { - if (!this._parts.path || this._parts.path === '/') { - return ''; - } - - var pos = this._parts.path.lastIndexOf('/'); - var res = this._parts.path.substring(pos+1); - - return v ? URI.decodePathSegment(res) : res; - } else { - var mutatedDirectory = false; - - if (v.charAt(0) === '/') { - v = v.substring(1); - } - - if (v.match(/\.?\//)) { - mutatedDirectory = true; - } - - var replace = new RegExp(escapeRegEx(this.filename()) + '$'); - v = URI.recodePath(v); - this._parts.path = this._parts.path.replace(replace, v); - - if (mutatedDirectory) { - this.normalizePath(build); - } else { - this.build(!build); - } - - return this; - } - }; - p.suffix = function(v, build) { - if (this._parts.urn) { - return v === undefined ? '' : this; - } - - if (v === undefined || v === true) { - if (!this._parts.path || this._parts.path === '/') { - return ''; - } - - var filename = this.filename(); - var pos = filename.lastIndexOf('.'); - var s, res; - - if (pos === -1) { - return ''; - } - - // suffix may only contain alnum characters (yup, I made this up.) - s = filename.substring(pos+1); - res = (/^[a-z0-9%]+$/i).test(s) ? s : ''; - return v ? URI.decodePathSegment(res) : res; - } else { - if (v.charAt(0) === '.') { - v = v.substring(1); - } - - var suffix = this.suffix(); - var replace; - - if (!suffix) { - if (!v) { - return this; - } - - this._parts.path += '.' + URI.recodePath(v); - } else if (!v) { - replace = new RegExp(escapeRegEx('.' + suffix) + '$'); - } else { - replace = new RegExp(escapeRegEx(suffix) + '$'); - } - - if (replace) { - v = URI.recodePath(v); - this._parts.path = this._parts.path.replace(replace, v); - } - - this.build(!build); - return this; - } - }; - p.segment = function(segment, v, build) { - var separator = this._parts.urn ? ':' : '/'; - var path = this.path(); - var absolute = path.substring(0, 1) === '/'; - var segments = path.split(separator); - - if (segment !== undefined && typeof segment !== 'number') { - build = v; - v = segment; - segment = undefined; - } - - if (segment !== undefined && typeof segment !== 'number') { - throw new Error('Bad segment "' + segment + '", must be 0-based integer'); - } - - if (absolute) { - segments.shift(); - } - - if (segment < 0) { - // allow negative indexes to address from the end - segment = Math.max(segments.length + segment, 0); - } - - if (v === undefined) { - /*jshint laxbreak: true */ - return segment === undefined - ? segments - : segments[segment]; - /*jshint laxbreak: false */ - } else if (segment === null || segments[segment] === undefined) { - if (isArray(v)) { - segments = []; - // collapse empty elements within array - for (var i=0, l=v.length; i < l; i++) { - if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) { - continue; - } - - if (segments.length && !segments[segments.length -1].length) { - segments.pop(); - } - - segments.push(trimSlashes(v[i])); - } - } else if (v || typeof v === 'string') { - v = trimSlashes(v); - if (segments[segments.length -1] === '') { - // empty trailing elements have to be overwritten - // to prevent results such as /foo//bar - segments[segments.length -1] = v; - } else { - segments.push(v); - } - } - } else { - if (v) { - segments[segment] = trimSlashes(v); - } else { - segments.splice(segment, 1); - } - } - - if (absolute) { - segments.unshift(''); - } - - return this.path(segments.join(separator), build); - }; - p.segmentCoded = function(segment, v, build) { - var segments, i, l; - - if (typeof segment !== 'number') { - build = v; - v = segment; - segment = undefined; - } - - if (v === undefined) { - segments = this.segment(segment, v, build); - if (!isArray(segments)) { - segments = segments !== undefined ? URI.decode(segments) : undefined; - } else { - for (i = 0, l = segments.length; i < l; i++) { - segments[i] = URI.decode(segments[i]); - } - } - - return segments; - } - - if (!isArray(v)) { - v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v; - } else { - for (i = 0, l = v.length; i < l; i++) { - v[i] = URI.encode(v[i]); - } - } - - return this.segment(segment, v, build); - }; - - // mutating query string - var q = p.query; - p.query = function(v, build) { - if (v === true) { - return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); - } else if (typeof v === 'function') { - var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); - var result = v.call(this, data); - this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); - this.build(!build); - return this; - } else if (v !== undefined && typeof v !== 'string') { - this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); - this.build(!build); - return this; - } else { - return q.call(this, v, build); - } - }; - p.setQuery = function(name, value, build) { - var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); - - if (typeof name === 'string' || name instanceof String) { - data[name] = value !== undefined ? value : null; - } else if (typeof name === 'object') { - for (var key in name) { - if (hasOwn.call(name, key)) { - data[key] = name[key]; - } - } - } else { - throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); - } - - this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); - if (typeof name !== 'string') { - build = value; - } - - this.build(!build); - return this; - }; - p.addQuery = function(name, value, build) { - var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); - URI.addQuery(data, name, value === undefined ? null : value); - this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); - if (typeof name !== 'string') { - build = value; - } - - this.build(!build); - return this; - }; - p.removeQuery = function(name, value, build) { - var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); - URI.removeQuery(data, name, value); - this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); - if (typeof name !== 'string') { - build = value; - } - - this.build(!build); - return this; - }; - p.hasQuery = function(name, value, withinArray) { - var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); - return URI.hasQuery(data, name, value, withinArray); - }; - p.setSearch = p.setQuery; - p.addSearch = p.addQuery; - p.removeSearch = p.removeQuery; - p.hasSearch = p.hasQuery; - - // sanitizing URLs - p.normalize = function() { - if (this._parts.urn) { - return this - .normalizeProtocol(false) - .normalizePath(false) - .normalizeQuery(false) - .normalizeFragment(false) - .build(); - } - - return this - .normalizeProtocol(false) - .normalizeHostname(false) - .normalizePort(false) - .normalizePath(false) - .normalizeQuery(false) - .normalizeFragment(false) - .build(); - }; - p.normalizeProtocol = function(build) { - if (typeof this._parts.protocol === 'string') { - this._parts.protocol = this._parts.protocol.toLowerCase(); - this.build(!build); - } - - return this; - }; - p.normalizeHostname = function(build) { - if (this._parts.hostname) { - if (this.is('IDN') && punycode) { - this._parts.hostname = punycode.toASCII(this._parts.hostname); - } else if (this.is('IPv6') && IPv6) { - this._parts.hostname = IPv6.best(this._parts.hostname); - } - - this._parts.hostname = this._parts.hostname.toLowerCase(); - this.build(!build); - } - - return this; - }; - p.normalizePort = function(build) { - // remove port of it's the protocol's default - if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) { - this._parts.port = null; - this.build(!build); - } - - return this; - }; - p.normalizePath = function(build) { - var _path = this._parts.path; - if (!_path) { - return this; - } - - if (this._parts.urn) { - this._parts.path = URI.recodeUrnPath(this._parts.path); - this.build(!build); - return this; - } - - if (this._parts.path === '/') { - return this; - } - - _path = URI.recodePath(_path); - - var _was_relative; - var _leadingParents = ''; - var _parent, _pos; - - // handle relative paths - if (_path.charAt(0) !== '/') { - _was_relative = true; - _path = '/' + _path; - } - - // handle relative files (as opposed to directories) - if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') { - _path += '/'; - } - - // resolve simples - _path = _path - .replace(/(\/(\.\/)+)|(\/\.$)/g, '/') - .replace(/\/{2,}/g, '/'); - - // remember leading parents - if (_was_relative) { - _leadingParents = _path.substring(1).match(/^(\.\.\/)+/) || ''; - if (_leadingParents) { - _leadingParents = _leadingParents[0]; - } - } - - // resolve parents - while (true) { - _parent = _path.search(/\/\.\.(\/|$)/); - if (_parent === -1) { - // no more ../ to resolve - break; - } else if (_parent === 0) { - // top level cannot be relative, skip it - _path = _path.substring(3); - continue; - } - - _pos = _path.substring(0, _parent).lastIndexOf('/'); - if (_pos === -1) { - _pos = _parent; - } - _path = _path.substring(0, _pos) + _path.substring(_parent + 3); - } - - // revert to relative - if (_was_relative && this.is('relative')) { - _path = _leadingParents + _path.substring(1); - } - - this._parts.path = _path; - this.build(!build); - return this; - }; - p.normalizePathname = p.normalizePath; - p.normalizeQuery = function(build) { - if (typeof this._parts.query === 'string') { - if (!this._parts.query.length) { - this._parts.query = null; - } else { - this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)); - } - - this.build(!build); - } - - return this; - }; - p.normalizeFragment = function(build) { - if (!this._parts.fragment) { - this._parts.fragment = null; - this.build(!build); - } - - return this; - }; - p.normalizeSearch = p.normalizeQuery; - p.normalizeHash = p.normalizeFragment; - - p.iso8859 = function() { - // expect unicode input, iso8859 output - var e = URI.encode; - var d = URI.decode; - - URI.encode = escape; - URI.decode = decodeURIComponent; - try { - this.normalize(); - } finally { - URI.encode = e; - URI.decode = d; - } - return this; - }; - - p.unicode = function() { - // expect iso8859 input, unicode output - var e = URI.encode; - var d = URI.decode; - - URI.encode = strictEncodeURIComponent; - URI.decode = unescape; - try { - this.normalize(); - } finally { - URI.encode = e; - URI.decode = d; - } - return this; - }; - - p.readable = function() { - var uri = this.clone(); - // removing username, password, because they shouldn't be displayed according to RFC 3986 - uri.username('').password('').normalize(); - var t = ''; - if (uri._parts.protocol) { - t += uri._parts.protocol + '://'; - } - - if (uri._parts.hostname) { - if (uri.is('punycode') && punycode) { - t += punycode.toUnicode(uri._parts.hostname); - if (uri._parts.port) { - t += ':' + uri._parts.port; - } - } else { - t += uri.host(); - } - } - - if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') { - t += '/'; - } - - t += uri.path(true); - if (uri._parts.query) { - var q = ''; - for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) { - var kv = (qp[i] || '').split('='); - q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace) - .replace(/&/g, '%26'); - - if (kv[1] !== undefined) { - q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace) - .replace(/&/g, '%26'); - } - } - t += '?' + q.substring(1); - } - - t += URI.decodeQuery(uri.hash(), true); - return t; - }; - - // resolving relative and absolute URLs - p.absoluteTo = function(base) { - var resolved = this.clone(); - var properties = ['protocol', 'username', 'password', 'hostname', 'port']; - var basedir, i, p; - - if (this._parts.urn) { - throw new Error('URNs do not have any generally defined hierarchical components'); - } - - if (!(base instanceof URI)) { - base = new URI(base); - } - - if (!resolved._parts.protocol) { - resolved._parts.protocol = base._parts.protocol; - } - - if (this._parts.hostname) { - return resolved; - } - - for (i = 0; (p = properties[i]); i++) { - resolved._parts[p] = base._parts[p]; - } - - if (!resolved._parts.path) { - resolved._parts.path = base._parts.path; - if (!resolved._parts.query) { - resolved._parts.query = base._parts.query; - } - } else if (resolved._parts.path.substring(-2) === '..') { - resolved._parts.path += '/'; - } - - if (resolved.path().charAt(0) !== '/') { - basedir = base.directory(); - basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : ''; - resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path; - resolved.normalizePath(); - } - - resolved.build(); - return resolved; - }; - p.relativeTo = function(base) { - var relative = this.clone().normalize(); - var relativeParts, baseParts, common, relativePath, basePath; - - if (relative._parts.urn) { - throw new Error('URNs do not have any generally defined hierarchical components'); - } - - base = new URI(base).normalize(); - relativeParts = relative._parts; - baseParts = base._parts; - relativePath = relative.path(); - basePath = base.path(); - - if (relativePath.charAt(0) !== '/') { - throw new Error('URI is already relative'); - } - - if (basePath.charAt(0) !== '/') { - throw new Error('Cannot calculate a URI relative to another relative URI'); - } - - if (relativeParts.protocol === baseParts.protocol) { - relativeParts.protocol = null; - } - - if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) { - return relative.build(); - } - - if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) { - return relative.build(); - } - - if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) { - relativeParts.hostname = null; - relativeParts.port = null; - } else { - return relative.build(); - } - - if (relativePath === basePath) { - relativeParts.path = ''; - return relative.build(); - } - - // determine common sub path - common = URI.commonPath(relativePath, basePath); - - // If the paths have nothing in common, return a relative URL with the absolute path. - if (!common) { - return relative.build(); - } - - var parents = baseParts.path - .substring(common.length) - .replace(/[^\/]*$/, '') - .replace(/.*?\//g, '../'); - - relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './'; - - return relative.build(); - }; - - // comparing URIs - p.equals = function(uri) { - var one = this.clone(); - var two = new URI(uri); - var one_map = {}; - var two_map = {}; - var checked = {}; - var one_query, two_query, key; - - one.normalize(); - two.normalize(); - - // exact match - if (one.toString() === two.toString()) { - return true; - } - - // extract query string - one_query = one.query(); - two_query = two.query(); - one.query(''); - two.query(''); - - // definitely not equal if not even non-query parts match - if (one.toString() !== two.toString()) { - return false; - } - - // query parameters have the same length, even if they're permuted - if (one_query.length !== two_query.length) { - return false; - } - - one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace); - two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace); - - for (key in one_map) { - if (hasOwn.call(one_map, key)) { - if (!isArray(one_map[key])) { - if (one_map[key] !== two_map[key]) { - return false; - } - } else if (!arraysEqual(one_map[key], two_map[key])) { - return false; - } - - checked[key] = true; - } - } - - for (key in two_map) { - if (hasOwn.call(two_map, key)) { - if (!checked[key]) { - // two contains a parameter not present in one - return false; - } - } - } - - return true; - }; - - // state - p.duplicateQueryParameters = function(v) { - this._parts.duplicateQueryParameters = !!v; - return this; - }; - - p.escapeQuerySpace = function(v) { - this._parts.escapeQuerySpace = !!v; - return this; - }; - - return URI; -})); - -},{"./IPv6":3,"./SecondLevelDomains":6,"./punycode":3}],8:[function(require,module,exports){ -var RSVP = require('rsvp'); -var URI = require('urijs'); -var core = require('./core'); -var Spine = require('./spine'); -var Locations = require('./locations'); -var Parser = require('./parser'); -var Navigation = require('./navigation'); -var Rendition = require('./rendition'); -var Unarchive = require('./unarchive'); -var request = require('./request'); -var EpubCFI = require('./epubcfi'); - -function Book(_url, options){ - - this.settings = core.extend(this.settings || {}, { - requestMethod: this.requestMethod - }); - - core.extend(this.settings, options); - - - // Promises - this.opening = new RSVP.defer(); - this.opened = this.opening.promise; - this.isOpen = false; - - this.url = undefined; - - this.loading = { - manifest: new RSVP.defer(), - spine: new RSVP.defer(), - metadata: new RSVP.defer(), - cover: new RSVP.defer(), - navigation: new RSVP.defer(), - pageList: new RSVP.defer() - }; - - this.loaded = { - manifest: this.loading.manifest.promise, - spine: this.loading.spine.promise, - metadata: this.loading.metadata.promise, - cover: this.loading.cover.promise, - navigation: this.loading.navigation.promise, - pageList: this.loading.pageList.promise - }; - - this.ready = RSVP.hash(this.loaded); - - // Queue for methods used before opening - this.isRendered = false; - // this._q = core.queue(this); - - this.request = this.settings.requestMethod.bind(this); - - this.spine = new Spine(this.request); - this.locations = new Locations(this.spine, this.request); - - if(_url) { - this.open(_url).catch(function (error) { - var err = new Error("Cannot load book at "+ _url ); - console.error(err); - - this.trigger("loadFailed", error); - }.bind(this)); - } -}; - -Book.prototype.open = function(_url, options){ - var uri; - var parse = new Parser(); - var epubPackage; - var epubContainer; - var book = this; - var containerPath = "META-INF/container.xml"; - var location; - var absoluteUri; - var isArrayBuffer = false; - var isBase64 = options && options.base64; - - if(!_url) { - this.opening.resolve(this); + + // Get package information from epub opf + book.unpack(packageXml); + + // Resolve promises + book.loading.manifest.resolve(book.package.manifest); + book.loading.metadata.resolve(book.package.metadata); + book.loading.spine.resolve(book.spine); + book.loading.cover.resolve(book.cover); + + book.isOpen = true; + + // Clear queue of any waiting book request + + // Resolve book opened promise + book.opening.resolve(book); + + }).catch(function(error) { + // handle errors in parsing the book + // console.error(error.message, error.stack); + book.opening.reject(error); + }); + return this.opened; - } - - // Reuse parsed url or create a new uri object - // if(typeof(_url) === "object") { - // uri = _url; - // } else { - // uri = core.uri(_url); - // } - if (_url instanceof ArrayBuffer || isBase64) { - isArrayBuffer = true; - this.url = '/'; - } else { - uri = URI(_url); - } - - if (window && window.location && uri) { - absoluteUri = uri.absoluteTo(window.location.href); - this.url = absoluteUri.toString(); - } else if (window && window.location) { - this.url = window.location.href; - } else { - this.url = _url; - } - - // Find path to the Container - if(uri && uri.suffix() === "opf") { - // Direct link to package, no container - this.packageUrl = _url; - this.containerUrl = ''; - - if(uri.origin()) { - this.baseUrl = uri.origin() + "/" + uri.directory() + "/"; - } else if(absoluteUri){ - this.baseUrl = absoluteUri.origin(); - this.baseUrl += absoluteUri.directory() + "/"; - } else { - this.baseUrl = uri.directory() + "/"; - } - - epubPackage = this.request(this.packageUrl) - .catch(function(error) { - book.opening.reject(error); - }); - - } else if(isArrayBuffer || isBase64 || this.isArchivedUrl(uri)) { - // Book is archived - this.url = '/'; - this.containerUrl = URI(containerPath).absoluteTo(this.url).toString(); - - epubContainer = this.unarchive(_url, isBase64). - then(function() { - return this.request(this.containerUrl); - }.bind(this)) - .catch(function(error) { - book.opening.reject(error); - }); - } - // Find the path to the Package from the container - else if (!uri.suffix()) { - - this.containerUrl = this.url + containerPath; - - epubContainer = this.request(this.containerUrl) - .catch(function(error) { - // handle errors in loading container - book.opening.reject(error); - }); - } - - if (epubContainer) { - epubPackage = epubContainer. - then(function(containerXml){ - return parse.container(containerXml); // Container has path to content - }). - then(function(paths){ - var packageUri = URI(paths.packagePath); - var absPackageUri = packageUri.absoluteTo(book.url); - var absWindowUri; - - book.packageUrl = absPackageUri.toString(); - book.encoding = paths.encoding; - - // Set Url relative to the content - if(absPackageUri.origin()) { - book.baseUrl = absPackageUri.origin() + absPackageUri.directory() + "/"; - } else { - if(packageUri.directory()) { - book.baseUrl = "/" + packageUri.directory() + "/"; - } else { - book.baseUrl = "/" - } - } - - return book.request(book.packageUrl); - }).catch(function(error) { - // handle errors in either of the two requests - book.opening.reject(error); - }); - } - - epubPackage.then(function(packageXml) { - - if (!packageXml) { + }; + + Book.prototype.unpack = function(packageXml){ + var book = this, + parse = new Parser(); + + book.package = parse.packageContents(packageXml); // Extract info from contents + if(!book.package) { return; } - - // Get package information from epub opf - book.unpack(packageXml); - - // Resolve promises - book.loading.manifest.resolve(book.package.manifest); - book.loading.metadata.resolve(book.package.metadata); - book.loading.spine.resolve(book.spine); - book.loading.cover.resolve(book.cover); - - book.isOpen = true; - - // Clear queue of any waiting book request - - // Resolve book opened promise - book.opening.resolve(book); - - }).catch(function(error) { - // handle errors in parsing the book - // console.error(error.message, error.stack); - book.opening.reject(error); - }); - - return this.opened; -}; - -Book.prototype.unpack = function(packageXml){ - var book = this, - parse = new Parser(); - - book.package = parse.packageContents(packageXml); // Extract info from contents - if(!book.package) { - return; - } - - book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths - - this.spine.load(book.package); - - book.navigation = new Navigation(book.package, this.request); - book.navigation.load().then(function(toc){ - book.toc = toc; - book.loading.navigation.resolve(book.toc); - }); - - // //-- Set Global Layout setting based on metadata - // MOVE TO RENDER - // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata); - - book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString(); -}; - -// Alias for book.spine.get -Book.prototype.section = function(target) { - return this.spine.get(target); -}; - -// Sugar to render a book -Book.prototype.renderTo = function(element, options) { - // var renderMethod = (options && options.method) ? - // options.method : - // "single"; - - this.rendition = new Rendition(this, options); - this.rendition.attachTo(element); - - return this.rendition; -}; - -Book.prototype.requestMethod = function(_url) { - // Switch request methods - if(this.unarchived) { - return this.unarchived.request(_url); - } else { - return request(_url, null, this.requestCredentials, this.requestHeaders); - } - -}; - -Book.prototype.setRequestCredentials = function(_credentials) { - this.requestCredentials = _credentials; -}; - -Book.prototype.setRequestHeaders = function(_headers) { - this.requestHeaders = _headers; -}; - -Book.prototype.unarchive = function(bookUrl, isBase64){ - this.unarchived = new Unarchive(); - return this.unarchived.open(bookUrl, isBase64); -}; - -//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub) -Book.prototype.isArchivedUrl = function(bookUrl){ - var uri; - var extension; - - if (bookUrl instanceof ArrayBuffer) { - return true; - } - - // Reuse parsed url or create a new uri object - // if(typeof(bookUrl) === "object") { - // uri = bookUrl; - // } else { - // uri = core.uri(bookUrl); - // } - uri = URI(bookUrl); - extension = uri.suffix(); - - if(extension && (extension == "epub" || extension == "zip")){ - return true; - } - - return false; -}; - -//-- Returns the cover -Book.prototype.coverUrl = function(){ - var retrieved = this.loaded.cover. - then(function(url) { - if(this.unarchived) { - return this.unarchived.createUrl(this.cover); - }else{ - return this.cover; - } - }.bind(this)); - - - - return retrieved; -}; - -Book.prototype.range = function(cfiRange) { - var cfi = new EpubCFI(cfiRange); - var item = this.spine.get(cfi.spinePos); - - return item.load().then(function (contents) { - var range = cfi.toRange(item.document); - return range; - }) -}; - -module.exports = Book; - -//-- Enable binding events to book -RSVP.EventTarget.mixin(Book.prototype); - -//-- Handle RSVP Errors -RSVP.on('error', function(event) { - console.error(event); -}); - -RSVP.configure('instrument', false); //-- true | will logging out all RSVP rejections -// RSVP.on('created', listener); -// RSVP.on('chained', listener); -// RSVP.on('fulfilled', listener); -RSVP.on('rejected', function(event){ - console.error(event.detail.message, event.detail.stack); -}); - -},{"./core":10,"./epubcfi":11,"./locations":14,"./navigation":21,"./parser":22,"./rendition":24,"./request":26,"./spine":28,"./unarchive":29,"rsvp":5,"urijs":7}],9:[function(require,module,exports){ -var RSVP = require('rsvp'); -var core = require('./core'); -var EpubCFI = require('./epubcfi'); -var Mapping = require('./mapping'); - - -function Contents(doc, content, cfiBase) { - // Blank Cfi for Parsing - this.epubcfi = new EpubCFI(); - - this.document = doc; - this.documentElement = this.document.documentElement; - this.content = content || this.document.body; - this.window = this.document.defaultView; - // Dom events to listen for - this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"]; - - this._size = { - width: 0, - height: 0 - } - - this.cfiBase = cfiBase || ""; - - this.listeners(); -}; - -Contents.prototype.width = function(w) { - // var frame = this.documentElement; - var frame = this.content; - - if (w && core.isNumber(w)) { - w = w + "px"; - } - - if (w) { - frame.style.width = w; - // this.content.style.width = w; - } - - return this.window.getComputedStyle(frame)['width']; - - -}; - -Contents.prototype.height = function(h) { - // var frame = this.documentElement; - var frame = this.content; - - if (h && core.isNumber(h)) { - h = h + "px"; - } - - if (h) { - frame.style.height = h; - // this.content.style.height = h; - } - - return this.window.getComputedStyle(frame)['height']; - -}; - -Contents.prototype.contentWidth = function(w) { - - var content = this.content || this.document.body; - - if (w && core.isNumber(w)) { - w = w + "px"; - } - - if (w) { - content.style.width = w; - } - - return this.window.getComputedStyle(content)['width']; - - -}; - -Contents.prototype.contentHeight = function(h) { - - var content = this.content || this.document.body; - - if (h && core.isNumber(h)) { - h = h + "px"; - } - - if (h) { - content.style.height = h; - } - - return this.window.getComputedStyle(content)['height']; - -}; - -Contents.prototype.textWidth = function() { - var width; - var range = this.document.createRange(); - var content = this.content || this.document.body; - - // Select the contents of frame - range.selectNodeContents(content); - - // get the width of the text content - width = range.getBoundingClientRect().width; - - return width; - -}; - -Contents.prototype.textHeight = function() { - var height; - var range = this.document.createRange(); - var content = this.content || this.document.body; - - range.selectNodeContents(content); - - height = range.getBoundingClientRect().height; - - return height; -}; - -Contents.prototype.scrollWidth = function() { - var width = this.documentElement.scrollWidth; - - return width; -}; - -Contents.prototype.scrollHeight = function() { - var height = this.documentElement.scrollHeight; - - return height; -}; - -Contents.prototype.overflow = function(overflow) { - - if (overflow) { - this.documentElement.style.overflow = overflow; - } - - return this.window.getComputedStyle(this.documentElement)['overflow']; -}; - -Contents.prototype.overflowX = function(overflow) { - - if (overflow) { - this.documentElement.style.overflowX = overflow; - } - - return this.window.getComputedStyle(this.documentElement)['overflowX']; -}; - -Contents.prototype.overflowY = function(overflow) { - - if (overflow) { - this.documentElement.style.overflowY = overflow; - } - - return this.window.getComputedStyle(this.documentElement)['overflowY']; -}; - -Contents.prototype.css = function(property, value) { - var content = this.content || this.document.body; - - if (value) { - content.style[property] = value; - } - - return this.window.getComputedStyle(content)[property]; -}; - -Contents.prototype.viewport = function(options) { - var width, height, scale, scalable; - var $viewport = this.document.querySelector("meta[name='viewport']"); - var newContent = ''; - - /** - * check for the viewport size - * - */ - if($viewport && $viewport.hasAttribute("content")) { - content = $viewport.getAttribute("content"); - contents = content.split(/\s*,\s*/); - if(contents[0]){ - width = contents[0].replace("width=", '').trim(); - } - if(contents[1]){ - height = contents[1].replace("height=", '').trim(); - } - if(contents[2]){ - scale = contents[2].replace("initial-scale=", '').trim(); - } - if(contents[3]){ - scalable = contents[3].replace("user-scalable=", '').trim(); - } - } - - if (options) { - - newContent += "width=" + (options.width || width); - newContent += ", height=" + (options.height || height); - if (options.scale || scale) { - newContent += ", initial-scale=" + (options.scale || scale); - } - if (options.scalable || scalable) { - newContent += ", user-scalable=" + (options.scalable || scalable); - } - - if (!$viewport) { - $viewport = this.document.createElement("meta"); - $viewport.setAttribute("name", "viewport"); - this.document.querySelector('head').appendChild($viewport); - } - - $viewport.setAttribute("content", newContent); - } - - - return { - width: parseInt(width), - height: parseInt(height) + + book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths + + this.spine.load(book.package); + + book.navigation = new Navigation(book.package, this.request); + book.navigation.load().then(function(toc){ + book.toc = toc; + book.loading.navigation.resolve(book.toc); + }); + + // //-- Set Global Layout setting based on metadata + // MOVE TO RENDER + // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata); + + book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString(); }; -}; + + // Alias for book.spine.get + Book.prototype.section = function(target) { + return this.spine.get(target); + }; + + // Sugar to render a book + Book.prototype.renderTo = function(element, options) { + // var renderMethod = (options && options.method) ? + // options.method : + // "single"; + + this.rendition = new Rendition(this, options); + this.rendition.attachTo(element); + + return this.rendition; + }; + + Book.prototype.requestMethod = function(_url) { + // Switch request methods + if(this.unarchived) { + return this.unarchived.request(_url); + } else { + return request(_url, null, this.requestCredentials, this.requestHeaders); + } + + }; + + Book.prototype.setRequestCredentials = function(_credentials) { + this.requestCredentials = _credentials; + }; + + Book.prototype.setRequestHeaders = function(_headers) { + this.requestHeaders = _headers; + }; + + Book.prototype.unarchive = function(bookUrl, isBase64){ + this.unarchived = new Unarchive(); + return this.unarchived.open(bookUrl, isBase64); + }; + + //-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub) + Book.prototype.isArchivedUrl = function(bookUrl){ + var uri; + var extension; + + if (bookUrl instanceof ArrayBuffer) { + return true; + } + + // Reuse parsed url or create a new uri object + // if(typeof(bookUrl) === "object") { + // uri = bookUrl; + // } else { + // uri = core.uri(bookUrl); + // } + uri = URI(bookUrl); + extension = uri.suffix(); + + if(extension && (extension == "epub" || extension == "zip")){ + return true; + } + + return false; + }; + + //-- Returns the cover + Book.prototype.coverUrl = function(){ + var retrieved = this.loaded.cover. + then(function(url) { + if(this.unarchived) { + return this.unarchived.createUrl(this.cover); + }else{ + return this.cover; + } + }.bind(this)); + + + + return retrieved; + }; + + Book.prototype.range = function(cfiRange) { + var cfi = new EpubCFI(cfiRange); + var item = this.spine.get(cfi.spinePos); + + return item.load().then(function (contents) { + var range = cfi.toRange(item.document); + return range; + }) + }; + + module.exports = Book; + + //-- Enable binding events to book + RSVP.EventTarget.mixin(Book.prototype); + + //-- Handle RSVP Errors + RSVP.on('error', function(event) { + console.error(event); + }); + + RSVP.configure('instrument', false); //-- true | will logging out all RSVP rejections + // RSVP.on('created', listener); + // RSVP.on('chained', listener); + // RSVP.on('fulfilled', listener); + RSVP.on('rejected', function(event){ + console.error(event.detail.message, event.detail.stack); + }); -// Contents.prototype.layout = function(layoutFunc) { -// -// this.iframe.style.display = "inline-block"; -// -// // Reset Body Styles -// this.content.style.margin = "0"; -// //this.document.body.style.display = "inline-block"; -// //this.document.documentElement.style.width = "auto"; -// -// if(layoutFunc){ -// layoutFunc(this); -// } -// -// this.onLayout(this); -// -// }; -// -// Contents.prototype.onLayout = function(view) { -// // stub -// }; +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { -Contents.prototype.expand = function() { - this.trigger("expand"); -}; + var require;/* WEBPACK VAR INJECTION */(function(process, setImmediate, global) {/*! + * @overview RSVP - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2016 Yehuda Katz, Tom Dale, Stefan Penner and contributors + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE + * @version 3.3.2 + */ + + (function (global, factory) { + true ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.RSVP = global.RSVP || {}))); + }(this, (function (exports) { 'use strict'; + + function indexOf(callbacks, callback) { + for (var i = 0, l = callbacks.length; i < l; i++) { + if (callbacks[i] === callback) { + return i; + } + } + + return -1; + } + + function callbacksFor(object) { + var callbacks = object._promiseCallbacks; + + if (!callbacks) { + callbacks = object._promiseCallbacks = {}; + } + + return callbacks; + } + + /** + @class RSVP.EventTarget + */ + var EventTarget = { + + /** + `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For + Example: + ```javascript + let object = {}; + RSVP.EventTarget.mixin(object); + object.on('finished', function(event) { + // handle event + }); + object.trigger('finished', { detail: value }); + ``` + `EventTarget.mixin` also works with prototypes: + ```javascript + let Person = function() {}; + RSVP.EventTarget.mixin(Person.prototype); + let yehuda = new Person(); + let tom = new Person(); + yehuda.on('poke', function(event) { + console.log('Yehuda says OW'); + }); + tom.on('poke', function(event) { + console.log('Tom says OW'); + }); + yehuda.trigger('poke'); + tom.trigger('poke'); + ``` + @method mixin + @for RSVP.EventTarget + @private + @param {Object} object object to extend with EventTarget methods + */ + mixin: function mixin(object) { + object['on'] = this['on']; + object['off'] = this['off']; + object['trigger'] = this['trigger']; + object._promiseCallbacks = undefined; + return object; + }, + + /** + Registers a callback to be executed when `eventName` is triggered + ```javascript + object.on('event', function(eventInfo){ + // handle the event + }); + object.trigger('event'); + ``` + @method on + @for RSVP.EventTarget + @private + @param {String} eventName name of the event to listen for + @param {Function} callback function to be called when the event is triggered. + */ + on: function on(eventName, callback) { + if (typeof callback !== 'function') { + throw new TypeError('Callback must be a function'); + } + + var allCallbacks = callbacksFor(this), + callbacks = undefined; + + callbacks = allCallbacks[eventName]; + + if (!callbacks) { + callbacks = allCallbacks[eventName] = []; + } + + if (indexOf(callbacks, callback) === -1) { + callbacks.push(callback); + } + }, + + /** + You can use `off` to stop firing a particular callback for an event: + ```javascript + function doStuff() { // do stuff! } + object.on('stuff', doStuff); + object.trigger('stuff'); // doStuff will be called + // Unregister ONLY the doStuff callback + object.off('stuff', doStuff); + object.trigger('stuff'); // doStuff will NOT be called + ``` + If you don't pass a `callback` argument to `off`, ALL callbacks for the + event will not be executed when the event fires. For example: + ```javascript + let callback1 = function(){}; + let callback2 = function(){}; + object.on('stuff', callback1); + object.on('stuff', callback2); + object.trigger('stuff'); // callback1 and callback2 will be executed. + object.off('stuff'); + object.trigger('stuff'); // callback1 and callback2 will not be executed! + ``` + @method off + @for RSVP.EventTarget + @private + @param {String} eventName event to stop listening to + @param {Function} callback optional argument. If given, only the function + given will be removed from the event's callback queue. If no `callback` + argument is given, all callbacks will be removed from the event's callback + queue. + */ + off: function off(eventName, callback) { + var allCallbacks = callbacksFor(this), + callbacks = undefined, + index = undefined; + + if (!callback) { + allCallbacks[eventName] = []; + return; + } + + callbacks = allCallbacks[eventName]; + + index = indexOf(callbacks, callback); + + if (index !== -1) { + callbacks.splice(index, 1); + } + }, + + /** + Use `trigger` to fire custom events. For example: + ```javascript + object.on('foo', function(){ + console.log('foo event happened!'); + }); + object.trigger('foo'); + // 'foo event happened!' logged to the console + ``` + You can also pass a value as a second argument to `trigger` that will be + passed as an argument to all event listeners for the event: + ```javascript + object.on('foo', function(value){ + console.log(value.name); + }); + object.trigger('foo', { name: 'bar' }); + // 'bar' logged to the console + ``` + @method trigger + @for RSVP.EventTarget + @private + @param {String} eventName name of the event to be triggered + @param {*} options optional value to be passed to any event handlers for + the given `eventName` + */ + trigger: function trigger(eventName, options, label) { + var allCallbacks = callbacksFor(this), + callbacks = undefined, + callback = undefined; + + if (callbacks = allCallbacks[eventName]) { + // Don't cache the callbacks.length since it may grow + for (var i = 0; i < callbacks.length; i++) { + callback = callbacks[i]; + + callback(options, label); + } + } + } + }; + + var config = { + instrument: false + }; + + EventTarget['mixin'](config); + + function configure(name, value) { + if (name === 'onerror') { + // handle for legacy users that expect the actual + // error to be passed to their function added via + // `RSVP.configure('onerror', someFunctionHere);` + config['on']('error', value); + return; + } + + if (arguments.length === 2) { + config[name] = value; + } else { + return config[name]; + } + } + + function objectOrFunction(x) { + return typeof x === 'function' || typeof x === 'object' && x !== null; + } + + function isFunction(x) { + return typeof x === 'function'; + } + + function isMaybeThenable(x) { + return typeof x === 'object' && x !== null; + } + + var _isArray = undefined; + if (!Array.isArray) { + _isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; + } else { + _isArray = Array.isArray; + } + + var isArray = _isArray; + + // Date.now is not available in browsers < IE9 + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility + var now = Date.now || function () { + return new Date().getTime(); + }; + + function F() {} + + var o_create = Object.create || function (o) { + if (arguments.length > 1) { + throw new Error('Second argument not supported'); + } + if (typeof o !== 'object') { + throw new TypeError('Argument must be an object'); + } + F.prototype = o; + return new F(); + }; + + var queue = []; + + function scheduleFlush() { + setTimeout(function () { + for (var i = 0; i < queue.length; i++) { + var entry = queue[i]; + + var payload = entry.payload; + + payload.guid = payload.key + payload.id; + payload.childGuid = payload.key + payload.childId; + if (payload.error) { + payload.stack = payload.error.stack; + } + + config['trigger'](entry.name, entry.payload); + } + queue.length = 0; + }, 50); + } + function instrument(eventName, promise, child) { + if (1 === queue.push({ + name: eventName, + payload: { + key: promise._guidKey, + id: promise._id, + eventName: eventName, + detail: promise._result, + childId: child && child._id, + label: promise._label, + timeStamp: now(), + error: config["instrument-with-stack"] ? new Error(promise._label) : null + } })) { + scheduleFlush(); + } + } + + /** + `RSVP.Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + let promise = new RSVP.Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = RSVP.Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @static + @param {*} object value that the returned promise will be resolved with + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` + */ + function resolve$1(object, label) { + /*jshint validthis:true */ + var Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + var promise = new Constructor(noop, label); + resolve(promise, object); + return promise; + } + + function withOwnPromise() { + return new TypeError('A promises callback cannot return that same promise.'); + } + + function noop() {} + + var PENDING = void 0; + var FULFILLED = 1; + var REJECTED = 2; + + var GET_THEN_ERROR = new ErrorObject(); + + function getThen(promise) { + try { + return promise.then; + } catch (error) { + GET_THEN_ERROR.error = error; + return GET_THEN_ERROR; + } + } + + function tryThen(then, value, fulfillmentHandler, rejectionHandler) { + try { + then.call(value, fulfillmentHandler, rejectionHandler); + } catch (e) { + return e; + } + } + + function handleForeignThenable(promise, thenable, then) { + config.async(function (promise) { + var sealed = false; + var error = tryThen(then, thenable, function (value) { + if (sealed) { + return; + } + sealed = true; + if (thenable !== value) { + resolve(promise, value, undefined); + } else { + fulfill(promise, value); + } + }, function (reason) { + if (sealed) { + return; + } + sealed = true; + + reject(promise, reason); + }, 'Settle: ' + (promise._label || ' unknown promise')); + + if (!sealed && error) { + sealed = true; + reject(promise, error); + } + }, promise); + } + + function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + thenable._onError = null; + reject(promise, thenable._result); + } else { + subscribe(thenable, undefined, function (value) { + if (thenable !== value) { + resolve(promise, value, undefined); + } else { + fulfill(promise, value); + } + }, function (reason) { + return reject(promise, reason); + }); + } + } + + function handleMaybeThenable(promise, maybeThenable, then$$) { + if (maybeThenable.constructor === promise.constructor && then$$ === then && promise.constructor.resolve === resolve$1) { + handleOwnThenable(promise, maybeThenable); + } else { + if (then$$ === GET_THEN_ERROR) { + reject(promise, GET_THEN_ERROR.error); + } else if (then$$ === undefined) { + fulfill(promise, maybeThenable); + } else if (isFunction(then$$)) { + handleForeignThenable(promise, maybeThenable, then$$); + } else { + fulfill(promise, maybeThenable); + } + } + } + + function resolve(promise, value) { + if (promise === value) { + fulfill(promise, value); + } else if (objectOrFunction(value)) { + handleMaybeThenable(promise, value, getThen(value)); + } else { + fulfill(promise, value); + } + } + + function publishRejection(promise) { + if (promise._onError) { + promise._onError(promise._result); + } + + publish(promise); + } + + function fulfill(promise, value) { + if (promise._state !== PENDING) { + return; + } + + promise._result = value; + promise._state = FULFILLED; + + if (promise._subscribers.length === 0) { + if (config.instrument) { + instrument('fulfilled', promise); + } + } else { + config.async(publish, promise); + } + } + + function reject(promise, reason) { + if (promise._state !== PENDING) { + return; + } + promise._state = REJECTED; + promise._result = reason; + config.async(publishRejection, promise); + } + + function subscribe(parent, child, onFulfillment, onRejection) { + var subscribers = parent._subscribers; + var length = subscribers.length; + + parent._onError = null; + + subscribers[length] = child; + subscribers[length + FULFILLED] = onFulfillment; + subscribers[length + REJECTED] = onRejection; + + if (length === 0 && parent._state) { + config.async(publish, parent); + } + } + + function publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; + + if (config.instrument) { + instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); + } + + if (subscribers.length === 0) { + return; + } + + var child = undefined, + callback = undefined, + detail = promise._result; + + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + + if (child) { + invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } + + promise._subscribers.length = 0; + } + + function ErrorObject() { + this.error = null; + } + + var TRY_CATCH_ERROR = new ErrorObject(); + + function tryCatch(callback, detail) { + try { + return callback(detail); + } catch (e) { + TRY_CATCH_ERROR.error = e; + return TRY_CATCH_ERROR; + } + } + + function invokeCallback(settled, promise, callback, detail) { + var hasCallback = isFunction(callback), + value = undefined, + error = undefined, + succeeded = undefined, + failed = undefined; + + if (hasCallback) { + value = tryCatch(callback, detail); + + if (value === TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value = null; + } else { + succeeded = true; + } + + if (promise === value) { + reject(promise, withOwnPromise()); + return; + } + } else { + value = detail; + succeeded = true; + } + + if (promise._state !== PENDING) { + // noop + } else if (hasCallback && succeeded) { + resolve(promise, value); + } else if (failed) { + reject(promise, error); + } else if (settled === FULFILLED) { + fulfill(promise, value); + } else if (settled === REJECTED) { + reject(promise, value); + } + } + + function initializePromise(promise, resolver) { + var resolved = false; + try { + resolver(function (value) { + if (resolved) { + return; + } + resolved = true; + resolve(promise, value); + }, function (reason) { + if (resolved) { + return; + } + resolved = true; + reject(promise, reason); + }); + } catch (e) { + reject(promise, e); + } + } + + function then(onFulfillment, onRejection, label) { + var _arguments = arguments; + + var parent = this; + var state = parent._state; + + if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { + config.instrument && instrument('chained', parent, parent); + return parent; + } + + parent._onError = null; + + var child = new parent.constructor(noop, label); + var result = parent._result; + + config.instrument && instrument('chained', parent, child); + + if (state) { + (function () { + var callback = _arguments[state - 1]; + config.async(function () { + return invokeCallback(state, child, callback, result); + }); + })(); + } else { + subscribe(parent, child, onFulfillment, onRejection); + } + + return child; + } + + function makeSettledResult(state, position, value) { + if (state === FULFILLED) { + return { + state: 'fulfilled', + value: value + }; + } else { + return { + state: 'rejected', + reason: value + }; + } + } + + function Enumerator(Constructor, input, abortOnReject, label) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop, label); + this._abortOnReject = abortOnReject; + + if (this._validateInput(input)) { + this._input = input; + this.length = input.length; + this._remaining = input.length; + + this._init(); + + if (this.length === 0) { + fulfill(this.promise, this._result); + } else { + this.length = this.length || 0; + this._enumerate(); + if (this._remaining === 0) { + fulfill(this.promise, this._result); + } + } + } else { + reject(this.promise, this._validationError()); + } + } + + Enumerator.prototype._validateInput = function (input) { + return isArray(input); + }; + + Enumerator.prototype._validationError = function () { + return new Error('Array Methods must be provided an Array'); + }; + + Enumerator.prototype._init = function () { + this._result = new Array(this.length); + }; + + Enumerator.prototype._enumerate = function () { + var length = this.length; + var promise = this.promise; + var input = this._input; + + for (var i = 0; promise._state === PENDING && i < length; i++) { + this._eachEntry(input[i], i); + } + }; + + Enumerator.prototype._settleMaybeThenable = function (entry, i) { + var c = this._instanceConstructor; + var resolve = c.resolve; + + if (resolve === resolve$1) { + var then$$ = getThen(entry); + + if (then$$ === then && entry._state !== PENDING) { + entry._onError = null; + this._settledAt(entry._state, i, entry._result); + } else if (typeof then$$ !== 'function') { + this._remaining--; + this._result[i] = this._makeResult(FULFILLED, i, entry); + } else if (c === Promise) { + var promise = new c(noop); + handleMaybeThenable(promise, entry, then$$); + this._willSettleAt(promise, i); + } else { + this._willSettleAt(new c(function (resolve) { + return resolve(entry); + }), i); + } + } else { + this._willSettleAt(resolve(entry), i); + } + }; + + Enumerator.prototype._eachEntry = function (entry, i) { + if (isMaybeThenable(entry)) { + this._settleMaybeThenable(entry, i); + } else { + this._remaining--; + this._result[i] = this._makeResult(FULFILLED, i, entry); + } + }; + + Enumerator.prototype._settledAt = function (state, i, value) { + var promise = this.promise; + + if (promise._state === PENDING) { + this._remaining--; + + if (this._abortOnReject && state === REJECTED) { + reject(promise, value); + } else { + this._result[i] = this._makeResult(state, i, value); + } + } + + if (this._remaining === 0) { + fulfill(promise, this._result); + } + }; + + Enumerator.prototype._makeResult = function (state, i, value) { + return value; + }; + + Enumerator.prototype._willSettleAt = function (promise, i) { + var enumerator = this; + + subscribe(promise, undefined, function (value) { + return enumerator._settledAt(FULFILLED, i, value); + }, function (reason) { + return enumerator._settledAt(REJECTED, i, reason); + }); + }; + + /** + `RSVP.Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.resolve(2); + let promise3 = RSVP.resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `RSVP.all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.reject(new Error("2")); + let promise3 = RSVP.reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static + */ + function all(entries, label) { + return new Enumerator(this, entries, true, /* abort on reject */label).promise; + } + + /** + `RSVP.Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + let promise1 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + RSVP.Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `RSVP.Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + let promise1 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + RSVP.Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} entries array of promises to observe + @param {String} label optional string for describing the promise returned. + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. + */ + function race(entries, label) { + /*jshint validthis:true */ + var Constructor = this; + + var promise = new Constructor(noop, label); + + if (!isArray(entries)) { + reject(promise, new TypeError('You must pass an array to race.')); + return promise; + } + + for (var i = 0; promise._state === PENDING && i < entries.length; i++) { + subscribe(Constructor.resolve(entries[i]), undefined, function (value) { + return resolve(promise, value); + }, function (reason) { + return reject(promise, reason); + }); + } + + return promise; + } + + /** + `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + let promise = new RSVP.Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = RSVP.Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {*} reason value that the returned promise will be rejected with. + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + function reject$1(reason, label) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(noop, label); + reject(promise, reason); + return promise; + } + + var guidKey = 'rsvp_' + now() + '-'; + var counter = 0; + + function needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); + } + + function needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); + } + + /** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise’s eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class RSVP.Promise + @param {function} resolver + @param {String} label optional string for labeling the promise. + Useful for tooling. + @constructor + */ + function Promise(resolver, label) { + this._id = counter++; + this._label = label; + this._state = undefined; + this._result = undefined; + this._subscribers = []; + + config.instrument && instrument('created', this); + + if (noop !== resolver) { + typeof resolver !== 'function' && needsResolver(); + this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + } + } + + Promise.cast = resolve$1; // deprecated + Promise.all = all; + Promise.race = race; + Promise.resolve = resolve$1; + Promise.reject = reject$1; + + Promise.prototype = { + constructor: Promise, + + _guidKey: guidKey, + + _onError: function _onError(reason) { + var promise = this; + config.after(function () { + if (promise._onError) { + config['trigger']('error', reason, promise._label); + } + }); + }, + + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + + Chaining + -------- + + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we\'re unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we\'re unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + + Assimilation + ------------ + + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + + If the assimliated promise rejects, then the downstream promise will also reject. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + + Simple Example + -------------- + + Synchronous Example + + ```javascript + let result; + + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + + Promise Example; + + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + + Advanced Example + -------------- + + Synchronous Example + + ```javascript + let author, books; + + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + + function foundBooks(books) { + + } + + function failure(reason) { + + } + + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + + Promise Example; + + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + + @method then + @param {Function} onFulfillment + @param {Function} onRejection + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + */ + then: then, + + /** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + + ```js + function findAuthor(){ + throw new Error('couldn\'t find that author'); + } + + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + + @method catch + @param {Function} onRejection + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + */ + 'catch': function _catch(onRejection, label) { + return this.then(undefined, onRejection, label); + }, + + /** + `finally` will be invoked regardless of the promise's fate just as native + try/catch/finally behaves + + Synchronous example: + + ```js + findAuthor() { + if (Math.random() > 0.5) { + throw new Error(); + } + return new Author(); + } + + try { + return findAuthor(); // succeed or fail + } catch(error) { + return findOtherAuther(); + } finally { + // always runs + // doesn't affect the return value + } + ``` + + Asynchronous example: + + ```js + findAuthor().catch(function(reason){ + return findOtherAuther(); + }).finally(function(){ + // author was either found, or not + }); + ``` + + @method finally + @param {Function} callback + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + */ + 'finally': function _finally(callback, label) { + var promise = this; + var constructor = promise.constructor; + + return promise.then(function (value) { + return constructor.resolve(callback()).then(function () { + return value; + }); + }, function (reason) { + return constructor.resolve(callback()).then(function () { + throw reason; + }); + }, label); + } + }; + + function Result() { + this.value = undefined; + } + + var ERROR = new Result(); + var GET_THEN_ERROR$1 = new Result(); + + function getThen$1(obj) { + try { + return obj.then; + } catch (error) { + ERROR.value = error; + return ERROR; + } + } + + function tryApply(f, s, a) { + try { + f.apply(s, a); + } catch (error) { + ERROR.value = error; + return ERROR; + } + } + + function makeObject(_, argumentNames) { + var obj = {}; + var length = _.length; + var args = new Array(length); + + for (var x = 0; x < length; x++) { + args[x] = _[x]; + } + + for (var i = 0; i < argumentNames.length; i++) { + var _name = argumentNames[i]; + obj[_name] = args[i + 1]; + } + + return obj; + } + + function arrayResult(_) { + var length = _.length; + var args = new Array(length - 1); + + for (var i = 1; i < length; i++) { + args[i - 1] = _[i]; + } + + return args; + } + + function wrapThenable(_then, promise) { + return { + then: function then(onFulFillment, onRejection) { + return _then.call(promise, onFulFillment, onRejection); + } + }; + } + + /** + `RSVP.denodeify` takes a 'node-style' function and returns a function that + will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the + browser when you'd prefer to use promises over using callbacks. For example, + `denodeify` transforms the following: + + ```javascript + let fs = require('fs'); + + fs.readFile('myfile.txt', function(err, data){ + if (err) return handleError(err); + handleData(data); + }); + ``` + + into: + + ```javascript + let fs = require('fs'); + let readFile = RSVP.denodeify(fs.readFile); + + readFile('myfile.txt').then(handleData, handleError); + ``` + + If the node function has multiple success parameters, then `denodeify` + just returns the first one: + + ```javascript + let request = RSVP.denodeify(require('request')); + + request('http://example.com').then(function(res) { + // ... + }); + ``` + + However, if you need all success parameters, setting `denodeify`'s + second parameter to `true` causes it to return all success parameters + as an array: + + ```javascript + let request = RSVP.denodeify(require('request'), true); + + request('http://example.com').then(function(result) { + // result[0] -> res + // result[1] -> body + }); + ``` + + Or if you pass it an array with names it returns the parameters as a hash: + + ```javascript + let request = RSVP.denodeify(require('request'), ['res', 'body']); + + request('http://example.com').then(function(result) { + // result.res + // result.body + }); + ``` + + Sometimes you need to retain the `this`: + + ```javascript + let app = require('express')(); + let render = RSVP.denodeify(app.render.bind(app)); + ``` + + The denodified function inherits from the original function. It works in all + environments, except IE 10 and below. Consequently all properties of the original + function are available to you. However, any properties you change on the + denodeified function won't be changed on the original function. Example: + + ```javascript + let request = RSVP.denodeify(require('request')), + cookieJar = request.jar(); // <- Inheritance is used here + + request('http://example.com', {jar: cookieJar}).then(function(res) { + // cookieJar.cookies holds now the cookies returned by example.com + }); + ``` + + Using `denodeify` makes it easier to compose asynchronous operations instead + of using callbacks. For example, instead of: + + ```javascript + let fs = require('fs'); + + fs.readFile('myfile.txt', function(err, data){ + if (err) { ... } // Handle error + fs.writeFile('myfile2.txt', data, function(err){ + if (err) { ... } // Handle error + console.log('done') + }); + }); + ``` + + you can chain the operations together using `then` from the returned promise: + + ```javascript + let fs = require('fs'); + let readFile = RSVP.denodeify(fs.readFile); + let writeFile = RSVP.denodeify(fs.writeFile); + + readFile('myfile.txt').then(function(data){ + return writeFile('myfile2.txt', data); + }).then(function(){ + console.log('done') + }).catch(function(error){ + // Handle error + }); + ``` + + @method denodeify + @static + @for RSVP + @param {Function} nodeFunc a 'node-style' function that takes a callback as + its last argument. The callback expects an error to be passed as its first + argument (if an error occurred, otherwise null), and the value from the + operation as its second argument ('function(err, value){ }'). + @param {Boolean|Array} [options] An optional paramter that if set + to `true` causes the promise to fulfill with the callback's success arguments + as an array. This is useful if the node function has multiple success + paramters. If you set this paramter to an array with names, the promise will + fulfill with a hash with these names as keys and the success parameters as + values. + @return {Function} a function that wraps `nodeFunc` to return an + `RSVP.Promise` + @static + */ + function denodeify(nodeFunc, options) { + var fn = function fn() { + var self = this; + var l = arguments.length; + var args = new Array(l + 1); + var promiseInput = false; + + for (var i = 0; i < l; ++i) { + var arg = arguments[i]; + + if (!promiseInput) { + // TODO: clean this up + promiseInput = needsPromiseInput(arg); + if (promiseInput === GET_THEN_ERROR$1) { + var p = new Promise(noop); + reject(p, GET_THEN_ERROR$1.value); + return p; + } else if (promiseInput && promiseInput !== true) { + arg = wrapThenable(promiseInput, arg); + } + } + args[i] = arg; + } + + var promise = new Promise(noop); + + args[l] = function (err, val) { + if (err) reject(promise, err);else if (options === undefined) resolve(promise, val);else if (options === true) resolve(promise, arrayResult(arguments));else if (isArray(options)) resolve(promise, makeObject(arguments, options));else resolve(promise, val); + }; + + if (promiseInput) { + return handlePromiseInput(promise, args, nodeFunc, self); + } else { + return handleValueInput(promise, args, nodeFunc, self); + } + }; + + fn.__proto__ = nodeFunc; + + return fn; + } + + function handleValueInput(promise, args, nodeFunc, self) { + var result = tryApply(nodeFunc, self, args); + if (result === ERROR) { + reject(promise, result.value); + } + return promise; + } + + function handlePromiseInput(promise, args, nodeFunc, self) { + return Promise.all(args).then(function (args) { + var result = tryApply(nodeFunc, self, args); + if (result === ERROR) { + reject(promise, result.value); + } + return promise; + }); + } + + function needsPromiseInput(arg) { + if (arg && typeof arg === 'object') { + if (arg.constructor === Promise) { + return true; + } else { + return getThen$1(arg); + } + } else { + return false; + } + } + + /** + This is a convenient alias for `RSVP.Promise.all`. + + @method all + @static + @for RSVP + @param {Array} array Array of promises. + @param {String} label An optional label. This is useful + for tooling. + */ + function all$1(array, label) { + return Promise.all(array, label); + } + + function AllSettled(Constructor, entries, label) { + this._superConstructor(Constructor, entries, false, /* don't abort on reject */label); + } + + AllSettled.prototype = o_create(Enumerator.prototype); + AllSettled.prototype._superConstructor = Enumerator; + AllSettled.prototype._makeResult = makeSettledResult; + AllSettled.prototype._validationError = function () { + return new Error('allSettled must be called with an array'); + }; + + /** + `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing + a fail-fast method, it waits until all the promises have returned and + shows you all the results. This is useful if you want to handle multiple + promises' failure states together as a set. + + Returns a promise that is fulfilled when all the given promises have been + settled. The return promise is fulfilled with an array of the states of + the promises passed into the `promises` array argument. + + Each state object will either indicate fulfillment or rejection, and + provide the corresponding value or reason. The states will take one of + the following formats: + + ```javascript + { state: 'fulfilled', value: value } + or + { state: 'rejected', reason: reason } + ``` + + Example: + + ```javascript + let promise1 = RSVP.Promise.resolve(1); + let promise2 = RSVP.Promise.reject(new Error('2')); + let promise3 = RSVP.Promise.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.allSettled(promises).then(function(array){ + // array == [ + // { state: 'fulfilled', value: 1 }, + // { state: 'rejected', reason: Error }, + // { state: 'rejected', reason: Error } + // ] + // Note that for the second item, reason.message will be '2', and for the + // third item, reason.message will be '3'. + }, function(error) { + // Not run. (This block would only be called if allSettled had failed, + // for instance if passed an incorrect argument type.) + }); + ``` + + @method allSettled + @static + @for RSVP + @param {Array} entries + @param {String} label - optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled with an array of the settled + states of the constituent promises. + */ + function allSettled(entries, label) { + return new AllSettled(Promise, entries, label).promise; + } + + /** + This is a convenient alias for `RSVP.Promise.race`. + + @method race + @static + @for RSVP + @param {Array} array Array of promises. + @param {String} label An optional label. This is useful + for tooling. + */ + function race$1(array, label) { + return Promise.race(array, label); + } + + function PromiseHash(Constructor, object, label) { + this._superConstructor(Constructor, object, true, label); + } + + PromiseHash.prototype = o_create(Enumerator.prototype); + PromiseHash.prototype._superConstructor = Enumerator; + PromiseHash.prototype._init = function () { + this._result = {}; + }; + + PromiseHash.prototype._validateInput = function (input) { + return input && typeof input === 'object'; + }; + + PromiseHash.prototype._validationError = function () { + return new Error('Promise.hash must be called with an object'); + }; + + PromiseHash.prototype._enumerate = function () { + var enumerator = this; + var promise = enumerator.promise; + var input = enumerator._input; + var results = []; + + for (var key in input) { + if (promise._state === PENDING && Object.prototype.hasOwnProperty.call(input, key)) { + results.push({ + position: key, + entry: input[key] + }); + } + } + + var length = results.length; + enumerator._remaining = length; + var result = undefined; + + for (var i = 0; promise._state === PENDING && i < length; i++) { + result = results[i]; + enumerator._eachEntry(result.entry, result.position); + } + }; + + /** + `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array + for its `promises` argument. + + Returns a promise that is fulfilled when all the given promises have been + fulfilled, or rejected if any of them become rejected. The returned promise + is fulfilled with a hash that has the same key names as the `promises` object + argument. If any of the values in the object are not promises, they will + simply be copied over to the fulfilled object. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.resolve(1), + yourPromise: RSVP.resolve(2), + theirPromise: RSVP.resolve(3), + notAPromise: 4 + }; + + RSVP.hash(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: 1, + // yourPromise: 2, + // theirPromise: 3, + // notAPromise: 4 + // } + }); + ```` + + If any of the `promises` given to `RSVP.hash` are rejected, the first promise + that is rejected will be given as the reason to the rejection handler. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.resolve(1), + rejectedPromise: RSVP.reject(new Error('rejectedPromise')), + anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')), + }; + + RSVP.hash(promises).then(function(hash){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === 'rejectedPromise' + }); + ``` + + An important note: `RSVP.hash` is intended for plain JavaScript objects that + are just a set of keys and values. `RSVP.hash` will NOT preserve prototype + chains. + + Example: + + ```javascript + function MyConstructor(){ + this.example = RSVP.resolve('Example'); + } + + MyConstructor.prototype = { + protoProperty: RSVP.resolve('Proto Property') + }; + + let myObject = new MyConstructor(); + + RSVP.hash(myObject).then(function(hash){ + // protoProperty will not be present, instead you will just have an + // object that looks like: + // { + // example: 'Example' + // } + // + // hash.hasOwnProperty('protoProperty'); // false + // 'undefined' === typeof hash.protoProperty + }); + ``` + + @method hash + @static + @for RSVP + @param {Object} object + @param {String} label optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all properties of `promises` + have been fulfilled, or rejected if any of them become rejected. + */ + function hash(object, label) { + return new PromiseHash(Promise, object, label).promise; + } + + function HashSettled(Constructor, object, label) { + this._superConstructor(Constructor, object, false, label); + } + + HashSettled.prototype = o_create(PromiseHash.prototype); + HashSettled.prototype._superConstructor = Enumerator; + HashSettled.prototype._makeResult = makeSettledResult; + + HashSettled.prototype._validationError = function () { + return new Error('hashSettled must be called with an object'); + }; + + /** + `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object + instead of an array for its `promises` argument. + + Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method, + but like `RSVP.allSettled`, `hashSettled` waits until all the + constituent promises have returned and then shows you all the results + with their states and values/reasons. This is useful if you want to + handle multiple promises' failure states together as a set. + + Returns a promise that is fulfilled when all the given promises have been + settled, or rejected if the passed parameters are invalid. + + The returned promise is fulfilled with a hash that has the same key names as + the `promises` object argument. If any of the values in the object are not + promises, they will be copied over to the fulfilled object and marked with state + 'fulfilled'. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.Promise.resolve(1), + yourPromise: RSVP.Promise.resolve(2), + theirPromise: RSVP.Promise.resolve(3), + notAPromise: 4 + }; + + RSVP.hashSettled(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: { state: 'fulfilled', value: 1 }, + // yourPromise: { state: 'fulfilled', value: 2 }, + // theirPromise: { state: 'fulfilled', value: 3 }, + // notAPromise: { state: 'fulfilled', value: 4 } + // } + }); + ``` + + If any of the `promises` given to `RSVP.hash` are rejected, the state will + be set to 'rejected' and the reason for rejection provided. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.Promise.resolve(1), + rejectedPromise: RSVP.Promise.reject(new Error('rejection')), + anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')), + }; + + RSVP.hashSettled(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: { state: 'fulfilled', value: 1 }, + // rejectedPromise: { state: 'rejected', reason: Error }, + // anotherRejectedPromise: { state: 'rejected', reason: Error }, + // } + // Note that for rejectedPromise, reason.message == 'rejection', + // and for anotherRejectedPromise, reason.message == 'more rejection'. + }); + ``` + + An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that + are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype + chains. + + Example: + + ```javascript + function MyConstructor(){ + this.example = RSVP.Promise.resolve('Example'); + } + + MyConstructor.prototype = { + protoProperty: RSVP.Promise.resolve('Proto Property') + }; + + let myObject = new MyConstructor(); + + RSVP.hashSettled(myObject).then(function(hash){ + // protoProperty will not be present, instead you will just have an + // object that looks like: + // { + // example: { state: 'fulfilled', value: 'Example' } + // } + // + // hash.hasOwnProperty('protoProperty'); // false + // 'undefined' === typeof hash.protoProperty + }); + ``` + + @method hashSettled + @for RSVP + @param {Object} object + @param {String} label optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when when all properties of `promises` + have been settled. + @static + */ + function hashSettled(object, label) { + return new HashSettled(Promise, object, label).promise; + } + + function rethrow(reason) { + setTimeout(function () { + throw reason; + }); + throw reason; + } + + /** + `RSVP.defer` returns an object similar to jQuery's `$.Deferred`. + `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s + interface. New code should use the `RSVP.Promise` constructor instead. + + The object returned from `RSVP.defer` is a plain object with three properties: + + * promise - an `RSVP.Promise`. + * reject - a function that causes the `promise` property on this object to + become rejected + * resolve - a function that causes the `promise` property on this object to + become fulfilled. + + Example: + + ```javascript + let deferred = RSVP.defer(); + + deferred.resolve("Success!"); + + deferred.promise.then(function(value){ + // value here is "Success!" + }); + ``` + + @method defer + @static + @for RSVP + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Object} + */ + function defer(label) { + var deferred = { resolve: undefined, reject: undefined }; + + deferred.promise = new Promise(function (resolve, reject) { + deferred.resolve = resolve; + deferred.reject = reject; + }, label); + + return deferred; + } + + /** + `RSVP.map` is similar to JavaScript's native `map` method, except that it + waits for all promises to become fulfilled before running the `mapFn` on + each item in given to `promises`. `RSVP.map` returns a promise that will + become fulfilled with the result of running `mapFn` on the values the promises + become fulfilled with. + + For example: + + ```javascript + + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.resolve(2); + let promise3 = RSVP.resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + let mapFn = function(item){ + return item + 1; + }; + + RSVP.map(promises, mapFn).then(function(result){ + // result is [ 2, 3, 4 ] + }); + ``` + + If any of the `promises` given to `RSVP.map` are rejected, the first promise + that is rejected will be given as an argument to the returned promise's + rejection handler. For example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.reject(new Error('2')); + let promise3 = RSVP.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + let mapFn = function(item){ + return item + 1; + }; + + RSVP.map(promises, mapFn).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === '2' + }); + ``` + + `RSVP.map` will also wait if a promise is returned from `mapFn`. For example, + say you want to get all comments from a set of blog posts, but you need + the blog posts first because they contain a url to those comments. + + ```javscript + + let mapFn = function(blogPost){ + // getComments does some ajax and returns an RSVP.Promise that is fulfilled + // with some comments data + return getComments(blogPost.comments_url); + }; + + // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled + // with some blog post data + RSVP.map(getBlogPosts(), mapFn).then(function(comments){ + // comments is the result of asking the server for the comments + // of all blog posts returned from getBlogPosts() + }); + ``` + + @method map + @static + @for RSVP + @param {Array} promises + @param {Function} mapFn function to be called on each fulfilled promise. + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled with the result of calling + `mapFn` on each fulfilled promise or value when they become fulfilled. + The promise will be rejected if any of the given `promises` become rejected. + @static + */ + function map(promises, mapFn, label) { + return Promise.all(promises, label).then(function (values) { + if (!isFunction(mapFn)) { + throw new TypeError("You must pass a function as map's second argument."); + } + + var length = values.length; + var results = new Array(length); + + for (var i = 0; i < length; i++) { + results[i] = mapFn(values[i]); + } + + return Promise.all(results, label); + }); + } + + /** + This is a convenient alias for `RSVP.Promise.resolve`. + + @method resolve + @static + @for RSVP + @param {*} value value that the returned promise will be resolved with + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` + */ + function resolve$2(value, label) { + return Promise.resolve(value, label); + } + + /** + This is a convenient alias for `RSVP.Promise.reject`. + + @method reject + @static + @for RSVP + @param {*} reason value that the returned promise will be rejected with. + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + function reject$2(reason, label) { + return Promise.reject(reason, label); + } + + /** + `RSVP.filter` is similar to JavaScript's native `filter` method, except that it + waits for all promises to become fulfilled before running the `filterFn` on + each item in given to `promises`. `RSVP.filter` returns a promise that will + become fulfilled with the result of running `filterFn` on the values the + promises become fulfilled with. + + For example: + + ```javascript + + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.resolve(2); + let promise3 = RSVP.resolve(3); + + let promises = [promise1, promise2, promise3]; + + let filterFn = function(item){ + return item > 1; + }; + + RSVP.filter(promises, filterFn).then(function(result){ + // result is [ 2, 3 ] + }); + ``` + + If any of the `promises` given to `RSVP.filter` are rejected, the first promise + that is rejected will be given as an argument to the returned promise's + rejection handler. For example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.reject(new Error('2')); + let promise3 = RSVP.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + let filterFn = function(item){ + return item > 1; + }; + + RSVP.filter(promises, filterFn).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === '2' + }); + ``` + + `RSVP.filter` will also wait for any promises returned from `filterFn`. + For instance, you may want to fetch a list of users then return a subset + of those users based on some asynchronous operation: + + ```javascript + + let alice = { name: 'alice' }; + let bob = { name: 'bob' }; + let users = [ alice, bob ]; + + let promises = users.map(function(user){ + return RSVP.resolve(user); + }); + + let filterFn = function(user){ + // Here, Alice has permissions to create a blog post, but Bob does not. + return getPrivilegesForUser(user).then(function(privs){ + return privs.can_create_blog_post === true; + }); + }; + RSVP.filter(promises, filterFn).then(function(users){ + // true, because the server told us only Alice can create a blog post. + users.length === 1; + // false, because Alice is the only user present in `users` + users[0] === bob; + }); + ``` + + @method filter + @static + @for RSVP + @param {Array} promises + @param {Function} filterFn - function to be called on each resolved value to + filter the final results. + @param {String} label optional string describing the promise. Useful for + tooling. + @return {Promise} + */ + + function resolveAll(promises, label) { + return Promise.all(promises, label); + } + + function resolveSingle(promise, label) { + return Promise.resolve(promise, label).then(function (promises) { + return resolveAll(promises, label); + }); + } + function filter(promises, filterFn, label) { + var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label); + return promise.then(function (values) { + if (!isFunction(filterFn)) { + throw new TypeError("You must pass a function as filter's second argument."); + } + + var length = values.length; + var filtered = new Array(length); + + for (var i = 0; i < length; i++) { + filtered[i] = filterFn(values[i]); + } + + return resolveAll(filtered, label).then(function (filtered) { + var results = new Array(length); + var newLength = 0; + + for (var i = 0; i < length; i++) { + if (filtered[i]) { + results[newLength] = values[i]; + newLength++; + } + } + + results.length = newLength; + + return results; + }); + }); + } + + var len = 0; + var vertxNext = undefined; + function asap(callback, arg) { + queue$1[len] = callback; + queue$1[len + 1] = arg; + len += 2; + if (len === 2) { + // If len is 1, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + scheduleFlush$1(); + } + } + + var browserWindow = typeof window !== 'undefined' ? window : undefined; + var browserGlobal = browserWindow || {}; + var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; + var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; + + // test for web worker but not in IE10 + var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; + + // node + function useNextTick() { + var nextTick = process.nextTick; + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // setImmediate should be used instead instead + var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/); + if (Array.isArray(version) && version[1] === '0' && version[2] === '10') { + nextTick = setImmediate; + } + return function () { + return nextTick(flush); + }; + } + + // vertx + function useVertxTimer() { + return function () { + return vertxNext(flush); + }; + } + + function useMutationObserver() { + var iterations = 0; + var observer = new BrowserMutationObserver(flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + + return function () { + return node.data = iterations = ++iterations % 2; + }; + } + + // web worker + function useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = flush; + return function () { + return channel.port2.postMessage(0); + }; + } + + function useSetTimeout() { + return function () { + return setTimeout(flush, 1); + }; + } + + var queue$1 = new Array(1000); + + function flush() { + for (var i = 0; i < len; i += 2) { + var callback = queue$1[i]; + var arg = queue$1[i + 1]; + + callback(arg); + + queue$1[i] = undefined; + queue$1[i + 1] = undefined; + } + + len = 0; + } + + function attemptVertex() { + try { + var r = require; + var vertx = __webpack_require__(5); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch (e) { + return useSetTimeout(); + } + } + + var scheduleFlush$1 = undefined; + // Decide what async method to use to triggering processing of queued callbacks: + if (isNode) { + scheduleFlush$1 = useNextTick(); + } else if (BrowserMutationObserver) { + scheduleFlush$1 = useMutationObserver(); + } else if (isWorker) { + scheduleFlush$1 = useMessageChannel(); + } else if (browserWindow === undefined && "function" === 'function') { + scheduleFlush$1 = attemptVertex(); + } else { + scheduleFlush$1 = useSetTimeout(); + } + + var platform = undefined; + + /* global self */ + if (typeof self === 'object') { + platform = self; + + /* global global */ + } else if (typeof global === 'object') { + platform = global; + } else { + throw new Error('no global: `self` or `global` found'); + } + + var _async$filter; + + function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + + // defaults + + // the default export here is for backwards compat: + // https://github.com/tildeio/rsvp.js/issues/434 + config.async = asap; + config.after = function (cb) { + return setTimeout(cb, 0); + }; + var cast = resolve$2; + + var async = function async(callback, arg) { + return config.async(callback, arg); + }; + + function on() { + config['on'].apply(config, arguments); + } + + function off() { + config['off'].apply(config, arguments); + } + + // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` + if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { + var callbacks = window['__PROMISE_INSTRUMENTATION__']; + configure('instrument', true); + for (var eventName in callbacks) { + if (callbacks.hasOwnProperty(eventName)) { + on(eventName, callbacks[eventName]); + } + } + }var rsvp = (_async$filter = { + cast: cast, + Promise: Promise, + EventTarget: EventTarget, + all: all$1, + allSettled: allSettled, + race: race$1, + hash: hash, + hashSettled: hashSettled, + rethrow: rethrow, + defer: defer, + denodeify: denodeify, + configure: configure, + on: on, + off: off, + resolve: resolve$2, + reject: reject$2, + map: map + }, _defineProperty(_async$filter, 'async', async), _defineProperty(_async$filter, 'filter', // babel seems to error if async isn't a computed prop here... + filter), _async$filter); + + exports['default'] = rsvp; + exports.cast = cast; + exports.Promise = Promise; + exports.EventTarget = EventTarget; + exports.all = all$1; + exports.allSettled = allSettled; + exports.race = race$1; + exports.hash = hash; + exports.hashSettled = hashSettled; + exports.rethrow = rethrow; + exports.defer = defer; + exports.denodeify = denodeify; + exports.configure = configure; + exports.on = on; + exports.off = off; + exports.resolve = resolve$2; + exports.reject = reject$2; + exports.map = map; + exports.async = async; + exports.filter = filter; + + Object.defineProperty(exports, '__esModule', { value: true }); + + }))); + //# sourceMappingURL=rsvp.map + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(3), __webpack_require__(4).setImmediate, (function() { return this; }()))) -Contents.prototype.listeners = function() { +/***/ }, +/* 3 */ +/***/ function(module, exports) { - this.imageLoadListeners(); + // shim for using process in browser + var process = module.exports = {}; + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; - this.mediaQueryListeners(); - // this.fontLoadListeners(); +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { - this.addEventListeners(); + /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(3).nextTick; + var apply = Function.prototype.apply; + var slice = Array.prototype.slice; + var immediateIds = {}; + var nextImmediateId = 0; + + // DOM APIs, for completeness + + exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); + }; + exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); + }; + exports.clearTimeout = + exports.clearInterval = function(timeout) { timeout.close(); }; + + function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; + } + Timeout.prototype.unref = Timeout.prototype.ref = function() {}; + Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); + }; + + // Does not start the time, just sets up the members needed. + exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; + }; + + exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; + }; + + exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); + } + }; + + // That's not how node.js implements it but the exposed api is the same. + exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { + var id = nextImmediateId++; + var args = arguments.length < 2 ? false : slice.call(arguments, 1); + + immediateIds[id] = true; + + nextTick(function onNextTick() { + if (immediateIds[id]) { + // fn.call() is faster so we optimize for the common use-case + // @see http://jsperf.com/call-apply-segu + if (args) { + fn.apply(null, args); + } else { + fn.call(null); + } + // Prevent ids from leaking + exports.clearImmediate(id); + } + }); + + return id; + }; + + exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { + delete immediateIds[id]; + }; + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4).setImmediate, __webpack_require__(4).clearImmediate)) - this.addSelectionListeners(); +/***/ }, +/* 5 */ +/***/ function(module, exports) { - this.resizeListeners(); + /* (ignored) */ -}; +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { -Contents.prototype.removeListeners = function() { + /*! + * URI.js - Mutating URLs + * + * Version: 1.18.1 + * + * Author: Rodney Rehm + * Web: http://medialize.github.io/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * + */ + (function (root, factory) { + 'use strict'; + // https://github.com/umdjs/umd/blob/master/returnExports.js + if (true) { + // Node + module.exports = factory(__webpack_require__(7), __webpack_require__(9), __webpack_require__(10)); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['./punycode', './IPv6', './SecondLevelDomains'], factory); + } else { + // Browser globals (root is window) + root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root); + } + }(this, function (punycode, IPv6, SLD, root) { + 'use strict'; + /*global location, escape, unescape */ + // FIXME: v2.0.0 renamce non-camelCase properties to uppercase + /*jshint camelcase: false */ + + // save current URI variable, if any + var _URI = root && root.URI; + + function URI(url, base) { + var _urlSupplied = arguments.length >= 1; + var _baseSupplied = arguments.length >= 2; + + // Allow instantiation without the 'new' keyword + if (!(this instanceof URI)) { + if (_urlSupplied) { + if (_baseSupplied) { + return new URI(url, base); + } + + return new URI(url); + } + + return new URI(); + } + + if (url === undefined) { + if (_urlSupplied) { + throw new TypeError('undefined is not a valid argument for URI'); + } + + if (typeof location !== 'undefined') { + url = location.href + ''; + } else { + url = ''; + } + } + + this.href(url); + + // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor + if (base !== undefined) { + return this.absoluteTo(base); + } + + return this; + } + + URI.version = '1.18.1'; + + var p = URI.prototype; + var hasOwn = Object.prototype.hasOwnProperty; + + function escapeRegEx(string) { + // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 + return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); + } + + function getType(value) { + // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value + if (value === undefined) { + return 'Undefined'; + } + + return String(Object.prototype.toString.call(value)).slice(8, -1); + } + + function isArray(obj) { + return getType(obj) === 'Array'; + } + + function filterArrayValues(data, value) { + var lookup = {}; + var i, length; + + if (getType(value) === 'RegExp') { + lookup = null; + } else if (isArray(value)) { + for (i = 0, length = value.length; i < length; i++) { + lookup[value[i]] = true; + } + } else { + lookup[value] = true; + } + + for (i = 0, length = data.length; i < length; i++) { + /*jshint laxbreak: true */ + var _match = lookup && lookup[data[i]] !== undefined + || !lookup && value.test(data[i]); + /*jshint laxbreak: false */ + if (_match) { + data.splice(i, 1); + length--; + i--; + } + } + + return data; + } + + function arrayContains(list, value) { + var i, length; + + // value may be string, number, array, regexp + if (isArray(value)) { + // Note: this can be optimized to O(n) (instead of current O(m * n)) + for (i = 0, length = value.length; i < length; i++) { + if (!arrayContains(list, value[i])) { + return false; + } + } + + return true; + } + + var _type = getType(value); + for (i = 0, length = list.length; i < length; i++) { + if (_type === 'RegExp') { + if (typeof list[i] === 'string' && list[i].match(value)) { + return true; + } + } else if (list[i] === value) { + return true; + } + } + + return false; + } + + function arraysEqual(one, two) { + if (!isArray(one) || !isArray(two)) { + return false; + } + + // arrays can't be equal if they have different amount of content + if (one.length !== two.length) { + return false; + } + + one.sort(); + two.sort(); + + for (var i = 0, l = one.length; i < l; i++) { + if (one[i] !== two[i]) { + return false; + } + } + + return true; + } + + function trimSlashes(text) { + var trim_expression = /^\/+|\/+$/g; + return text.replace(trim_expression, ''); + } + + URI._parts = function() { + return { + protocol: null, + username: null, + password: null, + hostname: null, + urn: null, + port: null, + path: null, + query: null, + fragment: null, + // state + duplicateQueryParameters: URI.duplicateQueryParameters, + escapeQuerySpace: URI.escapeQuerySpace + }; + }; + // state: allow duplicate query parameters (a=1&a=1) + URI.duplicateQueryParameters = false; + // state: replaces + with %20 (space in query strings) + URI.escapeQuerySpace = true; + // static properties + URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i; + URI.idn_expression = /[^a-z0-9\.-]/i; + URI.punycode_expression = /(xn--)/i; + // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care? + URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + // credits to Rich Brown + // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 + // specification: http://www.ietf.org/rfc/rfc4291.txt + 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*$/; + // expression used is "gruber revised" (@gruber v2) determined to be the + // best solution in a regex-golf we did a couple of ages ago at + // * http://mathiasbynens.be/demo/url-regex + // * http://rodneyrehm.de/t/url-regex.html + 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; + URI.findUri = { + // valid "scheme://" or "www." + start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi, + // everything up to the next whitespace + end: /[\s\r\n]|$/, + // trim trailing punctuation captured by end RegExp + trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/ + }; + // http://www.iana.org/assignments/uri-schemes.html + // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports + URI.defaultPorts = { + http: '80', + https: '443', + ftp: '21', + gopher: '70', + ws: '80', + wss: '443' + }; + // allowed hostname characters according to RFC 3986 + // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded + // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - + URI.invalid_hostname_characters = /[^a-zA-Z0-9\.-]/; + // map DOM Elements to their URI attribute + URI.domAttributes = { + 'a': 'href', + 'blockquote': 'cite', + 'link': 'href', + 'base': 'href', + 'script': 'src', + 'form': 'action', + 'img': 'src', + 'area': 'href', + 'iframe': 'src', + 'embed': 'src', + 'source': 'src', + 'track': 'src', + 'input': 'src', // but only if type="image" + 'audio': 'src', + 'video': 'src' + }; + URI.getDomAttribute = function(node) { + if (!node || !node.nodeName) { + return undefined; + } + + var nodeName = node.nodeName.toLowerCase(); + // should only expose src for type="image" + if (nodeName === 'input' && node.type !== 'image') { + return undefined; + } + + return URI.domAttributes[nodeName]; + }; + + function escapeForDumbFirefox36(value) { + // https://github.com/medialize/URI.js/issues/91 + return escape(value); + } + + // encoding / decoding according to RFC3986 + function strictEncodeURIComponent(string) { + // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent + return encodeURIComponent(string) + .replace(/[!'()*]/g, escapeForDumbFirefox36) + .replace(/\*/g, '%2A'); + } + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + URI.iso8859 = function() { + URI.encode = escape; + URI.decode = unescape; + }; + URI.unicode = function() { + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + }; + URI.characters = { + pathname: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig, + map: { + // -._~!'()* + '%24': '$', + '%26': '&', + '%2B': '+', + '%2C': ',', + '%3B': ';', + '%3D': '=', + '%3A': ':', + '%40': '@' + } + }, + decode: { + expression: /[\/\?#]/g, + map: { + '/': '%2F', + '?': '%3F', + '#': '%23' + } + } + }, + reserved: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig, + map: { + // gen-delims + '%3A': ':', + '%2F': '/', + '%3F': '?', + '%23': '#', + '%5B': '[', + '%5D': ']', + '%40': '@', + // sub-delims + '%21': '!', + '%24': '$', + '%26': '&', + '%27': '\'', + '%28': '(', + '%29': ')', + '%2A': '*', + '%2B': '+', + '%2C': ',', + '%3B': ';', + '%3D': '=' + } + } + }, + urnpath: { + // The characters under `encode` are the characters called out by RFC 2141 as being acceptable + // for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but + // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also + // note that the colon character is not featured in the encoding map; this is because URI.js + // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it + // should not appear unencoded in a segment itself. + // See also the note above about RFC3986 and capitalalized hex digits. + encode: { + expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig, + map: { + '%21': '!', + '%24': '$', + '%27': '\'', + '%28': '(', + '%29': ')', + '%2A': '*', + '%2B': '+', + '%2C': ',', + '%3B': ';', + '%3D': '=', + '%40': '@' + } + }, + // These characters are the characters called out by RFC2141 as "reserved" characters that + // should never appear in a URN, plus the colon character (see note above). + decode: { + expression: /[\/\?#:]/g, + map: { + '/': '%2F', + '?': '%3F', + '#': '%23', + ':': '%3A' + } + } + } + }; + URI.encodeQuery = function(string, escapeQuerySpace) { + var escaped = URI.encode(string + ''); + if (escapeQuerySpace === undefined) { + escapeQuerySpace = URI.escapeQuerySpace; + } + + return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped; + }; + URI.decodeQuery = function(string, escapeQuerySpace) { + string += ''; + if (escapeQuerySpace === undefined) { + escapeQuerySpace = URI.escapeQuerySpace; + } + + try { + return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string); + } catch(e) { + // we're not going to mess with weird encodings, + // give up and return the undecoded original string + // see https://github.com/medialize/URI.js/issues/87 + // see https://github.com/medialize/URI.js/issues/92 + return string; + } + }; + // generate encode/decode path functions + var _parts = {'encode':'encode', 'decode':'decode'}; + var _part; + var generateAccessor = function(_group, _part) { + return function(string) { + try { + return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) { + return URI.characters[_group][_part].map[c]; + }); + } catch (e) { + // we're not going to mess with weird encodings, + // give up and return the undecoded original string + // see https://github.com/medialize/URI.js/issues/87 + // see https://github.com/medialize/URI.js/issues/92 + return string; + } + }; + }; + + for (_part in _parts) { + URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]); + URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]); + } + + var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) { + return function(string) { + // Why pass in names of functions, rather than the function objects themselves? The + // definitions of some functions (but in particular, URI.decode) will occasionally change due + // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure + // that the functions we use here are "fresh". + var actualCodingFunc; + if (!_innerCodingFuncName) { + actualCodingFunc = URI[_codingFuncName]; + } else { + actualCodingFunc = function(string) { + return URI[_codingFuncName](URI[_innerCodingFuncName](string)); + }; + } + + var segments = (string + '').split(_sep); + + for (var i = 0, length = segments.length; i < length; i++) { + segments[i] = actualCodingFunc(segments[i]); + } + + return segments.join(_sep); + }; + }; + + // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions. + URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment'); + URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment'); + URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode'); + URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode'); + + URI.encodeReserved = generateAccessor('reserved', 'encode'); + + URI.parse = function(string, parts) { + var pos; + if (!parts) { + parts = {}; + } + // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] + + // extract fragment + pos = string.indexOf('#'); + if (pos > -1) { + // escaping? + parts.fragment = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + + // extract query + pos = string.indexOf('?'); + if (pos > -1) { + // escaping? + parts.query = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + + // extract protocol + if (string.substring(0, 2) === '//') { + // relative-scheme + parts.protocol = null; + string = string.substring(2); + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + pos = string.indexOf(':'); + if (pos > -1) { + parts.protocol = string.substring(0, pos) || null; + if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) { + // : may be within the path + parts.protocol = undefined; + } else if (string.substring(pos + 1, pos + 3) === '//') { + string = string.substring(pos + 3); + + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + string = string.substring(pos + 1); + parts.urn = true; + } + } + } + + // what's left must be the path + parts.path = string; + + // and we're done + return parts; + }; + URI.parseHost = function(string, parts) { + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + // https://github.com/medialize/URI.js/pull/233 + string = string.replace(/\\/g, '/'); + + // extract host:port + var pos = string.indexOf('/'); + var bracketPos; + var t; + + if (pos === -1) { + pos = string.length; + } + + if (string.charAt(0) === '[') { + // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 + // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts + // IPv6+port in the format [2001:db8::1]:80 (for the time being) + bracketPos = string.indexOf(']'); + parts.hostname = string.substring(1, bracketPos) || null; + parts.port = string.substring(bracketPos + 2, pos) || null; + if (parts.port === '/') { + parts.port = null; + } + } else { + var firstColon = string.indexOf(':'); + var firstSlash = string.indexOf('/'); + var nextColon = string.indexOf(':', firstColon + 1); + if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) { + // IPv6 host contains multiple colons - but no port + // this notation is actually not allowed by RFC 3986, but we're a liberal parser + parts.hostname = string.substring(0, pos) || null; + parts.port = null; + } else { + t = string.substring(0, pos).split(':'); + parts.hostname = t[0] || null; + parts.port = t[1] || null; + } + } + + if (parts.hostname && string.substring(pos).charAt(0) !== '/') { + pos++; + string = '/' + string; + } + + return string.substring(pos) || '/'; + }; + URI.parseAuthority = function(string, parts) { + string = URI.parseUserinfo(string, parts); + return URI.parseHost(string, parts); + }; + URI.parseUserinfo = function(string, parts) { + // extract username:password + var firstSlash = string.indexOf('/'); + var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); + var t; + + // authority@ must come before /path + if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { + t = string.substring(0, pos).split(':'); + parts.username = t[0] ? URI.decode(t[0]) : null; + t.shift(); + parts.password = t[0] ? URI.decode(t.join(':')) : null; + string = string.substring(pos + 1); + } else { + parts.username = null; + parts.password = null; + } + + return string; + }; + URI.parseQuery = function(string, escapeQuerySpace) { + if (!string) { + return {}; + } + + // throw out the funky business - "?"[name"="value"&"]+ + string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, ''); + + if (!string) { + return {}; + } + + var items = {}; + var splits = string.split('&'); + var length = splits.length; + var v, name, value; + + for (var i = 0; i < length; i++) { + v = splits[i].split('='); + name = URI.decodeQuery(v.shift(), escapeQuerySpace); + // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters + value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null; + + if (hasOwn.call(items, name)) { + if (typeof items[name] === 'string' || items[name] === null) { + items[name] = [items[name]]; + } + + items[name].push(value); + } else { + items[name] = value; + } + } + + return items; + }; + + URI.build = function(parts) { + var t = ''; + + if (parts.protocol) { + t += parts.protocol + ':'; + } + + if (!parts.urn && (t || parts.hostname)) { + t += '//'; + } + + t += (URI.buildAuthority(parts) || ''); + + if (typeof parts.path === 'string') { + if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') { + t += '/'; + } + + t += parts.path; + } + + if (typeof parts.query === 'string' && parts.query) { + t += '?' + parts.query; + } + + if (typeof parts.fragment === 'string' && parts.fragment) { + t += '#' + parts.fragment; + } + return t; + }; + URI.buildHost = function(parts) { + var t = ''; + + if (!parts.hostname) { + return ''; + } else if (URI.ip6_expression.test(parts.hostname)) { + t += '[' + parts.hostname + ']'; + } else { + t += parts.hostname; + } + + if (parts.port) { + t += ':' + parts.port; + } + + return t; + }; + URI.buildAuthority = function(parts) { + return URI.buildUserinfo(parts) + URI.buildHost(parts); + }; + URI.buildUserinfo = function(parts) { + var t = ''; + + if (parts.username) { + t += URI.encode(parts.username); + } + + if (parts.password) { + t += ':' + URI.encode(parts.password); + } + + if (t) { + t += '@'; + } + + return t; + }; + URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) { + // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html + // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed + // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax! + // URI.js treats the query string as being application/x-www-form-urlencoded + // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type + + var t = ''; + var unique, key, i, length; + for (key in data) { + if (hasOwn.call(data, key) && key) { + if (isArray(data[key])) { + unique = {}; + for (i = 0, length = data[key].length; i < length; i++) { + if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) { + t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace); + if (duplicateQueryParameters !== true) { + unique[data[key][i] + ''] = true; + } + } + } + } else if (data[key] !== undefined) { + t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace); + } + } + } + + return t.substring(1); + }; + URI.buildQueryParameter = function(name, value, escapeQuerySpace) { + // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded + // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization + return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : ''); + }; + + URI.addQuery = function(data, name, value) { + if (typeof name === 'object') { + for (var key in name) { + if (hasOwn.call(name, key)) { + URI.addQuery(data, key, name[key]); + } + } + } else if (typeof name === 'string') { + if (data[name] === undefined) { + data[name] = value; + return; + } else if (typeof data[name] === 'string') { + data[name] = [data[name]]; + } + + if (!isArray(value)) { + value = [value]; + } + + data[name] = (data[name] || []).concat(value); + } else { + throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); + } + }; + URI.removeQuery = function(data, name, value) { + var i, length, key; + + if (isArray(name)) { + for (i = 0, length = name.length; i < length; i++) { + data[name[i]] = undefined; + } + } else if (getType(name) === 'RegExp') { + for (key in data) { + if (name.test(key)) { + data[key] = undefined; + } + } + } else if (typeof name === 'object') { + for (key in name) { + if (hasOwn.call(name, key)) { + URI.removeQuery(data, key, name[key]); + } + } + } else if (typeof name === 'string') { + if (value !== undefined) { + if (getType(value) === 'RegExp') { + if (!isArray(data[name]) && value.test(data[name])) { + data[name] = undefined; + } else { + data[name] = filterArrayValues(data[name], value); + } + } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) { + data[name] = undefined; + } else if (isArray(data[name])) { + data[name] = filterArrayValues(data[name], value); + } + } else { + data[name] = undefined; + } + } else { + throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter'); + } + }; + URI.hasQuery = function(data, name, value, withinArray) { + switch (getType(name)) { + case 'String': + // Nothing to do here + break; + + case 'RegExp': + for (var key in data) { + if (hasOwn.call(data, key)) { + if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) { + return true; + } + } + } + + return false; + + case 'Object': + for (var _key in name) { + if (hasOwn.call(name, _key)) { + if (!URI.hasQuery(data, _key, name[_key])) { + return false; + } + } + } + + return true; + + default: + throw new TypeError('URI.hasQuery() accepts a string, regular expression or object as the name parameter'); + } + + switch (getType(value)) { + case 'Undefined': + // true if exists (but may be empty) + return name in data; // data[name] !== undefined; + + case 'Boolean': + // true if exists and non-empty + var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]); + return value === _booly; + + case 'Function': + // allow complex comparison + return !!value(data[name], name, data); + + case 'Array': + if (!isArray(data[name])) { + return false; + } + + var op = withinArray ? arrayContains : arraysEqual; + return op(data[name], value); + + case 'RegExp': + if (!isArray(data[name])) { + return Boolean(data[name] && data[name].match(value)); + } + + if (!withinArray) { + return false; + } + + return arrayContains(data[name], value); + + case 'Number': + value = String(value); + /* falls through */ + case 'String': + if (!isArray(data[name])) { + return data[name] === value; + } + + if (!withinArray) { + return false; + } + + return arrayContains(data[name], value); + + default: + throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter'); + } + }; + + + URI.joinPaths = function() { + var input = []; + var segments = []; + var nonEmptySegments = 0; + + for (var i = 0; i < arguments.length; i++) { + var url = new URI(arguments[i]); + input.push(url); + var _segments = url.segment(); + for (var s = 0; s < _segments.length; s++) { + if (typeof _segments[s] === 'string') { + segments.push(_segments[s]); + } + + if (_segments[s]) { + nonEmptySegments++; + } + } + } + + if (!segments.length || !nonEmptySegments) { + return new URI(''); + } + + var uri = new URI('').segment(segments); + + if (input[0].path() === '' || input[0].path().slice(0, 1) === '/') { + uri.path('/' + uri.path()); + } + + return uri.normalize(); + }; + + URI.commonPath = function(one, two) { + var length = Math.min(one.length, two.length); + var pos; + + // find first non-matching character + for (pos = 0; pos < length; pos++) { + if (one.charAt(pos) !== two.charAt(pos)) { + pos--; + break; + } + } + + if (pos < 1) { + return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : ''; + } + + // revert to last / + if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') { + pos = one.substring(0, pos).lastIndexOf('/'); + } + + return one.substring(0, pos + 1); + }; + + URI.withinString = function(string, callback, options) { + options || (options = {}); + var _start = options.start || URI.findUri.start; + var _end = options.end || URI.findUri.end; + var _trim = options.trim || URI.findUri.trim; + var _attributeOpen = /[a-z0-9-]=["']?$/i; + + _start.lastIndex = 0; + while (true) { + var match = _start.exec(string); + if (!match) { + break; + } + + var start = match.index; + if (options.ignoreHtml) { + // attribut(e=["']?$) + var attributeOpen = string.slice(Math.max(start - 3, 0), start); + if (attributeOpen && _attributeOpen.test(attributeOpen)) { + continue; + } + } + + var end = start + string.slice(start).search(_end); + var slice = string.slice(start, end).replace(_trim, ''); + if (options.ignore && options.ignore.test(slice)) { + continue; + } + + end = start + slice.length; + var result = callback(slice, start, end, string); + string = string.slice(0, start) + result + string.slice(end); + _start.lastIndex = start + result.length; + } + + _start.lastIndex = 0; + return string; + }; + + URI.ensureValidHostname = function(v) { + // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986) + // they are not part of DNS and therefore ignored by URI.js + + if (v.match(URI.invalid_hostname_characters)) { + // test punycode + if (!punycode) { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-] and Punycode.js is not available'); + } + + if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + } + }; + + // noConflict + URI.noConflict = function(removeAll) { + if (removeAll) { + var unconflicted = { + URI: this.noConflict() + }; + + if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') { + unconflicted.URITemplate = root.URITemplate.noConflict(); + } + + if (root.IPv6 && typeof root.IPv6.noConflict === 'function') { + unconflicted.IPv6 = root.IPv6.noConflict(); + } + + if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') { + unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict(); + } + + return unconflicted; + } else if (root.URI === this) { + root.URI = _URI; + } + + return this; + }; + + p.build = function(deferBuild) { + if (deferBuild === true) { + this._deferred_build = true; + } else if (deferBuild === undefined || this._deferred_build) { + this._string = URI.build(this._parts); + this._deferred_build = false; + } + + return this; + }; + + p.clone = function() { + return new URI(this); + }; + + p.valueOf = p.toString = function() { + return this.build(false)._string; + }; + + + function generateSimpleAccessor(_part){ + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ''; + } else { + this._parts[_part] = v || null; + this.build(!build); + return this; + } + }; + } + + function generatePrefixAccessor(_part, _key){ + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ''; + } else { + if (v !== null) { + v = v + ''; + if (v.charAt(0) === _key) { + v = v.substring(1); + } + } + + this._parts[_part] = v; + this.build(!build); + return this; + } + }; + } + + p.protocol = generateSimpleAccessor('protocol'); + p.username = generateSimpleAccessor('username'); + p.password = generateSimpleAccessor('password'); + p.hostname = generateSimpleAccessor('hostname'); + p.port = generateSimpleAccessor('port'); + p.query = generatePrefixAccessor('query', '?'); + p.fragment = generatePrefixAccessor('fragment', '#'); + + p.search = function(v, build) { + var t = this.query(v, build); + return typeof t === 'string' && t.length ? ('?' + t) : t; + }; + p.hash = function(v, build) { + var t = this.fragment(v, build); + return typeof t === 'string' && t.length ? ('#' + t) : t; + }; + + p.pathname = function(v, build) { + if (v === undefined || v === true) { + var res = this._parts.path || (this._parts.hostname ? '/' : ''); + return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res; + } else { + if (this._parts.urn) { + this._parts.path = v ? URI.recodeUrnPath(v) : ''; + } else { + this._parts.path = v ? URI.recodePath(v) : '/'; + } + this.build(!build); + return this; + } + }; + p.path = p.pathname; + p.href = function(href, build) { + var key; + + if (href === undefined) { + return this.toString(); + } + + this._string = ''; + this._parts = URI._parts(); + + var _URI = href instanceof URI; + var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname); + if (href.nodeName) { + var attribute = URI.getDomAttribute(href); + href = href[attribute] || ''; + _object = false; + } + + // window.location is reported to be an object, but it's not the sort + // of object we're looking for: + // * location.protocol ends with a colon + // * location.query != object.search + // * location.hash != object.fragment + // simply serializing the unknown object should do the trick + // (for location, not for everything...) + if (!_URI && _object && href.pathname !== undefined) { + href = href.toString(); + } + + if (typeof href === 'string' || href instanceof String) { + this._parts = URI.parse(String(href), this._parts); + } else if (_URI || _object) { + var src = _URI ? href._parts : href; + for (key in src) { + if (hasOwn.call(this._parts, key)) { + this._parts[key] = src[key]; + } + } + } else { + throw new TypeError('invalid input'); + } + + this.build(!build); + return this; + }; + + // identification accessors + p.is = function(what) { + var ip = false; + var ip4 = false; + var ip6 = false; + var name = false; + var sld = false; + var idn = false; + var punycode = false; + var relative = !this._parts.urn; + + if (this._parts.hostname) { + relative = false; + ip4 = URI.ip4_expression.test(this._parts.hostname); + ip6 = URI.ip6_expression.test(this._parts.hostname); + ip = ip4 || ip6; + name = !ip; + sld = name && SLD && SLD.has(this._parts.hostname); + idn = name && URI.idn_expression.test(this._parts.hostname); + punycode = name && URI.punycode_expression.test(this._parts.hostname); + } + + switch (what.toLowerCase()) { + case 'relative': + return relative; + + case 'absolute': + return !relative; + + // hostname identification + case 'domain': + case 'name': + return name; + + case 'sld': + return sld; + + case 'ip': + return ip; + + case 'ip4': + case 'ipv4': + case 'inet4': + return ip4; + + case 'ip6': + case 'ipv6': + case 'inet6': + return ip6; + + case 'idn': + return idn; + + case 'url': + return !this._parts.urn; + + case 'urn': + return !!this._parts.urn; + + case 'punycode': + return punycode; + } + + return null; + }; + + // component specific input validation + var _protocol = p.protocol; + var _port = p.port; + var _hostname = p.hostname; + + p.protocol = function(v, build) { + if (v !== undefined) { + if (v) { + // accept trailing :// + v = v.replace(/:(\/\/)?$/, ''); + + if (!v.match(URI.protocol_expression)) { + throw new TypeError('Protocol "' + v + '" contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]'); + } + } + } + return _protocol.call(this, v, build); + }; + p.scheme = p.protocol; + p.port = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v !== undefined) { + if (v === 0) { + v = null; + } + + if (v) { + v += ''; + if (v.charAt(0) === ':') { + v = v.substring(1); + } + + if (v.match(/[^0-9]/)) { + throw new TypeError('Port "' + v + '" contains characters other than [0-9]'); + } + } + } + return _port.call(this, v, build); + }; + p.hostname = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v !== undefined) { + var x = {}; + var res = URI.parseHost(v, x); + if (res !== '/') { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + + v = x.hostname; + } + return _hostname.call(this, v, build); + }; + + // compound accessors + p.origin = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + var protocol = this.protocol(); + var authority = this.authority(); + if (!authority) { + return ''; + } + + return (protocol ? protocol + '://' : '') + this.authority(); + } else { + var origin = URI(v); + this + .protocol(origin.protocol()) + .authority(origin.authority()) + .build(!build); + return this; + } + }; + p.host = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + return this._parts.hostname ? URI.buildHost(this._parts) : ''; + } else { + var res = URI.parseHost(v, this._parts); + if (res !== '/') { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + + this.build(!build); + return this; + } + }; + p.authority = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + return this._parts.hostname ? URI.buildAuthority(this._parts) : ''; + } else { + var res = URI.parseAuthority(v, this._parts); + if (res !== '/') { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + + this.build(!build); + return this; + } + }; + p.userinfo = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + var t = URI.buildUserinfo(this._parts); + return t ? t.substring(0, t.length -1) : t; + } else { + if (v[v.length-1] !== '@') { + v += '@'; + } + + URI.parseUserinfo(v, this._parts); + this.build(!build); + return this; + } + }; + p.resource = function(v, build) { + var parts; + + if (v === undefined) { + return this.path() + this.search() + this.hash(); + } + + parts = URI.parse(v); + this._parts.path = parts.path; + this._parts.query = parts.query; + this._parts.fragment = parts.fragment; + this.build(!build); + return this; + }; + + // fraction accessors + p.subdomain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + // convenience, return "www" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ''; + } + + // grab domain and add another segment + var end = this._parts.hostname.length - this.domain().length - 1; + return this._parts.hostname.substring(0, end) || ''; + } else { + var e = this._parts.hostname.length - this.domain().length; + var sub = this._parts.hostname.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(sub)); + + if (v && v.charAt(v.length - 1) !== '.') { + v += '.'; + } + + if (v) { + URI.ensureValidHostname(v); + } + + this._parts.hostname = this._parts.hostname.replace(replace, v); + this.build(!build); + return this; + } + }; + p.domain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + + // convenience, return "example.org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ''; + } + + // if hostname consists of 1 or 2 segments, it must be the domain + var t = this._parts.hostname.match(/\./g); + if (t && t.length < 2) { + return this._parts.hostname; + } + + // grab tld and add another segment + var end = this._parts.hostname.length - this.tld(build).length - 1; + end = this._parts.hostname.lastIndexOf('.', end -1) + 1; + return this._parts.hostname.substring(end) || ''; + } else { + if (!v) { + throw new TypeError('cannot set domain empty'); + } + + URI.ensureValidHostname(v); + + if (!this._parts.hostname || this.is('IP')) { + this._parts.hostname = v; + } else { + var replace = new RegExp(escapeRegEx(this.domain()) + '$'); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + + this.build(!build); + return this; + } + }; + p.tld = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + + // return "org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ''; + } + + var pos = this._parts.hostname.lastIndexOf('.'); + var tld = this._parts.hostname.substring(pos + 1); + + if (build !== true && SLD && SLD.list[tld.toLowerCase()]) { + return SLD.get(this._parts.hostname) || tld; + } + + return tld; + } else { + var replace; + + if (!v) { + throw new TypeError('cannot set TLD empty'); + } else if (v.match(/[^a-zA-Z0-9-]/)) { + if (SLD && SLD.is(v)) { + replace = new RegExp(escapeRegEx(this.tld()) + '$'); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } else { + throw new TypeError('TLD "' + v + '" contains characters other than [A-Z0-9]'); + } + } else if (!this._parts.hostname || this.is('IP')) { + throw new ReferenceError('cannot set TLD on non-domain host'); + } else { + replace = new RegExp(escapeRegEx(this.tld()) + '$'); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + + this.build(!build); + return this; + } + }; + p.directory = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined || v === true) { + if (!this._parts.path && !this._parts.hostname) { + return ''; + } + + if (this._parts.path === '/') { + return '/'; + } + + var end = this._parts.path.length - this.filename().length - 1; + var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : ''); + + return v ? URI.decodePath(res) : res; + + } else { + var e = this._parts.path.length - this.filename().length; + var directory = this._parts.path.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(directory)); + + // fully qualifier directories begin with a slash + if (!this.is('relative')) { + if (!v) { + v = '/'; + } + + if (v.charAt(0) !== '/') { + v = '/' + v; + } + } + + // directories always end with a slash + if (v && v.charAt(v.length - 1) !== '/') { + v += '/'; + } + + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + this.build(!build); + return this; + } + }; + p.filename = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ''; + } + + var pos = this._parts.path.lastIndexOf('/'); + var res = this._parts.path.substring(pos+1); + + return v ? URI.decodePathSegment(res) : res; + } else { + var mutatedDirectory = false; + + if (v.charAt(0) === '/') { + v = v.substring(1); + } + + if (v.match(/\.?\//)) { + mutatedDirectory = true; + } + + var replace = new RegExp(escapeRegEx(this.filename()) + '$'); + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + + if (mutatedDirectory) { + this.normalizePath(build); + } else { + this.build(!build); + } + + return this; + } + }; + p.suffix = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ''; + } + + var filename = this.filename(); + var pos = filename.lastIndexOf('.'); + var s, res; + + if (pos === -1) { + return ''; + } + + // suffix may only contain alnum characters (yup, I made this up.) + s = filename.substring(pos+1); + res = (/^[a-z0-9%]+$/i).test(s) ? s : ''; + return v ? URI.decodePathSegment(res) : res; + } else { + if (v.charAt(0) === '.') { + v = v.substring(1); + } + + var suffix = this.suffix(); + var replace; + + if (!suffix) { + if (!v) { + return this; + } + + this._parts.path += '.' + URI.recodePath(v); + } else if (!v) { + replace = new RegExp(escapeRegEx('.' + suffix) + '$'); + } else { + replace = new RegExp(escapeRegEx(suffix) + '$'); + } + + if (replace) { + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + } + + this.build(!build); + return this; + } + }; + p.segment = function(segment, v, build) { + var separator = this._parts.urn ? ':' : '/'; + var path = this.path(); + var absolute = path.substring(0, 1) === '/'; + var segments = path.split(separator); + + if (segment !== undefined && typeof segment !== 'number') { + build = v; + v = segment; + segment = undefined; + } + + if (segment !== undefined && typeof segment !== 'number') { + throw new Error('Bad segment "' + segment + '", must be 0-based integer'); + } + + if (absolute) { + segments.shift(); + } + + if (segment < 0) { + // allow negative indexes to address from the end + segment = Math.max(segments.length + segment, 0); + } + + if (v === undefined) { + /*jshint laxbreak: true */ + return segment === undefined + ? segments + : segments[segment]; + /*jshint laxbreak: false */ + } else if (segment === null || segments[segment] === undefined) { + if (isArray(v)) { + segments = []; + // collapse empty elements within array + for (var i=0, l=v.length; i < l; i++) { + if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) { + continue; + } + + if (segments.length && !segments[segments.length -1].length) { + segments.pop(); + } + + segments.push(trimSlashes(v[i])); + } + } else if (v || typeof v === 'string') { + v = trimSlashes(v); + if (segments[segments.length -1] === '') { + // empty trailing elements have to be overwritten + // to prevent results such as /foo//bar + segments[segments.length -1] = v; + } else { + segments.push(v); + } + } + } else { + if (v) { + segments[segment] = trimSlashes(v); + } else { + segments.splice(segment, 1); + } + } + + if (absolute) { + segments.unshift(''); + } + + return this.path(segments.join(separator), build); + }; + p.segmentCoded = function(segment, v, build) { + var segments, i, l; + + if (typeof segment !== 'number') { + build = v; + v = segment; + segment = undefined; + } + + if (v === undefined) { + segments = this.segment(segment, v, build); + if (!isArray(segments)) { + segments = segments !== undefined ? URI.decode(segments) : undefined; + } else { + for (i = 0, l = segments.length; i < l; i++) { + segments[i] = URI.decode(segments[i]); + } + } + + return segments; + } + + if (!isArray(v)) { + v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v; + } else { + for (i = 0, l = v.length; i < l; i++) { + v[i] = URI.encode(v[i]); + } + } + + return this.segment(segment, v, build); + }; + + // mutating query string + var q = p.query; + p.query = function(v, build) { + if (v === true) { + return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + } else if (typeof v === 'function') { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + var result = v.call(this, data); + this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + this.build(!build); + return this; + } else if (v !== undefined && typeof v !== 'string') { + this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + this.build(!build); + return this; + } else { + return q.call(this, v, build); + } + }; + p.setQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + + if (typeof name === 'string' || name instanceof String) { + data[name] = value !== undefined ? value : null; + } else if (typeof name === 'object') { + for (var key in name) { + if (hasOwn.call(name, key)) { + data[key] = name[key]; + } + } + } else { + throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); + } + + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + if (typeof name !== 'string') { + build = value; + } + + this.build(!build); + return this; + }; + p.addQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + URI.addQuery(data, name, value === undefined ? null : value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + if (typeof name !== 'string') { + build = value; + } + + this.build(!build); + return this; + }; + p.removeQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + URI.removeQuery(data, name, value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + if (typeof name !== 'string') { + build = value; + } + + this.build(!build); + return this; + }; + p.hasQuery = function(name, value, withinArray) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + return URI.hasQuery(data, name, value, withinArray); + }; + p.setSearch = p.setQuery; + p.addSearch = p.addQuery; + p.removeSearch = p.removeQuery; + p.hasSearch = p.hasQuery; + + // sanitizing URLs + p.normalize = function() { + if (this._parts.urn) { + return this + .normalizeProtocol(false) + .normalizePath(false) + .normalizeQuery(false) + .normalizeFragment(false) + .build(); + } + + return this + .normalizeProtocol(false) + .normalizeHostname(false) + .normalizePort(false) + .normalizePath(false) + .normalizeQuery(false) + .normalizeFragment(false) + .build(); + }; + p.normalizeProtocol = function(build) { + if (typeof this._parts.protocol === 'string') { + this._parts.protocol = this._parts.protocol.toLowerCase(); + this.build(!build); + } + + return this; + }; + p.normalizeHostname = function(build) { + if (this._parts.hostname) { + if (this.is('IDN') && punycode) { + this._parts.hostname = punycode.toASCII(this._parts.hostname); + } else if (this.is('IPv6') && IPv6) { + this._parts.hostname = IPv6.best(this._parts.hostname); + } + + this._parts.hostname = this._parts.hostname.toLowerCase(); + this.build(!build); + } + + return this; + }; + p.normalizePort = function(build) { + // remove port of it's the protocol's default + if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) { + this._parts.port = null; + this.build(!build); + } + + return this; + }; + p.normalizePath = function(build) { + var _path = this._parts.path; + if (!_path) { + return this; + } + + if (this._parts.urn) { + this._parts.path = URI.recodeUrnPath(this._parts.path); + this.build(!build); + return this; + } + + if (this._parts.path === '/') { + return this; + } + + _path = URI.recodePath(_path); + + var _was_relative; + var _leadingParents = ''; + var _parent, _pos; + + // handle relative paths + if (_path.charAt(0) !== '/') { + _was_relative = true; + _path = '/' + _path; + } + + // handle relative files (as opposed to directories) + if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') { + _path += '/'; + } + + // resolve simples + _path = _path + .replace(/(\/(\.\/)+)|(\/\.$)/g, '/') + .replace(/\/{2,}/g, '/'); + + // remember leading parents + if (_was_relative) { + _leadingParents = _path.substring(1).match(/^(\.\.\/)+/) || ''; + if (_leadingParents) { + _leadingParents = _leadingParents[0]; + } + } + + // resolve parents + while (true) { + _parent = _path.search(/\/\.\.(\/|$)/); + if (_parent === -1) { + // no more ../ to resolve + break; + } else if (_parent === 0) { + // top level cannot be relative, skip it + _path = _path.substring(3); + continue; + } + + _pos = _path.substring(0, _parent).lastIndexOf('/'); + if (_pos === -1) { + _pos = _parent; + } + _path = _path.substring(0, _pos) + _path.substring(_parent + 3); + } + + // revert to relative + if (_was_relative && this.is('relative')) { + _path = _leadingParents + _path.substring(1); + } + + this._parts.path = _path; + this.build(!build); + return this; + }; + p.normalizePathname = p.normalizePath; + p.normalizeQuery = function(build) { + if (typeof this._parts.query === 'string') { + if (!this._parts.query.length) { + this._parts.query = null; + } else { + this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)); + } + + this.build(!build); + } + + return this; + }; + p.normalizeFragment = function(build) { + if (!this._parts.fragment) { + this._parts.fragment = null; + this.build(!build); + } + + return this; + }; + p.normalizeSearch = p.normalizeQuery; + p.normalizeHash = p.normalizeFragment; + + p.iso8859 = function() { + // expect unicode input, iso8859 output + var e = URI.encode; + var d = URI.decode; + + URI.encode = escape; + URI.decode = decodeURIComponent; + try { + this.normalize(); + } finally { + URI.encode = e; + URI.decode = d; + } + return this; + }; + + p.unicode = function() { + // expect iso8859 input, unicode output + var e = URI.encode; + var d = URI.decode; + + URI.encode = strictEncodeURIComponent; + URI.decode = unescape; + try { + this.normalize(); + } finally { + URI.encode = e; + URI.decode = d; + } + return this; + }; + + p.readable = function() { + var uri = this.clone(); + // removing username, password, because they shouldn't be displayed according to RFC 3986 + uri.username('').password('').normalize(); + var t = ''; + if (uri._parts.protocol) { + t += uri._parts.protocol + '://'; + } + + if (uri._parts.hostname) { + if (uri.is('punycode') && punycode) { + t += punycode.toUnicode(uri._parts.hostname); + if (uri._parts.port) { + t += ':' + uri._parts.port; + } + } else { + t += uri.host(); + } + } + + if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') { + t += '/'; + } + + t += uri.path(true); + if (uri._parts.query) { + var q = ''; + for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) { + var kv = (qp[i] || '').split('='); + q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace) + .replace(/&/g, '%26'); + + if (kv[1] !== undefined) { + q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace) + .replace(/&/g, '%26'); + } + } + t += '?' + q.substring(1); + } + + t += URI.decodeQuery(uri.hash(), true); + return t; + }; + + // resolving relative and absolute URLs + p.absoluteTo = function(base) { + var resolved = this.clone(); + var properties = ['protocol', 'username', 'password', 'hostname', 'port']; + var basedir, i, p; + + if (this._parts.urn) { + throw new Error('URNs do not have any generally defined hierarchical components'); + } + + if (!(base instanceof URI)) { + base = new URI(base); + } + + if (!resolved._parts.protocol) { + resolved._parts.protocol = base._parts.protocol; + } + + if (this._parts.hostname) { + return resolved; + } + + for (i = 0; (p = properties[i]); i++) { + resolved._parts[p] = base._parts[p]; + } + + if (!resolved._parts.path) { + resolved._parts.path = base._parts.path; + if (!resolved._parts.query) { + resolved._parts.query = base._parts.query; + } + } else if (resolved._parts.path.substring(-2) === '..') { + resolved._parts.path += '/'; + } + + if (resolved.path().charAt(0) !== '/') { + basedir = base.directory(); + basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : ''; + resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path; + resolved.normalizePath(); + } + + resolved.build(); + return resolved; + }; + p.relativeTo = function(base) { + var relative = this.clone().normalize(); + var relativeParts, baseParts, common, relativePath, basePath; + + if (relative._parts.urn) { + throw new Error('URNs do not have any generally defined hierarchical components'); + } + + base = new URI(base).normalize(); + relativeParts = relative._parts; + baseParts = base._parts; + relativePath = relative.path(); + basePath = base.path(); + + if (relativePath.charAt(0) !== '/') { + throw new Error('URI is already relative'); + } + + if (basePath.charAt(0) !== '/') { + throw new Error('Cannot calculate a URI relative to another relative URI'); + } + + if (relativeParts.protocol === baseParts.protocol) { + relativeParts.protocol = null; + } + + if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) { + return relative.build(); + } + + if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) { + return relative.build(); + } + + if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) { + relativeParts.hostname = null; + relativeParts.port = null; + } else { + return relative.build(); + } + + if (relativePath === basePath) { + relativeParts.path = ''; + return relative.build(); + } + + // determine common sub path + common = URI.commonPath(relativePath, basePath); + + // If the paths have nothing in common, return a relative URL with the absolute path. + if (!common) { + return relative.build(); + } + + var parents = baseParts.path + .substring(common.length) + .replace(/[^\/]*$/, '') + .replace(/.*?\//g, '../'); + + relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './'; + + return relative.build(); + }; + + // comparing URIs + p.equals = function(uri) { + var one = this.clone(); + var two = new URI(uri); + var one_map = {}; + var two_map = {}; + var checked = {}; + var one_query, two_query, key; + + one.normalize(); + two.normalize(); + + // exact match + if (one.toString() === two.toString()) { + return true; + } + + // extract query string + one_query = one.query(); + two_query = two.query(); + one.query(''); + two.query(''); + + // definitely not equal if not even non-query parts match + if (one.toString() !== two.toString()) { + return false; + } + + // query parameters have the same length, even if they're permuted + if (one_query.length !== two_query.length) { + return false; + } + + one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace); + two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace); + + for (key in one_map) { + if (hasOwn.call(one_map, key)) { + if (!isArray(one_map[key])) { + if (one_map[key] !== two_map[key]) { + return false; + } + } else if (!arraysEqual(one_map[key], two_map[key])) { + return false; + } + + checked[key] = true; + } + } + + for (key in two_map) { + if (hasOwn.call(two_map, key)) { + if (!checked[key]) { + // two contains a parameter not present in one + return false; + } + } + } + + return true; + }; + + // state + p.duplicateQueryParameters = function(v) { + this._parts.duplicateQueryParameters = !!v; + return this; + }; + + p.escapeQuerySpace = function(v) { + this._parts.escapeQuerySpace = !!v; + return this; + }; + + return URI; + })); - this.removeEventListeners(); - this.removeSelectionListeners(); -}; +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { -Contents.prototype.resizeListeners = function() { - var width, height; - // Test size again - clearTimeout(this.expanding); + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.0 by @mathias */ + ;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)(module), (function() { return this; }()))) - width = this.scrollWidth(); - height = this.scrollHeight(); +/***/ }, +/* 8 */ +/***/ function(module, exports) { - if (width != this._size.width || height != this._size.height) { + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } - this._size = { + +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { + + /*! + * URI.js - Mutating URLs + * IPv6 Support + * + * Version: 1.18.1 + * + * Author: Rodney Rehm + * Web: http://medialize.github.io/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * + */ + + (function (root, factory) { + 'use strict'; + // https://github.com/umdjs/umd/blob/master/returnExports.js + if (true) { + // Node + module.exports = factory(); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory); + } else { + // Browser globals (root is window) + root.IPv6 = factory(root); + } + }(this, function (root) { + 'use strict'; + + /* + var _in = "fe80:0000:0000:0000:0204:61ff:fe9d:f156"; + var _out = IPv6.best(_in); + var _expected = "fe80::204:61ff:fe9d:f156"; + + console.log(_in, _out, _expected, _out === _expected); + */ + + // save current IPv6 variable, if any + var _IPv6 = root && root.IPv6; + + function bestPresentation(address) { + // based on: + // Javascript to test an IPv6 address for proper format, and to + // present the "best text representation" according to IETF Draft RFC at + // http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04 + // 8 Feb 2010 Rich Brown, Dartware, LLC + // Please feel free to use this code as long as you provide a link to + // http://www.intermapper.com + // http://intermapper.com/support/tools/IPV6-Validator.aspx + // http://download.dartware.com/thirdparty/ipv6validator.js + + var _address = address.toLowerCase(); + var segments = _address.split(':'); + var length = segments.length; + var total = 8; + + // trim colons (:: or ::a:b:c… or …a:b:c::) + if (segments[0] === '' && segments[1] === '' && segments[2] === '') { + // must have been :: + // remove first two items + segments.shift(); + segments.shift(); + } else if (segments[0] === '' && segments[1] === '') { + // must have been ::xxxx + // remove the first item + segments.shift(); + } else if (segments[length - 1] === '' && segments[length - 2] === '') { + // must have been xxxx:: + segments.pop(); + } + + length = segments.length; + + // adjust total segments for IPv4 trailer + if (segments[length - 1].indexOf('.') !== -1) { + // found a "." which means IPv4 + total = 7; + } + + // fill empty segments them with "0000" + var pos; + for (pos = 0; pos < length; pos++) { + if (segments[pos] === '') { + break; + } + } + + if (pos < total) { + segments.splice(pos, 1, '0000'); + while (segments.length < total) { + segments.splice(pos, 0, '0000'); + } + } + + // strip leading zeros + var _segments; + for (var i = 0; i < total; i++) { + _segments = segments[i].split(''); + for (var j = 0; j < 3 ; j++) { + if (_segments[0] === '0' && _segments.length > 1) { + _segments.splice(0,1); + } else { + break; + } + } + + segments[i] = _segments.join(''); + } + + // find longest sequence of zeroes and coalesce them into one segment + var best = -1; + var _best = 0; + var _current = 0; + var current = -1; + var inzeroes = false; + // i; already declared + + for (i = 0; i < total; i++) { + if (inzeroes) { + if (segments[i] === '0') { + _current += 1; + } else { + inzeroes = false; + if (_current > _best) { + best = current; + _best = _current; + } + } + } else { + if (segments[i] === '0') { + inzeroes = true; + current = i; + _current = 1; + } + } + } + + if (_current > _best) { + best = current; + _best = _current; + } + + if (_best > 1) { + segments.splice(best, _best, ''); + } + + length = segments.length; + + // assemble remaining segments + var result = ''; + if (segments[0] === '') { + result = ':'; + } + + for (i = 0; i < length; i++) { + result += segments[i]; + if (i === length - 1) { + break; + } + + result += ':'; + } + + if (segments[length - 1] === '') { + result += ':'; + } + + return result; + } + + function noConflict() { + /*jshint validthis: true */ + if (root.IPv6 === this) { + root.IPv6 = _IPv6; + } + + return this; + } + + return { + best: bestPresentation, + noConflict: noConflict + }; + })); + + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + /*! + * URI.js - Mutating URLs + * Second Level Domain (SLD) Support + * + * Version: 1.18.1 + * + * Author: Rodney Rehm + * Web: http://medialize.github.io/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * + */ + + (function (root, factory) { + 'use strict'; + // https://github.com/umdjs/umd/blob/master/returnExports.js + if (true) { + // Node + module.exports = factory(); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory); + } else { + // Browser globals (root is window) + root.SecondLevelDomains = factory(root); + } + }(this, function (root) { + 'use strict'; + + // save current SecondLevelDomains variable, if any + var _SecondLevelDomains = root && root.SecondLevelDomains; + + var SLD = { + // list of known Second Level Domains + // converted list of SLDs from https://github.com/gavingmiller/second-level-domains + // ---- + // publicsuffix.org is more current and actually used by a couple of browsers internally. + // downside is it also contains domains like "dyndns.org" - which is fine for the security + // issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js + // ---- + list: { + 'ac':' com gov mil net org ', + 'ae':' ac co gov mil name net org pro sch ', + 'af':' com edu gov net org ', + 'al':' com edu gov mil net org ', + 'ao':' co ed gv it og pb ', + 'ar':' com edu gob gov int mil net org tur ', + 'at':' ac co gv or ', + 'au':' asn com csiro edu gov id net org ', + 'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ', + 'bb':' biz co com edu gov info net org store tv ', + 'bh':' biz cc com edu gov info net org ', + 'bn':' com edu gov net org ', + 'bo':' com edu gob gov int mil net org tv ', + 'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ', + 'bs':' com edu gov net org ', + 'bz':' du et om ov rg ', + 'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ', + 'ck':' biz co edu gen gov info net org ', + 'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ', + 'co':' com edu gov mil net nom org ', + 'cr':' ac c co ed fi go or sa ', + 'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ', + 'do':' art com edu gob gov mil net org sld web ', + 'dz':' art asso com edu gov net org pol ', + 'ec':' com edu fin gov info med mil net org pro ', + 'eg':' com edu eun gov mil name net org sci ', + 'er':' com edu gov ind mil net org rochest w ', + 'es':' com edu gob nom org ', + 'et':' biz com edu gov info name net org ', + 'fj':' ac biz com info mil name net org pro ', + 'fk':' ac co gov net nom org ', + 'fr':' asso com f gouv nom prd presse tm ', + 'gg':' co net org ', + 'gh':' com edu gov mil org ', + 'gn':' ac com gov net org ', + 'gr':' com edu gov mil net org ', + 'gt':' com edu gob ind mil net org ', + 'gu':' com edu gov net org ', + 'hk':' com edu gov idv net org ', + 'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ', + 'id':' ac co go mil net or sch web ', + 'il':' ac co gov idf k12 muni net org ', + 'in':' ac co edu ernet firm gen gov i ind mil net nic org res ', + 'iq':' com edu gov i mil net org ', + 'ir':' ac co dnssec gov i id net org sch ', + 'it':' edu gov ', + 'je':' co net org ', + 'jo':' com edu gov mil name net org sch ', + 'jp':' ac ad co ed go gr lg ne or ', + 'ke':' ac co go info me mobi ne or sc ', + 'kh':' com edu gov mil net org per ', + 'ki':' biz com de edu gov info mob net org tel ', + 'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ', + 'kn':' edu gov net org ', + 'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ', + 'kw':' com edu gov net org ', + 'ky':' com edu gov net org ', + 'kz':' com edu gov mil net org ', + 'lb':' com edu gov net org ', + 'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ', + 'lr':' com edu gov net org ', + 'lv':' asn com conf edu gov id mil net org ', + 'ly':' com edu gov id med net org plc sch ', + 'ma':' ac co gov m net org press ', + 'mc':' asso tm ', + 'me':' ac co edu gov its net org priv ', + 'mg':' com edu gov mil nom org prd tm ', + 'mk':' com edu gov inf name net org pro ', + 'ml':' com edu gov net org presse ', + 'mn':' edu gov org ', + 'mo':' com edu gov net org ', + 'mt':' com edu gov net org ', + 'mv':' aero biz com coop edu gov info int mil museum name net org pro ', + 'mw':' ac co com coop edu gov int museum net org ', + 'mx':' com edu gob net org ', + 'my':' com edu gov mil name net org sch ', + 'nf':' arts com firm info net other per rec store web ', + 'ng':' biz com edu gov mil mobi name net org sch ', + 'ni':' ac co com edu gob mil net nom org ', + 'np':' com edu gov mil net org ', + 'nr':' biz com edu gov info net org ', + 'om':' ac biz co com edu gov med mil museum net org pro sch ', + 'pe':' com edu gob mil net nom org sld ', + 'ph':' com edu gov i mil net ngo org ', + 'pk':' biz com edu fam gob gok gon gop gos gov net org web ', + 'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ', + 'pr':' ac biz com edu est gov info isla name net org pro prof ', + 'ps':' com edu gov net org plo sec ', + 'pw':' belau co ed go ne or ', + 'ro':' arts com firm info nom nt org rec store tm www ', + 'rs':' ac co edu gov in org ', + 'sb':' com edu gov net org ', + 'sc':' com edu gov net org ', + 'sh':' co com edu gov net nom org ', + 'sl':' com edu gov net org ', + 'st':' co com consulado edu embaixada gov mil net org principe saotome store ', + 'sv':' com edu gob org red ', + 'sz':' ac co org ', + 'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ', + 'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ', + 'tw':' club com ebiz edu game gov idv mil net org ', + 'mu':' ac co com gov net or org ', + 'mz':' ac co edu gov org ', + 'na':' co com ', + 'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ', + 'pa':' abo ac com edu gob ing med net nom org sld ', + 'pt':' com edu gov int net nome org publ ', + 'py':' com edu gov mil net org ', + 'qa':' com edu gov mil net org ', + 're':' asso com nom ', + 'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ', + 'rw':' ac co com edu gouv gov int mil net ', + 'sa':' com edu gov med net org pub sch ', + 'sd':' com edu gov info med net org tv ', + 'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ', + 'sg':' com edu gov idn net org per ', + 'sn':' art com edu gouv org perso univ ', + 'sy':' com edu gov mil net news org ', + 'th':' ac co go in mi net or ', + 'tj':' ac biz co com edu go gov info int mil name net nic org test web ', + 'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ', + 'tz':' ac co go ne or ', + 'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ', + 'ug':' ac co go ne or org sc ', + 'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ', + 'us':' dni fed isa kids nsn ', + 'uy':' com edu gub mil net org ', + 've':' co com edu gob info mil net org web ', + 'vi':' co com k12 net org ', + 'vn':' ac biz com edu gov health info int name net org pro ', + 'ye':' co com gov ltd me net org plc ', + 'yu':' ac co edu gov org ', + 'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ', + 'zm':' ac co com edu gov net org sch ' + }, + // gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost + // in both performance and memory footprint. No initialization required. + // http://jsperf.com/uri-js-sld-regex-vs-binary-search/4 + // Following methods use lastIndexOf() rather than array.split() in order + // to avoid any memory allocations. + has: function(domain) { + var tldOffset = domain.lastIndexOf('.'); + if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { + return false; + } + var sldOffset = domain.lastIndexOf('.', tldOffset-1); + if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) { + return false; + } + var sldList = SLD.list[domain.slice(tldOffset+1)]; + if (!sldList) { + return false; + } + return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0; + }, + is: function(domain) { + var tldOffset = domain.lastIndexOf('.'); + if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { + return false; + } + var sldOffset = domain.lastIndexOf('.', tldOffset-1); + if (sldOffset >= 0) { + return false; + } + var sldList = SLD.list[domain.slice(tldOffset+1)]; + if (!sldList) { + return false; + } + return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0; + }, + get: function(domain) { + var tldOffset = domain.lastIndexOf('.'); + if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { + return null; + } + var sldOffset = domain.lastIndexOf('.', tldOffset-1); + if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) { + return null; + } + var sldList = SLD.list[domain.slice(tldOffset+1)]; + if (!sldList) { + return null; + } + if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) { + return null; + } + return domain.slice(sldOffset+1); + }, + noConflict: function(){ + if (root.SecondLevelDomains === this) { + root.SecondLevelDomains = _SecondLevelDomains; + } + return this; + } + }; + + return SLD; + })); + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var base64 = __webpack_require__(12); + + var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false; + /* + //-- Parse the different parts of a url, returning a object + function uri(url){ + var uri = { + protocol : '', + host : '', + path : '', + origin : '', + directory : '', + base : '', + filename : '', + extension : '', + fragment : '', + href : url + }, + doubleSlash = url.indexOf('://'), + search = url.indexOf('?'), + fragment = url.indexOf("#"), + withoutProtocol, + dot, + firstSlash; + + if(fragment != -1) { + uri.fragment = url.slice(fragment + 1); + url = url.slice(0, fragment); + } + + if(search != -1) { + uri.search = url.slice(search + 1); + url = url.slice(0, search); + href = url; + } + + if(doubleSlash != -1) { + uri.protocol = url.slice(0, doubleSlash); + withoutProtocol = url.slice(doubleSlash+3); + firstSlash = withoutProtocol.indexOf('/'); + + if(firstSlash === -1) { + uri.host = uri.path; + uri.path = ""; + } else { + uri.host = withoutProtocol.slice(0, firstSlash); + uri.path = withoutProtocol.slice(firstSlash); + } + + + uri.origin = uri.protocol + "://" + uri.host; + + uri.directory = folder(uri.path); + + uri.base = uri.origin + uri.directory; + // return origin; + } else { + uri.path = url; + uri.directory = folder(url); + uri.base = uri.directory; + } + + //-- Filename + uri.filename = url.replace(uri.base, ''); + dot = uri.filename.lastIndexOf('.'); + if(dot != -1) { + uri.extension = uri.filename.slice(dot+1); + } + return uri; + }; + + //-- Parse out the folder, will return everything before the last slash + function folder(url){ + + var lastSlash = url.lastIndexOf('/'); + + if(lastSlash == -1) var folder = ''; + + folder = url.slice(0, lastSlash + 1); + + return folder; + + }; + */ + function isElement(obj) { + return !!(obj && obj.nodeType == 1); + }; + + // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript + function uuid() { + var d = new Date().getTime(); + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random()*16)%16 | 0; + d = Math.floor(d/16); + return (c=='x' ? r : (r&0x7|0x8)).toString(16); + }); + return uuid; + }; + + // From Lodash + function values(object) { + var index = -1, + props = Object.keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + }; + + function resolveUrl(base, path) { + var url = [], + segments = [], + baseUri = uri(base), + pathUri = uri(path), + baseDirectory = baseUri.directory, + pathDirectory = pathUri.directory, + directories = [], + // folders = base.split("/"), + paths; + + // if(uri.host) { + // return path; + // } + + if(baseDirectory[0] === "/") { + baseDirectory = baseDirectory.substring(1); + } + + if(pathDirectory[pathDirectory.length-1] === "/") { + baseDirectory = baseDirectory.substring(0, baseDirectory.length-1); + } + + if(pathDirectory[0] === "/") { + pathDirectory = pathDirectory.substring(1); + } + + if(pathDirectory[pathDirectory.length-1] === "/") { + pathDirectory = pathDirectory.substring(0, pathDirectory.length-1); + } + + if(baseDirectory) { + directories = baseDirectory.split("/"); + } + + paths = pathDirectory.split("/"); + + paths.reverse().forEach(function(part, index){ + if(part === ".."){ + directories.pop(); + } else if(part === directories[directories.length-1]) { + directories.pop(); + segments.unshift(part); + } else { + segments.unshift(part); + } + }); + + url = [baseUri.origin]; + + if(directories.length) { + url = url.concat(directories); + } + + if(segments) { + url = url.concat(segments); + } + + url = url.concat(pathUri.filename); + + return url.join("/"); + }; + + function documentHeight() { + return Math.max( + document.documentElement.clientHeight, + document.body.scrollHeight, + document.documentElement.scrollHeight, + document.body.offsetHeight, + document.documentElement.offsetHeight + ); + }; + + function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + }; + + function prefixed(unprefixed) { + var vendors = ["Webkit", "Moz", "O", "ms" ], + prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'], + upper = unprefixed[0].toUpperCase() + unprefixed.slice(1), + length = vendors.length; + + if (typeof(document) === 'undefined' || typeof(document.body.style[unprefixed]) != 'undefined') { + return unprefixed; + } + + for ( var i=0; i < length; i++ ) { + if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') { + return vendors[i] + upper; + } + } + + return unprefixed; + }; + + function defaults(obj) { + for (var i = 1, length = arguments.length; i < length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + return obj; + }; + + function extend(target) { + var sources = [].slice.call(arguments, 1); + sources.forEach(function (source) { + if(!source) return; + Object.getOwnPropertyNames(source).forEach(function(propName) { + Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName)); + }); + }); + return target; + }; + + // Fast quicksort insert for sorted array -- based on: + // http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers + function insert(item, array, compareFunction) { + var location = locationOf(item, array, compareFunction); + array.splice(location, 0, item); + + return location; + }; + // Returns where something would fit in + function locationOf(item, array, compareFunction, _start, _end) { + var start = _start || 0; + var end = _end || array.length; + var pivot = parseInt(start + (end - start) / 2); + var compared; + if(!compareFunction){ + compareFunction = function(a, b) { + if(a > b) return 1; + if(a < b) return -1; + if(a = b) return 0; + }; + } + if(end-start <= 0) { + return pivot; + } + + compared = compareFunction(array[pivot], item); + if(end-start === 1) { + return compared > 0 ? pivot : pivot + 1; + } + + if(compared === 0) { + return pivot; + } + if(compared === -1) { + return locationOf(item, array, compareFunction, pivot, end); + } else{ + return locationOf(item, array, compareFunction, start, pivot); + } + }; + // Returns -1 of mpt found + function indexOfSorted(item, array, compareFunction, _start, _end) { + var start = _start || 0; + var end = _end || array.length; + var pivot = parseInt(start + (end - start) / 2); + var compared; + if(!compareFunction){ + compareFunction = function(a, b) { + if(a > b) return 1; + if(a < b) return -1; + if(a = b) return 0; + }; + } + if(end-start <= 0) { + return -1; // Not found + } + + compared = compareFunction(array[pivot], item); + if(end-start === 1) { + return compared === 0 ? pivot : -1; + } + if(compared === 0) { + return pivot; // Found + } + if(compared === -1) { + return indexOfSorted(item, array, compareFunction, pivot, end); + } else{ + return indexOfSorted(item, array, compareFunction, start, pivot); + } + }; + + function bounds(el) { + + var style = window.getComputedStyle(el); + var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; + var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; + + var width = 0; + var height = 0; + + widthProps.forEach(function(prop){ + width += parseFloat(style[prop]) || 0; + }); + + heightProps.forEach(function(prop){ + height += parseFloat(style[prop]) || 0; + }); + + return { + height: height, + width: width + }; + + }; + + function borders(el) { + + var style = window.getComputedStyle(el); + var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; + var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; + + var width = 0; + var height = 0; + + widthProps.forEach(function(prop){ + width += parseFloat(style[prop]) || 0; + }); + + heightProps.forEach(function(prop){ + height += parseFloat(style[prop]) || 0; + }); + + return { + height: height, + width: width + }; + + }; + + function windowBounds() { + + var width = window.innerWidth; + var height = window.innerHeight; + + return { + top: 0, + left: 0, + right: width, + bottom: height, width: width, height: height - } - - this.trigger("resize", this._size); - } - - this.expanding = setTimeout(this.resizeListeners.bind(this), 350); -}; - -//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js -Contents.prototype.mediaQueryListeners = function() { - var sheets = this.document.styleSheets; - var mediaChangeHandler = function(m){ - if(m.matches && !this._expanding) { - setTimeout(this.expand.bind(this), 1); - // this.expand(); - } - }.bind(this); - - for (var i = 0; i < sheets.length; i += 1) { - var rules = sheets[i].cssRules; - if(!rules) return; // Stylesheets changed - for (var j = 0; j < rules.length; j += 1) { - //if (rules[j].constructor === CSSMediaRule) { - if(rules[j].media){ - var mql = this.window.matchMedia(rules[j].media.mediaText); - mql.addListener(mediaChangeHandler); - //mql.onchange = mediaChangeHandler; - } - } - } -}; - -Contents.prototype.observe = function(target) { - var renderer = this; - - // create an observer instance - var observer = new MutationObserver(function(mutations) { - if(renderer._expanding) { - renderer.expand(); - } - // mutations.forEach(function(mutation) { - // console.log(mutation); - // }); - }); - - // configuration of the observer: - var config = { attributes: true, childList: true, characterData: true, subtree: true }; - - // pass in the target node, as well as the observer options - observer.observe(target, config); - - return observer; -}; - -Contents.prototype.imageLoadListeners = function(target) { - var images = this.document.querySelectorAll("img"); - var img; - for (var i = 0; i < images.length; i++) { - img = images[i]; - - if (typeof img.naturalWidth !== "undefined" && - img.naturalWidth === 0) { - img.onload = this.expand.bind(this); - } - } -}; - -Contents.prototype.fontLoadListeners = function(target) { - if (!this.document || !this.document.fonts) { - return; - } - - this.document.fonts.ready.then(function () { - this.expand(); - }.bind(this)); - -}; - -Contents.prototype.root = function() { - if(!this.document) return null; - return this.document.documentElement; -}; - -Contents.prototype.locationOf = function(target, ignoreClass) { - var position; - var targetPos = {"left": 0, "top": 0}; - - if(!this.document) return; - - if(this.epubcfi.isCfiString(target)) { - range = new EpubCFI(target).toRange(this.document, ignoreClass); - - if(range) { - if (range.startContainer.nodeType === Node.ELEMENT_NODE) { - position = range.startContainer.getBoundingClientRect(); - targetPos.left = position.left; - targetPos.top = position.top; - } else { - position = range.getBoundingClientRect(); - targetPos.left = position.left; - targetPos.top = position.top; - } - } - - } else if(typeof target === "string" && - target.indexOf("#") > -1) { - - id = target.substring(target.indexOf("#")+1); - el = this.document.getElementById(id); - - if(el) { - position = el.getBoundingClientRect(); - targetPos.left = position.left; - targetPos.top = position.top; - } - } - - return targetPos; -}; - -Contents.prototype.addStylesheet = function(src) { - return new RSVP.Promise(function(resolve, reject){ - var $stylesheet; - var ready = false; - - if(!this.document) { - resolve(false); - return; - } - - $stylesheet = this.document.createElement('link'); - $stylesheet.type = 'text/css'; - $stylesheet.rel = "stylesheet"; - $stylesheet.href = src; - $stylesheet.onload = $stylesheet.onreadystatechange = function() { - if ( !ready && (!this.readyState || this.readyState == 'complete') ) { - ready = true; - // Let apply - setTimeout(function(){ - resolve(true); - }, 1); - } }; - - this.document.head.appendChild($stylesheet); - - }.bind(this)); -}; - -// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule -Contents.prototype.addStylesheetRules = function(rules) { - var styleEl; - var styleSheet; - - if(!this.document) return; - - styleEl = this.document.createElement('style'); - - // Append style element to head - this.document.head.appendChild(styleEl); - - // Grab style sheet - styleSheet = styleEl.sheet; - - for (var i = 0, rl = rules.length; i < rl; i++) { - var j = 1, rule = rules[i], selector = rules[i][0], propStr = ''; - // If the second argument of a rule is an array of arrays, correct our variables. - if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') { - rule = rule[1]; - j = 0; - } - - for (var pl = rule.length; j < pl; j++) { - var prop = rule[j]; - propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\n'; - } - - // Insert CSS Rule - styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length); - } -}; - -Contents.prototype.addScript = function(src) { - - return new RSVP.Promise(function(resolve, reject){ - var $script; - var ready = false; - - if(!this.document) { - resolve(false); - return; - } - - $script = this.document.createElement('script'); - $script.type = 'text/javascript'; - $script.async = true; - $script.src = src; - $script.onload = $script.onreadystatechange = function() { - if ( !ready && (!this.readyState || this.readyState == 'complete') ) { - ready = true; - setTimeout(function(){ - resolve(true); - }, 1); - } - }; - - this.document.head.appendChild($script); - - }.bind(this)); -}; - -Contents.prototype.addEventListeners = function(){ - if(!this.document) { - return; - } - this.listenedEvents.forEach(function(eventName){ - this.document.addEventListener(eventName, this.triggerEvent.bind(this), false); - }, this); - -}; - -Contents.prototype.removeEventListeners = function(){ - if(!this.document) { - return; - } - this.listenedEvents.forEach(function(eventName){ - this.document.removeEventListener(eventName, this.triggerEvent, false); - }, this); - -}; - -// Pass browser events -Contents.prototype.triggerEvent = function(e){ - this.trigger(e.type, e); -}; - -Contents.prototype.addSelectionListeners = function(){ - if(!this.document) { - return; - } - this.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false); -}; - -Contents.prototype.removeSelectionListeners = function(){ - if(!this.document) { - return; - } - this.document.removeEventListener("selectionchange", this.onSelectionChange, false); -}; - -Contents.prototype.onSelectionChange = function(e){ - if (this.selectionEndTimeout) { - clearTimeout(this.selectionEndTimeout); - } - this.selectionEndTimeout = setTimeout(function() { - var selection = this.window.getSelection(); - this.triggerSelectedEvent(selection); - }.bind(this), 500); -}; - -Contents.prototype.triggerSelectedEvent = function(selection){ - var range, cfirange; - - if (selection && selection.rangeCount > 0) { - range = selection.getRangeAt(0); - if(!range.collapsed) { - // cfirange = this.section.cfiFromRange(range); - cfirange = new EpubCFI(range, this.cfiBase).toString(); - this.trigger("selected", cfirange); - this.trigger("selectedRange", range); - } - } -}; - -Contents.prototype.range = function(_cfi, ignoreClass){ - var cfi = new EpubCFI(_cfi); - return cfi.toRange(this.document, ignoreClass); -}; - -Contents.prototype.map = function(layout){ - var map = new Mapping(layout); - return map.section(); -}; - -Contents.prototype.size = function(width, height){ - - if (width >= 0) { - this.width(width); - } - - if (height >= 0) { - this.height(height); - } - - this.css("margin", "0"); - this.css("boxSizing", "border-box"); - -}; - -Contents.prototype.columns = function(width, height, columnWidth, gap){ - var COLUMN_AXIS = core.prefixed('columnAxis'); - var COLUMN_GAP = core.prefixed('columnGap'); - var COLUMN_WIDTH = core.prefixed('columnWidth'); - var COLUMN_FILL = core.prefixed('columnFill'); - var textWidth; - - this.width(width); - this.height(height); - - // Deal with Mobile trying to scale to viewport - this.viewport({ width: width, height: height, scale: 1.0 }); - - // this.overflowY("hidden"); - this.css("overflowY", "hidden"); - this.css("margin", "0"); - this.css("boxSizing", "border-box"); - this.css("maxWidth", "inherit"); - - this.css(COLUMN_AXIS, "horizontal"); - this.css(COLUMN_FILL, "auto"); - - this.css(COLUMN_GAP, gap+"px"); - this.css(COLUMN_WIDTH, columnWidth+"px"); -}; - -Contents.prototype.scale = function(scale, offsetX, offsetY){ - var scale = "scale(" + scale + ")"; - var translate = ''; - // this.css("position", "absolute")); - this.css("transformOrigin", "top left"); - - if (offsetX >= 0 || offsetY >= 0) { - translate = " translate(" + (offsetX || 0 )+ "px, " + (offsetY || 0 )+ "px )"; - } - - this.css("transform", scale + translate); -}; - -Contents.prototype.fit = function(width, height){ - var viewport = this.viewport(); - var widthScale = width / viewport.width; - var heightScale = height / viewport.height; - var scale = widthScale < heightScale ? widthScale : heightScale; - - var offsetY = (height - (viewport.height * scale)) / 2; - - this.width(width); - this.height(height); - this.overflow("hidden"); - - // Deal with Mobile trying to scale to viewport - this.viewport({ scale: 1.0 }); - - // Scale to the correct size - this.scale(scale, 0, offsetY); - - this.css("backgroundColor", "transparent"); -}; - -Contents.prototype.mapPage = function(cfiBase, start, end) { - var mapping = new Mapping(); - - return mapping.page(this, cfiBase, start, end); -}; - -Contents.prototype.destroy = function() { - // Stop observing - if(this.observer) { - this.observer.disconnect(); - } - - this.removeListeners(); - -}; - -RSVP.EventTarget.mixin(Contents.prototype); - -module.exports = Contents; - -},{"./core":10,"./epubcfi":11,"./mapping":20,"rsvp":5}],10:[function(require,module,exports){ -var RSVP = require('rsvp'); -var base64 = require('base64-js'); - -var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false; -/* -//-- Parse the different parts of a url, returning a object -function uri(url){ - var uri = { - protocol : '', - host : '', - path : '', - origin : '', - directory : '', - base : '', - filename : '', - extension : '', - fragment : '', - href : url - }, - doubleSlash = url.indexOf('://'), - search = url.indexOf('?'), - fragment = url.indexOf("#"), - withoutProtocol, - dot, - firstSlash; - - if(fragment != -1) { - uri.fragment = url.slice(fragment + 1); - url = url.slice(0, fragment); - } - - if(search != -1) { - uri.search = url.slice(search + 1); - url = url.slice(0, search); - href = url; - } - - if(doubleSlash != -1) { - uri.protocol = url.slice(0, doubleSlash); - withoutProtocol = url.slice(doubleSlash+3); - firstSlash = withoutProtocol.indexOf('/'); - - if(firstSlash === -1) { - uri.host = uri.path; - uri.path = ""; - } else { - uri.host = withoutProtocol.slice(0, firstSlash); - uri.path = withoutProtocol.slice(firstSlash); - } - - - uri.origin = uri.protocol + "://" + uri.host; - - uri.directory = folder(uri.path); - - uri.base = uri.origin + uri.directory; - // return origin; - } else { - uri.path = url; - uri.directory = folder(url); - uri.base = uri.directory; - } - - //-- Filename - uri.filename = url.replace(uri.base, ''); - dot = uri.filename.lastIndexOf('.'); - if(dot != -1) { - uri.extension = uri.filename.slice(dot+1); - } - return uri; -}; - -//-- Parse out the folder, will return everything before the last slash -function folder(url){ - - var lastSlash = url.lastIndexOf('/'); - - if(lastSlash == -1) var folder = ''; - - folder = url.slice(0, lastSlash + 1); - - return folder; - -}; -*/ -function isElement(obj) { - return !!(obj && obj.nodeType == 1); -}; - -// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript -function uuid() { - var d = new Date().getTime(); - var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = (d + Math.random()*16)%16 | 0; - d = Math.floor(d/16); - return (c=='x' ? r : (r&0x7|0x8)).toString(16); - }); - return uuid; -}; - -// From Lodash -function values(object) { - var index = -1, - props = Object.keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; - } - return result; -}; - -function resolveUrl(base, path) { - var url = [], - segments = [], - baseUri = uri(base), - pathUri = uri(path), - baseDirectory = baseUri.directory, - pathDirectory = pathUri.directory, - directories = [], - // folders = base.split("/"), - paths; - - // if(uri.host) { - // return path; - // } - - if(baseDirectory[0] === "/") { - baseDirectory = baseDirectory.substring(1); - } - - if(pathDirectory[pathDirectory.length-1] === "/") { - baseDirectory = baseDirectory.substring(0, baseDirectory.length-1); - } - - if(pathDirectory[0] === "/") { - pathDirectory = pathDirectory.substring(1); - } - - if(pathDirectory[pathDirectory.length-1] === "/") { - pathDirectory = pathDirectory.substring(0, pathDirectory.length-1); - } - - if(baseDirectory) { - directories = baseDirectory.split("/"); - } - - paths = pathDirectory.split("/"); - - paths.reverse().forEach(function(part, index){ - if(part === ".."){ - directories.pop(); - } else if(part === directories[directories.length-1]) { - directories.pop(); - segments.unshift(part); - } else { - segments.unshift(part); - } - }); - - url = [baseUri.origin]; - - if(directories.length) { - url = url.concat(directories); - } - - if(segments) { - url = url.concat(segments); - } - - url = url.concat(pathUri.filename); - - return url.join("/"); -}; - -function documentHeight() { - return Math.max( - document.documentElement.clientHeight, - document.body.scrollHeight, - document.documentElement.scrollHeight, - document.body.offsetHeight, - document.documentElement.offsetHeight - ); -}; - -function isNumber(n) { - return !isNaN(parseFloat(n)) && isFinite(n); -}; - -function prefixed(unprefixed) { - var vendors = ["Webkit", "Moz", "O", "ms" ], - prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'], - upper = unprefixed[0].toUpperCase() + unprefixed.slice(1), - length = vendors.length; - - if (typeof(document) === 'undefined' || typeof(document.body.style[unprefixed]) != 'undefined') { - return unprefixed; - } - - for ( var i=0; i < length; i++ ) { - if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') { - return vendors[i] + upper; - } - } - - return unprefixed; -}; - -function defaults(obj) { - for (var i = 1, length = arguments.length; i < length; i++) { - var source = arguments[i]; - for (var prop in source) { - if (obj[prop] === void 0) obj[prop] = source[prop]; - } - } - return obj; -}; - -function extend(target) { - var sources = [].slice.call(arguments, 1); - sources.forEach(function (source) { - if(!source) return; - Object.getOwnPropertyNames(source).forEach(function(propName) { - Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName)); + + }; + + //https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496 + function cleanStringForXpath(str) { + var parts = str.match(/[^'"]+|['"]/g); + parts = parts.map(function(part){ + if (part === "'") { + return '\"\'\"'; // output "'" + } + + if (part === '"') { + return "\'\"\'"; // output '"' + } + return "\'" + part + "\'"; }); - }); - return target; -}; - -// Fast quicksort insert for sorted array -- based on: -// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers -function insert(item, array, compareFunction) { - var location = locationOf(item, array, compareFunction); - array.splice(location, 0, item); - - return location; -}; -// Returns where something would fit in -function locationOf(item, array, compareFunction, _start, _end) { - var start = _start || 0; - var end = _end || array.length; - var pivot = parseInt(start + (end - start) / 2); - var compared; - if(!compareFunction){ - compareFunction = function(a, b) { - if(a > b) return 1; - if(a < b) return -1; - if(a = b) return 0; - }; - } - if(end-start <= 0) { - return pivot; - } - - compared = compareFunction(array[pivot], item); - if(end-start === 1) { - return compared > 0 ? pivot : pivot + 1; - } - - if(compared === 0) { - return pivot; - } - if(compared === -1) { - return locationOf(item, array, compareFunction, pivot, end); - } else{ - return locationOf(item, array, compareFunction, start, pivot); - } -}; -// Returns -1 of mpt found -function indexOfSorted(item, array, compareFunction, _start, _end) { - var start = _start || 0; - var end = _end || array.length; - var pivot = parseInt(start + (end - start) / 2); - var compared; - if(!compareFunction){ - compareFunction = function(a, b) { - if(a > b) return 1; - if(a < b) return -1; - if(a = b) return 0; - }; - } - if(end-start <= 0) { - return -1; // Not found - } - - compared = compareFunction(array[pivot], item); - if(end-start === 1) { - return compared === 0 ? pivot : -1; - } - if(compared === 0) { - return pivot; // Found - } - if(compared === -1) { - return indexOfSorted(item, array, compareFunction, pivot, end); - } else{ - return indexOfSorted(item, array, compareFunction, start, pivot); - } -}; - -function bounds(el) { - - var style = window.getComputedStyle(el); - var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; - var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; - - var width = 0; - var height = 0; - - widthProps.forEach(function(prop){ - width += parseFloat(style[prop]) || 0; - }); - - heightProps.forEach(function(prop){ - height += parseFloat(style[prop]) || 0; - }); - - return { - height: height, - width: width + return "concat(\'\'," + parts.join(",") + ")"; }; - -}; - -function borders(el) { - - var style = window.getComputedStyle(el); - var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; - var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; - - var width = 0; - var height = 0; - - widthProps.forEach(function(prop){ - width += parseFloat(style[prop]) || 0; - }); - - heightProps.forEach(function(prop){ - height += parseFloat(style[prop]) || 0; - }); - - return { - height: height, - width: width - }; - -}; - -function windowBounds() { - - var width = window.innerWidth; - var height = window.innerHeight; - - return { - top: 0, - left: 0, - right: width, - bottom: height, - width: width, - height: height - }; - -}; - -//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496 -function cleanStringForXpath(str) { - var parts = str.match(/[^'"]+|['"]/g); - parts = parts.map(function(part){ - if (part === "'") { - return '\"\'\"'; // output "'" - } - - if (part === '"') { - return "\'\"\'"; // output '"' - } - return "\'" + part + "\'"; - }); - return "concat(\'\'," + parts.join(",") + ")"; -}; - -function indexOfTextNode(textNode){ - var parent = textNode.parentNode; - var children = parent.childNodes; - var sib; - var index = -1; - for (var i = 0; i < children.length; i++) { - sib = children[i]; - if(sib.nodeType === Node.TEXT_NODE){ - index++; + + function indexOfTextNode(textNode){ + var parent = textNode.parentNode; + var children = parent.childNodes; + var sib; + var index = -1; + for (var i = 0; i < children.length; i++) { + sib = children[i]; + if(sib.nodeType === Node.TEXT_NODE){ + index++; + } + if(sib == textNode) break; } - if(sib == textNode) break; + + return index; + }; + + function isXml(ext) { + return ['xml', 'opf', 'ncx'].indexOf(ext) > -1; } - - return index; -}; - -function isXml(ext) { - return ['xml', 'opf', 'ncx'].indexOf(ext) > -1; -} - -function createBlob(content, mime){ - var blob = new Blob([content], {type : mime }); - - return blob; -}; - -function createBlobUrl(content, mime){ - var _URL = window.URL || window.webkitURL || window.mozURL; - var tempUrl; - var blob = this.createBlob(content, mime); - - tempUrl = _URL.createObjectURL(blob); - - return tempUrl; -}; - -function createBase64Url(content, mime){ - var string; - var data; - var datauri; - - if (typeof(content) !== "string") { - // Only handles strings - return; + + function createBlob(content, mime){ + var blob = new Blob([content], {type : mime }); + + return blob; + }; + + function createBlobUrl(content, mime){ + var _URL = window.URL || window.webkitURL || window.mozURL; + var tempUrl; + var blob = this.createBlob(content, mime); + + tempUrl = _URL.createObjectURL(blob); + + return tempUrl; + }; + + function createBase64Url(content, mime){ + var string; + var data; + var datauri; + + if (typeof(content) !== "string") { + // Only handles strings + return; + } + + data = btoa(content); + + datauri = "data:" + mime + ";base64," + data; + + return datauri; + }; + + function type(obj){ + return Object.prototype.toString.call(obj).slice(8, -1); } - - data = btoa(content); - - datauri = "data:" + mime + ";base64," + data; - - return datauri; -}; - -function type(obj){ - return Object.prototype.toString.call(obj).slice(8, -1); -} - -function parse(markup, mime) { - var doc; - // console.log("parse", markup); - - if (typeof DOMParser === "undefined") { - DOMParser = require('xmldom').DOMParser; + + function parse(markup, mime) { + var doc; + // console.log("parse", markup); + + if (typeof DOMParser === "undefined") { + DOMParser = __webpack_require__(13).DOMParser; + } + + + doc = new DOMParser().parseFromString(markup, mime); + + return doc; } - - - doc = new DOMParser().parseFromString(markup, mime); - - return doc; -} - -function qs(el, sel) { - var elements; - - if (typeof el.querySelector != "undefined") { - return el.querySelector(sel); - } else { - elements = el.getElementsByTagName(sel); - if (elements.length) { - return elements[0]; + + function qs(el, sel) { + var elements; + + if (typeof el.querySelector != "undefined") { + return el.querySelector(sel); + } else { + elements = el.getElementsByTagName(sel); + if (elements.length) { + return elements[0]; + } } } -} - -function qsa(el, sel) { - - if (typeof el.querySelector != "undefined") { - return el.querySelectorAll(sel); - } else { - return el.getElementsByTagName(sel); - } -} - -function qsp(el, sel, props) { - var q, filtered; - if (typeof el.querySelector != "undefined") { - sel += '['; - for (var prop in props) { - sel += prop + "='" + props[prop] + "'"; + + function qsa(el, sel) { + + if (typeof el.querySelector != "undefined") { + return el.querySelectorAll(sel); + } else { + return el.getElementsByTagName(sel); } - sel += ']'; - return el.querySelector(sel); - } else { - q = el.getElementsByTagName(sel); - filtered = Array.prototype.slice.call(q, 0).filter(function(el) { + } + + function qsp(el, sel, props) { + var q, filtered; + if (typeof el.querySelector != "undefined") { + sel += '['; for (var prop in props) { - if(el.getAttribute(prop) === props[prop]){ - return true; + sel += prop + "='" + props[prop] + "'"; + } + sel += ']'; + return el.querySelector(sel); + } else { + q = el.getElementsByTagName(sel); + filtered = Array.prototype.slice.call(q, 0).filter(function(el) { + for (var prop in props) { + if(el.getAttribute(prop) === props[prop]){ + return true; + } + } + return false; + }); + + if (filtered) { + return filtered[0]; + } + } + } + + function blob2base64(blob, cb) { + var reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onloadend = function() { + cb(reader.result); + } + } + + module.exports = { + // 'uri': uri, + // 'folder': folder, + 'isElement': isElement, + 'uuid': uuid, + 'values': values, + 'resolveUrl': resolveUrl, + 'indexOfSorted': indexOfSorted, + 'documentHeight': documentHeight, + 'isNumber': isNumber, + 'prefixed': prefixed, + 'defaults': defaults, + 'extend': extend, + 'insert': insert, + 'locationOf': locationOf, + 'indexOfSorted': indexOfSorted, + 'requestAnimationFrame': requestAnimationFrame, + 'bounds': bounds, + 'borders': borders, + 'windowBounds': windowBounds, + 'cleanStringForXpath': cleanStringForXpath, + 'indexOfTextNode': indexOfTextNode, + 'isXml': isXml, + 'createBlob': createBlob, + 'createBlobUrl': createBlobUrl, + 'type': type, + 'parse' : parse, + 'qs' : qs, + 'qsa' : qsa, + 'qsp' : qsp, + 'blob2base64' : blob2base64, + 'createBase64Url': createBase64Url + }; + + +/***/ }, +/* 12 */ +/***/ function(module, exports) { + + 'use strict' + + exports.byteLength = byteLength + exports.toByteArray = toByteArray + exports.fromByteArray = fromByteArray + + var lookup = [] + var revLookup = [] + var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + + var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i + } + + revLookup['-'.charCodeAt(0)] = 62 + revLookup['_'.charCodeAt(0)] = 63 + + function placeHoldersCount (b64) { + var len = b64.length + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 + } + + function byteLength (b64) { + // base64 is 4/3 + up to two characters of the original data + return b64.length * 3 / 4 - placeHoldersCount(b64) + } + + function toByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + var len = b64.length + placeHolders = placeHoldersCount(b64) + + arr = new Arr(len * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? len - 4 : len + + var L = 0 + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] + arr[L++] = (tmp >> 16) & 0xFF + arr[L++] = (tmp >> 8) & 0xFF + arr[L++] = tmp & 0xFF + } + + if (placeHolders === 2) { + tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[L++] = tmp & 0xFF + } else if (placeHolders === 1) { + tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[L++] = (tmp >> 8) & 0xFF + arr[L++] = tmp & 0xFF + } + + return arr + } + + function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] + } + + function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output.push(tripletToBase64(tmp)) + } + return output.join('') + } + + function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var output = '' + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + output += lookup[tmp >> 2] + output += lookup[(tmp << 4) & 0x3F] + output += '==' + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) + output += lookup[tmp >> 10] + output += lookup[(tmp >> 4) & 0x3F] + output += lookup[(tmp << 2) & 0x3F] + output += '=' + } + + parts.push(output) + + return parts.join('') + } + + +/***/ }, +/* 13 */ +/***/ function(module, exports) { + + module.exports = __WEBPACK_EXTERNAL_MODULE_13__; + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var core = __webpack_require__(11); + var EpubCFI = __webpack_require__(15); + var Hook = __webpack_require__(16); + var Section = __webpack_require__(17); + var replacements = __webpack_require__(19); + + function Spine(_request){ + this.request = _request; + this.spineItems = []; + this.spineByHref = {}; + this.spineById = {}; + + this.hooks = {}; + this.hooks.serialize = new Hook(); + this.hooks.content = new Hook(); + + // Register replacements + this.hooks.content.register(replacements.base); + this.hooks.content.register(replacements.canonical); + + this.epubcfi = new EpubCFI(); + + this.loaded = false; + }; + + Spine.prototype.load = function(_package) { + + this.items = _package.spine; + this.manifest = _package.manifest; + this.spineNodeIndex = _package.spineNodeIndex; + this.baseUrl = _package.baseUrl || ''; + this.length = this.items.length; + + this.items.forEach(function(item, index){ + var href, url; + var manifestItem = this.manifest[item.idref]; + var spineItem; + + item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref); + + if(manifestItem) { + item.href = manifestItem.href; + item.url = this.baseUrl + item.href; + + if(manifestItem.properties.length){ + item.properties.push.apply(item.properties, manifestItem.properties); } } - return false; + + // if(index > 0) { + item.prev = function(){ return this.get(index-1); }.bind(this); + // } + + // if(index+1 < this.items.length) { + item.next = function(){ return this.get(index+1); }.bind(this); + // } + + spineItem = new Section(item, this.hooks); + + this.append(spineItem); + + + }.bind(this)); + + this.loaded = true; + }; + + // book.spine.get(); + // book.spine.get(1); + // book.spine.get("chap1.html"); + // book.spine.get("#id1234"); + Spine.prototype.get = function(target) { + var index = 0; + + if(this.epubcfi.isCfiString(target)) { + cfi = new EpubCFI(target); + index = cfi.spinePos; + } else if(target && (typeof target === "number" || isNaN(target) === false)){ + index = target; + } else if(target && target.indexOf("#") === 0) { + index = this.spineById[target.substring(1)]; + } else if(target) { + // Remove fragments + target = target.split("#")[0]; + index = this.spineByHref[target]; + } + + return this.spineItems[index] || null; + }; + + Spine.prototype.append = function(section) { + var index = this.spineItems.length; + section.index = index; + + this.spineItems.push(section); + + this.spineByHref[section.href] = index; + this.spineById[section.idref] = index; + + return index; + }; + + Spine.prototype.prepend = function(section) { + var index = this.spineItems.unshift(section); + this.spineByHref[section.href] = 0; + this.spineById[section.idref] = 0; + + // Re-index + this.spineItems.forEach(function(item, index){ + item.index = index; }); - - if (filtered) { - return filtered[0]; + + return 0; + }; + + Spine.prototype.insert = function(section, index) { + + }; + + Spine.prototype.remove = function(section) { + var index = this.spineItems.indexOf(section); + + if(index > -1) { + delete this.spineByHref[section.href]; + delete this.spineById[section.idref]; + + return this.spineItems.splice(index, 1); } - } -} - -function blob2base64(blob, cb) { - var reader = new FileReader(); - reader.readAsDataURL(blob); - reader.onloadend = function() { - cb(reader.result); - } -} - -module.exports = { - // 'uri': uri, - // 'folder': folder, - 'isElement': isElement, - 'uuid': uuid, - 'values': values, - 'resolveUrl': resolveUrl, - 'indexOfSorted': indexOfSorted, - 'documentHeight': documentHeight, - 'isNumber': isNumber, - 'prefixed': prefixed, - 'defaults': defaults, - 'extend': extend, - 'insert': insert, - 'locationOf': locationOf, - 'indexOfSorted': indexOfSorted, - 'requestAnimationFrame': requestAnimationFrame, - 'bounds': bounds, - 'borders': borders, - 'windowBounds': windowBounds, - 'cleanStringForXpath': cleanStringForXpath, - 'indexOfTextNode': indexOfTextNode, - 'isXml': isXml, - 'createBlob': createBlob, - 'createBlobUrl': createBlobUrl, - 'type': type, - 'parse' : parse, - 'qs' : qs, - 'qsa' : qsa, - 'qsp' : qsp, - 'blob2base64' : blob2base64, - 'createBase64Url': createBase64Url -}; - -},{"base64-js":2,"rsvp":5,"xmldom":"xmldom"}],11:[function(require,module,exports){ -var URI = require('urijs'); -var core = require('./core'); - -/** - EPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html - - Implements: - - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3) - - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4) - - Does Not Implement: - - Temporal Offset (~) - - Spatial Offset (@) - - Temporal-Spatial Offset (~ + @) - - Text Location Assertion ([) -*/ - -function EpubCFI(cfiFrom, base, ignoreClass){ - var type; - - this.str = ''; - - this.base = {}; - this.spinePos = 0; // For compatibility - - this.range = false; // true || false; - - this.path = {}; - this.start = null; - this.end = null; - - // Allow instantiation without the 'new' keyword - if (!(this instanceof EpubCFI)) { - return new EpubCFI(cfiFrom, base, ignoreClass); - } - - if(typeof base === 'string') { - this.base = this.parseComponent(base); - } else if(typeof base === 'object' && base.steps) { - this.base = base; - } - - type = this.checkType(cfiFrom); + }; + + Spine.prototype.each = function() { + return this.spineItems.forEach.apply(this.spineItems, arguments); + }; + + module.exports = Spine; - if(type === 'string') { - this.str = cfiFrom; - return core.extend(this, this.parse(cfiFrom)); - } else if (type === 'range') { - return core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass)); - } else if (type === 'node') { - return core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass)); - } else if (type === 'EpubCFI' && cfiFrom.path) { - return cfiFrom; - } else if (!cfiFrom) { - return this; - } else { - throw new TypeError('not a valid argument for EpubCFI'); - } +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { -}; - -EpubCFI.prototype.checkType = function(cfi) { - - if (this.isCfiString(cfi)) { - return 'string'; - // Is a range object - } else if (typeof cfi === 'object' && core.type(cfi) === "Range"){ - return 'range'; - } else if (typeof cfi === 'object' && typeof(cfi.nodeType) != "undefined" ){ // || typeof cfi === 'function' - return 'node'; - } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){ - return 'EpubCFI'; - } else { - return false; - } -}; - -EpubCFI.prototype.parse = function(cfiStr) { - var cfi = { - spinePos: -1, - range: false, - base: {}, - path: {}, - start: null, - end: null + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + + /** + EPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html + + Implements: + - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3) + - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4) + + Does Not Implement: + - Temporal Offset (~) + - Spatial Offset (@) + - Temporal-Spatial Offset (~ + @) + - Text Location Assertion ([) + */ + + function EpubCFI(cfiFrom, base, ignoreClass){ + var type; + + this.str = ''; + + this.base = {}; + this.spinePos = 0; // For compatibility + + this.range = false; // true || false; + + this.path = {}; + this.start = null; + this.end = null; + + // Allow instantiation without the 'new' keyword + if (!(this instanceof EpubCFI)) { + return new EpubCFI(cfiFrom, base, ignoreClass); + } + + if(typeof base === 'string') { + this.base = this.parseComponent(base); + } else if(typeof base === 'object' && base.steps) { + this.base = base; + } + + type = this.checkType(cfiFrom); + + + if(type === 'string') { + this.str = cfiFrom; + return core.extend(this, this.parse(cfiFrom)); + } else if (type === 'range') { + return core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass)); + } else if (type === 'node') { + return core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass)); + } else if (type === 'EpubCFI' && cfiFrom.path) { + return cfiFrom; + } else if (!cfiFrom) { + return this; + } else { + throw new TypeError('not a valid argument for EpubCFI'); + } + + }; + + EpubCFI.prototype.checkType = function(cfi) { + + if (this.isCfiString(cfi)) { + return 'string'; + // Is a range object + } else if (typeof cfi === 'object' && core.type(cfi) === "Range"){ + return 'range'; + } else if (typeof cfi === 'object' && typeof(cfi.nodeType) != "undefined" ){ // || typeof cfi === 'function' + return 'node'; + } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){ + return 'EpubCFI'; + } else { + return false; + } + }; + + EpubCFI.prototype.parse = function(cfiStr) { + var cfi = { + spinePos: -1, + range: false, + base: {}, + path: {}, + start: null, + end: null + }; + var baseComponent, pathComponent, range; + + if(typeof cfiStr !== "string") { + return {spinePos: -1}; + } + + if(cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length-1] === ")") { + // Remove intial epubcfi( and ending ) + cfiStr = cfiStr.slice(8, cfiStr.length-1); + } + + baseComponent = this.getChapterComponent(cfiStr); + + // Make sure this is a valid cfi or return + if(!baseComponent) { + return {spinePos: -1}; + } + + cfi.base = this.parseComponent(baseComponent); + + pathComponent = this.getPathComponent(cfiStr); + cfi.path = this.parseComponent(pathComponent); + + range = this.getRange(cfiStr); + + if(range) { + cfi.range = true; + cfi.start = this.parseComponent(range[0]); + cfi.end = this.parseComponent(range[1]); + } + + // Get spine node position + // cfi.spineSegment = cfi.base.steps[1]; + + // Chapter segment is always the second step + cfi.spinePos = cfi.base.steps[1].index; + + return cfi; + }; + + EpubCFI.prototype.parseComponent = function(componentStr){ + var component = { + steps: [], + terminal: { + offset: null, + assertion: null + } }; - var baseComponent, pathComponent, range; - - if(typeof cfiStr !== "string") { - return {spinePos: -1}; - } - - if(cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length-1] === ")") { - // Remove intial epubcfi( and ending ) - cfiStr = cfiStr.slice(8, cfiStr.length-1); - } - - baseComponent = this.getChapterComponent(cfiStr); - - // Make sure this is a valid cfi or return - if(!baseComponent) { - return {spinePos: -1}; - } - - cfi.base = this.parseComponent(baseComponent); - - pathComponent = this.getPathComponent(cfiStr); - cfi.path = this.parseComponent(pathComponent); - - range = this.getRange(cfiStr); - - if(range) { - cfi.range = true; - cfi.start = this.parseComponent(range[0]); - cfi.end = this.parseComponent(range[1]); - } - - // Get spine node position - // cfi.spineSegment = cfi.base.steps[1]; - - // Chapter segment is always the second step - cfi.spinePos = cfi.base.steps[1].index; - - return cfi; -}; - -EpubCFI.prototype.parseComponent = function(componentStr){ - var component = { - steps: [], - terminal: { - offset: null, - assertion: null + var parts = componentStr.split(':'); + var steps = parts[0].split('/'); + var terminal; + + if(parts.length > 1) { + terminal = parts[1]; + component.terminal = this.parseTerminal(terminal); } + + if (steps[0] === '') { + steps.shift(); // Ignore the first slash + } + + component.steps = steps.map(function(step){ + return this.parseStep(step); + }.bind(this)); + + return component; }; - var parts = componentStr.split(':'); - var steps = parts[0].split('/'); - var terminal; - - if(parts.length > 1) { - terminal = parts[1]; - component.terminal = this.parseTerminal(terminal); - } - - if (steps[0] === '') { - steps.shift(); // Ignore the first slash - } - - component.steps = steps.map(function(step){ - return this.parseStep(step); - }.bind(this)); - - return component; -}; - -EpubCFI.prototype.parseStep = function(stepStr){ - var type, num, index, has_brackets, id; - - has_brackets = stepStr.match(/\[(.*)\]/); - if(has_brackets && has_brackets[1]){ - id = has_brackets[1]; - } - - //-- Check if step is a text node or element - num = parseInt(stepStr); - - if(isNaN(num)) { - return; - } - - if(num % 2 === 0) { // Even = is an element - type = "element"; - index = num / 2 - 1; - } else { - type = "text"; - index = (num - 1 ) / 2; - } - - return { - "type" : type, - 'index' : index, - 'id' : id || null + + EpubCFI.prototype.parseStep = function(stepStr){ + var type, num, index, has_brackets, id; + + has_brackets = stepStr.match(/\[(.*)\]/); + if(has_brackets && has_brackets[1]){ + id = has_brackets[1]; + } + + //-- Check if step is a text node or element + num = parseInt(stepStr); + + if(isNaN(num)) { + return; + } + + if(num % 2 === 0) { // Even = is an element + type = "element"; + index = num / 2 - 1; + } else { + type = "text"; + index = (num - 1 ) / 2; + } + + return { + "type" : type, + 'index' : index, + 'id' : id || null + }; }; -}; - -EpubCFI.prototype.parseTerminal = function(termialStr){ - var characterOffset, textLocationAssertion; - var assertion = termialStr.match(/\[(.*)\]/); - - if(assertion && assertion[1]){ - characterOffset = parseInt(termialStr.split('[')[0]) || null; - textLocationAssertion = assertion[1]; - } else { - characterOffset = parseInt(termialStr) || null; - } - - return { - 'offset': characterOffset, - 'assertion': textLocationAssertion + + EpubCFI.prototype.parseTerminal = function(termialStr){ + var characterOffset, textLocationAssertion; + var assertion = termialStr.match(/\[(.*)\]/); + + if(assertion && assertion[1]){ + characterOffset = parseInt(termialStr.split('[')[0]) || null; + textLocationAssertion = assertion[1]; + } else { + characterOffset = parseInt(termialStr) || null; + } + + return { + 'offset': characterOffset, + 'assertion': textLocationAssertion + }; + }; - -}; - -EpubCFI.prototype.getChapterComponent = function(cfiStr) { - - var indirection = cfiStr.split("!"); - - return indirection[0]; -}; - -EpubCFI.prototype.getPathComponent = function(cfiStr) { - - var indirection = cfiStr.split("!"); - - if(indirection[1]) { - ranges = indirection[1].split(','); - return ranges[0]; - } - -}; - -EpubCFI.prototype.getRange = function(cfiStr) { - - var ranges = cfiStr.split(","); - - if(ranges.length === 3){ - return [ - ranges[1], - ranges[2] - ]; - } - - return false; -}; - -EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) { - var splitStr = cfiStr.split(":"); - return splitStr[1] || ''; -}; - -EpubCFI.prototype.joinSteps = function(steps) { - if(!steps) { - return ""; - } - - return steps.map(function(part){ - var segment = ''; - - if(part.type === 'element') { - segment += (part.index + 1) * 2; + + EpubCFI.prototype.getChapterComponent = function(cfiStr) { + + var indirection = cfiStr.split("!"); + + return indirection[0]; + }; + + EpubCFI.prototype.getPathComponent = function(cfiStr) { + + var indirection = cfiStr.split("!"); + + if(indirection[1]) { + ranges = indirection[1].split(','); + return ranges[0]; } - - if(part.type === 'text') { - segment += 1 + (2 * part.index); // TODO: double check that this is odd + + }; + + EpubCFI.prototype.getRange = function(cfiStr) { + + var ranges = cfiStr.split(","); + + if(ranges.length === 3){ + return [ + ranges[1], + ranges[2] + ]; } - - if(part.id) { - segment += "[" + part.id + "]"; + + return false; + }; + + EpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) { + var splitStr = cfiStr.split(":"); + return splitStr[1] || ''; + }; + + EpubCFI.prototype.joinSteps = function(steps) { + if(!steps) { + return ""; } - - return segment; - - }).join('/'); - -}; - -EpubCFI.prototype.segmentString = function(segment) { - var segmentString = '/'; - - segmentString += this.joinSteps(segment.steps); - - if(segment.terminal && segment.terminal.offset != null){ - segmentString += ':' + segment.terminal.offset; - } - - if(segment.terminal && segment.terminal.assertion != null){ - segmentString += '[' + segment.terminal.assertion + ']'; - } - - return segmentString; -}; - -EpubCFI.prototype.toString = function() { - var cfiString = 'epubcfi('; - - cfiString += this.segmentString(this.base); - - cfiString += '!'; - cfiString += this.segmentString(this.path); - - // Add Range, if present - if(this.start) { - cfiString += ','; - cfiString += this.segmentString(this.start); - } - - if(this.end) { - cfiString += ','; - cfiString += this.segmentString(this.end); - } - - cfiString += ")"; - - 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 steps.map(function(part){ + var segment = ''; + + if(part.type === 'element') { + segment += (part.index + 1) * 2; + } + + if(part.type === 'text') { + segment += 1 + (2 * part.index); // TODO: double check that this is odd + } + + if(part.id) { + segment += "[" + part.id + "]"; + } + + return segment; + + }).join('/'); + + }; + + EpubCFI.prototype.segmentString = function(segment) { + var segmentString = '/'; + + segmentString += this.joinSteps(segment.steps); + + if(segment.terminal && segment.terminal.offset != null){ + segmentString += ':' + segment.terminal.offset; + } + + if(segment.terminal && segment.terminal.assertion != null){ + segmentString += '[' + segment.terminal.assertion + ']'; + } + + return segmentString; + }; + + EpubCFI.prototype.toString = function() { + var cfiString = 'epubcfi('; + + cfiString += this.segmentString(this.base); + + cfiString += '!'; + cfiString += this.segmentString(this.path); + + // Add Range, if present + if(this.start) { + cfiString += ','; + cfiString += this.segmentString(this.start); + } + + if(this.end) { + cfiString += ','; + cfiString += this.segmentString(this.end); + } + + cfiString += ")"; + + 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.path.steps[i].index > cfiTwo.path.steps[i].index) { - return 1; - } - if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) { + if(cfiOne.spinePos < cfiTwo.spinePos) { return -1; } - // Otherwise continue checking - } - - // All steps in First equal to Second and First is Less Specific - 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; -}; - -EpubCFI.prototype.step = function(node) { - var nodeType = (node.nodeType === Node.TEXT_NODE) ? 'text' : 'element'; - - return { - 'id' : node.id, - 'tagName' : node.tagName, - 'type' : nodeType, - 'index' : this.position(node) + + + // 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 equal to Second and First is Less Specific + 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; }; -}; - -EpubCFI.prototype.filteredStep = function(node, ignoreClass) { - var filteredNode = this.filter(node, ignoreClass); - var nodeType; - - // Node filtered, so ignore - if (!filteredNode) { - return; - } - - // Otherwise add the filter node in - nodeType = (filteredNode.nodeType === Node.TEXT_NODE) ? 'text' : 'element'; - - return { - 'id' : filteredNode.id, - 'tagName' : filteredNode.tagName, - 'type' : nodeType, - 'index' : this.filteredPosition(filteredNode, ignoreClass) - }; -}; - -EpubCFI.prototype.pathTo = function(node, offset, ignoreClass) { - var segment = { - steps: [], - terminal: { - offset: null, - assertion: null - } - }; - var currentNode = node; - var step; - - while(currentNode && currentNode.parentNode && - currentNode.parentNode.nodeType != Node.DOCUMENT_NODE) { - - if (ignoreClass) { - step = this.filteredStep(currentNode, ignoreClass); - } else { - step = this.step(currentNode); - } - - if (step) { - segment.steps.unshift(step); - } - - currentNode = currentNode.parentNode; - - } - - if (offset != null && offset >= 0) { - - segment.terminal.offset = offset; - - // Make sure we are getting to a textNode if there is an offset - if(segment.steps[segment.steps.length-1].type != "text") { - segment.steps.push({ - 'type' : "text", - 'index' : 0 - }); - } - - } - - - return segment; -} - -EpubCFI.prototype.equalStep = function(stepA, stepB) { - if (!stepA || !stepB) { - return false; - } - - if(stepA.index === stepB.index && - stepA.id === stepB.id && - stepA.type === stepB.type) { - return true; - } - - return false; -}; -EpubCFI.prototype.fromRange = function(range, base, ignoreClass) { - var cfi = { - range: false, - base: {}, - path: {}, - start: null, - end: null + + EpubCFI.prototype.step = function(node) { + var nodeType = (node.nodeType === Node.TEXT_NODE) ? 'text' : 'element'; + + return { + 'id' : node.id, + 'tagName' : node.tagName, + 'type' : nodeType, + 'index' : this.position(node) }; - - var start = range.startContainer; - var end = range.endContainer; - - var startOffset = range.startOffset; - var endOffset = range.endOffset; - - var needsIgnoring = false; - - if (ignoreClass) { - // Tell pathTo if / what to ignore - needsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null); - } - - - if (typeof base === 'string') { - cfi.base = this.parseComponent(base); - cfi.spinePos = cfi.base.steps[1].index; - } else if (typeof base === 'object') { - cfi.base = base; - } - - if (range.collapsed) { - if (needsIgnoring) { - startOffset = this.patchOffset(start, startOffset, ignoreClass); + }; + + EpubCFI.prototype.filteredStep = function(node, ignoreClass) { + var filteredNode = this.filter(node, ignoreClass); + var nodeType; + + // Node filtered, so ignore + if (!filteredNode) { + return; } - cfi.path = this.pathTo(start, startOffset, ignoreClass); - } else { - cfi.range = true; - - if (needsIgnoring) { - startOffset = this.patchOffset(start, startOffset, ignoreClass); - } - - cfi.start = this.pathTo(start, startOffset, ignoreClass); - - if (needsIgnoring) { - endOffset = this.patchOffset(end, endOffset, ignoreClass); - } - - cfi.end = this.pathTo(end, endOffset, ignoreClass); - - // Create a new empty path - cfi.path = { + + // Otherwise add the filter node in + nodeType = (filteredNode.nodeType === Node.TEXT_NODE) ? 'text' : 'element'; + + return { + 'id' : filteredNode.id, + 'tagName' : filteredNode.tagName, + 'type' : nodeType, + 'index' : this.filteredPosition(filteredNode, ignoreClass) + }; + }; + + EpubCFI.prototype.pathTo = function(node, offset, ignoreClass) { + var segment = { steps: [], - terminal: null - }; - - // Push steps that are shared between start and end to the common path - var len = cfi.start.steps.length; - var i; - - for (i = 0; i < len; i++) { - if (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) { - if(i == len-1) { - // Last step is equal, check terminals - if(cfi.start.terminal === cfi.end.terminal) { - // CFI's are equal - cfi.path.steps.push(cfi.start.steps[i]); - // Not a range - cfi.range = false; - } - } else { - cfi.path.steps.push(cfi.start.steps[i]); - } - - } else { - break; + terminal: { + offset: null, + assertion: null } }; - - cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length); - cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length); - - // TODO: Add Sanity check to make sure that the end if greater than the start - } - - return cfi; -} - -EpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) { - var cfi = { - range: false, - base: {}, - path: {}, - start: null, - end: null - }; - - var needsIgnoring = false; - - if (ignoreClass) { - // Tell pathTo if / what to ignore - needsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null); - } - - if (typeof base === 'string') { - cfi.base = this.parseComponent(base); - cfi.spinePos = cfi.base.steps[1].index; - } else if (typeof base === 'object') { - cfi.base = base; - } - - cfi.path = this.pathTo(anchor, null, ignoreClass); - - return cfi; -}; - - -EpubCFI.prototype.filter = function(anchor, ignoreClass) { - var needsIgnoring; - var sibling; // to join with - var parent, prevSibling, nextSibling; - var isText = false; - - if (anchor.nodeType === Node.TEXT_NODE) { - isText = true; - parent = anchor.parentNode; - needsIgnoring = anchor.parentNode.classList.contains(ignoreClass); - } else { - isText = false; - needsIgnoring = anchor.classList.contains(ignoreClass); - } - - if (needsIgnoring && isText) { - previousSibling = parent.previousSibling; - nextSibling = parent.nextSibling; - - // If the sibling is a text node, join the nodes - if (previousSibling && previousSibling.nodeType === Node.TEXT_NODE) { - sibling = previousSibling; - } else if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) { - sibling = nextSibling; + var currentNode = node; + var step; + + while(currentNode && currentNode.parentNode && + currentNode.parentNode.nodeType != Node.DOCUMENT_NODE) { + + if (ignoreClass) { + step = this.filteredStep(currentNode, ignoreClass); + } else { + step = this.step(currentNode); + } + + if (step) { + segment.steps.unshift(step); + } + + currentNode = currentNode.parentNode; + } - - if (sibling) { - return sibling; + + if (offset != null && offset >= 0) { + + segment.terminal.offset = offset; + + // Make sure we are getting to a textNode if there is an offset + if(segment.steps[segment.steps.length-1].type != "text") { + segment.steps.push({ + 'type' : "text", + 'index' : 0 + }); + } + + } + + + return segment; + } + + EpubCFI.prototype.equalStep = function(stepA, stepB) { + if (!stepA || !stepB) { + return false; + } + + if(stepA.index === stepB.index && + stepA.id === stepB.id && + stepA.type === stepB.type) { + return true; + } + + return false; + }; + EpubCFI.prototype.fromRange = function(range, base, ignoreClass) { + var cfi = { + range: false, + base: {}, + path: {}, + start: null, + end: null + }; + + var start = range.startContainer; + var end = range.endContainer; + + var startOffset = range.startOffset; + var endOffset = range.endOffset; + + var needsIgnoring = false; + + if (ignoreClass) { + // Tell pathTo if / what to ignore + needsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null); + } + + + if (typeof base === 'string') { + cfi.base = this.parseComponent(base); + cfi.spinePos = cfi.base.steps[1].index; + } else if (typeof base === 'object') { + cfi.base = base; + } + + if (range.collapsed) { + if (needsIgnoring) { + startOffset = this.patchOffset(start, startOffset, ignoreClass); + } + cfi.path = this.pathTo(start, startOffset, ignoreClass); } else { - // Parent will be ignored on next step + cfi.range = true; + + if (needsIgnoring) { + startOffset = this.patchOffset(start, startOffset, ignoreClass); + } + + cfi.start = this.pathTo(start, startOffset, ignoreClass); + + if (needsIgnoring) { + endOffset = this.patchOffset(end, endOffset, ignoreClass); + } + + cfi.end = this.pathTo(end, endOffset, ignoreClass); + + // Create a new empty path + cfi.path = { + steps: [], + terminal: null + }; + + // Push steps that are shared between start and end to the common path + var len = cfi.start.steps.length; + var i; + + for (i = 0; i < len; i++) { + if (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) { + if(i == len-1) { + // Last step is equal, check terminals + if(cfi.start.terminal === cfi.end.terminal) { + // CFI's are equal + cfi.path.steps.push(cfi.start.steps[i]); + // Not a range + cfi.range = false; + } + } else { + cfi.path.steps.push(cfi.start.steps[i]); + } + + } else { + break; + } + }; + + cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length); + cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length); + + // TODO: Add Sanity check to make sure that the end if greater than the start + } + + return cfi; + } + + EpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) { + var cfi = { + range: false, + base: {}, + path: {}, + start: null, + end: null + }; + + var needsIgnoring = false; + + if (ignoreClass) { + // Tell pathTo if / what to ignore + needsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null); + } + + if (typeof base === 'string') { + cfi.base = this.parseComponent(base); + cfi.spinePos = cfi.base.steps[1].index; + } else if (typeof base === 'object') { + cfi.base = base; + } + + cfi.path = this.pathTo(anchor, null, ignoreClass); + + return cfi; + }; + + + EpubCFI.prototype.filter = function(anchor, ignoreClass) { + var needsIgnoring; + var sibling; // to join with + var parent, prevSibling, nextSibling; + var isText = false; + + if (anchor.nodeType === Node.TEXT_NODE) { + isText = true; + parent = anchor.parentNode; + needsIgnoring = anchor.parentNode.classList.contains(ignoreClass); + } else { + isText = false; + needsIgnoring = anchor.classList.contains(ignoreClass); + } + + if (needsIgnoring && isText) { + previousSibling = parent.previousSibling; + nextSibling = parent.nextSibling; + + // If the sibling is a text node, join the nodes + if (previousSibling && previousSibling.nodeType === Node.TEXT_NODE) { + sibling = previousSibling; + } else if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) { + sibling = nextSibling; + } + + if (sibling) { + return sibling; + } else { + // Parent will be ignored on next step + return anchor; + } + + } else if (needsIgnoring && !isText) { + // Otherwise just skip the element node + return false; + } else { + // No need to filter return anchor; } - - } else if (needsIgnoring && !isText) { - // Otherwise just skip the element node - return false; - } else { - // No need to filter - return anchor; - } - -}; - -EpubCFI.prototype.patchOffset = function(anchor, offset, ignoreClass) { - var needsIgnoring; - var sibling; - - if (anchor.nodeType != Node.TEXT_NODE) { - console.error("Anchor must be a text node"); - return; - } - - var curr = anchor; - var totalOffset = offset; - - // If the parent is a ignored node, get offset from it's start - if (anchor.parentNode.classList.contains(ignoreClass)) { - curr = anchor.parentNode; - } - - while (curr.previousSibling) { - if(curr.previousSibling.nodeType === Node.ELEMENT_NODE) { - // Originally a text node, so join - if(curr.previousSibling.classList.contains(ignoreClass)){ + + }; + + EpubCFI.prototype.patchOffset = function(anchor, offset, ignoreClass) { + var needsIgnoring; + var sibling; + + if (anchor.nodeType != Node.TEXT_NODE) { + console.error("Anchor must be a text node"); + return; + } + + var curr = anchor; + var totalOffset = offset; + + // If the parent is a ignored node, get offset from it's start + if (anchor.parentNode.classList.contains(ignoreClass)) { + curr = anchor.parentNode; + } + + while (curr.previousSibling) { + if(curr.previousSibling.nodeType === Node.ELEMENT_NODE) { + // Originally a text node, so join + if(curr.previousSibling.classList.contains(ignoreClass)){ + totalOffset += curr.previousSibling.textContent.length; + } else { + break; // Normal node, dont join + } + } else { + // If the previous sibling is a text node, join the nodes totalOffset += curr.previousSibling.textContent.length; - } else { - break; // Normal node, dont join } + + curr = curr.previousSibling; + } + + return totalOffset; + + }; + + EpubCFI.prototype.normalizedMap = function(children, nodeType, ignoreClass) { + var output = {}; + var prevIndex = -1; + var i, len = children.length; + var currNodeType; + var prevNodeType; + + for (i = 0; i < len; i++) { + + currNodeType = children[i].nodeType; + + // Check if needs ignoring + if (currNodeType === Node.ELEMENT_NODE && + children[i].classList.contains(ignoreClass)) { + currNodeType = Node.TEXT_NODE; + } + + if (i > 0 && + currNodeType === Node.TEXT_NODE && + prevNodeType === Node.TEXT_NODE) { + // join text nodes + output[i] = prevIndex; + } else if (nodeType === currNodeType){ + prevIndex = prevIndex + 1; + output[i] = prevIndex; + } + + prevNodeType = currNodeType; + + } + + return output; + }; + + EpubCFI.prototype.position = function(anchor) { + var children, index, map; + + if (anchor.nodeType === Node.ELEMENT_NODE) { + children = anchor.parentNode.children; + index = Array.prototype.indexOf.call(children, anchor); } else { - // If the previous sibling is a text node, join the nodes - totalOffset += curr.previousSibling.textContent.length; + children = this.textNodes(anchor.parentNode); + index = children.indexOf(anchor); } - - curr = curr.previousSibling; - } - - return totalOffset; - -}; - -EpubCFI.prototype.normalizedMap = function(children, nodeType, ignoreClass) { - var output = {}; - var prevIndex = -1; - var i, len = children.length; - var currNodeType; - var prevNodeType; - - for (i = 0; i < len; i++) { - - currNodeType = children[i].nodeType; - - // Check if needs ignoring - if (currNodeType === Node.ELEMENT_NODE && - children[i].classList.contains(ignoreClass)) { - currNodeType = Node.TEXT_NODE; - } - - if (i > 0 && - currNodeType === Node.TEXT_NODE && - prevNodeType === Node.TEXT_NODE) { - // join text nodes - output[i] = prevIndex; - } else if (nodeType === currNodeType){ - prevIndex = prevIndex + 1; - output[i] = prevIndex; - } - - prevNodeType = currNodeType; - - } - - return output; -}; - -EpubCFI.prototype.position = function(anchor) { - var children, index, map; - - if (anchor.nodeType === Node.ELEMENT_NODE) { - children = anchor.parentNode.children; - index = Array.prototype.indexOf.call(children, anchor); - } else { - children = this.textNodes(anchor.parentNode); - index = children.indexOf(anchor); - } - - return index; -}; - -EpubCFI.prototype.filteredPosition = function(anchor, ignoreClass) { - var children, index, map; - - if (anchor.nodeType === Node.ELEMENT_NODE) { - children = anchor.parentNode.children; - map = this.normalizedMap(children, Node.ELEMENT_NODE, ignoreClass); - } else { - children = anchor.parentNode.childNodes; - // Inside an ignored node - if(anchor.parentNode.classList.contains(ignoreClass)) { - anchor = anchor.parentNode; + + return index; + }; + + EpubCFI.prototype.filteredPosition = function(anchor, ignoreClass) { + var children, index, map; + + if (anchor.nodeType === Node.ELEMENT_NODE) { + children = anchor.parentNode.children; + map = this.normalizedMap(children, Node.ELEMENT_NODE, ignoreClass); + } else { children = anchor.parentNode.childNodes; - } - map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass); - } - - - index = Array.prototype.indexOf.call(children, anchor); - - return map[index]; -}; - -EpubCFI.prototype.stepsToXpath = function(steps) { - var xpath = [".", "*"]; - - steps.forEach(function(step){ - var position = step.index + 1; - - if(step.id){ - xpath.push("*[position()=" + position + " and @id='" + step.id + "']"); - } else if(step.type === "text") { - xpath.push("text()[" + position + "]"); - } else { - xpath.push("*[" + position + "]"); - } - }); - - return xpath.join("/"); -}; - - -/* - -To get the last step if needed: - -// Get the terminal step -lastStep = steps[steps.length-1]; -// Get the query string -query = this.stepsToQuery(steps); -// Find the containing element -startContainerParent = doc.querySelector(query); -// Find the text node within that element -if(startContainerParent && lastStep.type == "text") { - container = startContainerParent.childNodes[lastStep.index]; -} -*/ -EpubCFI.prototype.stepsToQuerySelector = function(steps) { - var query = ["html"]; - - steps.forEach(function(step){ - var position = step.index + 1; - - if(step.id){ - query.push("#" + step.id); - } else if(step.type === "text") { - // unsupported in querySelector - // query.push("text()[" + position + "]"); - } else { - query.push("*:nth-child(" + position + ")"); - } - }); - - return query.join(">"); - -}; - -EpubCFI.prototype.textNodes = function(container, ignoreClass) { - return Array.prototype.slice.call(container.childNodes). - filter(function (node) { - if (node.nodeType === Node.TEXT_NODE) { - return true; - } else if (ignoreClass && node.classList.contains(ignoreClass)) { - return true; + // Inside an ignored node + if(anchor.parentNode.classList.contains(ignoreClass)) { + anchor = anchor.parentNode; + children = anchor.parentNode.childNodes; } - return false; - }); -}; - -EpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) { - var doc = _doc || document; - var container = doc.documentElement; - var step; - var len = steps.length; - var i; - - for (i = 0; i < len; i++) { - step = steps[i]; - - if(step.type === "element") { - container = container.children[step.index]; - } else if(step.type === "text"){ - container = this.textNodes(container, ignoreClass)[step.index]; + map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass); } - + + + index = Array.prototype.indexOf.call(children, anchor); + + return map[index]; }; - - return container; -}; - -EpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) { - var doc = _doc || document; - var container; - var xpath; - - if(!ignoreClass && typeof doc.evaluate != 'undefined') { - xpath = this.stepsToXpath(steps); - container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; - } else if(ignoreClass) { - container = this.walkToNode(steps, doc, ignoreClass); - } else { - container = this.walkToNode(steps, doc); - } - - return container; -}; - -EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) { - var container = this.findNode(steps.slice(0,-1), _doc, ignoreClass); - var children = container.childNodes; - var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass); - var i; - var child; - var len; - var childIndex; - var lastStepIndex = steps[steps.length-1].index; - - for (var childIndex in map) { - if (!map.hasOwnProperty(childIndex)) return; - - if(map[childIndex] === lastStepIndex) { - child = children[childIndex]; - len = child.textContent.length; - if(offset > len) { - offset = offset - len; + + EpubCFI.prototype.stepsToXpath = function(steps) { + var xpath = [".", "*"]; + + steps.forEach(function(step){ + var position = step.index + 1; + + if(step.id){ + xpath.push("*[position()=" + position + " and @id='" + step.id + "']"); + } else if(step.type === "text") { + xpath.push("text()[" + position + "]"); } else { - if (child.nodeType === Node.ELEMENT_NODE) { - container = child.childNodes[0]; + xpath.push("*[" + position + "]"); + } + }); + + return xpath.join("/"); + }; + + + /* + + To get the last step if needed: + + // Get the terminal step + lastStep = steps[steps.length-1]; + // Get the query string + query = this.stepsToQuery(steps); + // Find the containing element + startContainerParent = doc.querySelector(query); + // Find the text node within that element + if(startContainerParent && lastStep.type == "text") { + container = startContainerParent.childNodes[lastStep.index]; + } + */ + EpubCFI.prototype.stepsToQuerySelector = function(steps) { + var query = ["html"]; + + steps.forEach(function(step){ + var position = step.index + 1; + + if(step.id){ + query.push("#" + step.id); + } else if(step.type === "text") { + // unsupported in querySelector + // query.push("text()[" + position + "]"); + } else { + query.push("*:nth-child(" + position + ")"); + } + }); + + return query.join(">"); + + }; + + EpubCFI.prototype.textNodes = function(container, ignoreClass) { + return Array.prototype.slice.call(container.childNodes). + filter(function (node) { + if (node.nodeType === Node.TEXT_NODE) { + return true; + } else if (ignoreClass && node.classList.contains(ignoreClass)) { + return true; + } + return false; + }); + }; + + EpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) { + var doc = _doc || document; + var container = doc.documentElement; + var step; + var len = steps.length; + var i; + + for (i = 0; i < len; i++) { + step = steps[i]; + + if(step.type === "element") { + container = container.children[step.index]; + } else if(step.type === "text"){ + container = this.textNodes(container, ignoreClass)[step.index]; + } + + }; + + return container; + }; + + EpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) { + var doc = _doc || document; + var container; + var xpath; + + if(!ignoreClass && typeof doc.evaluate != 'undefined') { + xpath = this.stepsToXpath(steps); + container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; + } else if(ignoreClass) { + container = this.walkToNode(steps, doc, ignoreClass); + } else { + container = this.walkToNode(steps, doc); + } + + return container; + }; + + EpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) { + var container = this.findNode(steps.slice(0,-1), _doc, ignoreClass); + var children = container.childNodes; + var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass); + var i; + var child; + var len; + var childIndex; + var lastStepIndex = steps[steps.length-1].index; + + for (var childIndex in map) { + if (!map.hasOwnProperty(childIndex)) return; + + if(map[childIndex] === lastStepIndex) { + child = children[childIndex]; + len = child.textContent.length; + if(offset > len) { + offset = offset - len; } else { - container = child; - } - break; - } - } - } - - return { - container: container, - offset: offset - }; - -}; - -EpubCFI.prototype.toRange = function(_doc, ignoreClass) { - var doc = _doc || document; - var range = doc.createRange(); - var start, end, startContainer, endContainer; - var cfi = this; - var startSteps, endSteps; - var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false; - var missed; - - if (cfi.range) { - start = cfi.start; - startSteps = cfi.path.steps.concat(start.steps); - startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null); - end = cfi.end; - endSteps = cfi.path.steps.concat(end.steps); - endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null); - } else { - start = cfi.path; - startSteps = cfi.path.steps; - startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null); - } - - if(startContainer) { - try { - - if(start.terminal.offset != null) { - range.setStart(startContainer, start.terminal.offset); - } else { - range.setStart(startContainer, 0); - } - - } catch (e) { - missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null); - range.setStart(missed.container, missed.offset); - } - } else { - // No start found - return null; - } - - if (endContainer) { - try { - - if(end.terminal.offset != null) { - range.setEnd(endContainer, end.terminal.offset); - } else { - range.setEnd(endContainer, 0); - } - - } catch (e) { - missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null); - range.setEnd(missed.container, missed.offset); - } - } - - - // doc.defaultView.getSelection().addRange(range); - return range; -}; - -// is a cfi string, should be wrapped with "epubcfi()" -EpubCFI.prototype.isCfiString = function(str) { - if(typeof str === 'string' && - str.indexOf("epubcfi(") === 0 && - str[str.length-1] === ")") { - return true; - } - - return false; -}; - -EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) { - var pos = parseInt(_pos), - spineNodeIndex = _spineNodeIndex + 1, - cfi = '/'+spineNodeIndex+'/'; - - cfi += (pos + 1) * 2; - - if(id) { - cfi += "[" + id + "]"; - } - - return cfi; -}; - -module.exports = EpubCFI; - -},{"./core":10,"urijs":7}],12:[function(require,module,exports){ -var RSVP = require('rsvp'); - -//-- Hooks allow for injecting functions that must all complete in order before finishing -// They will execute in parallel but all must finish before continuing -// Functions may return a promise if they are asycn. - -// this.content = new EPUBJS.Hook(); -// this.content.register(function(){}); -// this.content.trigger(args).then(function(){}); - -function Hook(context){ - this.context = context || this; - this.hooks = []; -}; - -// Adds a function to be run before a hook completes -Hook.prototype.register = function(){ - for(var i = 0; i < arguments.length; ++i) { - if (typeof arguments[i] === "function") { - this.hooks.push(arguments[i]); - } else { - // unpack array - for(var j = 0; j < arguments[i].length; ++j) { - this.hooks.push(arguments[i][j]); - } - } - } -}; - -// Triggers a hook to run all functions -Hook.prototype.trigger = function(){ - var args = arguments; - var context = this.context; - var promises = []; - - this.hooks.forEach(function(task, i) { - var executing = task.apply(context, args); - - if(executing && typeof executing["then"] === "function") { - // Task is a function that returns a promise - promises.push(executing); - } - // Otherwise Task resolves immediately, continue - }); - - - return RSVP.all(promises); -}; - -// Adds a function to be run before a hook completes -Hook.prototype.list = function(){ - return this.hooks; -}; - -Hook.prototype.clear = function(){ - return this.hooks = []; -}; - -module.exports = Hook; - -},{"rsvp":5}],13:[function(require,module,exports){ -var core = require('./core'); -var RSVP = require('rsvp'); - -function Layout(settings){ - this.name = settings.layout || "reflowable"; - this._spread = (settings.spread === "none") ? false : true; - this._minSpreadWidth = settings.spread || 800; - this._evenSpreads = settings.evenSpreads || false; - - if (settings.flow === "scrolled-continuous" || - settings.flow === "scrolled-doc") { - this._flow = "scrolled"; - } else { - this._flow = "paginated"; - } - - - this.width = 0; - this.height = 0; - this.spreadWidth = 0; - this.delta = 0; - - this.columnWidth = 0; - this.gap = 0; - this.divisor = 1; -}; - -// paginated | scrolled -Layout.prototype.flow = function(flow) { - this._flow = (flow === "paginated") ? "paginated" : "scrolled"; -} - -// true | false -Layout.prototype.spread = function(spread, min) { - - this._spread = (spread === "none") ? false : true; - - if (min >= 0) { - this._minSpreadWidth = min; - } -} - -Layout.prototype.calculate = function(_width, _height, _gap){ - - var divisor = 1; - var gap = _gap || 0; - - //-- Check the width and create even width columns - var fullWidth = Math.floor(_width); - var width = _width; - - var section = Math.floor(width / 8); - - var colWidth; - var spreadWidth; - var delta; - - if (this._spread && width >= this._minSpreadWidth) { - divisor = 2; - } else { - divisor = 1; - } - - if (this.name === "reflowable" && this._flow === "paginated" && !(_gap >= 0)) { - gap = ((section % 2 === 0) ? section : section - 1); - } - - if (this.name === "pre-paginated" ) { - gap = 0; - } - - //-- Double Page - if(divisor > 1) { - colWidth = Math.floor((width - gap) / divisor); - } else { - colWidth = width; - } - - if (this.name === "pre-paginated" && divisor > 1) { - width = colWidth; - } - - spreadWidth = colWidth * divisor; - - delta = (colWidth + gap) * divisor; - - this.width = width; - this.height = _height; - this.spreadWidth = spreadWidth; - this.delta = delta; - - this.columnWidth = colWidth; - this.gap = gap; - this.divisor = divisor; -}; - -Layout.prototype.format = function(contents){ - var formating; - - if (this.name === "pre-paginated") { - formating = contents.fit(this.columnWidth, this.height); - } else if (this._flow === "paginated") { - formating = contents.columns(this.width, this.height, this.columnWidth, this.gap); - } else { // scrolled - formating = contents.size(this.width, null); - } - - return formating; // might be a promise in some View Managers -}; - -Layout.prototype.count = function(totalWidth) { - // var totalWidth = contents.scrollWidth(); - var spreads = Math.ceil( totalWidth / this.spreadWidth); - - return { - spreads : spreads, - pages : spreads * this.divisor - }; -}; - -module.exports = Layout; - -},{"./core":10,"rsvp":5}],14:[function(require,module,exports){ -var core = require('./core'); -var Queue = require('./queue'); -var EpubCFI = require('./epubcfi'); -var RSVP = require('rsvp'); - -function Locations(spine, request) { - this.spine = spine; - this.request = request; - - this.q = new Queue(this); - this.epubcfi = new EpubCFI(); - - this._locations = []; - this.total = 0; - - this.break = 150; - - this._current = 0; - -}; - -// Load all of sections in the book -Locations.prototype.generate = function(chars) { - - if (chars) { - this.break = chars; - } - - this.q.pause(); - - this.spine.each(function(section) { - - this.q.enqueue(this.process, section); - - }.bind(this)); - - return this.q.run().then(function() { - this.total = this._locations.length-1; - - if (this._currentCfi) { - this.currentLocation = this._currentCfi; - } - - return this._locations; - // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end)); - }.bind(this)); - -}; - -Locations.prototype.process = function(section) { - - return section.load(this.request) - .then(function(contents) { - - var range; - var doc = contents.ownerDocument; - var counter = 0; - - this.sprint(contents, function(node) { - var len = node.length; - var dist; - var pos = 0; - - // Start range - if (counter == 0) { - range = doc.createRange(); - range.setStart(node, 0); - } - - dist = this.break - counter; - - // Node is smaller than a break - if(dist > len){ - counter += len; - pos = len; - } - - while (pos < len) { - counter = this.break; - pos += this.break; - - // Gone over - if(pos >= len){ - // Continue counter for next node - counter = len - (pos - this.break); - - // At End + if (child.nodeType === Node.ELEMENT_NODE) { + container = child.childNodes[0]; } else { - // End the previous range - range.setEnd(node, pos); - cfi = section.cfiFromRange(range); - this._locations.push(cfi); - counter = 0; - - // Start new range - pos += 1; - range = doc.createRange(); - range.setStart(node, pos); + container = child; } - } - - - - }.bind(this)); - - // Close remaining - if (range) { - range.setEnd(prev, prev.length); - cfi = section.cfiFromRange(range); - this._locations.push(cfi) - counter = 0; - } - - }.bind(this)); - -}; - -Locations.prototype.sprint = function(root, func) { - var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); - - while ((node = treeWalker.nextNode())) { - func(node); - } - -}; - -Locations.prototype.locationFromCfi = function(cfi){ - // Check if the location has not been set yet - if(this._locations.length === 0) { - return -1; - } - - return core.locationOf(cfi, this._locations, this.epubcfi.compare); -}; - -Locations.prototype.precentageFromCfi = function(cfi) { - // Find closest cfi - var loc = this.locationFromCfi(cfi); - // Get percentage in total - return this.precentageFromLocation(loc); -}; - -Locations.prototype.percentageFromLocation = function(loc) { - if (!loc || !this.total) { - return 0; - } - return (loc / this.total); -}; - -Locations.prototype.cfiFromLocation = function(loc){ - var cfi = -1; - // check that pg is an int - if(typeof loc != "number"){ - loc = parseInt(pg); - } - - if(loc >= 0 && loc < this._locations.length) { - cfi = this._locations[loc]; - } - - return cfi; -}; - -Locations.prototype.cfiFromPercentage = function(value){ - var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1 - var loc = Math.ceil(this.total * percentage); - - return this.cfiFromLocation(loc); -}; - -Locations.prototype.load = function(locations){ - this._locations = JSON.parse(locations); - this.total = this._locations.length-1; - return this._locations; -}; - -Locations.prototype.save = function(json){ - return JSON.stringify(this._locations); -}; - -Locations.prototype.getCurrent = function(json){ - return this._current; -}; - -Locations.prototype.setCurrent = function(curr){ - var loc; - - if(typeof curr == "string"){ - this._currentCfi = curr; - } else if (typeof curr == "number") { - this._current = curr; - } else { - return; - } - - if(this._locations.length === 0) { - return; - } - - if(typeof curr == "string"){ - loc = this.locationFromCfi(curr); - this._current = loc; - } else { - loc = curr; - } - - this.trigger("changed", { - percentage: this.precentageFromLocation(loc) - }); -}; - -Object.defineProperty(Locations.prototype, 'currentLocation', { - get: function () { - return this._current; - }, - set: function (curr) { - this.setCurrent(curr); - } -}); - -RSVP.EventTarget.mixin(Locations.prototype); - -module.exports = Locations; - -},{"./core":10,"./epubcfi":11,"./queue":23,"rsvp":5}],15:[function(require,module,exports){ -var RSVP = require('rsvp'); -var core = require('../../core'); -var DefaultViewManager = require('../default'); - -function ContinuousViewManager(options) { - - DefaultViewManager.apply(this, arguments); // call super constructor. - - this.name = "continuous"; - - this.settings = core.extend(this.settings || {}, { - infinite: true, - overflow: "auto", - axis: "vertical", - offset: 500, - offsetDelta: 250, - width: undefined, - height: undefined - }); - - core.extend(this.settings, options.settings || {}); - - // Gap can be 0, byt defaults doesn't handle that - if (options.settings.gap != "undefined" && options.settings.gap === 0) { - this.settings.gap = options.settings.gap; - } - - // this.viewSettings.axis = this.settings.axis; - this.viewSettings = { - ignoreClass: this.settings.ignoreClass, - axis: this.settings.axis, - layout: this.layout, - width: 0, - height: 0 - }; - - this.scrollTop = 0; - this.scrollLeft = 0; -}; - -// subclass extends superclass -ContinuousViewManager.prototype = Object.create(DefaultViewManager.prototype); -ContinuousViewManager.prototype.constructor = ContinuousViewManager; - -ContinuousViewManager.prototype.display = function(section, target){ - return DefaultViewManager.prototype.display.call(this, section, target) - .then(function () { - return this.fill(); - }.bind(this)); -}; - -ContinuousViewManager.prototype.fill = function(_full){ - var full = _full || new RSVP.defer(); - - this.check().then(function(result) { - if (result) { - this.fill(full); - } else { - full.resolve(); - } - }.bind(this)); - - return full.promise; -} - -ContinuousViewManager.prototype.moveTo = function(offset){ - // var bounds = this.stage.bounds(); - // var dist = Math.floor(offset.top / bounds.height) * bounds.height; - var distX = 0, - distY = 0; - - var offsetX = 0, - offsetY = 0; - - if(this.settings.axis === "vertical") { - distY = offset.top; - offsetY = offset.top+this.settings.offset; - } else { - distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta; - offsetX = distX+this.settings.offset; - } - - return this.check(offsetX, offsetY) - .then(function(){ - this.scrollBy(distX, distY); - }.bind(this)); -}; - -/* -ContinuousViewManager.prototype.afterDisplayed = function(currView){ - var next = currView.section.next(); - var prev = currView.section.prev(); - var index = this.views.indexOf(currView); - var prevView, nextView; - - if(index + 1 === this.views.length && next) { - nextView = this.createView(next); - this.q.enqueue(this.append.bind(this), nextView); - } - - if(index === 0 && prev) { - prevView = this.createView(prev, this.viewSettings); - this.q.enqueue(this.prepend.bind(this), prevView); - } - - // this.removeShownListeners(currView); - // currView.onShown = this.afterDisplayed.bind(this); - this.trigger("added", currView.section); - -}; -*/ - -ContinuousViewManager.prototype.resize = function(width, height){ - - // Clear the queue - this.q.clear(); - - this._stageSize = this.stage.size(width, height); - this._bounds = this.bounds(); - - // Update for new views - this.viewSettings.width = this._stageSize.width; - this.viewSettings.height = this._stageSize.height; - - // Update for existing views - this.views.each(function(view) { - view.size(this._stageSize.width, this._stageSize.height); - }.bind(this)); - - this.updateLayout(); - - // if(this.location) { - // this.rendition.display(this.location.start); - // } - - this.trigger("resized", { - width: this.stage.width, - height: this.stage.height - }); - -}; - -ContinuousViewManager.prototype.onResized = function(e) { - - // this.views.clear(); - - clearTimeout(this.resizeTimeout); - this.resizeTimeout = setTimeout(function(){ - this.resize(); - }.bind(this), 150); -}; - -ContinuousViewManager.prototype.afterResized = function(view){ - this.trigger("resize", view.section); -}; - -// Remove Previous Listeners if present -ContinuousViewManager.prototype.removeShownListeners = function(view){ - - // view.off("shown", this.afterDisplayed); - // view.off("shown", this.afterDisplayedAbove); - view.onDisplayed = function(){}; - -}; - - -// ContinuousViewManager.prototype.append = function(section){ -// return this.q.enqueue(function() { -// -// this._append(section); -// -// -// }.bind(this)); -// }; -// -// ContinuousViewManager.prototype.prepend = function(section){ -// return this.q.enqueue(function() { -// -// this._prepend(section); -// -// }.bind(this)); -// -// }; - -ContinuousViewManager.prototype.append = function(section){ - var view = this.createView(section); - this.views.append(view); - return view; -}; - -ContinuousViewManager.prototype.prepend = function(section){ - var view = this.createView(section); - - view.on("resized", this.counter.bind(this)); - - this.views.prepend(view); - return view; -}; - -ContinuousViewManager.prototype.counter = function(bounds){ - - if(this.settings.axis === "vertical") { - this.scrollBy(0, bounds.heightDelta, true); - } else { - this.scrollBy(bounds.widthDelta, 0, true); - } - -}; - -ContinuousViewManager.prototype.update = function(_offset){ - var container = this.bounds(); - var views = this.views.all(); - var viewsLength = views.length; - var visible = []; - var offset = typeof _offset != "undefined" ? _offset : (this.settings.offset || 0); - var isVisible; - var view; - - var updating = new RSVP.defer(); - var promises = []; - - for (var i = 0; i < viewsLength; i++) { - view = views[i]; - - isVisible = this.isVisible(view, offset, offset, container); - - if(isVisible === true) { - if (!view.displayed) { - promises.push(view.display(this.request).then(function (view) { - view.show(); - })); - } - visible.push(view); - } else { - this.q.enqueue(view.destroy.bind(view)); - - clearTimeout(this.trimTimeout); - this.trimTimeout = setTimeout(function(){ - this.q.enqueue(this.trim.bind(this)); - }.bind(this), 250); - } - - } - - if(promises.length){ - return RSVP.all(promises); - } else { - updating.resolve(); - return updating.promise; - } - -}; - -ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){ - var last, first, next, prev; - - var checking = new RSVP.defer(); - var newViews = []; - - var horizontal = (this.settings.axis === "horizontal"); - var delta = this.settings.offset || 0; - - if (_offsetLeft && horizontal) { - delta = _offsetLeft; - } - - if (_offsetTop && !horizontal) { - delta = _offsetTop; - } - - var bounds = this._bounds; // bounds saved this until resize - - var offset = horizontal ? this.scrollLeft : this.scrollTop; - var visibleLength = horizontal ? bounds.width : bounds.height; - var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight; - - if (offset + visibleLength + delta >= contentLength) { - last = this.views.last(); - next = last && last.section.next(); - if(next) { - newViews.push(this.append(next)); - } - } - - if (offset - delta < 0 ) { - first = this.views.first(); - prev = first && first.section.prev(); - if(prev) { - newViews.push(this.prepend(prev)); - } - } - - if(newViews.length){ - // RSVP.all(promises) - // .then(function() { - // Check to see if anything new is on screen after rendering - return this.q.enqueue(function(){ - return this.update(delta); - }.bind(this)); - - - // }.bind(this)); - - } else { - checking.resolve(false); - return checking.promise; - } - - -}; - -ContinuousViewManager.prototype.trim = function(){ - var task = new RSVP.defer(); - var displayed = this.views.displayed(); - var first = displayed[0]; - var last = displayed[displayed.length-1]; - var firstIndex = this.views.indexOf(first); - var lastIndex = this.views.indexOf(last); - var above = this.views.slice(0, firstIndex); - var below = this.views.slice(lastIndex+1); - - // Erase all but last above - for (var i = 0; i < above.length-1; i++) { - this.erase(above[i], above); - } - - // Erase all except first below - for (var j = 1; j < below.length; j++) { - this.erase(below[j]); - } - - task.resolve(); - return task.promise; -}; - -ContinuousViewManager.prototype.erase = function(view, above){ //Trim - - var prevTop; - var prevLeft; - - if(this.settings.height) { - prevTop = this.container.scrollTop; - prevLeft = this.container.scrollLeft; - } else { - prevTop = window.scrollY; - prevLeft = window.scrollX; - } - - var bounds = view.bounds(); - - this.views.remove(view); - - if(above) { - - if(this.settings.axis === "vertical") { - this.scrollTo(0, prevTop - bounds.height, true); - } else { - this.scrollTo(prevLeft - bounds.width, 0, true); - } - } - -}; - -ContinuousViewManager.prototype.addEventListeners = function(stage){ - - window.addEventListener('unload', function(e){ - this.ignore = true; - // this.scrollTo(0,0); - this.destroy(); - }.bind(this)); - - this.addScrollListeners(); -}; - -ContinuousViewManager.prototype.addScrollListeners = function() { - var scroller; - - this.tick = core.requestAnimationFrame; - - if(this.settings.height) { - this.prevScrollTop = this.container.scrollTop; - this.prevScrollLeft = this.container.scrollLeft; - } else { - this.prevScrollTop = window.scrollY; - this.prevScrollLeft = window.scrollX; - } - - this.scrollDeltaVert = 0; - this.scrollDeltaHorz = 0; - - if(this.settings.height) { - scroller = this.container; - this.scrollTop = this.container.scrollTop; - this.scrollLeft = this.container.scrollLeft; - } else { - scroller = window; - this.scrollTop = window.scrollY; - this.scrollLeft = window.scrollX; - } - - scroller.addEventListener("scroll", this.onScroll.bind(this)); - - // this.tick.call(window, this.onScroll.bind(this)); - - this.scrolled = false; - -}; - -ContinuousViewManager.prototype.onScroll = function(){ - - // if(!this.ignore) { - - if(this.settings.height) { - scrollTop = this.container.scrollTop; - scrollLeft = this.container.scrollLeft; - } else { - scrollTop = window.scrollY; - scrollLeft = window.scrollX; - } - - this.scrollTop = scrollTop; - this.scrollLeft = scrollLeft; - - if(!this.ignore) { - - if((this.scrollDeltaVert === 0 && - this.scrollDeltaHorz === 0) || - this.scrollDeltaVert > this.settings.offsetDelta || - this.scrollDeltaHorz > this.settings.offsetDelta) { - - this.q.enqueue(function() { - this.check(); - }.bind(this)); - // this.check(); - - this.scrollDeltaVert = 0; - this.scrollDeltaHorz = 0; - - this.trigger("scroll", { - top: scrollTop, - left: scrollLeft - }); - - clearTimeout(this.afterScrolled); - this.afterScrolled = setTimeout(function () { - this.trigger("scrolled", { - top: this.scrollTop, - left: this.scrollLeft - }); - }.bind(this)); - - } - - } else { - this.ignore = false; - } - - this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop); - this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft); - - this.prevScrollTop = scrollTop; - this.prevScrollLeft = scrollLeft; - - clearTimeout(this.scrollTimeout); - this.scrollTimeout = setTimeout(function(){ - this.scrollDeltaVert = 0; - this.scrollDeltaHorz = 0; - }.bind(this), 150); - - - this.scrolled = false; - // } - - // this.tick.call(window, this.onScroll.bind(this)); - -}; - - -// ContinuousViewManager.prototype.resizeView = function(view) { -// -// if(this.settings.axis === "horizontal") { -// view.lock("height", this.stage.width, this.stage.height); -// } else { -// view.lock("width", this.stage.width, this.stage.height); -// } -// -// }; - -ContinuousViewManager.prototype.currentLocation = function(){ - - if (this.settings.axis === "vertical") { - this.location = this.scrolledLocation(); - } else { - this.location = this.paginatedLocation(); - } - - return this.location; -}; - -ContinuousViewManager.prototype.scrolledLocation = function(){ - - var visible = this.visible(); - var startPage, endPage; - - var container = this.container.getBoundingClientRect(); - - if(visible.length === 1) { - return this.mapping.page(visible[0].contents, visible[0].section.cfiBase); - } - - if(visible.length > 1) { - - startPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase); - endPage = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase); - - return { - start: startPage.start, - end: endPage.end - }; - } - -}; - -ContinuousViewManager.prototype.paginatedLocation = function(){ - var visible = this.visible(); - var startA, startB, endA, endB; - var pageLeft, pageRight; - var container = this.container.getBoundingClientRect(); - - if(visible.length === 1) { - startA = container.left - visible[0].position().left; - endA = startA + this.layout.spreadWidth; - - return this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA); - } - - if(visible.length > 1) { - - // Left Col - startA = container.left - visible[0].position().left; - endA = startA + this.layout.columnWidth; - - // Right Col - startB = container.left + this.layout.spreadWidth - visible[visible.length-1].position().left; - endB = startB + this.layout.columnWidth; - - pageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA); - pageRight = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase, startB, endB); - - return { - start: pageLeft.start, - end: pageRight.end - }; - } -}; - -/* -Continuous.prototype.current = function(what){ - var view, top; - var container = this.container.getBoundingClientRect(); - var length = this.views.length - 1; - - if(this.settings.axis === "horizontal") { - - for (var i = length; i >= 0; i--) { - view = this.views[i]; - left = view.position().left; - - if(left < container.right) { - - if(this._current == view) { break; } - - this._current = view; - break; } } - - } else { - - for (var i = length; i >= 0; i--) { - view = this.views[i]; - top = view.bounds().top; - if(top < container.bottom) { - - if(this._current == view) { - break; - } - - this._current = view; - - break; - } - } - - } - - return this._current; -}; -*/ - -ContinuousViewManager.prototype.updateLayout = function() { - - if (!this.stage) { - return; - } - - if(this.settings.axis === "vertical") { - this.layout.calculate(this._stageSize.width, this._stageSize.height); - } else { - this.layout.calculate( - this._stageSize.width, - this._stageSize.height, - this.settings.gap - ); - - // Set the look ahead offset for what is visible - this.settings.offset = this.layout.delta; - - this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]); - - } - - // Set the dimensions for views - this.viewSettings.width = this.layout.width; - this.viewSettings.height = this.layout.height; - - this.setLayout(this.layout); - -}; - -ContinuousViewManager.prototype.next = function(){ - - if(this.settings.axis === "horizontal") { - - this.scrollLeft = this.container.scrollLeft; - - if(this.container.scrollLeft + - this.container.offsetWidth + - this.layout.delta < this.container.scrollWidth) { - this.scrollBy(this.layout.delta, 0); - } else { - this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); - } - - } else { - this.scrollBy(0, this.layout.height); - } -}; - -ContinuousViewManager.prototype.prev = function(){ - if(this.settings.axis === "horizontal") { - this.scrollBy(-this.layout.delta, 0); - } else { - this.scrollBy(0, -this.layout.height); - } -}; - -ContinuousViewManager.prototype.updateFlow = function(flow){ - var axis = (flow === "paginated") ? "horizontal" : "vertical"; - - this.settings.axis = axis; - - this.viewSettings.axis = axis; - - this.settings.overflow = (flow === "paginated") ? "hidden" : "auto"; - - // this.views.each(function(view){ - // view.setAxis(axis); - // }); - - if (this.settings.axis === "vertical") { - this.settings.infinite = true; - } else { - this.settings.infinite = false; - } - -}; -module.exports = ContinuousViewManager; - -},{"../../core":10,"../default":16,"rsvp":5}],16:[function(require,module,exports){ -var RSVP = require('rsvp'); -var core = require('../../core'); -var EpubCFI = require('../../epubcfi'); -var Mapping = require('../../mapping'); -var Queue = require('../../queue'); -var Stage = require('../helpers/stage'); -var Views = require('../helpers/views'); - -function DefaultViewManager(options) { - - this.name = "default"; - this.View = options.view; - this.request = options.request; - this.renditionQueue = options.queue; - this.q = new Queue(this); - - this.settings = core.extend(this.settings || {}, { - infinite: true, - hidden: false, - width: undefined, - height: undefined, - // globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'}, - // layout: null, - axis: "vertical", - ignoreClass: '' - }); - - core.extend(this.settings, options.settings || {}); - - this.viewSettings = { - ignoreClass: this.settings.ignoreClass, - axis: this.settings.axis, - layout: this.layout, - width: 0, - height: 0 - }; - -} - -DefaultViewManager.prototype.render = function(element, size){ - - // Save the stage - this.stage = new Stage({ - width: size.width, - height: size.height, - overflow: this.settings.overflow, - hidden: this.settings.hidden, - axis: this.settings.axis - }); - - this.stage.attachTo(element); - - // Get this stage container div - this.container = this.stage.getContainer(); - - // Views array methods - this.views = new Views(this.container); - - // Calculate Stage Size - this._bounds = this.bounds(); - this._stageSize = this.stage.size(); - - // Set the dimensions for views - this.viewSettings.width = this._stageSize.width; - this.viewSettings.height = this._stageSize.height; - - // Function to handle a resize event. - // Will only attach if width and height are both fixed. - this.stage.onResize(this.onResized.bind(this)); - - // Add Event Listeners - this.addEventListeners(); - - // Add Layout method - // this.applyLayoutMethod(); - if (this.layout) { - this.updateLayout(); - } -}; - -DefaultViewManager.prototype.addEventListeners = function(){ - window.addEventListener('unload', function(e){ - this.destroy(); - }.bind(this)); -}; - -DefaultViewManager.prototype.destroy = function(){ - // this.views.each(function(view){ - // view.destroy(); - // }); - - /* - - clearTimeout(this.trimTimeout); - if(this.settings.hidden) { - this.element.removeChild(this.wrapper); - } else { - this.element.removeChild(this.container); - } - */ -}; - -DefaultViewManager.prototype.onResized = function(e) { - clearTimeout(this.resizeTimeout); - this.resizeTimeout = setTimeout(function(){ - this.resize(); - }.bind(this), 150); -}; - -DefaultViewManager.prototype.resize = function(width, height){ - - // Clear the queue - this.q.clear(); - - this._stageSize = this.stage.size(width, height); - this._bounds = this.bounds(); - - // Update for new views - this.viewSettings.width = this._stageSize.width; - this.viewSettings.height = this._stageSize.height; - - // Update for existing views - this.views.each(function(view) { - view.size(this._stageSize.width, this._stageSize.height); - }.bind(this)); - - this.updateLayout(); - - this.trigger("resized", { - width: this.stage.width, - height: this.stage.height - }); - -}; - -DefaultViewManager.prototype.createView = function(section) { - return new this.View(section, this.viewSettings); -}; - -DefaultViewManager.prototype.display = function(section, target){ - - var displaying = new RSVP.defer(); - var displayed = displaying.promise; - - // Check to make sure the section we want isn't already shown - var visible = this.views.find(section); - - // View is already shown, just move to correct location - if(visible && target) { - offset = visible.locationOf(target); - this.moveTo(offset); - displaying.resolve(); - return displayed; - } - - // Hide all current views - this.views.hide(); - - this.views.clear(); - - this.add(section) - .then(function(){ - var next; - if (this.layout.name === "pre-paginated" && - this.layout.divisor > 1) { - next = section.next(); - if (next) { - return this.add(next); - } - } - }.bind(this)) - .then(function(view){ - - // Move to correct place within the section, if needed - if(target) { - offset = view.locationOf(target); - this.moveTo(offset); - } - - this.views.show(); - - displaying.resolve(); - - }.bind(this)) - // .then(function(){ - // return this.hooks.display.trigger(view); - // }.bind(this)) - // .then(function(){ - // this.views.show(); - // }.bind(this)); - return displayed; -}; - -DefaultViewManager.prototype.afterDisplayed = function(view){ - this.trigger("added", view); -}; - -DefaultViewManager.prototype.afterResized = function(view){ - this.trigger("resize", view.section); -}; - -// DefaultViewManager.prototype.moveTo = function(offset){ -// this.scrollTo(offset.left, offset.top); -// }; - -DefaultViewManager.prototype.moveTo = function(offset){ - var distX = 0, - distY = 0; - - if(this.settings.axis === "vertical") { - distY = offset.top; - } else { - distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta; - - if (distX + this.layout.delta > this.container.scrollWidth) { - distX = this.container.scrollWidth - this.layout.delta; - } - } - - this.scrollTo(distX, distY); -}; - -DefaultViewManager.prototype.add = function(section){ - var view = this.createView(section); - - this.views.append(view); - - // view.on("shown", this.afterDisplayed.bind(this)); - view.onDisplayed = this.afterDisplayed.bind(this); - view.onResize = this.afterResized.bind(this); - - return view.display(this.request); - -}; - -DefaultViewManager.prototype.append = function(section){ - var view = this.createView(section); - this.views.append(view); - return view.display(this.request); -}; - -DefaultViewManager.prototype.prepend = function(section){ - var view = this.createView(section); - - this.views.prepend(view); - return view.display(this.request); -}; -// DefaultViewManager.prototype.resizeView = function(view) { -// -// if(this.settings.globalLayoutProperties.layout === "pre-paginated") { -// view.lock("both", this.bounds.width, this.bounds.height); -// } else { -// view.lock("width", this.bounds.width, this.bounds.height); -// } -// -// }; - -DefaultViewManager.prototype.next = function(){ - var next; - var view; - var left; - - if(!this.views.length) return; - - if(this.settings.axis === "horizontal") { - - this.scrollLeft = this.container.scrollLeft; - - left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta; - - if(left < this.container.scrollWidth) { - this.scrollBy(this.layout.delta, 0); - } else if (left - this.layout.columnWidth === this.container.scrollWidth) { - this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); - } else { - next = this.views.last().section.next(); - } - - - } else { - - next = this.views.last().section.next(); - - } - - if(next) { - this.views.clear(); - - return this.append(next) - .then(function(){ - var right; - if (this.layout.name && this.layout.divisor > 1) { - right = next.next(); - if (right) { - return this.append(right); - } - } - }.bind(this)) - .then(function(){ - this.views.show(); - }.bind(this)); - } - - -}; - -DefaultViewManager.prototype.prev = function(){ - var prev; - var view; - var left; - - if(!this.views.length) return; - - if(this.settings.axis === "horizontal") { - - this.scrollLeft = this.container.scrollLeft; - - left = this.container.scrollLeft; - - if(left > 0) { - this.scrollBy(-this.layout.delta, 0); - } else { - prev = this.views.first().section.prev(); - } - - - } else { - - prev = this.views.first().section.prev(); - - } - - if(prev) { - this.views.clear(); - - return this.prepend(prev) - .then(function(){ - var left; - if (this.layout.name && this.layout.divisor > 1) { - left = prev.prev(); - if (left) { - return this.prepend(left); - } - } - }.bind(this)) - .then(function(){ - if(this.settings.axis === "horizontal") { - this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); - } - this.views.show(); - }.bind(this)); - } -}; - -DefaultViewManager.prototype.current = function(){ - var visible = this.visible(); - if(visible.length){ - // Current is the last visible view - return visible[visible.length-1]; - } - return null; -}; - -DefaultViewManager.prototype.currentLocation = function(){ - var view; - var start, end; - - if(this.views.length) { - view = this.views.first(); - start = container.left - view.position().left; - end = start + this.layout.spread; - - return this.mapping.page(view, view.section.cfiBase); - } - -}; - -DefaultViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){ - var position = view.position(); - var container = _container || this.bounds(); - - if(this.settings.axis === "horizontal" && - position.right > container.left - offsetPrev && - position.left < container.right + offsetNext) { - - return true; - - } else if(this.settings.axis === "vertical" && - position.bottom > container.top - offsetPrev && - position.top < container.bottom + offsetNext) { - - return true; - } - - return false; - -}; - -DefaultViewManager.prototype.visible = function(){ - // return this.views.displayed(); - var container = this.bounds(); - var views = this.views.displayed(); - var viewsLength = views.length; - var visible = []; - var isVisible; - var view; - - for (var i = 0; i < viewsLength; i++) { - view = views[i]; - isVisible = this.isVisible(view, 0, 0, container); - - if(isVisible === true) { - visible.push(view); - } - - } - return visible; -}; - -DefaultViewManager.prototype.scrollBy = function(x, y, silent){ - if(silent) { - this.ignore = true; - } - - if(this.settings.height) { - - if(x) this.container.scrollLeft += x; - if(y) this.container.scrollTop += y; - - } else { - window.scrollBy(x,y); - } - // console.log("scrollBy", x, y); - this.scrolled = true; - this.onScroll(); -}; - -DefaultViewManager.prototype.scrollTo = function(x, y, silent){ - if(silent) { - this.ignore = true; - } - - if(this.settings.height) { - this.container.scrollLeft = x; - this.container.scrollTop = y; - } else { - window.scrollTo(x,y); - } - // console.log("scrollTo", x, y); - this.scrolled = true; - this.onScroll(); - // if(this.container.scrollLeft != x){ - // setTimeout(function() { - // this.scrollTo(x, y, silent); - // }.bind(this), 10); - // return; - // }; - }; - -DefaultViewManager.prototype.onScroll = function(){ - -}; - -DefaultViewManager.prototype.bounds = function() { - var bounds; - - bounds = this.stage.bounds(); - - return bounds; -}; - -DefaultViewManager.prototype.applyLayout = function(layout) { - - this.layout = layout; - this.updateLayout(); - - this.mapping = new Mapping(this.layout); - // this.manager.layout(this.layout.format); -}; - -DefaultViewManager.prototype.updateLayout = function() { - if (!this.stage) { - return; - } - - this._stageSize = this.stage.size(); - - if(this.settings.axis === "vertical") { - this.layout.calculate(this._stageSize.width, this._stageSize.height); - } else { - this.layout.calculate( - this._stageSize.width, - this._stageSize.height, - this.settings.gap - ); - - // Set the look ahead offset for what is visible - this.settings.offset = this.layout.delta; - - this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]); - - } - - // Set the dimensions for views - this.viewSettings.width = this.layout.width; - this.viewSettings.height = this.layout.height; - - this.setLayout(this.layout); - -}; - -DefaultViewManager.prototype.setLayout = function(layout){ - - this.viewSettings.layout = layout; - - if(this.views) { - - this.views.each(function(view){ - view.setLayout(layout); - }); - - } - -}; - -DefaultViewManager.prototype.updateFlow = function(flow){ - var axis = (flow === "paginated") ? "horizontal" : "vertical"; - - this.settings.axis = axis; - - this.viewSettings.axis = axis; - - this.settings.overflow = (flow === "paginated") ? "hidden" : "auto"; - // this.views.each(function(view){ - // view.setAxis(axis); - // }); - -}; - - //-- Enable binding events to Manager - RSVP.EventTarget.mixin(DefaultViewManager.prototype); - - module.exports = DefaultViewManager; - -},{"../../core":10,"../../epubcfi":11,"../../mapping":20,"../../queue":23,"../helpers/stage":17,"../helpers/views":18,"rsvp":5}],17:[function(require,module,exports){ -var core = require('../../core'); - -function Stage(_options) { - this.settings = _options || {}; - this.id = "epubjs-container-" + core.uuid(); - - this.container = this.create(this.settings); - - if(this.settings.hidden) { - this.wrapper = this.wrap(this.container); - } - -} - -/** -* Creates an element to render to. -* Resizes to passed width and height or to the elements size -*/ -Stage.prototype.create = function(options){ - var height = options.height;// !== false ? options.height : "100%"; - var width = options.width;// !== false ? options.width : "100%"; - var overflow = options.overflow || false; - var axis = options.axis || "vertical"; - - if(options.height && core.isNumber(options.height)) { - height = options.height + "px"; - } - - if(options.width && core.isNumber(options.width)) { - width = options.width + "px"; - } - - // Create new container element - container = document.createElement("div"); - - container.id = this.id; - container.classList.add("epub-container"); - - // Style Element - // container.style.fontSize = "0"; - container.style.wordSpacing = "0"; - container.style.lineHeight = "0"; - container.style.verticalAlign = "top"; - - if(axis === "horizontal") { - container.style.whiteSpace = "nowrap"; - } - - if(width){ - container.style.width = width; - } - - if(height){ - container.style.height = height; - } - - if (overflow) { - container.style.overflow = overflow; - } - - return container; -}; - -Stage.wrap = function(container) { - var wrapper = document.createElement("div"); - - wrapper.style.visibility = "hidden"; - wrapper.style.overflow = "hidden"; - wrapper.style.width = "0"; - wrapper.style.height = "0"; - - wrapper.appendChild(container); - return wrapper; -}; - - -Stage.prototype.getElement = function(_element){ - var element; - - if(core.isElement(_element)) { - element = _element; - } else if (typeof _element === "string") { - element = document.getElementById(_element); - } - - if(!element){ - console.error("Not an Element"); - return; - } - - return element; -}; - -Stage.prototype.attachTo = function(what){ - - var element = this.getElement(what); - var base; - - if(!element){ - return; - } - - if(this.settings.hidden) { - base = this.wrapper; - } else { - base = this.container; - } - - element.appendChild(base); - - this.element = element; - - return element; - -}; - -Stage.prototype.getContainer = function() { - return this.container; -}; - -Stage.prototype.onResize = function(func){ - // Only listen to window for resize event if width and height are not fixed. - // This applies if it is set to a percent or auto. - if(!core.isNumber(this.settings.width) || - !core.isNumber(this.settings.height) ) { - window.addEventListener("resize", func, false); - } - -}; - -Stage.prototype.size = function(width, height){ - var bounds; - // var width = _width || this.settings.width; - // var height = _height || this.settings.height; - - // If width or height are set to false, inherit them from containing element - if(width === null) { - bounds = this.element.getBoundingClientRect(); - - if(bounds.width) { - width = bounds.width; - this.container.style.width = bounds.width + "px"; - } - } - - if(height === null) { - bounds = bounds || this.element.getBoundingClientRect(); - - if(bounds.height) { - height = bounds.height; - this.container.style.height = bounds.height + "px"; - } - - } - - if(!core.isNumber(width)) { - bounds = this.container.getBoundingClientRect(); - width = bounds.width; - //height = bounds.height; - } - - if(!core.isNumber(height)) { - bounds = bounds || this.container.getBoundingClientRect(); - //width = bounds.width; - height = bounds.height; - } - - - this.containerStyles = window.getComputedStyle(this.container); - - this.containerPadding = { - left: parseFloat(this.containerStyles["padding-left"]) || 0, - right: parseFloat(this.containerStyles["padding-right"]) || 0, - top: parseFloat(this.containerStyles["padding-top"]) || 0, - bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0 - }; - - return { - width: width - - this.containerPadding.left - - this.containerPadding.right, - height: height - - this.containerPadding.top - - this.containerPadding.bottom - }; - -}; - -Stage.prototype.bounds = function(){ - - if(!this.container) { - return core.windowBounds(); - } else { - return this.container.getBoundingClientRect(); - } - -} - -Stage.prototype.getSheet = function(){ - var style = document.createElement("style"); - - // WebKit hack --> https://davidwalsh.name/add-rules-stylesheets - style.appendChild(document.createTextNode("")); - - document.head.appendChild(style); - - return style.sheet; -} - -Stage.prototype.addStyleRules = function(selector, rulesArray){ - var scope = "#" + this.id + " "; - var rules = ""; - - if(!this.sheet){ - this.sheet = this.getSheet(); - } - - rulesArray.forEach(function(set) { - for (var prop in set) { - if(set.hasOwnProperty(prop)) { - rules += prop + ":" + set[prop] + ";"; - } - } - }) - - this.sheet.insertRule(scope + selector + " {" + rules + "}", 0); -} - - - -module.exports = Stage; - -},{"../../core":10}],18:[function(require,module,exports){ -function Views(container) { - this.container = container; - this._views = []; - this.length = 0; - this.hidden = false; -}; - -Views.prototype.all = function() { - return this._views; -}; - -Views.prototype.first = function() { - return this._views[0]; -}; - -Views.prototype.last = function() { - return this._views[this._views.length-1]; -}; - -Views.prototype.indexOf = function(view) { - return this._views.indexOf(view); -}; - -Views.prototype.slice = function() { - return this._views.slice.apply(this._views, arguments); -}; - -Views.prototype.get = function(i) { - return this._views[i]; -}; - -Views.prototype.append = function(view){ - this._views.push(view); - if(this.container){ - this.container.appendChild(view.element); - } - this.length++; - return view; -}; - -Views.prototype.prepend = function(view){ - this._views.unshift(view); - if(this.container){ - this.container.insertBefore(view.element, this.container.firstChild); - } - this.length++; - return view; -}; - -Views.prototype.insert = function(view, index) { - this._views.splice(index, 0, view); - - if(this.container){ - if(index < this.container.children.length){ - this.container.insertBefore(view.element, this.container.children[index]); - } else { - this.container.appendChild(view.element); - } - } - - this.length++; - return view; -}; - -Views.prototype.remove = function(view) { - var index = this._views.indexOf(view); - - if(index > -1) { - this._views.splice(index, 1); - } - - - this.destroy(view); - - this.length--; -}; - -Views.prototype.destroy = function(view) { - view.off("resized"); - - if(view.displayed){ - view.destroy(); - } - - if(this.container){ - this.container.removeChild(view.element); - } - view = null; -}; - -// Iterators - -Views.prototype.each = function() { - return this._views.forEach.apply(this._views, arguments); -}; - -Views.prototype.clear = function(){ - // Remove all views - var view; - var len = this.length; - - if(!this.length) return; - - for (var i = 0; i < len; i++) { - view = this._views[i]; - this.destroy(view); - } - - this._views = []; - this.length = 0; -}; - -Views.prototype.find = function(section){ - - var view; - var len = this.length; - - for (var i = 0; i < len; i++) { - view = this._views[i]; - if(view.displayed && view.section.index == section.index) { - return view; - } - } - -}; - -Views.prototype.displayed = function(){ - var displayed = []; - var view; - var len = this.length; - - for (var i = 0; i < len; i++) { - view = this._views[i]; - if(view.displayed){ - displayed.push(view); - } - } - return displayed; -}; - -Views.prototype.show = function(){ - var view; - var len = this.length; - - for (var i = 0; i < len; i++) { - view = this._views[i]; - if(view.displayed){ - view.show(); - } - } - this.hidden = false; -}; - -Views.prototype.hide = function(){ - var view; - var len = this.length; - - for (var i = 0; i < len; i++) { - view = this._views[i]; - if(view.displayed){ - view.hide(); - } - } - this.hidden = true; -}; - -module.exports = Views; - -},{}],19:[function(require,module,exports){ -var RSVP = require('rsvp'); -var core = require('../../core'); -var EpubCFI = require('../../epubcfi'); -var Contents = require('../../contents'); - -function IframeView(section, options) { - this.settings = core.extend({ - ignoreClass : '', - axis: 'vertical', - width: 0, - height: 0, - layout: undefined, - globalLayoutProperties: {}, - }, options || {}); - - this.id = "epubjs-view-" + core.uuid(); - this.section = section; - this.index = section.index; - - this.element = this.container(this.settings.axis); - - this.added = false; - this.displayed = false; - this.rendered = false; - - this.width = this.settings.width; - this.height = this.settings.height; - - this.fixedWidth = 0; - this.fixedHeight = 0; - - // Blank Cfi for Parsing - this.epubcfi = new EpubCFI(); - - this.layout = this.settings.layout; - // Dom events to listen for - // this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"]; -}; - -IframeView.prototype.container = function(axis) { - var element = document.createElement('div'); - - element.classList.add("epub-view"); - - // this.element.style.minHeight = "100px"; - element.style.height = "0px"; - element.style.width = "0px"; - element.style.overflow = "hidden"; - - if(axis && axis == "horizontal"){ - element.style.display = "inline-block"; - } else { - element.style.display = "block"; - } - - return element; -}; - -IframeView.prototype.create = function() { - - if(this.iframe) { - return this.iframe; - } - - if(!this.element) { - this.element = this.createContainer(); - } - - this.iframe = document.createElement('iframe'); - this.iframe.id = this.id; - this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations - this.iframe.style.overflow = "hidden"; - this.iframe.seamless = "seamless"; - // Back up if seamless isn't supported - this.iframe.style.border = "none"; - - this.resizing = true; - - // this.iframe.style.display = "none"; - this.element.style.visibility = "hidden"; - this.iframe.style.visibility = "hidden"; - - this.iframe.style.width = "0"; - this.iframe.style.height = "0"; - this._width = 0; - this._height = 0; - - this.element.appendChild(this.iframe); - this.added = true; - - this.elementBounds = core.bounds(this.element); - - // if(width || height){ - // this.resize(width, height); - // } else if(this.width && this.height){ - // this.resize(this.width, this.height); - // } else { - // this.iframeBounds = core.bounds(this.iframe); - // } - - // Firefox has trouble with baseURI and srcdoc - // TODO: Disable for now in firefox - - if(!!("srcdoc" in this.iframe)) { - this.supportsSrcdoc = true; - } else { - this.supportsSrcdoc = false; - } - - return this.iframe; -}; - -IframeView.prototype.render = function(request, show) { - - // view.onLayout = this.layout.format.bind(this.layout); - this.create(); - - // Fit to size of the container, apply padding - this.size(); - - if(!this.sectionRender) { - this.sectionRender = this.section.render(request); - } - - // Render Chain - return this.sectionRender - .then(function(contents){ - return this.load(contents); - }.bind(this)) - // .then(function(doc){ - // return this.hooks.content.trigger(view, this); - // }.bind(this)) - .then(function(){ - // this.settings.layout.format(view.contents); - // return this.hooks.layout.trigger(view, this); - }.bind(this)) - // .then(function(){ - // return this.display(); - // }.bind(this)) - // .then(function(){ - // return this.hooks.render.trigger(view, this); - // }.bind(this)) - .then(function(){ - - // apply the layout function to the contents - this.settings.layout.format(this.contents); - - // Expand the iframe to the full size of the content - this.expand(); - - // Listen for events that require an expansion of the iframe - this.addListeners(); - - if(show !== false) { - //this.q.enqueue(function(view){ - // this.show(); - //}, view); - } - // this.map = new Map(view, this.layout); - //this.hooks.show.trigger(view, this); - this.trigger("rendered", this.section); - - }.bind(this)) - .catch(function(e){ - this.trigger("loaderror", e); - }.bind(this)); - -}; - -// Determine locks base on settings -IframeView.prototype.size = function(_width, _height) { - var width = _width || this.settings.width; - var height = _height || this.settings.height; - - if(this.layout.name === "pre-paginated") { - this.lock("both", width, height); - } else if(this.settings.axis === "horizontal") { - this.lock("height", width, height); - } else { - this.lock("width", width, height); - } - -}; - -// Lock an axis to element dimensions, taking borders into account -IframeView.prototype.lock = function(what, width, height) { - var elBorders = core.borders(this.element); - var iframeBorders; - - if(this.iframe) { - iframeBorders = core.borders(this.iframe); - } else { - iframeBorders = {width: 0, height: 0}; - } - - if(what == "width" && core.isNumber(width)){ - this.lockedWidth = width - elBorders.width - iframeBorders.width; - this.resize(this.lockedWidth, width); // width keeps ratio correct - } - - if(what == "height" && core.isNumber(height)){ - this.lockedHeight = height - elBorders.height - iframeBorders.height; - this.resize(width, this.lockedHeight); - } - - if(what === "both" && - core.isNumber(width) && - core.isNumber(height)){ - - this.lockedWidth = width - elBorders.width - iframeBorders.width; - this.lockedHeight = height - elBorders.height - iframeBorders.height; - - this.resize(this.lockedWidth, this.lockedHeight); - } - - if(this.displayed && this.iframe) { - - // this.contents.layout(); - this.expand(); - - } - - - -}; - -// Resize a single axis based on content dimensions -IframeView.prototype.expand = function(force) { - var width = this.lockedWidth; - var height = this.lockedHeight; - var columns; - - var textWidth, textHeight; - - if(!this.iframe || this._expanding) return; - - this._expanding = true; - - // Expand Horizontally - // if(height && !width) { - if(this.settings.axis === "horizontal") { - // Get the width of the text - textWidth = this.contents.textWidth(); - // Check if the textWidth has changed - if(textWidth != this._textWidth){ - // Get the contentWidth by resizing the iframe - // Check with a min reset of the textWidth - width = this.contentWidth(textWidth); - - columns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap)); - - if ( this.settings.layout.divisor > 1 && - this.settings.layout.name === "reflowable" && - (columns % 2 > 0)) { - // add a blank page - width += this.settings.layout.gap + this.settings.layout.columnWidth; - } - - // Save the textWdith - this._textWidth = textWidth; - // Save the contentWidth - this._contentWidth = width; - } else { - // Otherwise assume content height hasn't changed - width = this._contentWidth; - } - } // Expand Vertically - else if(this.settings.axis === "vertical") { - textHeight = this.contents.textHeight(); - if(textHeight != this._textHeight){ - height = this.contentHeight(textHeight); - this._textHeight = textHeight; - this._contentHeight = height; - } else { - height = this._contentHeight; - } - - } - - // Only Resize if dimensions have changed or - // if Frame is still hidden, so needs reframing - if(this._needsReframe || width != this._width || height != this._height){ - this.resize(width, height); - } - - this._expanding = false; -}; - -IframeView.prototype.contentWidth = function(min) { - var prev; - var width; - - // Save previous width - prev = this.iframe.style.width; - // Set the iframe size to min, width will only ever be greater - // Will preserve the aspect ratio - this.iframe.style.width = (min || 0) + "px"; - // Get the scroll overflow width - width = this.contents.scrollWidth(); - // Reset iframe size back - this.iframe.style.width = prev; - return width; -}; - -IframeView.prototype.contentHeight = function(min) { - var prev; - var height; - - prev = this.iframe.style.height; - this.iframe.style.height = (min || 0) + "px"; - height = this.contents.scrollHeight(); - - this.iframe.style.height = prev; - return height; -}; - - -IframeView.prototype.resize = function(width, height) { - - if(!this.iframe) return; - - if(core.isNumber(width)){ - this.iframe.style.width = width + "px"; - this._width = width; - } - - if(core.isNumber(height)){ - this.iframe.style.height = height + "px"; - this._height = height; - } - - this.iframeBounds = core.bounds(this.iframe); - - this.reframe(this.iframeBounds.width, this.iframeBounds.height); - -}; - -IframeView.prototype.reframe = function(width, height) { - var size; - - // if(!this.displayed) { - // this._needsReframe = true; - // return; - // } - if(core.isNumber(width)){ - this.element.style.width = width + "px"; - } - - if(core.isNumber(height)){ - this.element.style.height = height + "px"; - } - - this.prevBounds = this.elementBounds; - - this.elementBounds = core.bounds(this.element); - - size = { - width: this.elementBounds.width, - height: this.elementBounds.height, - widthDelta: this.elementBounds.width - this.prevBounds.width, - heightDelta: this.elementBounds.height - this.prevBounds.height, - }; - - this.onResize(this, size); - - this.trigger("resized", size); - -}; - - -IframeView.prototype.load = function(contents) { - var loading = new RSVP.defer(); - var loaded = loading.promise; - - if(!this.iframe) { - loading.reject(new Error("No Iframe Available")); - return loaded; - } - - this.iframe.onload = function(event) { - - this.onLoad(event, loading); - - }.bind(this); - - if(this.supportsSrcdoc){ - this.iframe.srcdoc = contents; - } else { - - this.document = this.iframe.contentDocument; - - if(!this.document) { - loading.reject(new Error("No Document Available")); - return loaded; - } - - this.iframe.contentDocument.open(); - this.iframe.contentDocument.write(contents); - this.iframe.contentDocument.close(); - - } - - return loaded; -}; - -IframeView.prototype.onLoad = function(event, promise) { - - this.window = this.iframe.contentWindow; - this.document = this.iframe.contentDocument; - - this.contents = new Contents(this.document, this.document.body, this.section.cfiBase); - - this.rendering = false; - - var link = this.document.querySelector("link[rel='canonical']"); - if (link) { - link.setAttribute("href", this.section.url); - } else { - link = this.document.createElement("link"); - link.setAttribute("rel", "canonical"); - link.setAttribute("href", this.section.url); - this.document.querySelector("head").appendChild(link); - } - - this.contents.on("expand", function () { - if(this.displayed && this.iframe) { - this.expand(); - } - }); - - promise.resolve(this.contents); -}; - - - -// IframeView.prototype.layout = function(layoutFunc) { -// -// this.iframe.style.display = "inline-block"; -// -// // Reset Body Styles -// // this.document.body.style.margin = "0"; -// //this.document.body.style.display = "inline-block"; -// //this.document.documentElement.style.width = "auto"; -// -// if(layoutFunc){ -// this.layoutFunc = layoutFunc; -// } -// -// this.contents.layout(this.layoutFunc); -// -// }; -// -// IframeView.prototype.onLayout = function(view) { -// // stub -// }; - -IframeView.prototype.setLayout = function(layout) { - this.layout = layout; -}; - -IframeView.prototype.setAxis = function(axis) { - this.settings.axis = axis; -}; - -IframeView.prototype.resizeListenters = function() { - // Test size again - clearTimeout(this.expanding); - this.expanding = setTimeout(this.expand.bind(this), 350); -}; - -IframeView.prototype.addListeners = function() { - //TODO: Add content listeners for expanding -}; - -IframeView.prototype.removeListeners = function(layoutFunc) { - //TODO: remove content listeners for expanding -}; - -IframeView.prototype.display = function(request) { - var displayed = new RSVP.defer(); - - if (!this.displayed) { - - this.render(request).then(function () { - - this.trigger("displayed", this); - this.onDisplayed(this); - - this.displayed = true; - displayed.resolve(this); - - }.bind(this)); - - } else { - displayed.resolve(this); - } - - - return displayed.promise; -}; - -IframeView.prototype.show = function() { - - this.element.style.visibility = "visible"; - - if(this.iframe){ - this.iframe.style.visibility = "visible"; - } - - this.trigger("shown", this); -}; - -IframeView.prototype.hide = function() { - // this.iframe.style.display = "none"; - this.element.style.visibility = "hidden"; - this.iframe.style.visibility = "hidden"; - - this.stopExpanding = true; - this.trigger("hidden", this); -}; - -IframeView.prototype.position = function() { - return this.element.getBoundingClientRect(); -}; - -IframeView.prototype.locationOf = function(target) { - var parentPos = this.iframe.getBoundingClientRect(); - var targetPos = this.contents.locationOf(target, this.settings.ignoreClass); - - return { - "left": window.scrollX + parentPos.left + targetPos.left, - "top": window.scrollY + parentPos.top + targetPos.top - }; -}; - -IframeView.prototype.onDisplayed = function(view) { - // Stub, override with a custom functions -}; - -IframeView.prototype.onResize = function(view, e) { - // Stub, override with a custom functions -}; - -IframeView.prototype.bounds = function() { - if(!this.elementBounds) { - this.elementBounds = core.bounds(this.element); - } - return this.elementBounds; -}; - -IframeView.prototype.destroy = function() { - - if(this.displayed){ - this.displayed = false; - - this.removeListeners(); - - this.stopExpanding = true; - this.element.removeChild(this.iframe); - this.displayed = false; - this.iframe = null; - - this._textWidth = null; - this._textHeight = null; - this._width = null; - this._height = null; - } - // this.element.style.height = "0px"; - // this.element.style.width = "0px"; -}; - -RSVP.EventTarget.mixin(IframeView.prototype); - -module.exports = IframeView; - -},{"../../contents":9,"../../core":10,"../../epubcfi":11,"rsvp":5}],20:[function(require,module,exports){ -var EpubCFI = require('./epubcfi'); - -function Mapping(layout){ - this.layout = layout; -}; - -Mapping.prototype.section = function(view) { - var ranges = this.findRanges(view); - var map = this.rangeListToCfiList(view.section.cfiBase, ranges); - - return map; -}; - -Mapping.prototype.page = function(contents, cfiBase, start, end) { - var root = contents && contents.document ? contents.document.body : false; - - if (!root) { - return; - } - - return this.rangePairToCfiPair(cfiBase, { - start: this.findStart(root, start, end), - end: this.findEnd(root, start, end) - }); -}; - -Mapping.prototype.walk = function(root, func) { - //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false); - var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { - acceptNode: function (node) { - if ( node.data.trim().length > 0 ) { - return NodeFilter.FILTER_ACCEPT; - } else { - return NodeFilter.FILTER_REJECT; - } - } - }, false); - var node; - var result; - while ((node = treeWalker.nextNode())) { - result = func(node); - if(result) break; - } - - return result; -}; - -Mapping.prototype.findRanges = function(view){ - var columns = []; - var scrollWidth = view.contents.scrollWidth(); - var count = this.layout.count(scrollWidth); - var column = this.layout.column; - var gap = this.layout.gap; - var start, end; - - for (var i = 0; i < count.pages; i++) { - start = (column + gap) * i; - end = (column * (i+1)) + (gap * i); - columns.push({ - start: this.findStart(view.document.body, start, end), - end: this.findEnd(view.document.body, start, end) - }); - } - - return columns; -}; - -Mapping.prototype.findStart = function(root, start, end){ - var stack = [root]; - var $el; - var found; - var $prev = root; - while (stack.length) { - - $el = stack.shift(); - - found = this.walk($el, function(node){ - var left, right; - var elPos; - var elRange; - - - if(node.nodeType == Node.TEXT_NODE){ - elRange = document.createRange(); - elRange.selectNodeContents(node); - elPos = elRange.getBoundingClientRect(); - } else { - elPos = node.getBoundingClientRect(); - } - - left = elPos.left; - right = elPos.right; - - if( left >= start && left <= end ) { - return node; - } else if (right > start) { - return node; - } else { - $prev = node; - stack.push(node); - } - - }); - - if(found) { - return this.findTextStartRange(found, start, end); - } - - } - - // Return last element - return this.findTextStartRange($prev, start, end); -}; - -Mapping.prototype.findEnd = function(root, start, end){ - var stack = [root]; - var $el; - var $prev = root; - var found; - - while (stack.length) { - - $el = stack.shift(); - - found = this.walk($el, function(node){ - - var left, right; - var elPos; - var elRange; - - - if(node.nodeType == Node.TEXT_NODE){ - elRange = document.createRange(); - elRange.selectNodeContents(node); - elPos = elRange.getBoundingClientRect(); - } else { - elPos = node.getBoundingClientRect(); - } - - left = elPos.left; - right = elPos.right; - - if(left > end && $prev) { - return $prev; - } else if(right > end) { - return node; - } else { - $prev = node; - stack.push(node); - } - - }); - - - if(found){ - return this.findTextEndRange(found, start, end); - } - - } - - // end of chapter - return this.findTextEndRange($prev, start, end); -}; - - -Mapping.prototype.findTextStartRange = function(node, start, end){ - var ranges = this.splitTextNodeIntoRanges(node); - var prev; - var range; - var pos; - - for (var i = 0; i < ranges.length; i++) { - range = ranges[i]; - - pos = range.getBoundingClientRect(); - - if( pos.left >= start ) { - return range; - } - - prev = range; - - } - - return ranges[0]; -}; - -Mapping.prototype.findTextEndRange = function(node, start, end){ - var ranges = this.splitTextNodeIntoRanges(node); - var prev; - var range; - var pos; - - for (var i = 0; i < ranges.length; i++) { - range = ranges[i]; - - pos = range.getBoundingClientRect(); - - if(pos.left > end && prev) { - return prev; - } else if(pos.right > end) { - return range; - } - - prev = range; - - } - - // Ends before limit - return ranges[ranges.length-1]; - -}; - -Mapping.prototype.splitTextNodeIntoRanges = function(node, _splitter){ - var ranges = []; - var textContent = node.textContent || ""; - var text = textContent.trim(); - var range; - var rect; - var list; - var doc = node.ownerDocument; - var splitter = _splitter || " "; - - pos = text.indexOf(splitter); - - if(pos === -1 || node.nodeType != Node.TEXT_NODE) { - range = doc.createRange(); - range.selectNodeContents(node); - return [range]; - } - - range = doc.createRange(); - range.setStart(node, 0); - range.setEnd(node, pos); - ranges.push(range); - range = false; - - while ( pos != -1 ) { - - pos = text.indexOf(splitter, pos + 1); - if(pos > 0) { - - if(range) { - range.setEnd(node, pos); - ranges.push(range); - } - - range = doc.createRange(); - range.setStart(node, pos+1); - } - } - - if(range) { - range.setEnd(node, text.length); - ranges.push(range); - } - - return ranges; -}; - - - -Mapping.prototype.rangePairToCfiPair = function(cfiBase, rangePair){ - - var startRange = rangePair.start; - var endRange = rangePair.end; - - startRange.collapse(true); - endRange.collapse(true); - - // startCfi = section.cfiFromRange(startRange); - // endCfi = section.cfiFromRange(endRange); - startCfi = new EpubCFI(startRange, cfiBase).toString(); - endCfi = new EpubCFI(endRange, cfiBase).toString(); - - return { - start: startCfi, - end: endCfi - }; - -}; - -Mapping.prototype.rangeListToCfiList = function(cfiBase, columns){ - var map = []; - var rangePair, cifPair; - - for (var i = 0; i < columns.length; i++) { - cifPair = this.rangePairToCfiPair(cfiBase, columns[i]); - - map.push(cifPair); - - } - - return map; -}; - -module.exports = Mapping; - -},{"./epubcfi":11}],21:[function(require,module,exports){ -var core = require('./core'); -var Parser = require('./parser'); -var RSVP = require('rsvp'); -var URI = require('urijs'); - -function Navigation(_package, _request){ - var navigation = this; - var parse = new Parser(); - var request = _request || require('./request'); - - this.package = _package; - this.toc = []; - this.tocByHref = {}; - this.tocById = {}; - - if(_package.navPath) { - this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString(); - this.nav = {}; - - this.nav.load = function(_request){ - var loading = new RSVP.defer(); - var loaded = loading.promise; - - request(navigation.navUrl, 'xml').then(function(xml){ - navigation.toc = parse.nav(xml); - navigation.loaded(navigation.toc); - loading.resolve(navigation.toc); - }); - - return loaded; - }; - - } - - if(_package.ncxPath) { - this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString(); - this.ncx = {}; - - this.ncx.load = function(_request){ - var loading = new RSVP.defer(); - var loaded = loading.promise; - - request(navigation.ncxUrl, 'xml').then(function(xml){ - navigation.toc = parse.toc(xml); - navigation.loaded(navigation.toc); - loading.resolve(navigation.toc); - }); - - return loaded; - }; - - } -}; - -// Load the navigation -Navigation.prototype.load = function(_request) { - var request = _request || require('./request'); - var loading, loaded; - - if(this.nav) { - loading = this.nav.load(); - } else if(this.ncx) { - loading = this.ncx.load(); - } else { - loaded = new RSVP.defer(); - loaded.resolve([]); - loading = loaded.promise; - } - - return loading; - -}; - -Navigation.prototype.loaded = function(toc) { - var item; - - for (var i = 0; i < toc.length; i++) { - item = toc[i]; - this.tocByHref[item.href] = i; - this.tocById[item.id] = i; - } - -}; - -// Get an item from the navigation -Navigation.prototype.get = function(target) { - var index; - - if(!target) { - return this.toc; - } - - if(target.indexOf("#") === 0) { - index = this.tocById[target.substring(1)]; - } else if(target in this.tocByHref){ - index = this.tocByHref[target]; - } - - return this.toc[index]; -}; - -module.exports = Navigation; - -},{"./core":10,"./parser":22,"./request":26,"rsvp":5,"urijs":7}],22:[function(require,module,exports){ -var URI = require('urijs'); -var core = require('./core'); -var EpubCFI = require('./epubcfi'); - - -function Parser(){}; - -Parser.prototype.container = function(containerXml){ - //-- - var rootfile, fullpath, folder, encoding; - - if(!containerXml) { - console.error("Container File Not Found"); - return; - } - - rootfile = core.qs(containerXml, "rootfile"); - - if(!rootfile) { - console.error("No RootFile Found"); - return; - } - - fullpath = rootfile.getAttribute('full-path'); - folder = URI(fullpath).directory(); - encoding = containerXml.xmlEncoding; - - //-- Now that we have the path we can parse the contents + return { - 'packagePath' : fullpath, - 'basePath' : folder, - 'encoding' : encoding + container: container, + offset: offset }; -}; - -Parser.prototype.identifier = function(packageXml){ - var metadataNode; - - if(!packageXml) { - console.error("Package File Not Found"); - return; - } - - metadataNode = core.qs(packageXml, "metadata"); - - if(!metadataNode) { - console.error("No Metadata Found"); - return; - } - - return this.getElementText(metadataNode, "identifier"); -}; - -Parser.prototype.packageContents = function(packageXml){ - var parse = this; - var metadataNode, manifestNode, spineNode; - var manifest, navPath, ncxPath, coverPath; - var spineNodeIndex; - var spine; - var spineIndexByURL; - var metadata; - - if(!packageXml) { - console.error("Package File Not Found"); - return; - } - - metadataNode = core.qs(packageXml, "metadata"); - if(!metadataNode) { - console.error("No Metadata Found"); - return; - } - - manifestNode = core.qs(packageXml, "manifest"); - if(!manifestNode) { - console.error("No Manifest Found"); - return; - } - - spineNode = core.qs(packageXml, "spine"); - if(!spineNode) { - console.error("No Spine Found"); - return; - } - - manifest = parse.manifest(manifestNode); - navPath = parse.findNavPath(manifestNode); - ncxPath = parse.findNcxPath(manifestNode, spineNode); - coverPath = parse.findCoverPath(packageXml); - - spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode); - - spine = parse.spine(spineNode, manifest); - - metadata = parse.metadata(metadataNode); - - metadata.direction = spineNode.getAttribute("page-progression-direction"); - - return { - 'metadata' : metadata, - 'spine' : spine, - 'manifest' : manifest, - 'navPath' : navPath, - 'ncxPath' : ncxPath, - 'coverPath': coverPath, - 'spineNodeIndex' : spineNodeIndex + }; -}; - -//-- Find TOC NAV -Parser.prototype.findNavPath = function(manifestNode){ - // Find item with property 'nav' - // Should catch nav irregardless of order - // var node = manifestNode.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']"); - var node = core.qsp(manifestNode, "item", {"properties":"nav"}); - return node ? node.getAttribute('href') : false; -}; - -//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx" -Parser.prototype.findNcxPath = function(manifestNode, spineNode){ - // var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); - var node = core.qsp(manifestNode, "item", {"media-type":"application/x-dtbncx+xml"}); - var tocId; - - // If we can't find the toc by media-type then try to look for id of the item in the spine attributes as - // according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2, - // "The item that describes the NCX must be referenced by the spine toc attribute." - if (!node) { - tocId = spineNode.getAttribute("toc"); - if(tocId) { - // node = manifestNode.querySelector("item[id='" + tocId + "']"); - node = manifestNode.getElementById(tocId); + + EpubCFI.prototype.toRange = function(_doc, ignoreClass) { + var doc = _doc || document; + var range = doc.createRange(); + var start, end, startContainer, endContainer; + var cfi = this; + var startSteps, endSteps; + var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false; + var missed; + + if (cfi.range) { + start = cfi.start; + startSteps = cfi.path.steps.concat(start.steps); + startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null); + end = cfi.end; + endSteps = cfi.path.steps.concat(end.steps); + endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null); + } else { + start = cfi.path; + startSteps = cfi.path.steps; + startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null); } - } - - return node ? node.getAttribute('href') : false; -}; - -//-- Expanded to match Readium web components -Parser.prototype.metadata = function(xml){ - var metadata = {}, - p = this; - - metadata.title = p.getElementText(xml, 'title'); - metadata.creator = p.getElementText(xml, 'creator'); - metadata.description = p.getElementText(xml, 'description'); - - metadata.pubdate = p.getElementText(xml, 'date'); - - metadata.publisher = p.getElementText(xml, 'publisher'); - - metadata.identifier = p.getElementText(xml, "identifier"); - metadata.language = p.getElementText(xml, "language"); - metadata.rights = p.getElementText(xml, "rights"); - - metadata.modified_date = p.getPropertyText(xml, 'dcterms:modified'); - - metadata.layout = p.getPropertyText(xml, "rendition:layout"); - metadata.orientation = p.getPropertyText(xml, 'rendition:orientation'); - metadata.flow = p.getPropertyText(xml, 'rendition:flow'); - metadata.viewport = p.getPropertyText(xml, 'rendition:viewport'); - // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction"); - - return metadata; -}; - -//-- Find Cover: -//-- Fallback for Epub 2.0 -Parser.prototype.findCoverPath = function(packageXml){ - var pkg = core.qs(packageXml, "package"); - var epubVersion = pkg.getAttribute('version'); - - if (epubVersion === '2.0') { - var metaCover = core.qsp(packageXml, 'meta', {'name':'cover'}); - if (metaCover) { - var coverId = metaCover.getAttribute('content'); - // var cover = packageXml.querySelector("item[id='" + coverId + "']"); - var cover = packageXml.getElementById(coverId); - return cover ? cover.getAttribute('href') : false; + + if(startContainer) { + try { + + if(start.terminal.offset != null) { + range.setStart(startContainer, start.terminal.offset); + } else { + range.setStart(startContainer, 0); + } + + } catch (e) { + missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null); + range.setStart(missed.container, missed.offset); + } + } else { + // No start found + return null; } - else { - return false; - } - } - else { - // var node = packageXml.querySelector("item[properties='cover-image']"); - var node = core.qsp(packageXml, 'item', {'properties':'cover-image'}); - return node ? node.getAttribute('href') : false; - } -}; - -Parser.prototype.getElementText = function(xml, tag){ - var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag), - el; - - if(!found || found.length === 0) return ''; - - el = found[0]; - - if(el.childNodes.length){ - return el.childNodes[0].nodeValue; - } - - return ''; - -}; - -Parser.prototype.getPropertyText = function(xml, property){ - var el = core.qsp(xml, "meta", {"property":property}); - - if(el && el.childNodes.length){ - return el.childNodes[0].nodeValue; - } - - return ''; -}; - -Parser.prototype.querySelectorText = function(xml, q){ - var el = xml.querySelector(q); - - if(el && el.childNodes.length){ - return el.childNodes[0].nodeValue; - } - - return ''; -}; - -Parser.prototype.manifest = function(manifestXml){ - var manifest = {}; - - //-- Turn items into an array - // var selected = manifestXml.querySelectorAll("item"); - var selected = core.qsa(manifestXml, "item"); - var items = Array.prototype.slice.call(selected); - - //-- Create an object with the id as key - items.forEach(function(item){ - var id = item.getAttribute('id'), - href = item.getAttribute('href') || '', - type = item.getAttribute('media-type') || '', - properties = item.getAttribute('properties') || ''; - - manifest[id] = { - 'href' : href, - // 'url' : href, - 'type' : type, - 'properties' : properties.length ? properties.split(' ') : [] - }; - - }); - - return manifest; - -}; - -Parser.prototype.spine = function(spineXml, manifest){ - var spine = []; - - var selected = spineXml.getElementsByTagName("itemref"), - items = Array.prototype.slice.call(selected); - - var epubcfi = new EpubCFI(); - - //-- Add to array to mantain ordering and cross reference with manifest - items.forEach(function(item, index){ - var idref = item.getAttribute('idref'); - // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id); - var props = item.getAttribute('properties') || ''; - var propArray = props.length ? props.split(' ') : []; - // var manifestProps = manifest[Id].properties; - // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : []; - - var itemref = { - 'idref' : idref, - 'linear' : item.getAttribute('linear') || '', - 'properties' : propArray, - // 'href' : manifest[Id].href, - // 'url' : manifest[Id].url, - 'index' : index - // 'cfiBase' : cfiBase - }; - spine.push(itemref); - }); - - return spine; -}; - -Parser.prototype.querySelectorByType = function(html, element, type){ - var query; - if (typeof html.querySelector != "undefined") { - query = html.querySelector(element+'[*|type="'+type+'"]'); - } - // Handle IE not supporting namespaced epub:type in querySelector - if(!query || query.length === 0) { - query = core.qsa(html, element); - for (var i = 0; i < query.length; i++) { - if(query[i].getAttributeNS("http://www.idpf.org/2007/ops", "type") === type) { - return query[i]; + + if (endContainer) { + try { + + if(end.terminal.offset != null) { + range.setEnd(endContainer, end.terminal.offset); + } else { + range.setEnd(endContainer, 0); + } + + } catch (e) { + missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null); + range.setEnd(missed.container, missed.offset); } } - } else { - return query; - } -}; - -Parser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){ - var navElement = this.querySelectorByType(navHtml, "nav", "toc"); - // var navItems = navElement ? navElement.querySelectorAll("ol li") : []; - var navItems = navElement ? core.qsa(navElement, "li") : []; - var length = navItems.length; - var i; - var toc = {}; - var list = []; - var item, parent; - - if(!navItems || length === 0) return list; - - for (i = 0; i < length; ++i) { - item = this.navItem(navItems[i], spineIndexByURL, bookSpine); - toc[item.id] = item; - if(!item.parent) { - list.push(item); - } else { - parent = toc[item.parent]; - parent.subitems.push(item); - } - } - - return list; -}; - -Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){ - var id = item.getAttribute('id') || false, - // content = item.querySelector("a, span"), - content = core.qs(item, "a"), - src = content.getAttribute('href') || '', - text = content.textContent || "", - // split = src.split("#"), - // baseUrl = split[0], - // spinePos = spineIndexByURL[baseUrl], - // spineItem = bookSpine[spinePos], - subitems = [], - parentNode = item.parentNode, - parent; - // cfi = spineItem ? spineItem.cfi : ''; - - if(parentNode && parentNode.nodeName === "navPoint") { - parent = parentNode.getAttribute('id'); - } - - /* - if(!id) { - if(spinePos) { - spineItem = bookSpine[spinePos]; - id = spineItem.id; - cfi = spineItem.cfi; - } else { - id = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid(); - item.setAttribute('id', id); - } - } - */ - - return { - "id": id, - "href": src, - "label": text, - "subitems" : subitems, - "parent" : parent + + + // doc.defaultView.getSelection().addRange(range); + return range; }; -}; - -Parser.prototype.ncx = function(tocXml, spineIndexByURL, bookSpine){ - // var navPoints = tocXml.querySelectorAll("navMap navPoint"); - var navPoints = core.qsa(tocXml, "navPoint"); - var length = navPoints.length; - var i; - var toc = {}; - var list = []; - var item, parent; - - if(!navPoints || length === 0) return list; - - for (i = 0; i < length; ++i) { - item = this.ncxItem(navPoints[i], spineIndexByURL, bookSpine); - toc[item.id] = item; - if(!item.parent) { - list.push(item); - } else { - parent = toc[item.parent]; - parent.subitems.push(item); + + // is a cfi string, should be wrapped with "epubcfi()" + EpubCFI.prototype.isCfiString = function(str) { + if(typeof str === 'string' && + str.indexOf("epubcfi(") === 0 && + str[str.length-1] === ")") { + return true; } - } - - return list; -}; - -Parser.prototype.ncxItem = function(item, spineIndexByURL, bookSpine){ - var id = item.getAttribute('id') || false, - // content = item.querySelector("content"), - content = core.qs(item, "content"), - src = content.getAttribute('src'), - // navLabel = item.querySelector("navLabel"), - navLabel = core.qs(item, "navLabel"), - text = navLabel.textContent ? navLabel.textContent : "", - // split = src.split("#"), - // baseUrl = split[0], - // spinePos = spineIndexByURL[baseUrl], - // spineItem = bookSpine[spinePos], - subitems = [], - parentNode = item.parentNode, - parent; - // cfi = spineItem ? spineItem.cfi : ''; - - if(parentNode && parentNode.nodeName === "navPoint") { - parent = parentNode.getAttribute('id'); - } - - /* - if(!id) { - if(spinePos) { - spineItem = bookSpine[spinePos]; - id = spineItem.id; - cfi = spineItem.cfi; - } else { - id = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid(); - item.setAttribute('id', id); - } - } - */ - - return { - "id": id, - "href": src, - "label": text, - "subitems" : subitems, - "parent" : parent + + return false; }; -}; + + EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) { + var pos = parseInt(_pos), + spineNodeIndex = _spineNodeIndex + 1, + cfi = '/'+spineNodeIndex+'/'; + + cfi += (pos + 1) * 2; + + if(id) { + cfi += "[" + id + "]"; + } + + return cfi; + }; + + module.exports = EpubCFI; -Parser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){ - var navElement = this.querySelectorByType(navHtml, "nav", "page-list"); - // var navItems = navElement ? navElement.querySelectorAll("ol li") : []; - var navItems = navElement ? core.qsa(navElement, "li") : []; - var length = navItems.length; - var i; - var toc = {}; - var list = []; - var item; - if(!navItems || length === 0) return list; +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { - for (i = 0; i < length; ++i) { - item = this.pageListItem(navItems[i], spineIndexByURL, bookSpine); - list.push(item); - } - - return list; -}; - -Parser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){ - var id = item.getAttribute('id') || false, - // content = item.querySelector("a"), - content = core.qs(item, "a"), - href = content.getAttribute('href') || '', - text = content.textContent || "", - page = parseInt(text), - isCfi = href.indexOf("epubcfi"), - split, - packageUrl, - cfi; - - if(isCfi != -1) { - split = href.split("#"); - packageUrl = split[0]; - cfi = split.length > 1 ? split[1] : false; - return { - "cfi" : cfi, - "href" : href, - "packageUrl" : packageUrl, - "page" : page - }; - } else { - return { - "href" : href, - "page" : page - }; - } -}; - -module.exports = Parser; - -},{"./core":10,"./epubcfi":11,"urijs":7}],23:[function(require,module,exports){ -var RSVP = require('rsvp'); -var core = require('./core'); - -function Queue(_context){ - this._q = []; - this.context = _context; - this.tick = core.requestAnimationFrame; - this.running = false; - this.paused = false; -}; - -// Add an item to the queue -Queue.prototype.enqueue = function() { - var deferred, promise; - var queued; - var task = [].shift.call(arguments); - var args = arguments; - - // Handle single args without context - // if(args && !Array.isArray(args)) { - // args = [args]; - // } - if(!task) { - return console.error("No Task Provided"); - } - - if(typeof task === "function"){ - - deferred = new RSVP.defer(); - promise = deferred.promise; - - queued = { - "task" : task, - "args" : args, - //"context" : context, - "deferred" : deferred, - "promise" : promise - }; - - } else { - // Task is a promise - queued = { - "promise" : task - }; - - } - - this._q.push(queued); - - // Wait to start queue flush - if (this.paused == false && !this.running) { - // setTimeout(this.flush.bind(this), 0); - // this.tick.call(window, this.run.bind(this)); - this.run(); - } - - return queued.promise; -}; - -// Run one item -Queue.prototype.dequeue = function(){ - var inwait, task, result; - - if(this._q.length) { - inwait = this._q.shift(); - task = inwait.task; - if(task){ - // console.log(task) - - result = task.apply(this.context, inwait.args); - - if(result && typeof result["then"] === "function") { + var RSVP = __webpack_require__(2); + + //-- Hooks allow for injecting functions that must all complete in order before finishing + // They will execute in parallel but all must finish before continuing + // Functions may return a promise if they are asycn. + + // this.content = new EPUBJS.Hook(); + // this.content.register(function(){}); + // this.content.trigger(args).then(function(){}); + + function Hook(context){ + this.context = context || this; + this.hooks = []; + }; + + // Adds a function to be run before a hook completes + Hook.prototype.register = function(){ + for(var i = 0; i < arguments.length; ++i) { + if (typeof arguments[i] === "function") { + this.hooks.push(arguments[i]); + } else { + // unpack array + for(var j = 0; j < arguments[i].length; ++j) { + this.hooks.push(arguments[i][j]); + } + } + } + }; + + // Triggers a hook to run all functions + Hook.prototype.trigger = function(){ + var args = arguments; + var context = this.context; + var promises = []; + + this.hooks.forEach(function(task, i) { + var executing = task.apply(context, args); + + if(executing && typeof executing["then"] === "function") { // Task is a function that returns a promise - return result.then(function(){ - inwait.deferred.resolve.apply(this.context, arguments); - }.bind(this)); - } else { - // Task resolves immediately - inwait.deferred.resolve.apply(this.context, result); - return inwait.promise; + promises.push(executing); } + // Otherwise Task resolves immediately, continue + }); + + + return RSVP.all(promises); + }; + + // Adds a function to be run before a hook completes + Hook.prototype.list = function(){ + return this.hooks; + }; + + Hook.prototype.clear = function(){ + return this.hooks = []; + }; + + module.exports = Hook; +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { - } else if(inwait.promise) { - // Task is a promise - return inwait.promise; - } - - } else { - inwait = new RSVP.defer(); - inwait.deferred.resolve(); - return inwait.promise; - } - -}; - -// Run All Immediately -Queue.prototype.dump = function(){ - while(this._q.length) { - this.dequeue(); - } -}; - -// Run all sequentially, at convince - -Queue.prototype.run = function(){ - - if(!this.running){ - this.running = true; - this.defered = new RSVP.defer(); - } - - this.tick.call(window, function() { - - if(this._q.length) { - - this.dequeue() + var RSVP = __webpack_require__(2); + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + var EpubCFI = __webpack_require__(15); + var Hook = __webpack_require__(16); + + function Section(item, hooks){ + this.idref = item.idref; + this.linear = item.linear; + this.properties = item.properties; + this.index = item.index; + this.href = item.href; + this.url = item.url; + this.next = item.next; + this.prev = item.prev; + + this.cfiBase = item.cfiBase; + + if (hooks) { + this.hooks = hooks; + } else { + this.hooks = {}; + this.hooks.serialize = new Hook(this); + this.hooks.content = new Hook(this); + } + + }; + + + Section.prototype.load = function(_request){ + var request = _request || this.request || __webpack_require__(18); + var loading = new RSVP.defer(); + var loaded = loading.promise; + + if(this.contents) { + loading.resolve(this.contents); + } else { + request(this.url) + .then(function(xml){ + var base; + var directory = URI(this.url).directory(); + + this.document = xml; + this.contents = xml.documentElement; + + return this.hooks.content.trigger(this.document, this); + }.bind(this)) .then(function(){ - this.run(); - }.bind(this)); - - } else { - this.defered.resolve(); - this.running = undefined; - } - - }.bind(this)); - - // Unpause - if(this.paused == true) { - this.paused = false; - } - - return this.defered.promise; -}; - -// Flush all, as quickly as possible -Queue.prototype.flush = function(){ - - if(this.running){ - return this.running; - } - - if(this._q.length) { - this.running = this.dequeue() - .then(function(){ - this.running = undefined; - return this.flush(); - }.bind(this)); - - return this.running; - } - -}; - -// Clear all items in wait -Queue.prototype.clear = function(){ - this._q = []; - this.running = false; -}; - -Queue.prototype.length = function(){ - return this._q.length; -}; - -Queue.prototype.pause = function(){ - this.paused = true; -}; - -// Create a new task from a callback -function Task(task, args, context){ - - return function(){ - var toApply = arguments || []; - - return new RSVP.Promise(function(resolve, reject) { - var callback = function(value){ - resolve(value); - }; - // Add the callback to the arguments list - toApply.push(callback); - - // Apply all arguments to the functions - task.apply(this, toApply); - - }.bind(this)); - - }; - -}; - -module.exports = Queue; - -},{"./core":10,"rsvp":5}],24:[function(require,module,exports){ -var RSVP = require('rsvp'); -var URI = require('urijs'); -var core = require('./core'); -var replace = require('./replacements'); -var Hook = require('./hook'); -var EpubCFI = require('./epubcfi'); -var Queue = require('./queue'); -var Layout = require('./layout'); -var Mapping = require('./mapping'); - -function Rendition(book, options) { - - this.settings = core.extend(this.settings || {}, { - width: null, - height: null, - ignoreClass: '', - manager: "single", - view: "iframe", - flow: null, - layout: null, - spread: null, - minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always), - useBase64: true - }); - - core.extend(this.settings, options); - - this.viewSettings = { - ignoreClass: this.settings.ignoreClass - }; - - this.book = book; - - this.views = null; - - //-- Adds Hook methods to the Rendition prototype - this.hooks = {}; - this.hooks.display = new Hook(this); - this.hooks.serialize = new Hook(this); - this.hooks.content = new Hook(this); - this.hooks.layout = new Hook(this); - this.hooks.render = new Hook(this); - this.hooks.show = new Hook(this); - - this.hooks.content.register(replace.links.bind(this)); - this.hooks.content.register(this.passViewEvents.bind(this)); - - // this.hooks.display.register(this.afterDisplay.bind(this)); - - this.epubcfi = new EpubCFI(); - - this.q = new Queue(this); - - this.q.enqueue(this.book.opened); - - // Block the queue until rendering is started - // this.starting = new RSVP.defer(); - // this.started = this.starting.promise; - this.q.enqueue(this.start); - - if(this.book.unarchived) { - this.q.enqueue(this.replacements.bind(this)); - } - -}; - -Rendition.prototype.setManager = function(manager) { - this.manager = manager; -}; - -Rendition.prototype.requireManager = function(manager) { - var viewManager; - - // If manager is a string, try to load from register managers, - // or require included managers directly - if (typeof manager === "string") { - // Use global or require - viewManager = typeof ePub != "undefined" ? ePub.ViewManagers[manager] : undefined; //require('./managers/'+manager); - } else { - // otherwise, assume we were passed a function - viewManager = manager - } - - return viewManager; -}; - -Rendition.prototype.requireView = function(view) { - var View; - - if (typeof view == "string") { - View = typeof ePub != "undefined" ? ePub.Views[view] : undefined; //require('./views/'+view); - } else { - // otherwise, assume we were passed a function - View = view - } - - return View; -}; - -Rendition.prototype.start = function(){ - - if(!this.manager) { - this.ViewManager = this.requireManager(this.settings.manager); - this.View = this.requireView(this.settings.view); - - this.manager = new this.ViewManager({ - view: this.View, - queue: this.q, - request: this.book.request, - settings: this.settings - }); - } - - // Parse metadata to get layout props - this.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata); - - this.flow(this.settings.globalLayoutProperties.flow); - - this.layout(this.settings.globalLayoutProperties); - - // Listen for displayed views - this.manager.on("added", this.afterDisplayed.bind(this)); - - // Listen for resizing - this.manager.on("resized", this.onResized.bind(this)); - - // Listen for scroll changes - this.manager.on("scroll", this.reportLocation.bind(this)); - - - this.on('displayed', this.reportLocation.bind(this)); - - // Trigger that rendering has started - this.trigger("started"); - - // Start processing queue - // this.starting.resolve(); -}; - -// Call to attach the container to an element in the dom -// Container must be attached before rendering can begin -Rendition.prototype.attachTo = function(element){ - - return this.q.enqueue(function () { - - // Start rendering - this.manager.render(element, { - "width" : this.settings.width, - "height" : this.settings.height - }); - - // Trigger Attached - this.trigger("attached"); - - }.bind(this)); - -}; - -Rendition.prototype.display = function(target){ - - // if (!this.book.spine.spineItems.length > 0) { - // Book isn't open yet - // return this.q.enqueue(this.display, target); - // } - - return this.q.enqueue(this._display, target); - -}; - -Rendition.prototype._display = function(target){ - var isCfiString = this.epubcfi.isCfiString(target); - var displaying = new RSVP.defer(); - var displayed = displaying.promise; - var section; - var moveTo; - - section = this.book.spine.get(target); - - if(!section){ - displaying.reject(new Error("No Section Found")); - return displayed; - } - - // Trim the target fragment - // removing the chapter - if(!isCfiString && typeof target === "string" && - target.indexOf("#") > -1) { - moveTo = target.substring(target.indexOf("#")+1); - } - - if (isCfiString) { - moveTo = target; - } - - return this.manager.display(section, moveTo) - .then(function(){ - this.trigger("displayed", section); - }.bind(this)); - -}; - -/* -Rendition.prototype.render = function(view, show) { - - // view.onLayout = this.layout.format.bind(this.layout); - view.create(); - - // Fit to size of the container, apply padding - this.manager.resizeView(view); - - // Render Chain - return view.section.render(this.book.request) - .then(function(contents){ - return view.load(contents); - }.bind(this)) - .then(function(doc){ - return this.hooks.content.trigger(view, this); - }.bind(this)) - .then(function(){ - this.layout.format(view.contents); - return this.hooks.layout.trigger(view, this); - }.bind(this)) - .then(function(){ - return view.display(); - }.bind(this)) - .then(function(){ - return this.hooks.render.trigger(view, this); - }.bind(this)) - .then(function(){ - if(show !== false) { - this.q.enqueue(function(view){ - view.show(); - }, view); - } - // this.map = new Map(view, this.layout); - this.hooks.show.trigger(view, this); - this.trigger("rendered", view.section); - - }.bind(this)) - .catch(function(e){ - this.trigger("loaderror", e); - }.bind(this)); - -}; -*/ - -Rendition.prototype.afterDisplayed = function(view){ - this.hooks.content.trigger(view, this); - this.trigger("rendered", view.section); - this.reportLocation(); -}; - -Rendition.prototype.onResized = function(size){ - - if(this.location) { - this.display(this.location.start); - } - - this.trigger("resized", { - width: size.width, - height: size.height - }); - -}; - -Rendition.prototype.moveTo = function(offset){ - this.manager.moveTo(offset); -}; - -Rendition.prototype.next = function(){ - return this.q.enqueue(this.manager.next.bind(this.manager)) - .then(this.reportLocation.bind(this)); -}; - -Rendition.prototype.prev = function(){ - return this.q.enqueue(this.manager.prev.bind(this.manager)) - .then(this.reportLocation.bind(this)); -}; - -//-- http://www.idpf.org/epub/301/spec/epub-publications.html#meta-properties-rendering -Rendition.prototype.determineLayoutProperties = function(metadata){ - var settings; - var layout = this.settings.layout || metadata.layout || "reflowable"; - var spread = this.settings.spread || metadata.spread || "auto"; - var orientation = this.settings.orientation || metadata.orientation || "auto"; - var flow = this.settings.flow || metadata.flow || "auto"; - var viewport = metadata.viewport || ""; - var minSpreadWidth = this.settings.minSpreadWidth || metadata.minSpreadWidth || 800; - - if (this.settings.width >= 0 && this.settings.height >= 0) { - viewport = "width="+this.settings.width+", height="+this.settings.height+""; - } - - settings = { - layout : layout, - spread : spread, - orientation : orientation, - flow : flow, - viewport : viewport, - minSpreadWidth : minSpreadWidth - }; - - return settings; -}; - -// Rendition.prototype.applyLayoutProperties = function(){ -// var settings = this.determineLayoutProperties(this.book.package.metadata); -// -// this.flow(settings.flow); -// -// this.layout(settings); -// }; - -// paginated | scrolled -// (scrolled-continuous vs scrolled-doc are handled by different view managers) -Rendition.prototype.flow = function(_flow){ - var flow; - if (_flow === "scrolled-doc" || _flow === "scrolled-continuous") { - flow = "scrolled"; - } - - if (_flow === "auto" || _flow === "paginated") { - flow = "paginated"; - } - - if (this._layout) { - this._layout.flow(flow); - } - - if (this.manager) { - this.manager.updateFlow(flow); - } -}; - -// reflowable | pre-paginated -Rendition.prototype.layout = function(settings){ - if (settings) { - this._layout = new Layout(settings); - this._layout.spread(settings.spread, this.settings.minSpreadWidth); - - this.mapping = new Mapping(this._layout); - } - - if (this.manager && this._layout) { - this.manager.applyLayout(this._layout); - } - - return this._layout; -}; - -// none | auto (TODO: implement landscape, portrait, both) -Rendition.prototype.spread = function(spread, min){ - - this._layout.spread(spread, min); - - if (this.manager.isRendered()) { - this.manager.updateLayout(); - } -}; - - -Rendition.prototype.reportLocation = function(){ - return this.q.enqueue(function(){ - var location = this.manager.currentLocation(); - if (location && location.then && typeof location.then === 'function') { - location.then(function(result) { - this.location = result; - this.trigger("locationChanged", this.location); - }.bind(this)); - } else if (location) { - this.location = location; - this.trigger("locationChanged", this.location); - } - - }.bind(this)); -}; - - -Rendition.prototype.destroy = function(){ - // Clear the queue - this.q.clear(); - - this.manager.destroy(); -}; - -Rendition.prototype.passViewEvents = function(view){ - view.contents.listenedEvents.forEach(function(e){ - view.on(e, this.triggerViewEvent.bind(this)); - }.bind(this)); - - view.on("selected", this.triggerSelectedEvent.bind(this)); -}; - -Rendition.prototype.triggerViewEvent = function(e){ - this.trigger(e.type, e); -}; - -Rendition.prototype.triggerSelectedEvent = function(cfirange){ - this.trigger("selected", cfirange); -}; - -Rendition.prototype.replacements = function(){ - // Wait for loading - // return this.q.enqueue(function () { - // Get thes books manifest - var manifest = this.book.package.manifest; - var manifestArray = Object.keys(manifest). - map(function (key){ - return manifest[key]; - }); - - // Exclude HTML - var items = manifestArray. - filter(function (item){ - if (item.type != "application/xhtml+xml" && - item.type != "text/html") { - return true; - } - }); - - // Only CSS - var css = items. - filter(function (item){ - if (item.type === "text/css") { - return true; - } - }); - - // Css Urls - var cssUrls = css.map(function(item) { - return item.href; - }); - - // All Assets Urls - var urls = items. - map(function(item) { - return item.href; - }.bind(this)); - - // Create blob urls for all the assets - var processing = urls. - map(function(url) { - var absolute = URI(url).absoluteTo(this.book.baseUrl).toString(); - // Full url from archive base - return this.book.unarchived.createUrl(absolute, {"base64": this.settings.useBase64}); - }.bind(this)); - - var replacementUrls; - - // After all the urls are created - return RSVP.all(processing) - .then(function(_replacementUrls) { - var replaced = []; - - replacementUrls = _replacementUrls; - - // Replace Asset Urls in the text of all css files - cssUrls.forEach(function(href) { - replaced.push(this.replaceCss(href, urls, replacementUrls)); - }.bind(this)); - - return RSVP.all(replaced); - - }.bind(this)) - .then(function () { - // Replace Asset Urls in chapters - // by registering a hook after the sections contents has been serialized - this.book.spine.hooks.serialize.register(function(output, section) { - - this.replaceAssets(section, urls, replacementUrls); - - }.bind(this)); - - }.bind(this)) - .catch(function(reason){ - console.error(reason); - }); - // }.bind(this)); -}; - -Rendition.prototype.replaceCss = function(href, urls, replacementUrls){ - var newUrl; - var indexInUrls; - - // Find the absolute url of the css file - var fileUri = URI(href); - var absolute = fileUri.absoluteTo(this.book.baseUrl).toString(); - // Get the text of the css file from the archive - var textResponse = this.book.unarchived.getText(absolute); - // Get asset links relative to css file - var relUrls = urls. - map(function(assetHref) { - var assetUri = URI(assetHref).absoluteTo(this.book.baseUrl); - var relative = assetUri.relativeTo(absolute).toString(); - return relative; - }.bind(this)); - - return textResponse.then(function (text) { - // Replacements in the css text - text = replace.substitute(text, relUrls, replacementUrls); - - // Get the new url - if (this.settings.useBase64) { - newUrl = core.createBase64Url(text, 'text/css'); - } else { - newUrl = core.createBlobUrl(text, 'text/css'); - } - - // switch the url in the replacementUrls - indexInUrls = urls.indexOf(href); - if (indexInUrls > -1) { - replacementUrls[indexInUrls] = newUrl; - } - - return new RSVP.Promise(function(resolve, reject){ - resolve(urls, replacementUrls); - }); - - }.bind(this)); - -}; - -Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){ - var fileUri = URI(section.url); - // Get Urls relative to current sections - var relUrls = urls. - map(function(href) { - var assetUri = URI(href).absoluteTo(this.book.baseUrl); - var relative = assetUri.relativeTo(fileUri).toString(); - return relative; - }.bind(this)); - - - section.output = replace.substitute(section.output, relUrls, replacementUrls); -}; - -Rendition.prototype.range = function(_cfi, ignoreClass){ - var cfi = new EpubCFI(_cfi); - var found = this.visible().filter(function (view) { - if(cfi.spinePos === view.index) return true; - }); - - // Should only every return 1 item - if (found.length) { - return found[0].range(cfi, ignoreClass); - } -}; - -Rendition.prototype.adjustImages = function(view) { - - view.addStylesheetRules([ - ["img", - ["max-width", (view.layout.spreadWidth) + "px"], - ["max-height", (view.layout.height) + "px"] - ] - ]); - return new RSVP.Promise(function(resolve, reject){ - // Wait to apply - setTimeout(function() { - resolve(); - }, 1); - }); -}; - -//-- Enable binding events to Renderer -RSVP.EventTarget.mixin(Rendition.prototype); - -module.exports = Rendition; - -},{"./core":10,"./epubcfi":11,"./hook":12,"./layout":13,"./mapping":20,"./queue":23,"./replacements":25,"rsvp":5,"urijs":7}],25:[function(require,module,exports){ -var URI = require('urijs'); -var core = require('./core'); - -function base(doc, section){ - var base; - var head; - - if(!doc){ - return; - } - - // head = doc.querySelector("head"); - // base = head.querySelector("base"); - head = core.qs(doc, "head"); - base = core.qs(head, "base"); - - if(!base) { - base = doc.createElement("base"); - head.insertBefore(base, head.firstChild); - } - - base.setAttribute("href", section.url); -} - -function canonical(doc, section){ - var head; - var link; - var url = section.url; // window.location.origin + window.location.pathname + "?loc=" + encodeURIComponent(section.url); - - if(!doc){ - return; - } - - head = core.qs(doc, "head"); - link = core.qs(head, "link[rel='canonical']"); - - if (link) { - link.setAttribute("href", url); - } else { - link = doc.createElement("link"); - link.setAttribute("rel", "canonical"); - link.setAttribute("href", url); - head.appendChild(link); - } -} - -function links(view, renderer) { - - var links = view.document.querySelectorAll("a[href]"); - var replaceLinks = function(link){ - var href = link.getAttribute("href"); - - if(href.indexOf("mailto:") === 0){ - return; - } - - var linkUri = URI(href); - var absolute = linkUri.absoluteTo(view.section.url); - var relative = absolute.relativeTo(this.book.baseUrl).toString(); - - if(linkUri.protocol()){ - - link.setAttribute("target", "_blank"); - - }else{ - /* - if(baseDirectory) { - // We must ensure that the file:// protocol is preserved for - // local file links, as in certain contexts (such as under - // Titanium), file links without the file:// protocol will not - // work - if (baseUri.protocol === "file") { - relative = core.resolveUrl(baseUri.base, href); - } else { - relative = core.resolveUrl(baseDirectory, href); - } - } else { - relative = href; - } - */ - - if(linkUri.fragment()) { - // do nothing with fragment yet - } else { - link.onclick = function(){ - renderer.display(relative); - return false; - }; - } - - } - }.bind(this); - - for (var i = 0; i < links.length; i++) { - replaceLinks(links[i]); - } - - -}; - -function substitute(content, urls, replacements) { - urls.forEach(function(url, i){ - if (url && replacements[i]) { - content = content.replace(new RegExp(url, 'g'), replacements[i]); - } - }); - return content; -} -module.exports = { - 'base': base, - 'canonical' : canonical, - 'links': links, - 'substitute': substitute -}; - -},{"./core":10,"urijs":7}],26:[function(require,module,exports){ -var RSVP = require('rsvp'); -var URI = require('urijs'); -var core = require('./core'); - -function request(url, type, withCredentials, headers) { - var supportsURL = (typeof window != "undefined") ? window.URL : false; // TODO: fallback for url if window isn't defined - var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer"; - var uri; - - var deferred = new RSVP.defer(); - - var xhr = new XMLHttpRequest(); - - //-- Check from PDF.js: - // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js - var xhrPrototype = XMLHttpRequest.prototype; - - var header; - - if (!('overrideMimeType' in xhrPrototype)) { - // IE10 might have response, but not overrideMimeType - Object.defineProperty(xhrPrototype, 'overrideMimeType', { - value: function xmlHttpRequestOverrideMimeType(mimeType) {} - }); - } - if(withCredentials) { - xhr.withCredentials = true; - } - - xhr.onreadystatechange = handler; - xhr.onerror = err; - - xhr.open("GET", url, true); - - for(header in headers) { - xhr.setRequestHeader(header, headers[header]); - } - - if(type == "json") { - xhr.setRequestHeader("Accept", "application/json"); - } - - // If type isn't set, determine it from the file extension - if(!type) { - uri = URI(url); - type = uri.suffix(); - } - - if(type == 'blob'){ - xhr.responseType = BLOB_RESPONSE; - } - - - if(core.isXml(type)) { - // xhr.responseType = "document"; - xhr.overrideMimeType('text/xml'); // for OPF parsing - } - - if(type == 'xhtml') { - // xhr.responseType = "document"; - } - - if(type == 'html' || type == 'htm') { - // xhr.responseType = "document"; - } - - if(type == "binary") { - xhr.responseType = "arraybuffer"; - } - - xhr.send(); - - function err(e) { - console.error(e); - deferred.reject(e); - } - - function handler() { - if (this.readyState === XMLHttpRequest.DONE) { - - if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls - var r; - - if (!this.response && !this.responseXML) { - deferred.reject({ - status: this.status, - message : "Empty Response", - stack : new Error().stack - }); - return deferred.promise; - } - - if (this.status === 403) { - deferred.reject({ - status: this.status, - response: this.response, - message : "Forbidden", - stack : new Error().stack - }); - return deferred.promise; - } - - if((this.responseType == '' || this.responseType == 'document') - && this.responseXML){ - r = this.responseXML; - } else - if(core.isXml(type)){ - // xhr.overrideMimeType('text/xml'); // for OPF parsing - // If this.responseXML wasn't set, try to parse using a DOMParser from text - r = core.parse(this.response, "text/xml"); - }else - if(type == 'xhtml'){ - r = core.parse(this.response, "application/xhtml+xml"); - }else - if(type == 'html' || type == 'htm'){ - r = core.parse(this.response, "text/html"); - }else - if(type == 'json'){ - r = JSON.parse(this.response); - }else - if(type == 'blob'){ - - if(supportsURL) { - r = this.response; - } else { - //-- Safari doesn't support responseType blob, so create a blob from arraybuffer - r = new Blob([this.response]); - } - - }else{ - r = this.response; - } - - deferred.resolve(r); - } else { - - deferred.reject({ - status: this.status, - message : this.response, - stack : new Error().stack + loading.resolve(this.contents); + }.bind(this)) + .catch(function(error){ + loading.reject(error); }); - + } + + return loaded; + }; + + Section.prototype.base = function(_document){ + var task = new RSVP.defer(); + var base = _document.createElement("base"); // TODO: check if exists + var head; + console.log(window.location.origin + "/" +this.url); + + base.setAttribute("href", window.location.origin + "/" +this.url); + + if(_document) { + head = _document.querySelector("head"); } - } - } - - return deferred.promise; -}; - -module.exports = request; - -},{"./core":10,"rsvp":5,"urijs":7}],27:[function(require,module,exports){ -var RSVP = require('rsvp'); -var URI = require('urijs'); -var core = require('./core'); -var EpubCFI = require('./epubcfi'); -var Hook = require('./hook'); - -function Section(item, hooks){ - this.idref = item.idref; - this.linear = item.linear; - this.properties = item.properties; - this.index = item.index; - this.href = item.href; - this.url = item.url; - this.next = item.next; - this.prev = item.prev; - - this.cfiBase = item.cfiBase; - - if (hooks) { - this.hooks = hooks; - } else { - this.hooks = {}; - this.hooks.serialize = new Hook(this); - this.hooks.content = new Hook(this); - } - -}; - - -Section.prototype.load = function(_request){ - var request = _request || this.request || require('./request'); - var loading = new RSVP.defer(); - var loaded = loading.promise; - - if(this.contents) { - loading.resolve(this.contents); - } else { - request(this.url) - .then(function(xml){ - var base; - var directory = URI(this.url).directory(); - - this.document = xml; - this.contents = xml.documentElement; - - return this.hooks.content.trigger(this.document, this); - }.bind(this)) - .then(function(){ - loading.resolve(this.contents); + if(head) { + head.insertBefore(base, head.firstChild); + task.resolve(); + } else { + task.reject(new Error("No head to insert into")); + } + + + return task.promise; + }; + + Section.prototype.beforeSectionLoad = function(){ + // Stub for a hook - replace me for now + }; + + Section.prototype.render = function(_request){ + var rendering = new RSVP.defer(); + var rendered = rendering.promise; + this.output; // TODO: better way to return this from hooks? + + this.load(_request). + then(function(contents){ + var serializer; + + if (typeof XMLSerializer === "undefined") { + XMLSerializer = __webpack_require__(13).XMLSerializer; + } + serializer = new XMLSerializer(); + this.output = serializer.serializeToString(contents); + return this.output; + }.bind(this)). + then(function(){ + return this.hooks.serialize.trigger(this.output, this); + }.bind(this)). + then(function(){ + rendering.resolve(this.output); }.bind(this)) .catch(function(error){ - loading.reject(error); + rendering.reject(error); }); - } - - return loaded; -}; - -Section.prototype.base = function(_document){ - var task = new RSVP.defer(); - var base = _document.createElement("base"); // TODO: check if exists - var head; - console.log(window.location.origin + "/" +this.url); - - base.setAttribute("href", window.location.origin + "/" +this.url); - - if(_document) { - head = _document.querySelector("head"); - } - if(head) { - head.insertBefore(base, head.firstChild); - task.resolve(); - } else { - task.reject(new Error("No head to insert into")); - } - - - return task.promise; -}; - -Section.prototype.beforeSectionLoad = function(){ - // Stub for a hook - replace me for now -}; - -Section.prototype.render = function(_request){ - var rendering = new RSVP.defer(); - var rendered = rendering.promise; - this.output; // TODO: better way to return this from hooks? - - this.load(_request). - then(function(contents){ - var serializer; - - if (typeof XMLSerializer === "undefined") { - XMLSerializer = require('xmldom').XMLSerializer; + + return rendered; + }; + + Section.prototype.find = function(_query){ + + }; + + /** + * Reconciles the current chapters layout properies with + * the global layout properities. + * Takes: global layout settings object, chapter properties string + * Returns: Object with layout properties + */ + Section.prototype.reconcileLayoutSettings = function(global){ + //-- Get the global defaults + var settings = { + layout : global.layout, + spread : global.spread, + orientation : global.orientation + }; + + //-- Get the chapter's display type + this.properties.forEach(function(prop){ + var rendition = prop.replace("rendition:", ''); + var split = rendition.indexOf("-"); + var property, value; + + if(split != -1){ + property = rendition.slice(0, split); + value = rendition.slice(split+1); + + settings[property] = value; } - serializer = new XMLSerializer(); - this.output = serializer.serializeToString(contents); - return this.output; - }.bind(this)). - then(function(){ - return this.hooks.serialize.trigger(this.output, this); - }.bind(this)). - then(function(){ - rendering.resolve(this.output); - }.bind(this)) - .catch(function(error){ - rendering.reject(error); }); + return settings; + }; + + Section.prototype.cfiFromRange = function(_range) { + return new EpubCFI(_range, this.cfiBase).toString(); + }; + + Section.prototype.cfiFromElement = function(el) { + return new EpubCFI(el, this.cfiBase).toString(); + }; + + module.exports = Section; - return rendered; -}; -Section.prototype.find = function(_query){ +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { -}; + var RSVP = __webpack_require__(2); + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + + function request(url, type, withCredentials, headers) { + var supportsURL = (typeof window != "undefined") ? window.URL : false; // TODO: fallback for url if window isn't defined + var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer"; + var uri; + + var deferred = new RSVP.defer(); + + var xhr = new XMLHttpRequest(); + + //-- Check from PDF.js: + // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js + var xhrPrototype = XMLHttpRequest.prototype; + + var header; + + if (!('overrideMimeType' in xhrPrototype)) { + // IE10 might have response, but not overrideMimeType + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) {} + }); + } + if(withCredentials) { + xhr.withCredentials = true; + } + + xhr.onreadystatechange = handler; + xhr.onerror = err; + + xhr.open("GET", url, true); + + for(header in headers) { + xhr.setRequestHeader(header, headers[header]); + } + + if(type == "json") { + xhr.setRequestHeader("Accept", "application/json"); + } + + // If type isn't set, determine it from the file extension + if(!type) { + uri = URI(url); + type = uri.suffix(); + } + + if(type == 'blob'){ + xhr.responseType = BLOB_RESPONSE; + } + + + if(core.isXml(type)) { + // xhr.responseType = "document"; + xhr.overrideMimeType('text/xml'); // for OPF parsing + } + + if(type == 'xhtml') { + // xhr.responseType = "document"; + } + + if(type == 'html' || type == 'htm') { + // xhr.responseType = "document"; + } + + if(type == "binary") { + xhr.responseType = "arraybuffer"; + } + + xhr.send(); + + function err(e) { + console.error(e); + deferred.reject(e); + } + + function handler() { + if (this.readyState === XMLHttpRequest.DONE) { + + if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls + var r; + + if (!this.response && !this.responseXML) { + deferred.reject({ + status: this.status, + message : "Empty Response", + stack : new Error().stack + }); + return deferred.promise; + } + + if (this.status === 403) { + deferred.reject({ + status: this.status, + response: this.response, + message : "Forbidden", + stack : new Error().stack + }); + return deferred.promise; + } + + if((this.responseType == '' || this.responseType == 'document') + && this.responseXML){ + r = this.responseXML; + } else + if(core.isXml(type)){ + // xhr.overrideMimeType('text/xml'); // for OPF parsing + // If this.responseXML wasn't set, try to parse using a DOMParser from text + r = core.parse(this.response, "text/xml"); + }else + if(type == 'xhtml'){ + r = core.parse(this.response, "application/xhtml+xml"); + }else + if(type == 'html' || type == 'htm'){ + r = core.parse(this.response, "text/html"); + }else + if(type == 'json'){ + r = JSON.parse(this.response); + }else + if(type == 'blob'){ + + if(supportsURL) { + r = this.response; + } else { + //-- Safari doesn't support responseType blob, so create a blob from arraybuffer + r = new Blob([this.response]); + } + + }else{ + r = this.response; + } + + deferred.resolve(r); + } else { + + deferred.reject({ + status: this.status, + message : this.response, + stack : new Error().stack + }); + + } + } + } + + return deferred.promise; + }; + + module.exports = request; -/** -* Reconciles the current chapters layout properies with -* the global layout properities. -* Takes: global layout settings object, chapter properties string -* Returns: Object with layout properties -*/ -Section.prototype.reconcileLayoutSettings = function(global){ - //-- Get the global defaults - var settings = { - layout : global.layout, - spread : global.spread, - orientation : global.orientation + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + + function base(doc, section){ + var base; + var head; + + if(!doc){ + return; + } + + // head = doc.querySelector("head"); + // base = head.querySelector("base"); + head = core.qs(doc, "head"); + base = core.qs(head, "base"); + + if(!base) { + base = doc.createElement("base"); + head.insertBefore(base, head.firstChild); + } + + base.setAttribute("href", section.url); + } + + function canonical(doc, section){ + var head; + var link; + var url = section.url; // window.location.origin + window.location.pathname + "?loc=" + encodeURIComponent(section.url); + + if(!doc){ + return; + } + + head = core.qs(doc, "head"); + link = core.qs(head, "link[rel='canonical']"); + + if (link) { + link.setAttribute("href", url); + } else { + link = doc.createElement("link"); + link.setAttribute("rel", "canonical"); + link.setAttribute("href", url); + head.appendChild(link); + } + } + + function links(view, renderer) { + + var links = view.document.querySelectorAll("a[href]"); + var replaceLinks = function(link){ + var href = link.getAttribute("href"); + + if(href.indexOf("mailto:") === 0){ + return; + } + + var linkUri = URI(href); + var absolute = linkUri.absoluteTo(view.section.url); + var relative = absolute.relativeTo(this.book.baseUrl).toString(); + + if(linkUri.protocol()){ + + link.setAttribute("target", "_blank"); + + }else{ + /* + if(baseDirectory) { + // We must ensure that the file:// protocol is preserved for + // local file links, as in certain contexts (such as under + // Titanium), file links without the file:// protocol will not + // work + if (baseUri.protocol === "file") { + relative = core.resolveUrl(baseUri.base, href); + } else { + relative = core.resolveUrl(baseDirectory, href); + } + } else { + relative = href; + } + */ + + if(linkUri.fragment()) { + // do nothing with fragment yet + } else { + link.onclick = function(){ + renderer.display(relative); + return false; + }; + } + + } + }.bind(this); + + for (var i = 0; i < links.length; i++) { + replaceLinks(links[i]); + } + + + }; + + function substitute(content, urls, replacements) { + urls.forEach(function(url, i){ + if (url && replacements[i]) { + content = content.replace(new RegExp(url, 'g'), replacements[i]); + } + }); + return content; + } + module.exports = { + 'base': base, + 'canonical' : canonical, + 'links': links, + 'substitute': substitute }; - //-- Get the chapter's display type - this.properties.forEach(function(prop){ - var rendition = prop.replace("rendition:", ''); - var split = rendition.indexOf("-"); - var property, value; - if(split != -1){ - property = rendition.slice(0, split); - value = rendition.slice(split+1); +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { - settings[property] = value; + var core = __webpack_require__(11); + var Queue = __webpack_require__(21); + var EpubCFI = __webpack_require__(15); + var RSVP = __webpack_require__(2); + + function Locations(spine, request) { + this.spine = spine; + this.request = request; + + this.q = new Queue(this); + this.epubcfi = new EpubCFI(); + + this._locations = []; + this.total = 0; + + this.break = 150; + + this._current = 0; + + }; + + // Load all of sections in the book + Locations.prototype.generate = function(chars) { + + if (chars) { + this.break = chars; + } + + this.q.pause(); + + this.spine.each(function(section) { + + this.q.enqueue(this.process, section); + + }.bind(this)); + + return this.q.run().then(function() { + this.total = this._locations.length-1; + + if (this._currentCfi) { + this.currentLocation = this._currentCfi; + } + + return this._locations; + // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end)); + }.bind(this)); + + }; + + Locations.prototype.process = function(section) { + + return section.load(this.request) + .then(function(contents) { + + var range; + var doc = contents.ownerDocument; + var counter = 0; + + this.sprint(contents, function(node) { + var len = node.length; + var dist; + var pos = 0; + + // Start range + if (counter == 0) { + range = doc.createRange(); + range.setStart(node, 0); + } + + dist = this.break - counter; + + // Node is smaller than a break + if(dist > len){ + counter += len; + pos = len; + } + + while (pos < len) { + counter = this.break; + pos += this.break; + + // Gone over + if(pos >= len){ + // Continue counter for next node + counter = len - (pos - this.break); + + // At End + } else { + // End the previous range + range.setEnd(node, pos); + cfi = section.cfiFromRange(range); + this._locations.push(cfi); + counter = 0; + + // Start new range + pos += 1; + range = doc.createRange(); + range.setStart(node, pos); + } + } + + + + }.bind(this)); + + // Close remaining + if (range) { + range.setEnd(prev, prev.length); + cfi = section.cfiFromRange(range); + this._locations.push(cfi) + counter = 0; + } + + }.bind(this)); + + }; + + Locations.prototype.sprint = function(root, func) { + var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); + + while ((node = treeWalker.nextNode())) { + func(node); + } + + }; + + Locations.prototype.locationFromCfi = function(cfi){ + // Check if the location has not been set yet + if(this._locations.length === 0) { + return -1; + } + + return core.locationOf(cfi, this._locations, this.epubcfi.compare); + }; + + Locations.prototype.precentageFromCfi = function(cfi) { + // Find closest cfi + var loc = this.locationFromCfi(cfi); + // Get percentage in total + return this.precentageFromLocation(loc); + }; + + Locations.prototype.percentageFromLocation = function(loc) { + if (!loc || !this.total) { + return 0; + } + return (loc / this.total); + }; + + Locations.prototype.cfiFromLocation = function(loc){ + var cfi = -1; + // check that pg is an int + if(typeof loc != "number"){ + loc = parseInt(pg); + } + + if(loc >= 0 && loc < this._locations.length) { + cfi = this._locations[loc]; + } + + return cfi; + }; + + Locations.prototype.cfiFromPercentage = function(value){ + var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1 + var loc = Math.ceil(this.total * percentage); + + return this.cfiFromLocation(loc); + }; + + Locations.prototype.load = function(locations){ + this._locations = JSON.parse(locations); + this.total = this._locations.length-1; + return this._locations; + }; + + Locations.prototype.save = function(json){ + return JSON.stringify(this._locations); + }; + + Locations.prototype.getCurrent = function(json){ + return this._current; + }; + + Locations.prototype.setCurrent = function(curr){ + var loc; + + if(typeof curr == "string"){ + this._currentCfi = curr; + } else if (typeof curr == "number") { + this._current = curr; + } else { + return; + } + + if(this._locations.length === 0) { + return; + } + + if(typeof curr == "string"){ + loc = this.locationFromCfi(curr); + this._current = loc; + } else { + loc = curr; + } + + this.trigger("changed", { + percentage: this.precentageFromLocation(loc) + }); + }; + + Object.defineProperty(Locations.prototype, 'currentLocation', { + get: function () { + return this._current; + }, + set: function (curr) { + this.setCurrent(curr); } }); - return settings; -}; + + RSVP.EventTarget.mixin(Locations.prototype); + + module.exports = Locations; -Section.prototype.cfiFromRange = function(_range) { - return new EpubCFI(_range, this.cfiBase).toString(); -}; -Section.prototype.cfiFromElement = function(el) { - return new EpubCFI(el, this.cfiBase).toString(); -}; +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { -module.exports = Section; + var RSVP = __webpack_require__(2); + var core = __webpack_require__(11); + + function Queue(_context){ + this._q = []; + this.context = _context; + this.tick = core.requestAnimationFrame; + this.running = false; + this.paused = false; + }; + + // Add an item to the queue + Queue.prototype.enqueue = function() { + var deferred, promise; + var queued; + var task = [].shift.call(arguments); + var args = arguments; + + // Handle single args without context + // if(args && !Array.isArray(args)) { + // args = [args]; + // } + if(!task) { + return console.error("No Task Provided"); + } + + if(typeof task === "function"){ + + deferred = new RSVP.defer(); + promise = deferred.promise; + + queued = { + "task" : task, + "args" : args, + //"context" : context, + "deferred" : deferred, + "promise" : promise + }; + + } else { + // Task is a promise + queued = { + "promise" : task + }; + + } + + this._q.push(queued); + + // Wait to start queue flush + if (this.paused == false && !this.running) { + // setTimeout(this.flush.bind(this), 0); + // this.tick.call(window, this.run.bind(this)); + this.run(); + } + + return queued.promise; + }; + + // Run one item + Queue.prototype.dequeue = function(){ + var inwait, task, result; + + if(this._q.length) { + inwait = this._q.shift(); + task = inwait.task; + if(task){ + // console.log(task) + + result = task.apply(this.context, inwait.args); + + if(result && typeof result["then"] === "function") { + // Task is a function that returns a promise + return result.then(function(){ + inwait.deferred.resolve.apply(this.context, arguments); + }.bind(this)); + } else { + // Task resolves immediately + inwait.deferred.resolve.apply(this.context, result); + return inwait.promise; + } + + + + } else if(inwait.promise) { + // Task is a promise + return inwait.promise; + } + + } else { + inwait = new RSVP.defer(); + inwait.deferred.resolve(); + return inwait.promise; + } + + }; + + // Run All Immediately + Queue.prototype.dump = function(){ + while(this._q.length) { + this.dequeue(); + } + }; + + // Run all sequentially, at convince + + Queue.prototype.run = function(){ + + if(!this.running){ + this.running = true; + this.defered = new RSVP.defer(); + } + + this.tick.call(window, function() { + + if(this._q.length) { + + this.dequeue() + .then(function(){ + this.run(); + }.bind(this)); + + } else { + this.defered.resolve(); + this.running = undefined; + } + + }.bind(this)); + + // Unpause + if(this.paused == true) { + this.paused = false; + } + + return this.defered.promise; + }; + + // Flush all, as quickly as possible + Queue.prototype.flush = function(){ + + if(this.running){ + return this.running; + } + + if(this._q.length) { + this.running = this.dequeue() + .then(function(){ + this.running = undefined; + return this.flush(); + }.bind(this)); + + return this.running; + } + + }; + + // Clear all items in wait + Queue.prototype.clear = function(){ + this._q = []; + this.running = false; + }; + + Queue.prototype.length = function(){ + return this._q.length; + }; + + Queue.prototype.pause = function(){ + this.paused = true; + }; + + // Create a new task from a callback + function Task(task, args, context){ + + return function(){ + var toApply = arguments || []; + + return new RSVP.Promise(function(resolve, reject) { + var callback = function(value){ + resolve(value); + }; + // Add the callback to the arguments list + toApply.push(callback); + + // Apply all arguments to the functions + task.apply(this, toApply); + + }.bind(this)); + + }; + + }; + + module.exports = Queue; -},{"./core":10,"./epubcfi":11,"./hook":12,"./request":26,"rsvp":5,"urijs":7,"xmldom":"xmldom"}],28:[function(require,module,exports){ -var RSVP = require('rsvp'); -var core = require('./core'); -var EpubCFI = require('./epubcfi'); -var Hook = require('./hook'); -var Section = require('./section'); -var replacements = require('./replacements'); -function Spine(_request){ - this.request = _request; - this.spineItems = []; - this.spineByHref = {}; - this.spineById = {}; +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { - this.hooks = {}; - this.hooks.serialize = new Hook(); - this.hooks.content = new Hook(); - - // Register replacements - this.hooks.content.register(replacements.base); - this.hooks.content.register(replacements.canonical); - - this.epubcfi = new EpubCFI(); - - this.loaded = false; -}; - -Spine.prototype.load = function(_package) { - - this.items = _package.spine; - this.manifest = _package.manifest; - this.spineNodeIndex = _package.spineNodeIndex; - this.baseUrl = _package.baseUrl || ''; - this.length = this.items.length; - - this.items.forEach(function(item, index){ - var href, url; - var manifestItem = this.manifest[item.idref]; - var spineItem; - - item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref); - - if(manifestItem) { - item.href = manifestItem.href; - item.url = this.baseUrl + item.href; - - if(manifestItem.properties.length){ - item.properties.push.apply(item.properties, manifestItem.properties); + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + var EpubCFI = __webpack_require__(15); + + + function Parser(){}; + + Parser.prototype.container = function(containerXml){ + //-- + var rootfile, fullpath, folder, encoding; + + if(!containerXml) { + console.error("Container File Not Found"); + return; + } + + rootfile = core.qs(containerXml, "rootfile"); + + if(!rootfile) { + console.error("No RootFile Found"); + return; + } + + fullpath = rootfile.getAttribute('full-path'); + folder = URI(fullpath).directory(); + encoding = containerXml.xmlEncoding; + + //-- Now that we have the path we can parse the contents + return { + 'packagePath' : fullpath, + 'basePath' : folder, + 'encoding' : encoding + }; + }; + + Parser.prototype.identifier = function(packageXml){ + var metadataNode; + + if(!packageXml) { + console.error("Package File Not Found"); + return; + } + + metadataNode = core.qs(packageXml, "metadata"); + + if(!metadataNode) { + console.error("No Metadata Found"); + return; + } + + return this.getElementText(metadataNode, "identifier"); + }; + + Parser.prototype.packageContents = function(packageXml){ + var parse = this; + var metadataNode, manifestNode, spineNode; + var manifest, navPath, ncxPath, coverPath; + var spineNodeIndex; + var spine; + var spineIndexByURL; + var metadata; + + if(!packageXml) { + console.error("Package File Not Found"); + return; + } + + metadataNode = core.qs(packageXml, "metadata"); + if(!metadataNode) { + console.error("No Metadata Found"); + return; + } + + manifestNode = core.qs(packageXml, "manifest"); + if(!manifestNode) { + console.error("No Manifest Found"); + return; + } + + spineNode = core.qs(packageXml, "spine"); + if(!spineNode) { + console.error("No Spine Found"); + return; + } + + manifest = parse.manifest(manifestNode); + navPath = parse.findNavPath(manifestNode); + ncxPath = parse.findNcxPath(manifestNode, spineNode); + coverPath = parse.findCoverPath(packageXml); + + spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode); + + spine = parse.spine(spineNode, manifest); + + metadata = parse.metadata(metadataNode); + + metadata.direction = spineNode.getAttribute("page-progression-direction"); + + return { + 'metadata' : metadata, + 'spine' : spine, + 'manifest' : manifest, + 'navPath' : navPath, + 'ncxPath' : ncxPath, + 'coverPath': coverPath, + 'spineNodeIndex' : spineNodeIndex + }; + }; + + //-- Find TOC NAV + Parser.prototype.findNavPath = function(manifestNode){ + // Find item with property 'nav' + // Should catch nav irregardless of order + // var node = manifestNode.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']"); + var node = core.qsp(manifestNode, "item", {"properties":"nav"}); + return node ? node.getAttribute('href') : false; + }; + + //-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx" + Parser.prototype.findNcxPath = function(manifestNode, spineNode){ + // var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); + var node = core.qsp(manifestNode, "item", {"media-type":"application/x-dtbncx+xml"}); + var tocId; + + // If we can't find the toc by media-type then try to look for id of the item in the spine attributes as + // according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2, + // "The item that describes the NCX must be referenced by the spine toc attribute." + if (!node) { + tocId = spineNode.getAttribute("toc"); + if(tocId) { + // node = manifestNode.querySelector("item[id='" + tocId + "']"); + node = manifestNode.getElementById(tocId); } } - - // if(index > 0) { - item.prev = function(){ return this.get(index-1); }.bind(this); - // } - - // if(index+1 < this.items.length) { - item.next = function(){ return this.get(index+1); }.bind(this); - // } - - spineItem = new Section(item, this.hooks); - - this.append(spineItem); - - - }.bind(this)); - - this.loaded = true; -}; - -// book.spine.get(); -// book.spine.get(1); -// book.spine.get("chap1.html"); -// book.spine.get("#id1234"); -Spine.prototype.get = function(target) { - var index = 0; - - if(this.epubcfi.isCfiString(target)) { - cfi = new EpubCFI(target); - index = cfi.spinePos; - } else if(target && (typeof target === "number" || isNaN(target) === false)){ - index = target; - } else if(target && target.indexOf("#") === 0) { - index = this.spineById[target.substring(1)]; - } else if(target) { - // Remove fragments - target = target.split("#")[0]; - index = this.spineByHref[target]; - } - - return this.spineItems[index] || null; -}; - -Spine.prototype.append = function(section) { - var index = this.spineItems.length; - section.index = index; - - this.spineItems.push(section); - - this.spineByHref[section.href] = index; - this.spineById[section.idref] = index; - - return index; -}; - -Spine.prototype.prepend = function(section) { - var index = this.spineItems.unshift(section); - this.spineByHref[section.href] = 0; - this.spineById[section.idref] = 0; - - // Re-index - this.spineItems.forEach(function(item, index){ - item.index = index; - }); - - return 0; -}; - -Spine.prototype.insert = function(section, index) { - -}; - -Spine.prototype.remove = function(section) { - var index = this.spineItems.indexOf(section); - - if(index > -1) { - delete this.spineByHref[section.href]; - delete this.spineById[section.idref]; - - return this.spineItems.splice(index, 1); - } -}; - -Spine.prototype.each = function() { - return this.spineItems.forEach.apply(this.spineItems, arguments); -}; - -module.exports = Spine; - -},{"./core":10,"./epubcfi":11,"./hook":12,"./replacements":25,"./section":27,"rsvp":5}],29:[function(require,module,exports){ -var RSVP = require('rsvp'); -var URI = require('urijs'); -var core = require('./core'); -var request = require('./request'); -var mime = require('../libs/mime/mime'); - -function Unarchive() { - - this.checkRequirements(); - this.urlCache = {}; - -} - -Unarchive.prototype.checkRequirements = function(callback){ - try { - if (typeof JSZip !== 'undefined') { - this.zip = new JSZip(); + + return node ? node.getAttribute('href') : false; + }; + + //-- Expanded to match Readium web components + Parser.prototype.metadata = function(xml){ + var metadata = {}, + p = this; + + metadata.title = p.getElementText(xml, 'title'); + metadata.creator = p.getElementText(xml, 'creator'); + metadata.description = p.getElementText(xml, 'description'); + + metadata.pubdate = p.getElementText(xml, 'date'); + + metadata.publisher = p.getElementText(xml, 'publisher'); + + metadata.identifier = p.getElementText(xml, "identifier"); + metadata.language = p.getElementText(xml, "language"); + metadata.rights = p.getElementText(xml, "rights"); + + metadata.modified_date = p.getPropertyText(xml, 'dcterms:modified'); + + metadata.layout = p.getPropertyText(xml, "rendition:layout"); + metadata.orientation = p.getPropertyText(xml, 'rendition:orientation'); + metadata.flow = p.getPropertyText(xml, 'rendition:flow'); + metadata.viewport = p.getPropertyText(xml, 'rendition:viewport'); + // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction"); + + return metadata; + }; + + //-- Find Cover: + //-- Fallback for Epub 2.0 + Parser.prototype.findCoverPath = function(packageXml){ + var pkg = core.qs(packageXml, "package"); + var epubVersion = pkg.getAttribute('version'); + + if (epubVersion === '2.0') { + var metaCover = core.qsp(packageXml, 'meta', {'name':'cover'}); + if (metaCover) { + var coverId = metaCover.getAttribute('content'); + // var cover = packageXml.querySelector("item[id='" + coverId + "']"); + var cover = packageXml.getElementById(coverId); + return cover ? cover.getAttribute('href') : false; + } + else { + return false; + } + } + else { + // var node = packageXml.querySelector("item[properties='cover-image']"); + var node = core.qsp(packageXml, 'item', {'properties':'cover-image'}); + return node ? node.getAttribute('href') : false; + } + }; + + Parser.prototype.getElementText = function(xml, tag){ + var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag), + el; + + if(!found || found.length === 0) return ''; + + el = found[0]; + + if(el.childNodes.length){ + return el.childNodes[0].nodeValue; + } + + return ''; + + }; + + Parser.prototype.getPropertyText = function(xml, property){ + var el = core.qsp(xml, "meta", {"property":property}); + + if(el && el.childNodes.length){ + return el.childNodes[0].nodeValue; + } + + return ''; + }; + + Parser.prototype.querySelectorText = function(xml, q){ + var el = xml.querySelector(q); + + if(el && el.childNodes.length){ + return el.childNodes[0].nodeValue; + } + + return ''; + }; + + Parser.prototype.manifest = function(manifestXml){ + var manifest = {}; + + //-- Turn items into an array + // var selected = manifestXml.querySelectorAll("item"); + var selected = core.qsa(manifestXml, "item"); + var items = Array.prototype.slice.call(selected); + + //-- Create an object with the id as key + items.forEach(function(item){ + var id = item.getAttribute('id'), + href = item.getAttribute('href') || '', + type = item.getAttribute('media-type') || '', + properties = item.getAttribute('properties') || ''; + + manifest[id] = { + 'href' : href, + // 'url' : href, + 'type' : type, + 'properties' : properties.length ? properties.split(' ') : [] + }; + + }); + + return manifest; + + }; + + Parser.prototype.spine = function(spineXml, manifest){ + var spine = []; + + var selected = spineXml.getElementsByTagName("itemref"), + items = Array.prototype.slice.call(selected); + + var epubcfi = new EpubCFI(); + + //-- Add to array to mantain ordering and cross reference with manifest + items.forEach(function(item, index){ + var idref = item.getAttribute('idref'); + // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id); + var props = item.getAttribute('properties') || ''; + var propArray = props.length ? props.split(' ') : []; + // var manifestProps = manifest[Id].properties; + // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : []; + + var itemref = { + 'idref' : idref, + 'linear' : item.getAttribute('linear') || '', + 'properties' : propArray, + // 'href' : manifest[Id].href, + // 'url' : manifest[Id].url, + 'index' : index + // 'cfiBase' : cfiBase + }; + spine.push(itemref); + }); + + return spine; + }; + + Parser.prototype.querySelectorByType = function(html, element, type){ + var query; + if (typeof html.querySelector != "undefined") { + query = html.querySelector(element+'[*|type="'+type+'"]'); + } + // Handle IE not supporting namespaced epub:type in querySelector + if(!query || query.length === 0) { + query = core.qsa(html, element); + for (var i = 0; i < query.length; i++) { + if(query[i].getAttributeNS("http://www.idpf.org/2007/ops", "type") === type) { + return query[i]; + } + } } else { - JSZip = require('jszip'); - this.zip = new JSZip(); + return query; } - } catch (e) { - console.error("JSZip lib not loaded"); - } -}; + }; + + Parser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){ + var navElement = this.querySelectorByType(navHtml, "nav", "toc"); + // var navItems = navElement ? navElement.querySelectorAll("ol li") : []; + var navItems = navElement ? core.qsa(navElement, "li") : []; + var length = navItems.length; + var i; + var toc = {}; + var list = []; + var item, parent; + + if(!navItems || length === 0) return list; + + for (i = 0; i < length; ++i) { + item = this.navItem(navItems[i], spineIndexByURL, bookSpine); + toc[item.id] = item; + if(!item.parent) { + list.push(item); + } else { + parent = toc[item.parent]; + parent.subitems.push(item); + } + } + + return list; + }; + + Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){ + var id = item.getAttribute('id') || false, + // content = item.querySelector("a, span"), + content = core.qs(item, "a"), + src = content.getAttribute('href') || '', + text = content.textContent || "", + // split = src.split("#"), + // baseUrl = split[0], + // spinePos = spineIndexByURL[baseUrl], + // spineItem = bookSpine[spinePos], + subitems = [], + parentNode = item.parentNode, + parent; + // cfi = spineItem ? spineItem.cfi : ''; + + if(parentNode && parentNode.nodeName === "navPoint") { + parent = parentNode.getAttribute('id'); + } + + /* + if(!id) { + if(spinePos) { + spineItem = bookSpine[spinePos]; + id = spineItem.id; + cfi = spineItem.cfi; + } else { + id = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid(); + item.setAttribute('id', id); + } + } + */ + + return { + "id": id, + "href": src, + "label": text, + "subitems" : subitems, + "parent" : parent + }; + }; + + Parser.prototype.ncx = function(tocXml, spineIndexByURL, bookSpine){ + // var navPoints = tocXml.querySelectorAll("navMap navPoint"); + var navPoints = core.qsa(tocXml, "navPoint"); + var length = navPoints.length; + var i; + var toc = {}; + var list = []; + var item, parent; + + if(!navPoints || length === 0) return list; + + for (i = 0; i < length; ++i) { + item = this.ncxItem(navPoints[i], spineIndexByURL, bookSpine); + toc[item.id] = item; + if(!item.parent) { + list.push(item); + } else { + parent = toc[item.parent]; + parent.subitems.push(item); + } + } + + return list; + }; + + Parser.prototype.ncxItem = function(item, spineIndexByURL, bookSpine){ + var id = item.getAttribute('id') || false, + // content = item.querySelector("content"), + content = core.qs(item, "content"), + src = content.getAttribute('src'), + // navLabel = item.querySelector("navLabel"), + navLabel = core.qs(item, "navLabel"), + text = navLabel.textContent ? navLabel.textContent : "", + // split = src.split("#"), + // baseUrl = split[0], + // spinePos = spineIndexByURL[baseUrl], + // spineItem = bookSpine[spinePos], + subitems = [], + parentNode = item.parentNode, + parent; + // cfi = spineItem ? spineItem.cfi : ''; + + if(parentNode && parentNode.nodeName === "navPoint") { + parent = parentNode.getAttribute('id'); + } + + /* + if(!id) { + if(spinePos) { + spineItem = bookSpine[spinePos]; + id = spineItem.id; + cfi = spineItem.cfi; + } else { + id = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid(); + item.setAttribute('id', id); + } + } + */ + + return { + "id": id, + "href": src, + "label": text, + "subitems" : subitems, + "parent" : parent + }; + }; + + Parser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){ + var navElement = this.querySelectorByType(navHtml, "nav", "page-list"); + // var navItems = navElement ? navElement.querySelectorAll("ol li") : []; + var navItems = navElement ? core.qsa(navElement, "li") : []; + var length = navItems.length; + var i; + var toc = {}; + var list = []; + var item; + + if(!navItems || length === 0) return list; + + for (i = 0; i < length; ++i) { + item = this.pageListItem(navItems[i], spineIndexByURL, bookSpine); + list.push(item); + } + + return list; + }; + + Parser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){ + var id = item.getAttribute('id') || false, + // content = item.querySelector("a"), + content = core.qs(item, "a"), + href = content.getAttribute('href') || '', + text = content.textContent || "", + page = parseInt(text), + isCfi = href.indexOf("epubcfi"), + split, + packageUrl, + cfi; + + if(isCfi != -1) { + split = href.split("#"); + packageUrl = split[0]; + cfi = split.length > 1 ? split[1] : false; + return { + "cfi" : cfi, + "href" : href, + "packageUrl" : packageUrl, + "page" : page + }; + } else { + return { + "href" : href, + "page" : page + }; + } + }; + + module.exports = Parser; -Unarchive.prototype.open = function(zipUrl, isBase64){ - if (zipUrl instanceof ArrayBuffer || isBase64) { - return this.zip.loadAsync(zipUrl, {"base64": isBase64}); - } else { - return request(zipUrl, "binary") - .then(function(data){ - return this.zip.loadAsync(data); - }.bind(this)); - } -}; -Unarchive.prototype.request = function(url, type){ - var deferred = new RSVP.defer(); - var response; - var r; +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { - // If type isn't set, determine it from the file extension - if(!type) { - uri = URI(url); - type = uri.suffix(); - } + var core = __webpack_require__(11); + var Parser = __webpack_require__(22); + var RSVP = __webpack_require__(2); + var URI = __webpack_require__(6); + + function Navigation(_package, _request){ + var navigation = this; + var parse = new Parser(); + var request = _request || __webpack_require__(18); + + this.package = _package; + this.toc = []; + this.tocByHref = {}; + this.tocById = {}; + + if(_package.navPath) { + this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString(); + this.nav = {}; + + this.nav.load = function(_request){ + var loading = new RSVP.defer(); + var loaded = loading.promise; + + request(navigation.navUrl, 'xml').then(function(xml){ + navigation.toc = parse.nav(xml); + navigation.loaded(navigation.toc); + loading.resolve(navigation.toc); + }); + + return loaded; + }; + + } + + if(_package.ncxPath) { + this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString(); + this.ncx = {}; + + this.ncx.load = function(_request){ + var loading = new RSVP.defer(); + var loaded = loading.promise; + + request(navigation.ncxUrl, 'xml').then(function(xml){ + navigation.toc = parse.toc(xml); + navigation.loaded(navigation.toc); + loading.resolve(navigation.toc); + }); + + return loaded; + }; + + } + }; + + // Load the navigation + Navigation.prototype.load = function(_request) { + var request = _request || __webpack_require__(18); + var loading, loaded; + + if(this.nav) { + loading = this.nav.load(); + } else if(this.ncx) { + loading = this.ncx.load(); + } else { + loaded = new RSVP.defer(); + loaded.resolve([]); + loading = loaded.promise; + } + + return loading; + + }; + + Navigation.prototype.loaded = function(toc) { + var item; + + for (var i = 0; i < toc.length; i++) { + item = toc[i]; + this.tocByHref[item.href] = i; + this.tocById[item.id] = i; + } + + }; + + // Get an item from the navigation + Navigation.prototype.get = function(target) { + var index; + + if(!target) { + return this.toc; + } + + if(target.indexOf("#") === 0) { + index = this.tocById[target.substring(1)]; + } else if(target in this.tocByHref){ + index = this.tocByHref[target]; + } + + return this.toc[index]; + }; + + module.exports = Navigation; - if(type == 'blob'){ - response = this.getBlob(url); - } else { - response = this.getText(url); - } - if (response) { - response.then(function (r) { - result = this.handleResponse(r, type); - deferred.resolve(result); +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + var replace = __webpack_require__(19); + var Hook = __webpack_require__(16); + var EpubCFI = __webpack_require__(15); + var Queue = __webpack_require__(21); + var Layout = __webpack_require__(25); + var Mapping = __webpack_require__(26); + + function Rendition(book, options) { + + this.settings = core.extend(this.settings || {}, { + width: null, + height: null, + ignoreClass: '', + manager: "single", + view: "iframe", + flow: null, + layout: null, + spread: null, + minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always), + useBase64: true + }); + + core.extend(this.settings, options); + + this.viewSettings = { + ignoreClass: this.settings.ignoreClass + }; + + this.book = book; + + this.views = null; + + //-- Adds Hook methods to the Rendition prototype + this.hooks = {}; + this.hooks.display = new Hook(this); + this.hooks.serialize = new Hook(this); + this.hooks.content = new Hook(this); + this.hooks.layout = new Hook(this); + this.hooks.render = new Hook(this); + this.hooks.show = new Hook(this); + + this.hooks.content.register(replace.links.bind(this)); + this.hooks.content.register(this.passViewEvents.bind(this)); + + // this.hooks.display.register(this.afterDisplay.bind(this)); + + this.epubcfi = new EpubCFI(); + + this.q = new Queue(this); + + this.q.enqueue(this.book.opened); + + // Block the queue until rendering is started + // this.starting = new RSVP.defer(); + // this.started = this.starting.promise; + this.q.enqueue(this.start); + + if(this.book.unarchived) { + this.q.enqueue(this.replacements.bind(this)); + } + + }; + + Rendition.prototype.setManager = function(manager) { + this.manager = manager; + }; + + Rendition.prototype.requireManager = function(manager) { + var viewManager; + + // If manager is a string, try to load from register managers, + // or require included managers directly + if (typeof manager === "string") { + // Use global or require + viewManager = typeof ePub != "undefined" ? ePub.ViewManagers[manager] : undefined; //require('./managers/'+manager); + } else { + // otherwise, assume we were passed a function + viewManager = manager + } + + return viewManager; + }; + + Rendition.prototype.requireView = function(view) { + var View; + + if (typeof view == "string") { + View = typeof ePub != "undefined" ? ePub.Views[view] : undefined; //require('./views/'+view); + } else { + // otherwise, assume we were passed a function + View = view + } + + return View; + }; + + Rendition.prototype.start = function(){ + + if(!this.manager) { + this.ViewManager = this.requireManager(this.settings.manager); + this.View = this.requireView(this.settings.view); + + this.manager = new this.ViewManager({ + view: this.View, + queue: this.q, + request: this.book.request, + settings: this.settings + }); + } + + // Parse metadata to get layout props + this.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata); + + this.flow(this.settings.globalLayoutProperties.flow); + + this.layout(this.settings.globalLayoutProperties); + + // Listen for displayed views + this.manager.on("added", this.afterDisplayed.bind(this)); + + // Listen for resizing + this.manager.on("resized", this.onResized.bind(this)); + + // Listen for scroll changes + this.manager.on("scroll", this.reportLocation.bind(this)); + + + this.on('displayed', this.reportLocation.bind(this)); + + // Trigger that rendering has started + this.trigger("started"); + + // Start processing queue + // this.starting.resolve(); + }; + + // Call to attach the container to an element in the dom + // Container must be attached before rendering can begin + Rendition.prototype.attachTo = function(element){ + + return this.q.enqueue(function () { + + // Start rendering + this.manager.render(element, { + "width" : this.settings.width, + "height" : this.settings.height + }); + + // Trigger Attached + this.trigger("attached"); + }.bind(this)); - } else { - deferred.reject({ - message : "File not found in the epub: " + url, - stack : new Error().stack + + }; + + Rendition.prototype.display = function(target){ + + // if (!this.book.spine.spineItems.length > 0) { + // Book isn't open yet + // return this.q.enqueue(this.display, target); + // } + + return this.q.enqueue(this._display, target); + + }; + + Rendition.prototype._display = function(target){ + var isCfiString = this.epubcfi.isCfiString(target); + var displaying = new RSVP.defer(); + var displayed = displaying.promise; + var section; + var moveTo; + + section = this.book.spine.get(target); + + if(!section){ + displaying.reject(new Error("No Section Found")); + return displayed; + } + + // Trim the target fragment + // removing the chapter + if(!isCfiString && typeof target === "string" && + target.indexOf("#") > -1) { + moveTo = target.substring(target.indexOf("#")+1); + } + + if (isCfiString) { + moveTo = target; + } + + return this.manager.display(section, moveTo) + .then(function(){ + this.trigger("displayed", section); + }.bind(this)); + + }; + + /* + Rendition.prototype.render = function(view, show) { + + // view.onLayout = this.layout.format.bind(this.layout); + view.create(); + + // Fit to size of the container, apply padding + this.manager.resizeView(view); + + // Render Chain + return view.section.render(this.book.request) + .then(function(contents){ + return view.load(contents); + }.bind(this)) + .then(function(doc){ + return this.hooks.content.trigger(view, this); + }.bind(this)) + .then(function(){ + this.layout.format(view.contents); + return this.hooks.layout.trigger(view, this); + }.bind(this)) + .then(function(){ + return view.display(); + }.bind(this)) + .then(function(){ + return this.hooks.render.trigger(view, this); + }.bind(this)) + .then(function(){ + if(show !== false) { + this.q.enqueue(function(view){ + view.show(); + }, view); + } + // this.map = new Map(view, this.layout); + this.hooks.show.trigger(view, this); + this.trigger("rendered", view.section); + + }.bind(this)) + .catch(function(e){ + this.trigger("loaderror", e); + }.bind(this)); + + }; + */ + + Rendition.prototype.afterDisplayed = function(view){ + this.hooks.content.trigger(view, this); + this.trigger("rendered", view.section); + this.reportLocation(); + }; + + Rendition.prototype.onResized = function(size){ + + if(this.location) { + this.display(this.location.start); + } + + this.trigger("resized", { + width: size.width, + height: size.height }); - } - return deferred.promise; -}; - -Unarchive.prototype.handleResponse = function(response, type){ - var r; - - if(type == "json") { - r = JSON.parse(response); - } - else - if(core.isXml(type)) { - r = core.parse(response, "text/xml"); - } - else - if(type == 'xhtml') { - r = core.parse(response, "application/xhtml+xml"); - } - else - if(type == 'html' || type == 'htm') { - r = core.parse(response, "text/html"); - } else { - r = response; - } - - return r; -}; - -Unarchive.prototype.getBlob = function(url, _mimeType){ - var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash - var entry = this.zip.file(decodededUrl); - var mimeType; - - if(entry) { - mimeType = _mimeType || mime.lookup(entry.name); - return entry.async("uint8array").then(function(uint8array) { - return new Blob([uint8array], {type : mimeType}); + + }; + + Rendition.prototype.moveTo = function(offset){ + this.manager.moveTo(offset); + }; + + Rendition.prototype.next = function(){ + return this.q.enqueue(this.manager.next.bind(this.manager)) + .then(this.reportLocation.bind(this)); + }; + + Rendition.prototype.prev = function(){ + return this.q.enqueue(this.manager.prev.bind(this.manager)) + .then(this.reportLocation.bind(this)); + }; + + //-- http://www.idpf.org/epub/301/spec/epub-publications.html#meta-properties-rendering + Rendition.prototype.determineLayoutProperties = function(metadata){ + var settings; + var layout = this.settings.layout || metadata.layout || "reflowable"; + var spread = this.settings.spread || metadata.spread || "auto"; + var orientation = this.settings.orientation || metadata.orientation || "auto"; + var flow = this.settings.flow || metadata.flow || "auto"; + var viewport = metadata.viewport || ""; + var minSpreadWidth = this.settings.minSpreadWidth || metadata.minSpreadWidth || 800; + + if (this.settings.width >= 0 && this.settings.height >= 0) { + viewport = "width="+this.settings.width+", height="+this.settings.height+""; + } + + settings = { + layout : layout, + spread : spread, + orientation : orientation, + flow : flow, + viewport : viewport, + minSpreadWidth : minSpreadWidth + }; + + return settings; + }; + + // Rendition.prototype.applyLayoutProperties = function(){ + // var settings = this.determineLayoutProperties(this.book.package.metadata); + // + // this.flow(settings.flow); + // + // this.layout(settings); + // }; + + // paginated | scrolled + // (scrolled-continuous vs scrolled-doc are handled by different view managers) + Rendition.prototype.flow = function(_flow){ + var flow; + if (_flow === "scrolled-doc" || _flow === "scrolled-continuous") { + flow = "scrolled"; + } + + if (_flow === "auto" || _flow === "paginated") { + flow = "paginated"; + } + + if (this._layout) { + this._layout.flow(flow); + } + + if (this.manager) { + this.manager.updateFlow(flow); + } + }; + + // reflowable | pre-paginated + Rendition.prototype.layout = function(settings){ + if (settings) { + this._layout = new Layout(settings); + this._layout.spread(settings.spread, this.settings.minSpreadWidth); + + this.mapping = new Mapping(this._layout); + } + + if (this.manager && this._layout) { + this.manager.applyLayout(this._layout); + } + + return this._layout; + }; + + // none | auto (TODO: implement landscape, portrait, both) + Rendition.prototype.spread = function(spread, min){ + + this._layout.spread(spread, min); + + if (this.manager.isRendered()) { + this.manager.updateLayout(); + } + }; + + + Rendition.prototype.reportLocation = function(){ + return this.q.enqueue(function(){ + var location = this.manager.currentLocation(); + if (location && location.then && typeof location.then === 'function') { + location.then(function(result) { + this.location = result; + this.trigger("locationChanged", this.location); + }.bind(this)); + } else if (location) { + this.location = location; + this.trigger("locationChanged", this.location); + } + + }.bind(this)); + }; + + + Rendition.prototype.destroy = function(){ + // Clear the queue + this.q.clear(); + + this.manager.destroy(); + }; + + Rendition.prototype.passViewEvents = function(view){ + view.contents.listenedEvents.forEach(function(e){ + view.on(e, this.triggerViewEvent.bind(this)); + }.bind(this)); + + view.on("selected", this.triggerSelectedEvent.bind(this)); + }; + + Rendition.prototype.triggerViewEvent = function(e){ + this.trigger(e.type, e); + }; + + Rendition.prototype.triggerSelectedEvent = function(cfirange){ + this.trigger("selected", cfirange); + }; + + Rendition.prototype.replacements = function(){ + // Wait for loading + // return this.q.enqueue(function () { + // Get thes books manifest + var manifest = this.book.package.manifest; + var manifestArray = Object.keys(manifest). + map(function (key){ + return manifest[key]; + }); + + // Exclude HTML + var items = manifestArray. + filter(function (item){ + if (item.type != "application/xhtml+xml" && + item.type != "text/html") { + return true; + } + }); + + // Only CSS + var css = items. + filter(function (item){ + if (item.type === "text/css") { + return true; + } + }); + + // Css Urls + var cssUrls = css.map(function(item) { + return item.href; + }); + + // All Assets Urls + var urls = items. + map(function(item) { + return item.href; + }.bind(this)); + + // Create blob urls for all the assets + var processing = urls. + map(function(url) { + var absolute = URI(url).absoluteTo(this.book.baseUrl).toString(); + // Full url from archive base + return this.book.unarchived.createUrl(absolute, {"base64": this.settings.useBase64}); + }.bind(this)); + + var replacementUrls; + + // After all the urls are created + return RSVP.all(processing) + .then(function(_replacementUrls) { + var replaced = []; + + replacementUrls = _replacementUrls; + + // Replace Asset Urls in the text of all css files + cssUrls.forEach(function(href) { + replaced.push(this.replaceCss(href, urls, replacementUrls)); + }.bind(this)); + + return RSVP.all(replaced); + + }.bind(this)) + .then(function () { + // Replace Asset Urls in chapters + // by registering a hook after the sections contents has been serialized + this.book.spine.hooks.serialize.register(function(output, section) { + + this.replaceAssets(section, urls, replacementUrls); + + }.bind(this)); + + }.bind(this)) + .catch(function(reason){ + console.error(reason); + }); + // }.bind(this)); + }; + + Rendition.prototype.replaceCss = function(href, urls, replacementUrls){ + var newUrl; + var indexInUrls; + + // Find the absolute url of the css file + var fileUri = URI(href); + var absolute = fileUri.absoluteTo(this.book.baseUrl).toString(); + // Get the text of the css file from the archive + var textResponse = this.book.unarchived.getText(absolute); + // Get asset links relative to css file + var relUrls = urls. + map(function(assetHref) { + var assetUri = URI(assetHref).absoluteTo(this.book.baseUrl); + var relative = assetUri.relativeTo(absolute).toString(); + return relative; + }.bind(this)); + + return textResponse.then(function (text) { + // Replacements in the css text + text = replace.substitute(text, relUrls, replacementUrls); + + // Get the new url + if (this.settings.useBase64) { + newUrl = core.createBase64Url(text, 'text/css'); + } else { + newUrl = core.createBlobUrl(text, 'text/css'); + } + + // switch the url in the replacementUrls + indexInUrls = urls.indexOf(href); + if (indexInUrls > -1) { + replacementUrls[indexInUrls] = newUrl; + } + + return new RSVP.Promise(function(resolve, reject){ + resolve(urls, replacementUrls); + }); + + }.bind(this)); + + }; + + Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){ + var fileUri = URI(section.url); + // Get Urls relative to current sections + var relUrls = urls. + map(function(href) { + var assetUri = URI(href).absoluteTo(this.book.baseUrl); + var relative = assetUri.relativeTo(fileUri).toString(); + return relative; + }.bind(this)); + + + section.output = replace.substitute(section.output, relUrls, replacementUrls); + }; + + Rendition.prototype.range = function(_cfi, ignoreClass){ + var cfi = new EpubCFI(_cfi); + var found = this.visible().filter(function (view) { + if(cfi.spinePos === view.index) return true; }); - } -}; - -Unarchive.prototype.getText = function(url, encoding){ - var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash - var entry = this.zip.file(decodededUrl); - - if(entry) { - return entry.async("string").then(function(text) { - return text; + + // Should only every return 1 item + if (found.length) { + return found[0].range(cfi, ignoreClass); + } + }; + + Rendition.prototype.adjustImages = function(view) { + + view.addStylesheetRules([ + ["img", + ["max-width", (view.layout.spreadWidth) + "px"], + ["max-height", (view.layout.height) + "px"] + ] + ]); + return new RSVP.Promise(function(resolve, reject){ + // Wait to apply + setTimeout(function() { + resolve(); + }, 1); }); + }; + + //-- Enable binding events to Renderer + RSVP.EventTarget.mixin(Rendition.prototype); + + module.exports = Rendition; + + +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { + + var core = __webpack_require__(11); + var RSVP = __webpack_require__(2); + + function Layout(settings){ + this.name = settings.layout || "reflowable"; + this._spread = (settings.spread === "none") ? false : true; + this._minSpreadWidth = settings.spread || 800; + this._evenSpreads = settings.evenSpreads || false; + + if (settings.flow === "scrolled-continuous" || + settings.flow === "scrolled-doc") { + this._flow = "scrolled"; + } else { + this._flow = "paginated"; + } + + + this.width = 0; + this.height = 0; + this.spreadWidth = 0; + this.delta = 0; + + this.columnWidth = 0; + this.gap = 0; + this.divisor = 1; + }; + + // paginated | scrolled + Layout.prototype.flow = function(flow) { + this._flow = (flow === "paginated") ? "paginated" : "scrolled"; } -}; + + // true | false + Layout.prototype.spread = function(spread, min) { + + this._spread = (spread === "none") ? false : true; + + if (min >= 0) { + this._minSpreadWidth = min; + } + } + + Layout.prototype.calculate = function(_width, _height, _gap){ + + var divisor = 1; + var gap = _gap || 0; + + //-- Check the width and create even width columns + var fullWidth = Math.floor(_width); + var width = _width; + + var section = Math.floor(width / 8); + + var colWidth; + var spreadWidth; + var delta; + + if (this._spread && width >= this._minSpreadWidth) { + divisor = 2; + } else { + divisor = 1; + } + + if (this.name === "reflowable" && this._flow === "paginated" && !(_gap >= 0)) { + gap = ((section % 2 === 0) ? section : section - 1); + } + + if (this.name === "pre-paginated" ) { + gap = 0; + } + + //-- Double Page + if(divisor > 1) { + colWidth = Math.floor((width - gap) / divisor); + } else { + colWidth = width; + } + + if (this.name === "pre-paginated" && divisor > 1) { + width = colWidth; + } + + spreadWidth = colWidth * divisor; + + delta = (colWidth + gap) * divisor; + + this.width = width; + this.height = _height; + this.spreadWidth = spreadWidth; + this.delta = delta; + + this.columnWidth = colWidth; + this.gap = gap; + this.divisor = divisor; + }; + + Layout.prototype.format = function(contents){ + var formating; + + if (this.name === "pre-paginated") { + formating = contents.fit(this.columnWidth, this.height); + } else if (this._flow === "paginated") { + formating = contents.columns(this.width, this.height, this.columnWidth, this.gap); + } else { // scrolled + formating = contents.size(this.width, null); + } + + return formating; // might be a promise in some View Managers + }; + + Layout.prototype.count = function(totalWidth) { + // var totalWidth = contents.scrollWidth(); + var spreads = Math.ceil( totalWidth / this.spreadWidth); + + return { + spreads : spreads, + pages : spreads * this.divisor + }; + }; + + module.exports = Layout; -Unarchive.prototype.getBase64 = function(url, _mimeType){ - var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash - var entry = this.zip.file(decodededUrl); - var mimeType; - if(entry) { - mimeType = _mimeType || mime.lookup(entry.name); - return entry.async("base64").then(function(data) { - return "data:" + mimeType + ";base64," + data; +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { + + var EpubCFI = __webpack_require__(15); + + function Mapping(layout){ + this.layout = layout; + }; + + Mapping.prototype.section = function(view) { + var ranges = this.findRanges(view); + var map = this.rangeListToCfiList(view.section.cfiBase, ranges); + + return map; + }; + + Mapping.prototype.page = function(contents, cfiBase, start, end) { + var root = contents && contents.document ? contents.document.body : false; + + if (!root) { + return; + } + + return this.rangePairToCfiPair(cfiBase, { + start: this.findStart(root, start, end), + end: this.findEnd(root, start, end) }); + }; + + Mapping.prototype.walk = function(root, func) { + //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false); + var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { + acceptNode: function (node) { + if ( node.data.trim().length > 0 ) { + return NodeFilter.FILTER_ACCEPT; + } else { + return NodeFilter.FILTER_REJECT; + } + } + }, false); + var node; + var result; + while ((node = treeWalker.nextNode())) { + result = func(node); + if(result) break; + } + + return result; + }; + + Mapping.prototype.findRanges = function(view){ + var columns = []; + var scrollWidth = view.contents.scrollWidth(); + var count = this.layout.count(scrollWidth); + var column = this.layout.column; + var gap = this.layout.gap; + var start, end; + + for (var i = 0; i < count.pages; i++) { + start = (column + gap) * i; + end = (column * (i+1)) + (gap * i); + columns.push({ + start: this.findStart(view.document.body, start, end), + end: this.findEnd(view.document.body, start, end) + }); + } + + return columns; + }; + + Mapping.prototype.findStart = function(root, start, end){ + var stack = [root]; + var $el; + var found; + var $prev = root; + while (stack.length) { + + $el = stack.shift(); + + found = this.walk($el, function(node){ + var left, right; + var elPos; + var elRange; + + + if(node.nodeType == Node.TEXT_NODE){ + elRange = document.createRange(); + elRange.selectNodeContents(node); + elPos = elRange.getBoundingClientRect(); + } else { + elPos = node.getBoundingClientRect(); + } + + left = elPos.left; + right = elPos.right; + + if( left >= start && left <= end ) { + return node; + } else if (right > start) { + return node; + } else { + $prev = node; + stack.push(node); + } + + }); + + if(found) { + return this.findTextStartRange(found, start, end); + } + + } + + // Return last element + return this.findTextStartRange($prev, start, end); + }; + + Mapping.prototype.findEnd = function(root, start, end){ + var stack = [root]; + var $el; + var $prev = root; + var found; + + while (stack.length) { + + $el = stack.shift(); + + found = this.walk($el, function(node){ + + var left, right; + var elPos; + var elRange; + + + if(node.nodeType == Node.TEXT_NODE){ + elRange = document.createRange(); + elRange.selectNodeContents(node); + elPos = elRange.getBoundingClientRect(); + } else { + elPos = node.getBoundingClientRect(); + } + + left = elPos.left; + right = elPos.right; + + if(left > end && $prev) { + return $prev; + } else if(right > end) { + return node; + } else { + $prev = node; + stack.push(node); + } + + }); + + + if(found){ + return this.findTextEndRange(found, start, end); + } + + } + + // end of chapter + return this.findTextEndRange($prev, start, end); + }; + + + Mapping.prototype.findTextStartRange = function(node, start, end){ + var ranges = this.splitTextNodeIntoRanges(node); + var prev; + var range; + var pos; + + for (var i = 0; i < ranges.length; i++) { + range = ranges[i]; + + pos = range.getBoundingClientRect(); + + if( pos.left >= start ) { + return range; + } + + prev = range; + + } + + return ranges[0]; + }; + + Mapping.prototype.findTextEndRange = function(node, start, end){ + var ranges = this.splitTextNodeIntoRanges(node); + var prev; + var range; + var pos; + + for (var i = 0; i < ranges.length; i++) { + range = ranges[i]; + + pos = range.getBoundingClientRect(); + + if(pos.left > end && prev) { + return prev; + } else if(pos.right > end) { + return range; + } + + prev = range; + + } + + // Ends before limit + return ranges[ranges.length-1]; + + }; + + Mapping.prototype.splitTextNodeIntoRanges = function(node, _splitter){ + var ranges = []; + var textContent = node.textContent || ""; + var text = textContent.trim(); + var range; + var rect; + var list; + var doc = node.ownerDocument; + var splitter = _splitter || " "; + + pos = text.indexOf(splitter); + + if(pos === -1 || node.nodeType != Node.TEXT_NODE) { + range = doc.createRange(); + range.selectNodeContents(node); + return [range]; + } + + range = doc.createRange(); + range.setStart(node, 0); + range.setEnd(node, pos); + ranges.push(range); + range = false; + + while ( pos != -1 ) { + + pos = text.indexOf(splitter, pos + 1); + if(pos > 0) { + + if(range) { + range.setEnd(node, pos); + ranges.push(range); + } + + range = doc.createRange(); + range.setStart(node, pos+1); + } + } + + if(range) { + range.setEnd(node, text.length); + ranges.push(range); + } + + return ranges; + }; + + + + Mapping.prototype.rangePairToCfiPair = function(cfiBase, rangePair){ + + var startRange = rangePair.start; + var endRange = rangePair.end; + + startRange.collapse(true); + endRange.collapse(true); + + // startCfi = section.cfiFromRange(startRange); + // endCfi = section.cfiFromRange(endRange); + startCfi = new EpubCFI(startRange, cfiBase).toString(); + endCfi = new EpubCFI(endRange, cfiBase).toString(); + + return { + start: startCfi, + end: endCfi + }; + + }; + + Mapping.prototype.rangeListToCfiList = function(cfiBase, columns){ + var map = []; + var rangePair, cifPair; + + for (var i = 0; i < columns.length; i++) { + cifPair = this.rangePairToCfiPair(cfiBase, columns[i]); + + map.push(cifPair); + + } + + return map; + }; + + module.exports = Mapping; + + +/***/ }, +/* 27 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var URI = __webpack_require__(6); + var core = __webpack_require__(11); + var request = __webpack_require__(18); + var mime = __webpack_require__(28); + + function Unarchive() { + + this.checkRequirements(); + this.urlCache = {}; + } -}; - -Unarchive.prototype.createUrl = function(url, options){ - var deferred = new RSVP.defer(); - var _URL = window.URL || window.webkitURL || window.mozURL; - var tempUrl; - var blob; - var response; - var useBase64 = options && options.base64; - - if(url in this.urlCache) { - deferred.resolve(this.urlCache[url]); + + Unarchive.prototype.checkRequirements = function(callback){ + try { + if (typeof JSZip !== 'undefined') { + this.zip = new JSZip(); + } else { + JSZip = __webpack_require__(29); + this.zip = new JSZip(); + } + } catch (e) { + console.error("JSZip lib not loaded"); + } + }; + + Unarchive.prototype.open = function(zipUrl, isBase64){ + if (zipUrl instanceof ArrayBuffer || isBase64) { + return this.zip.loadAsync(zipUrl, {"base64": isBase64}); + } else { + return request(zipUrl, "binary") + .then(function(data){ + return this.zip.loadAsync(data); + }.bind(this)); + } + }; + + Unarchive.prototype.request = function(url, type){ + var deferred = new RSVP.defer(); + var response; + var r; + + // If type isn't set, determine it from the file extension + if(!type) { + uri = URI(url); + type = uri.suffix(); + } + + if(type == 'blob'){ + response = this.getBlob(url); + } else { + response = this.getText(url); + } + + if (response) { + response.then(function (r) { + result = this.handleResponse(r, type); + deferred.resolve(result); + }.bind(this)); + } else { + deferred.reject({ + message : "File not found in the epub: " + url, + stack : new Error().stack + }); + } return deferred.promise; - } - - if (useBase64) { - response = this.getBase64(url); - - if (response) { - response.then(function(tempUrl) { - - this.urlCache[url] = tempUrl; - deferred.resolve(tempUrl); - - }.bind(this)); - + }; + + Unarchive.prototype.handleResponse = function(response, type){ + var r; + + if(type == "json") { + r = JSON.parse(response); } - - } else { - - response = this.getBlob(url); - - if (response) { - response.then(function(blob) { - - tempUrl = _URL.createObjectURL(blob); - this.urlCache[url] = tempUrl; - deferred.resolve(tempUrl); - - }.bind(this)); - + else + if(core.isXml(type)) { + r = core.parse(response, "text/xml"); } + else + if(type == 'xhtml') { + r = core.parse(response, "application/xhtml+xml"); + } + else + if(type == 'html' || type == 'htm') { + r = core.parse(response, "text/html"); + } else { + r = response; + } + + return r; + }; + + Unarchive.prototype.getBlob = function(url, _mimeType){ + var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash + var entry = this.zip.file(decodededUrl); + var mimeType; + + if(entry) { + mimeType = _mimeType || mime.lookup(entry.name); + return entry.async("uint8array").then(function(uint8array) { + return new Blob([uint8array], {type : mimeType}); + }); + } + }; + + Unarchive.prototype.getText = function(url, encoding){ + var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash + var entry = this.zip.file(decodededUrl); + + if(entry) { + return entry.async("string").then(function(text) { + return text; + }); + } + }; + + Unarchive.prototype.getBase64 = function(url, _mimeType){ + var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash + var entry = this.zip.file(decodededUrl); + var mimeType; + + if(entry) { + mimeType = _mimeType || mime.lookup(entry.name); + return entry.async("base64").then(function(data) { + return "data:" + mimeType + ";base64," + data; + }); + } + }; + + Unarchive.prototype.createUrl = function(url, options){ + var deferred = new RSVP.defer(); + var _URL = window.URL || window.webkitURL || window.mozURL; + var tempUrl; + var blob; + var response; + var useBase64 = options && options.base64; + + if(url in this.urlCache) { + deferred.resolve(this.urlCache[url]); + return deferred.promise; + } + + if (useBase64) { + response = this.getBase64(url); + + if (response) { + response.then(function(tempUrl) { + + this.urlCache[url] = tempUrl; + deferred.resolve(tempUrl); + + }.bind(this)); + + } + + } else { + + response = this.getBlob(url); + + if (response) { + response.then(function(blob) { + + tempUrl = _URL.createObjectURL(blob); + this.urlCache[url] = tempUrl; + deferred.resolve(tempUrl); + + }.bind(this)); + + } + } + + + if (!response) { + deferred.reject({ + message : "File not found in the epub: " + url, + stack : new Error().stack + }); + } + + return deferred.promise; + }; + + Unarchive.prototype.revokeUrl = function(url){ + var _URL = window.URL || window.webkitURL || window.mozURL; + var fromCache = this.urlCache[url]; + if(fromCache) _URL.revokeObjectURL(fromCache); + }; + + module.exports = Unarchive; + + +/***/ }, +/* 28 */ +/***/ function(module, exports) { + + /* + From Zip.js, by Gildas Lormeau + edited down + */ + + var table = { + "application" : { + "ecmascript" : [ "es", "ecma" ], + "javascript" : "js", + "ogg" : "ogx", + "pdf" : "pdf", + "postscript" : [ "ps", "ai", "eps", "epsi", "epsf", "eps2", "eps3" ], + "rdf+xml" : "rdf", + "smil" : [ "smi", "smil" ], + "xhtml+xml" : [ "xhtml", "xht" ], + "xml" : [ "xml", "xsl", "xsd", "opf", "ncx" ], + "zip" : "zip", + "x-httpd-eruby" : "rhtml", + "x-latex" : "latex", + "x-maker" : [ "frm", "maker", "frame", "fm", "fb", "book", "fbdoc" ], + "x-object" : "o", + "x-shockwave-flash" : [ "swf", "swfl" ], + "x-silverlight" : "scr", + "epub+zip" : "epub", + "font-tdpfr" : "pfr", + "inkml+xml" : [ "ink", "inkml" ], + "json" : "json", + "jsonml+json" : "jsonml", + "mathml+xml" : "mathml", + "metalink+xml" : "metalink", + "mp4" : "mp4s", + // "oebps-package+xml" : "opf", + "omdoc+xml" : "omdoc", + "oxps" : "oxps", + "vnd.amazon.ebook" : "azw", + "widget" : "wgt", + // "x-dtbncx+xml" : "ncx", + "x-dtbook+xml" : "dtb", + "x-dtbresource+xml" : "res", + "x-font-bdf" : "bdf", + "x-font-ghostscript" : "gsf", + "x-font-linux-psf" : "psf", + "x-font-otf" : "otf", + "x-font-pcf" : "pcf", + "x-font-snf" : "snf", + "x-font-ttf" : [ "ttf", "ttc" ], + "x-font-type1" : [ "pfa", "pfb", "pfm", "afm" ], + "x-font-woff" : "woff", + "x-mobipocket-ebook" : [ "prc", "mobi" ], + "x-mspublisher" : "pub", + "x-nzb" : "nzb", + "x-tgif" : "obj", + "xaml+xml" : "xaml", + "xml-dtd" : "dtd", + "xproc+xml" : "xpl", + "xslt+xml" : "xslt", + "internet-property-stream" : "acx", + "x-compress" : "z", + "x-compressed" : "tgz", + "x-gzip" : "gz", + }, + "audio" : { + "flac" : "flac", + "midi" : [ "mid", "midi", "kar", "rmi" ], + "mpeg" : [ "mpga", "mpega", "mp2", "mp3", "m4a", "mp2a", "m2a", "m3a" ], + "mpegurl" : "m3u", + "ogg" : [ "oga", "ogg", "spx" ], + "x-aiff" : [ "aif", "aiff", "aifc" ], + "x-ms-wma" : "wma", + "x-wav" : "wav", + "adpcm" : "adp", + "mp4" : "mp4a", + "webm" : "weba", + "x-aac" : "aac", + "x-caf" : "caf", + "x-matroska" : "mka", + "x-pn-realaudio-plugin" : "rmp", + "xm" : "xm", + "mid" : [ "mid", "rmi" ] + }, + "image" : { + "gif" : "gif", + "ief" : "ief", + "jpeg" : [ "jpeg", "jpg", "jpe" ], + "pcx" : "pcx", + "png" : "png", + "svg+xml" : [ "svg", "svgz" ], + "tiff" : [ "tiff", "tif" ], + "x-icon" : "ico", + "bmp" : "bmp", + "webp" : "webp", + "x-pict" : [ "pic", "pct" ], + "x-tga" : "tga", + "cis-cod" : "cod" + }, + "text" : { + "cache-manifest" : [ "manifest", "appcache" ], + "css" : "css", + "csv" : "csv", + "html" : [ "html", "htm", "shtml", "stm" ], + "mathml" : "mml", + "plain" : [ "txt", "text", "brf", "conf", "def", "list", "log", "in", "bas" ], + "richtext" : "rtx", + "tab-separated-values" : "tsv", + "x-bibtex" : "bib" + }, + "video" : { + "mpeg" : [ "mpeg", "mpg", "mpe", "m1v", "m2v", "mp2", "mpa", "mpv2" ], + "mp4" : [ "mp4", "mp4v", "mpg4" ], + "quicktime" : [ "qt", "mov" ], + "ogg" : "ogv", + "vnd.mpegurl" : [ "mxu", "m4u" ], + "x-flv" : "flv", + "x-la-asf" : [ "lsf", "lsx" ], + "x-mng" : "mng", + "x-ms-asf" : [ "asf", "asx", "asr" ], + "x-ms-wm" : "wm", + "x-ms-wmv" : "wmv", + "x-ms-wmx" : "wmx", + "x-ms-wvx" : "wvx", + "x-msvideo" : "avi", + "x-sgi-movie" : "movie", + "x-matroska" : [ "mpv", "mkv", "mk3d", "mks" ], + "3gpp2" : "3g2", + "h261" : "h261", + "h263" : "h263", + "h264" : "h264", + "jpeg" : "jpgv", + "jpm" : [ "jpm", "jpgm" ], + "mj2" : [ "mj2", "mjp2" ], + "vnd.ms-playready.media.pyv" : "pyv", + "vnd.uvvu.mp4" : [ "uvu", "uvvu" ], + "vnd.vivo" : "viv", + "webm" : "webm", + "x-f4v" : "f4v", + "x-m4v" : "m4v", + "x-ms-vob" : "vob", + "x-smv" : "smv" + } + }; + + var mimeTypes = (function() { + var type, subtype, val, index, mimeTypes = {}; + for (type in table) { + if (table.hasOwnProperty(type)) { + for (subtype in table[type]) { + if (table[type].hasOwnProperty(subtype)) { + val = table[type][subtype]; + if (typeof val == "string") { + mimeTypes[val] = type + "/" + subtype; + } else { + for (index = 0; index < val.length; index++) { + mimeTypes[val[index]] = type + "/" + subtype; + } + } + } + } + } + } + return mimeTypes; + })(); + + var defaultValue = "text/plain";//"application/octet-stream"; + + function lookup(filename) { + return filename && mimeTypes[filename.split(".").pop().toLowerCase()] || defaultValue; + }; + + module.exports = { + 'lookup': lookup } - if (!response) { - deferred.reject({ - message : "File not found in the epub: " + url, - stack : new Error().stack +/***/ }, +/* 29 */ +/***/ function(module, exports) { + + if(typeof __WEBPACK_EXTERNAL_MODULE_29__ === 'undefined') {var e = new Error("Cannot find module \"JSZip\""); e.code = 'MODULE_NOT_FOUND'; throw e;} + module.exports = __WEBPACK_EXTERNAL_MODULE_29__; + +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var core = __webpack_require__(11); + var EpubCFI = __webpack_require__(15); + var Mapping = __webpack_require__(26); + + + function Contents(doc, content, cfiBase) { + // Blank Cfi for Parsing + this.epubcfi = new EpubCFI(); + + this.document = doc; + this.documentElement = this.document.documentElement; + this.content = content || this.document.body; + this.window = this.document.defaultView; + // Dom events to listen for + this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"]; + + this._size = { + width: 0, + height: 0 + } + + this.cfiBase = cfiBase || ""; + + this.listeners(); + }; + + Contents.prototype.width = function(w) { + // var frame = this.documentElement; + var frame = this.content; + + if (w && core.isNumber(w)) { + w = w + "px"; + } + + if (w) { + frame.style.width = w; + // this.content.style.width = w; + } + + return this.window.getComputedStyle(frame)['width']; + + + }; + + Contents.prototype.height = function(h) { + // var frame = this.documentElement; + var frame = this.content; + + if (h && core.isNumber(h)) { + h = h + "px"; + } + + if (h) { + frame.style.height = h; + // this.content.style.height = h; + } + + return this.window.getComputedStyle(frame)['height']; + + }; + + Contents.prototype.contentWidth = function(w) { + + var content = this.content || this.document.body; + + if (w && core.isNumber(w)) { + w = w + "px"; + } + + if (w) { + content.style.width = w; + } + + return this.window.getComputedStyle(content)['width']; + + + }; + + Contents.prototype.contentHeight = function(h) { + + var content = this.content || this.document.body; + + if (h && core.isNumber(h)) { + h = h + "px"; + } + + if (h) { + content.style.height = h; + } + + return this.window.getComputedStyle(content)['height']; + + }; + + Contents.prototype.textWidth = function() { + var width; + var range = this.document.createRange(); + var content = this.content || this.document.body; + + // Select the contents of frame + range.selectNodeContents(content); + + // get the width of the text content + width = range.getBoundingClientRect().width; + + return width; + + }; + + Contents.prototype.textHeight = function() { + var height; + var range = this.document.createRange(); + var content = this.content || this.document.body; + + range.selectNodeContents(content); + + height = range.getBoundingClientRect().height; + + return height; + }; + + Contents.prototype.scrollWidth = function() { + var width = this.documentElement.scrollWidth; + + return width; + }; + + Contents.prototype.scrollHeight = function() { + var height = this.documentElement.scrollHeight; + + return height; + }; + + Contents.prototype.overflow = function(overflow) { + + if (overflow) { + this.documentElement.style.overflow = overflow; + } + + return this.window.getComputedStyle(this.documentElement)['overflow']; + }; + + Contents.prototype.overflowX = function(overflow) { + + if (overflow) { + this.documentElement.style.overflowX = overflow; + } + + return this.window.getComputedStyle(this.documentElement)['overflowX']; + }; + + Contents.prototype.overflowY = function(overflow) { + + if (overflow) { + this.documentElement.style.overflowY = overflow; + } + + return this.window.getComputedStyle(this.documentElement)['overflowY']; + }; + + Contents.prototype.css = function(property, value) { + var content = this.content || this.document.body; + + if (value) { + content.style[property] = value; + } + + return this.window.getComputedStyle(content)[property]; + }; + + Contents.prototype.viewport = function(options) { + var width, height, scale, scalable; + var $viewport = this.document.querySelector("meta[name='viewport']"); + var newContent = ''; + + /** + * check for the viewport size + * + */ + if($viewport && $viewport.hasAttribute("content")) { + content = $viewport.getAttribute("content"); + contents = content.split(/\s*,\s*/); + if(contents[0]){ + width = contents[0].replace("width=", '').trim(); + } + if(contents[1]){ + height = contents[1].replace("height=", '').trim(); + } + if(contents[2]){ + scale = contents[2].replace("initial-scale=", '').trim(); + } + if(contents[3]){ + scalable = contents[3].replace("user-scalable=", '').trim(); + } + } + + if (options) { + + newContent += "width=" + (options.width || width); + newContent += ", height=" + (options.height || height); + if (options.scale || scale) { + newContent += ", initial-scale=" + (options.scale || scale); + } + if (options.scalable || scalable) { + newContent += ", user-scalable=" + (options.scalable || scalable); + } + + if (!$viewport) { + $viewport = this.document.createElement("meta"); + $viewport.setAttribute("name", "viewport"); + this.document.querySelector('head').appendChild($viewport); + } + + $viewport.setAttribute("content", newContent); + } + + + return { + width: parseInt(width), + height: parseInt(height) + }; + }; + + + // Contents.prototype.layout = function(layoutFunc) { + // + // this.iframe.style.display = "inline-block"; + // + // // Reset Body Styles + // this.content.style.margin = "0"; + // //this.document.body.style.display = "inline-block"; + // //this.document.documentElement.style.width = "auto"; + // + // if(layoutFunc){ + // layoutFunc(this); + // } + // + // this.onLayout(this); + // + // }; + // + // Contents.prototype.onLayout = function(view) { + // // stub + // }; + + Contents.prototype.expand = function() { + this.trigger("expand"); + }; + + Contents.prototype.listeners = function() { + + this.imageLoadListeners(); + + this.mediaQueryListeners(); + + // this.fontLoadListeners(); + + this.addEventListeners(); + + this.addSelectionListeners(); + + this.resizeListeners(); + + }; + + Contents.prototype.removeListeners = function() { + + this.removeEventListeners(); + + this.removeSelectionListeners(); + }; + + Contents.prototype.resizeListeners = function() { + var width, height; + // Test size again + clearTimeout(this.expanding); + + width = this.scrollWidth(); + height = this.scrollHeight(); + + if (width != this._size.width || height != this._size.height) { + + this._size = { + width: width, + height: height + } + + this.trigger("resize", this._size); + } + + this.expanding = setTimeout(this.resizeListeners.bind(this), 350); + }; + + //https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js + Contents.prototype.mediaQueryListeners = function() { + var sheets = this.document.styleSheets; + var mediaChangeHandler = function(m){ + if(m.matches && !this._expanding) { + setTimeout(this.expand.bind(this), 1); + // this.expand(); + } + }.bind(this); + + for (var i = 0; i < sheets.length; i += 1) { + var rules = sheets[i].cssRules; + if(!rules) return; // Stylesheets changed + for (var j = 0; j < rules.length; j += 1) { + //if (rules[j].constructor === CSSMediaRule) { + if(rules[j].media){ + var mql = this.window.matchMedia(rules[j].media.mediaText); + mql.addListener(mediaChangeHandler); + //mql.onchange = mediaChangeHandler; + } + } + } + }; + + Contents.prototype.observe = function(target) { + var renderer = this; + + // create an observer instance + var observer = new MutationObserver(function(mutations) { + if(renderer._expanding) { + renderer.expand(); + } + // mutations.forEach(function(mutation) { + // console.log(mutation); + // }); }); + + // configuration of the observer: + var config = { attributes: true, childList: true, characterData: true, subtree: true }; + + // pass in the target node, as well as the observer options + observer.observe(target, config); + + return observer; + }; + + Contents.prototype.imageLoadListeners = function(target) { + var images = this.document.querySelectorAll("img"); + var img; + for (var i = 0; i < images.length; i++) { + img = images[i]; + + if (typeof img.naturalWidth !== "undefined" && + img.naturalWidth === 0) { + img.onload = this.expand.bind(this); + } + } + }; + + Contents.prototype.fontLoadListeners = function(target) { + if (!this.document || !this.document.fonts) { + return; + } + + this.document.fonts.ready.then(function () { + this.expand(); + }.bind(this)); + + }; + + Contents.prototype.root = function() { + if(!this.document) return null; + return this.document.documentElement; + }; + + Contents.prototype.locationOf = function(target, ignoreClass) { + var position; + var targetPos = {"left": 0, "top": 0}; + + if(!this.document) return; + + if(this.epubcfi.isCfiString(target)) { + range = new EpubCFI(target).toRange(this.document, ignoreClass); + + if(range) { + if (range.startContainer.nodeType === Node.ELEMENT_NODE) { + position = range.startContainer.getBoundingClientRect(); + targetPos.left = position.left; + targetPos.top = position.top; + } else { + position = range.getBoundingClientRect(); + targetPos.left = position.left; + targetPos.top = position.top; + } + } + + } else if(typeof target === "string" && + target.indexOf("#") > -1) { + + id = target.substring(target.indexOf("#")+1); + el = this.document.getElementById(id); + + if(el) { + position = el.getBoundingClientRect(); + targetPos.left = position.left; + targetPos.top = position.top; + } + } + + return targetPos; + }; + + Contents.prototype.addStylesheet = function(src) { + return new RSVP.Promise(function(resolve, reject){ + var $stylesheet; + var ready = false; + + if(!this.document) { + resolve(false); + return; + } + + $stylesheet = this.document.createElement('link'); + $stylesheet.type = 'text/css'; + $stylesheet.rel = "stylesheet"; + $stylesheet.href = src; + $stylesheet.onload = $stylesheet.onreadystatechange = function() { + if ( !ready && (!this.readyState || this.readyState == 'complete') ) { + ready = true; + // Let apply + setTimeout(function(){ + resolve(true); + }, 1); + } + }; + + this.document.head.appendChild($stylesheet); + + }.bind(this)); + }; + + // https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule + Contents.prototype.addStylesheetRules = function(rules) { + var styleEl; + var styleSheet; + + if(!this.document) return; + + styleEl = this.document.createElement('style'); + + // Append style element to head + this.document.head.appendChild(styleEl); + + // Grab style sheet + styleSheet = styleEl.sheet; + + for (var i = 0, rl = rules.length; i < rl; i++) { + var j = 1, rule = rules[i], selector = rules[i][0], propStr = ''; + // If the second argument of a rule is an array of arrays, correct our variables. + if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') { + rule = rule[1]; + j = 0; + } + + for (var pl = rule.length; j < pl; j++) { + var prop = rule[j]; + propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\n'; + } + + // Insert CSS Rule + styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length); + } + }; + + Contents.prototype.addScript = function(src) { + + return new RSVP.Promise(function(resolve, reject){ + var $script; + var ready = false; + + if(!this.document) { + resolve(false); + return; + } + + $script = this.document.createElement('script'); + $script.type = 'text/javascript'; + $script.async = true; + $script.src = src; + $script.onload = $script.onreadystatechange = function() { + if ( !ready && (!this.readyState || this.readyState == 'complete') ) { + ready = true; + setTimeout(function(){ + resolve(true); + }, 1); + } + }; + + this.document.head.appendChild($script); + + }.bind(this)); + }; + + Contents.prototype.addEventListeners = function(){ + if(!this.document) { + return; + } + this.listenedEvents.forEach(function(eventName){ + this.document.addEventListener(eventName, this.triggerEvent.bind(this), false); + }, this); + + }; + + Contents.prototype.removeEventListeners = function(){ + if(!this.document) { + return; + } + this.listenedEvents.forEach(function(eventName){ + this.document.removeEventListener(eventName, this.triggerEvent, false); + }, this); + + }; + + // Pass browser events + Contents.prototype.triggerEvent = function(e){ + this.trigger(e.type, e); + }; + + Contents.prototype.addSelectionListeners = function(){ + if(!this.document) { + return; + } + this.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false); + }; + + Contents.prototype.removeSelectionListeners = function(){ + if(!this.document) { + return; + } + this.document.removeEventListener("selectionchange", this.onSelectionChange, false); + }; + + Contents.prototype.onSelectionChange = function(e){ + if (this.selectionEndTimeout) { + clearTimeout(this.selectionEndTimeout); + } + this.selectionEndTimeout = setTimeout(function() { + var selection = this.window.getSelection(); + this.triggerSelectedEvent(selection); + }.bind(this), 500); + }; + + Contents.prototype.triggerSelectedEvent = function(selection){ + var range, cfirange; + + if (selection && selection.rangeCount > 0) { + range = selection.getRangeAt(0); + if(!range.collapsed) { + // cfirange = this.section.cfiFromRange(range); + cfirange = new EpubCFI(range, this.cfiBase).toString(); + this.trigger("selected", cfirange); + this.trigger("selectedRange", range); + } + } + }; + + Contents.prototype.range = function(_cfi, ignoreClass){ + var cfi = new EpubCFI(_cfi); + return cfi.toRange(this.document, ignoreClass); + }; + + Contents.prototype.map = function(layout){ + var map = new Mapping(layout); + return map.section(); + }; + + Contents.prototype.size = function(width, height){ + + if (width >= 0) { + this.width(width); + } + + if (height >= 0) { + this.height(height); + } + + this.css("margin", "0"); + this.css("boxSizing", "border-box"); + + }; + + Contents.prototype.columns = function(width, height, columnWidth, gap){ + var COLUMN_AXIS = core.prefixed('columnAxis'); + var COLUMN_GAP = core.prefixed('columnGap'); + var COLUMN_WIDTH = core.prefixed('columnWidth'); + var COLUMN_FILL = core.prefixed('columnFill'); + var textWidth; + + this.width(width); + this.height(height); + + // Deal with Mobile trying to scale to viewport + this.viewport({ width: width, height: height, scale: 1.0 }); + + // this.overflowY("hidden"); + this.css("overflowY", "hidden"); + this.css("margin", "0"); + this.css("boxSizing", "border-box"); + this.css("maxWidth", "inherit"); + + this.css(COLUMN_AXIS, "horizontal"); + this.css(COLUMN_FILL, "auto"); + + this.css(COLUMN_GAP, gap+"px"); + this.css(COLUMN_WIDTH, columnWidth+"px"); + }; + + Contents.prototype.scale = function(scale, offsetX, offsetY){ + var scale = "scale(" + scale + ")"; + var translate = ''; + // this.css("position", "absolute")); + this.css("transformOrigin", "top left"); + + if (offsetX >= 0 || offsetY >= 0) { + translate = " translate(" + (offsetX || 0 )+ "px, " + (offsetY || 0 )+ "px )"; + } + + this.css("transform", scale + translate); + }; + + Contents.prototype.fit = function(width, height){ + var viewport = this.viewport(); + var widthScale = width / viewport.width; + var heightScale = height / viewport.height; + var scale = widthScale < heightScale ? widthScale : heightScale; + + var offsetY = (height - (viewport.height * scale)) / 2; + + this.width(width); + this.height(height); + this.overflow("hidden"); + + // Deal with Mobile trying to scale to viewport + this.viewport({ scale: 1.0 }); + + // Scale to the correct size + this.scale(scale, 0, offsetY); + + this.css("backgroundColor", "transparent"); + }; + + Contents.prototype.mapPage = function(cfiBase, start, end) { + var mapping = new Mapping(); + + return mapping.page(this, cfiBase, start, end); + }; + + Contents.prototype.destroy = function() { + // Stop observing + if(this.observer) { + this.observer.disconnect(); + } + + this.removeListeners(); + + }; + + RSVP.EventTarget.mixin(Contents.prototype); + + module.exports = Contents; + + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var core = __webpack_require__(11); + var EpubCFI = __webpack_require__(15); + var Contents = __webpack_require__(30); + + function IframeView(section, options) { + this.settings = core.extend({ + ignoreClass : '', + axis: 'vertical', + width: 0, + height: 0, + layout: undefined, + globalLayoutProperties: {}, + }, options || {}); + + this.id = "epubjs-view-" + core.uuid(); + this.section = section; + this.index = section.index; + + this.element = this.container(this.settings.axis); + + this.added = false; + this.displayed = false; + this.rendered = false; + + this.width = this.settings.width; + this.height = this.settings.height; + + this.fixedWidth = 0; + this.fixedHeight = 0; + + // Blank Cfi for Parsing + this.epubcfi = new EpubCFI(); + + this.layout = this.settings.layout; + // Dom events to listen for + // this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"]; + }; + + IframeView.prototype.container = function(axis) { + var element = document.createElement('div'); + + element.classList.add("epub-view"); + + // this.element.style.minHeight = "100px"; + element.style.height = "0px"; + element.style.width = "0px"; + element.style.overflow = "hidden"; + + if(axis && axis == "horizontal"){ + element.style.display = "inline-block"; + } else { + element.style.display = "block"; + } + + return element; + }; + + IframeView.prototype.create = function() { + + if(this.iframe) { + return this.iframe; + } + + if(!this.element) { + this.element = this.createContainer(); + } + + this.iframe = document.createElement('iframe'); + this.iframe.id = this.id; + this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations + this.iframe.style.overflow = "hidden"; + this.iframe.seamless = "seamless"; + // Back up if seamless isn't supported + this.iframe.style.border = "none"; + + this.resizing = true; + + // this.iframe.style.display = "none"; + this.element.style.visibility = "hidden"; + this.iframe.style.visibility = "hidden"; + + this.iframe.style.width = "0"; + this.iframe.style.height = "0"; + this._width = 0; + this._height = 0; + + this.element.appendChild(this.iframe); + this.added = true; + + this.elementBounds = core.bounds(this.element); + + // if(width || height){ + // this.resize(width, height); + // } else if(this.width && this.height){ + // this.resize(this.width, this.height); + // } else { + // this.iframeBounds = core.bounds(this.iframe); + // } + + // Firefox has trouble with baseURI and srcdoc + // TODO: Disable for now in firefox + + if(!!("srcdoc" in this.iframe)) { + this.supportsSrcdoc = true; + } else { + this.supportsSrcdoc = false; + } + + return this.iframe; + }; + + IframeView.prototype.render = function(request, show) { + + // view.onLayout = this.layout.format.bind(this.layout); + this.create(); + + // Fit to size of the container, apply padding + this.size(); + + if(!this.sectionRender) { + this.sectionRender = this.section.render(request); + } + + // Render Chain + return this.sectionRender + .then(function(contents){ + return this.load(contents); + }.bind(this)) + // .then(function(doc){ + // return this.hooks.content.trigger(view, this); + // }.bind(this)) + .then(function(){ + // this.settings.layout.format(view.contents); + // return this.hooks.layout.trigger(view, this); + }.bind(this)) + // .then(function(){ + // return this.display(); + // }.bind(this)) + // .then(function(){ + // return this.hooks.render.trigger(view, this); + // }.bind(this)) + .then(function(){ + + // apply the layout function to the contents + this.settings.layout.format(this.contents); + + // Expand the iframe to the full size of the content + this.expand(); + + // Listen for events that require an expansion of the iframe + this.addListeners(); + + if(show !== false) { + //this.q.enqueue(function(view){ + // this.show(); + //}, view); + } + // this.map = new Map(view, this.layout); + //this.hooks.show.trigger(view, this); + this.trigger("rendered", this.section); + + }.bind(this)) + .catch(function(e){ + this.trigger("loaderror", e); + }.bind(this)); + + }; + + // Determine locks base on settings + IframeView.prototype.size = function(_width, _height) { + var width = _width || this.settings.width; + var height = _height || this.settings.height; + + if(this.layout.name === "pre-paginated") { + this.lock("both", width, height); + } else if(this.settings.axis === "horizontal") { + this.lock("height", width, height); + } else { + this.lock("width", width, height); + } + + }; + + // Lock an axis to element dimensions, taking borders into account + IframeView.prototype.lock = function(what, width, height) { + var elBorders = core.borders(this.element); + var iframeBorders; + + if(this.iframe) { + iframeBorders = core.borders(this.iframe); + } else { + iframeBorders = {width: 0, height: 0}; + } + + if(what == "width" && core.isNumber(width)){ + this.lockedWidth = width - elBorders.width - iframeBorders.width; + this.resize(this.lockedWidth, width); // width keeps ratio correct + } + + if(what == "height" && core.isNumber(height)){ + this.lockedHeight = height - elBorders.height - iframeBorders.height; + this.resize(width, this.lockedHeight); + } + + if(what === "both" && + core.isNumber(width) && + core.isNumber(height)){ + + this.lockedWidth = width - elBorders.width - iframeBorders.width; + this.lockedHeight = height - elBorders.height - iframeBorders.height; + + this.resize(this.lockedWidth, this.lockedHeight); + } + + if(this.displayed && this.iframe) { + + // this.contents.layout(); + this.expand(); + + } + + + + }; + + // Resize a single axis based on content dimensions + IframeView.prototype.expand = function(force) { + var width = this.lockedWidth; + var height = this.lockedHeight; + var columns; + + var textWidth, textHeight; + + if(!this.iframe || this._expanding) return; + + this._expanding = true; + + // Expand Horizontally + // if(height && !width) { + if(this.settings.axis === "horizontal") { + // Get the width of the text + textWidth = this.contents.textWidth(); + // Check if the textWidth has changed + if(textWidth != this._textWidth){ + // Get the contentWidth by resizing the iframe + // Check with a min reset of the textWidth + width = this.contentWidth(textWidth); + + columns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap)); + + if ( this.settings.layout.divisor > 1 && + this.settings.layout.name === "reflowable" && + (columns % 2 > 0)) { + // add a blank page + width += this.settings.layout.gap + this.settings.layout.columnWidth; + } + + // Save the textWdith + this._textWidth = textWidth; + // Save the contentWidth + this._contentWidth = width; + } else { + // Otherwise assume content height hasn't changed + width = this._contentWidth; + } + } // Expand Vertically + else if(this.settings.axis === "vertical") { + textHeight = this.contents.textHeight(); + if(textHeight != this._textHeight){ + height = this.contentHeight(textHeight); + this._textHeight = textHeight; + this._contentHeight = height; + } else { + height = this._contentHeight; + } + + } + + // Only Resize if dimensions have changed or + // if Frame is still hidden, so needs reframing + if(this._needsReframe || width != this._width || height != this._height){ + this.resize(width, height); + } + + this._expanding = false; + }; + + IframeView.prototype.contentWidth = function(min) { + var prev; + var width; + + // Save previous width + prev = this.iframe.style.width; + // Set the iframe size to min, width will only ever be greater + // Will preserve the aspect ratio + this.iframe.style.width = (min || 0) + "px"; + // Get the scroll overflow width + width = this.contents.scrollWidth(); + // Reset iframe size back + this.iframe.style.width = prev; + return width; + }; + + IframeView.prototype.contentHeight = function(min) { + var prev; + var height; + + prev = this.iframe.style.height; + this.iframe.style.height = (min || 0) + "px"; + height = this.contents.scrollHeight(); + + this.iframe.style.height = prev; + return height; + }; + + + IframeView.prototype.resize = function(width, height) { + + if(!this.iframe) return; + + if(core.isNumber(width)){ + this.iframe.style.width = width + "px"; + this._width = width; + } + + if(core.isNumber(height)){ + this.iframe.style.height = height + "px"; + this._height = height; + } + + this.iframeBounds = core.bounds(this.iframe); + + this.reframe(this.iframeBounds.width, this.iframeBounds.height); + + }; + + IframeView.prototype.reframe = function(width, height) { + var size; + + // if(!this.displayed) { + // this._needsReframe = true; + // return; + // } + if(core.isNumber(width)){ + this.element.style.width = width + "px"; + } + + if(core.isNumber(height)){ + this.element.style.height = height + "px"; + } + + this.prevBounds = this.elementBounds; + + this.elementBounds = core.bounds(this.element); + + size = { + width: this.elementBounds.width, + height: this.elementBounds.height, + widthDelta: this.elementBounds.width - this.prevBounds.width, + heightDelta: this.elementBounds.height - this.prevBounds.height, + }; + + this.onResize(this, size); + + this.trigger("resized", size); + + }; + + + IframeView.prototype.load = function(contents) { + var loading = new RSVP.defer(); + var loaded = loading.promise; + + if(!this.iframe) { + loading.reject(new Error("No Iframe Available")); + return loaded; + } + + this.iframe.onload = function(event) { + + this.onLoad(event, loading); + + }.bind(this); + + if(this.supportsSrcdoc){ + this.iframe.srcdoc = contents; + } else { + + this.document = this.iframe.contentDocument; + + if(!this.document) { + loading.reject(new Error("No Document Available")); + return loaded; + } + + this.iframe.contentDocument.open(); + this.iframe.contentDocument.write(contents); + this.iframe.contentDocument.close(); + + } + + return loaded; + }; + + IframeView.prototype.onLoad = function(event, promise) { + + this.window = this.iframe.contentWindow; + this.document = this.iframe.contentDocument; + + this.contents = new Contents(this.document, this.document.body, this.section.cfiBase); + + this.rendering = false; + + var link = this.document.querySelector("link[rel='canonical']"); + if (link) { + link.setAttribute("href", this.section.url); + } else { + link = this.document.createElement("link"); + link.setAttribute("rel", "canonical"); + link.setAttribute("href", this.section.url); + this.document.querySelector("head").appendChild(link); + } + + this.contents.on("expand", function () { + if(this.displayed && this.iframe) { + this.expand(); + } + }); + + promise.resolve(this.contents); + }; + + + + // IframeView.prototype.layout = function(layoutFunc) { + // + // this.iframe.style.display = "inline-block"; + // + // // Reset Body Styles + // // this.document.body.style.margin = "0"; + // //this.document.body.style.display = "inline-block"; + // //this.document.documentElement.style.width = "auto"; + // + // if(layoutFunc){ + // this.layoutFunc = layoutFunc; + // } + // + // this.contents.layout(this.layoutFunc); + // + // }; + // + // IframeView.prototype.onLayout = function(view) { + // // stub + // }; + + IframeView.prototype.setLayout = function(layout) { + this.layout = layout; + }; + + IframeView.prototype.setAxis = function(axis) { + this.settings.axis = axis; + }; + + IframeView.prototype.resizeListenters = function() { + // Test size again + clearTimeout(this.expanding); + this.expanding = setTimeout(this.expand.bind(this), 350); + }; + + IframeView.prototype.addListeners = function() { + //TODO: Add content listeners for expanding + }; + + IframeView.prototype.removeListeners = function(layoutFunc) { + //TODO: remove content listeners for expanding + }; + + IframeView.prototype.display = function(request) { + var displayed = new RSVP.defer(); + + if (!this.displayed) { + + this.render(request).then(function () { + + this.trigger("displayed", this); + this.onDisplayed(this); + + this.displayed = true; + displayed.resolve(this); + + }.bind(this)); + + } else { + displayed.resolve(this); + } + + + return displayed.promise; + }; + + IframeView.prototype.show = function() { + + this.element.style.visibility = "visible"; + + if(this.iframe){ + this.iframe.style.visibility = "visible"; + } + + this.trigger("shown", this); + }; + + IframeView.prototype.hide = function() { + // this.iframe.style.display = "none"; + this.element.style.visibility = "hidden"; + this.iframe.style.visibility = "hidden"; + + this.stopExpanding = true; + this.trigger("hidden", this); + }; + + IframeView.prototype.position = function() { + return this.element.getBoundingClientRect(); + }; + + IframeView.prototype.locationOf = function(target) { + var parentPos = this.iframe.getBoundingClientRect(); + var targetPos = this.contents.locationOf(target, this.settings.ignoreClass); + + return { + "left": window.scrollX + parentPos.left + targetPos.left, + "top": window.scrollY + parentPos.top + targetPos.top + }; + }; + + IframeView.prototype.onDisplayed = function(view) { + // Stub, override with a custom functions + }; + + IframeView.prototype.onResize = function(view, e) { + // Stub, override with a custom functions + }; + + IframeView.prototype.bounds = function() { + if(!this.elementBounds) { + this.elementBounds = core.bounds(this.element); + } + return this.elementBounds; + }; + + IframeView.prototype.destroy = function() { + + if(this.displayed){ + this.displayed = false; + + this.removeListeners(); + + this.stopExpanding = true; + this.element.removeChild(this.iframe); + this.displayed = false; + this.iframe = null; + + this._textWidth = null; + this._textHeight = null; + this._width = null; + this._height = null; + } + // this.element.style.height = "0px"; + // this.element.style.width = "0px"; + }; + + RSVP.EventTarget.mixin(IframeView.prototype); + + module.exports = IframeView; + + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var core = __webpack_require__(11); + var EpubCFI = __webpack_require__(15); + var Mapping = __webpack_require__(26); + var Queue = __webpack_require__(21); + var Stage = __webpack_require__(33); + var Views = __webpack_require__(34); + + function DefaultViewManager(options) { + + this.name = "default"; + this.View = options.view; + this.request = options.request; + this.renditionQueue = options.queue; + this.q = new Queue(this); + + this.settings = core.extend(this.settings || {}, { + infinite: true, + hidden: false, + width: undefined, + height: undefined, + // globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'}, + // layout: null, + axis: "vertical", + ignoreClass: '' + }); + + core.extend(this.settings, options.settings || {}); + + this.viewSettings = { + ignoreClass: this.settings.ignoreClass, + axis: this.settings.axis, + layout: this.layout, + width: 0, + height: 0 + }; + } + + DefaultViewManager.prototype.render = function(element, size){ + + // Save the stage + this.stage = new Stage({ + width: size.width, + height: size.height, + overflow: this.settings.overflow, + hidden: this.settings.hidden, + axis: this.settings.axis + }); + + this.stage.attachTo(element); + + // Get this stage container div + this.container = this.stage.getContainer(); + + // Views array methods + this.views = new Views(this.container); + + // Calculate Stage Size + this._bounds = this.bounds(); + this._stageSize = this.stage.size(); + + // Set the dimensions for views + this.viewSettings.width = this._stageSize.width; + this.viewSettings.height = this._stageSize.height; + + // Function to handle a resize event. + // Will only attach if width and height are both fixed. + this.stage.onResize(this.onResized.bind(this)); + + // Add Event Listeners + this.addEventListeners(); + + // Add Layout method + // this.applyLayoutMethod(); + if (this.layout) { + this.updateLayout(); + } + }; + + DefaultViewManager.prototype.addEventListeners = function(){ + window.addEventListener('unload', function(e){ + this.destroy(); + }.bind(this)); + }; + + DefaultViewManager.prototype.destroy = function(){ + // this.views.each(function(view){ + // view.destroy(); + // }); + + /* + + clearTimeout(this.trimTimeout); + if(this.settings.hidden) { + this.element.removeChild(this.wrapper); + } else { + this.element.removeChild(this.container); + } + */ + }; + + DefaultViewManager.prototype.onResized = function(e) { + clearTimeout(this.resizeTimeout); + this.resizeTimeout = setTimeout(function(){ + this.resize(); + }.bind(this), 150); + }; + + DefaultViewManager.prototype.resize = function(width, height){ + + // Clear the queue + this.q.clear(); + + this._stageSize = this.stage.size(width, height); + this._bounds = this.bounds(); + + // Update for new views + this.viewSettings.width = this._stageSize.width; + this.viewSettings.height = this._stageSize.height; + + // Update for existing views + this.views.each(function(view) { + view.size(this._stageSize.width, this._stageSize.height); + }.bind(this)); + + this.updateLayout(); + + this.trigger("resized", { + width: this.stage.width, + height: this.stage.height + }); + + }; + + DefaultViewManager.prototype.createView = function(section) { + return new this.View(section, this.viewSettings); + }; + + DefaultViewManager.prototype.display = function(section, target){ + + var displaying = new RSVP.defer(); + var displayed = displaying.promise; + + // Check to make sure the section we want isn't already shown + var visible = this.views.find(section); + + // View is already shown, just move to correct location + if(visible && target) { + offset = visible.locationOf(target); + this.moveTo(offset); + displaying.resolve(); + return displayed; + } + + // Hide all current views + this.views.hide(); + + this.views.clear(); + + this.add(section) + .then(function(){ + var next; + if (this.layout.name === "pre-paginated" && + this.layout.divisor > 1) { + next = section.next(); + if (next) { + return this.add(next); + } + } + }.bind(this)) + .then(function(view){ + + // Move to correct place within the section, if needed + if(target) { + offset = view.locationOf(target); + this.moveTo(offset); + } + + this.views.show(); + + displaying.resolve(); + + }.bind(this)) + // .then(function(){ + // return this.hooks.display.trigger(view); + // }.bind(this)) + // .then(function(){ + // this.views.show(); + // }.bind(this)); + return displayed; + }; + + DefaultViewManager.prototype.afterDisplayed = function(view){ + this.trigger("added", view); + }; + + DefaultViewManager.prototype.afterResized = function(view){ + this.trigger("resize", view.section); + }; + + // DefaultViewManager.prototype.moveTo = function(offset){ + // this.scrollTo(offset.left, offset.top); + // }; + + DefaultViewManager.prototype.moveTo = function(offset){ + var distX = 0, + distY = 0; + + if(this.settings.axis === "vertical") { + distY = offset.top; + } else { + distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta; + + if (distX + this.layout.delta > this.container.scrollWidth) { + distX = this.container.scrollWidth - this.layout.delta; + } + } + + this.scrollTo(distX, distY); + }; + + DefaultViewManager.prototype.add = function(section){ + var view = this.createView(section); + + this.views.append(view); + + // view.on("shown", this.afterDisplayed.bind(this)); + view.onDisplayed = this.afterDisplayed.bind(this); + view.onResize = this.afterResized.bind(this); + + return view.display(this.request); + + }; + + DefaultViewManager.prototype.append = function(section){ + var view = this.createView(section); + this.views.append(view); + return view.display(this.request); + }; + + DefaultViewManager.prototype.prepend = function(section){ + var view = this.createView(section); + + this.views.prepend(view); + return view.display(this.request); + }; + // DefaultViewManager.prototype.resizeView = function(view) { + // + // if(this.settings.globalLayoutProperties.layout === "pre-paginated") { + // view.lock("both", this.bounds.width, this.bounds.height); + // } else { + // view.lock("width", this.bounds.width, this.bounds.height); + // } + // + // }; + + DefaultViewManager.prototype.next = function(){ + var next; + var view; + var left; + + if(!this.views.length) return; + + if(this.settings.axis === "horizontal") { + + this.scrollLeft = this.container.scrollLeft; + + left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta; + + if(left < this.container.scrollWidth) { + this.scrollBy(this.layout.delta, 0); + } else if (left - this.layout.columnWidth === this.container.scrollWidth) { + this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); + } else { + next = this.views.last().section.next(); + } + + + } else { + + next = this.views.last().section.next(); + + } + + if(next) { + this.views.clear(); + + return this.append(next) + .then(function(){ + var right; + if (this.layout.name && this.layout.divisor > 1) { + right = next.next(); + if (right) { + return this.append(right); + } + } + }.bind(this)) + .then(function(){ + this.views.show(); + }.bind(this)); + } + + + }; + + DefaultViewManager.prototype.prev = function(){ + var prev; + var view; + var left; + + if(!this.views.length) return; + + if(this.settings.axis === "horizontal") { + + this.scrollLeft = this.container.scrollLeft; + + left = this.container.scrollLeft; + + if(left > 0) { + this.scrollBy(-this.layout.delta, 0); + } else { + prev = this.views.first().section.prev(); + } + + + } else { + + prev = this.views.first().section.prev(); + + } + + if(prev) { + this.views.clear(); + + return this.prepend(prev) + .then(function(){ + var left; + if (this.layout.name && this.layout.divisor > 1) { + left = prev.prev(); + if (left) { + return this.prepend(left); + } + } + }.bind(this)) + .then(function(){ + if(this.settings.axis === "horizontal") { + this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); + } + this.views.show(); + }.bind(this)); + } + }; + + DefaultViewManager.prototype.current = function(){ + var visible = this.visible(); + if(visible.length){ + // Current is the last visible view + return visible[visible.length-1]; + } + return null; + }; + + DefaultViewManager.prototype.currentLocation = function(){ + var view; + var start, end; + + if(this.views.length) { + view = this.views.first(); + start = container.left - view.position().left; + end = start + this.layout.spread; + + return this.mapping.page(view, view.section.cfiBase); + } + + }; + + DefaultViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){ + var position = view.position(); + var container = _container || this.bounds(); + + if(this.settings.axis === "horizontal" && + position.right > container.left - offsetPrev && + position.left < container.right + offsetNext) { + + return true; + + } else if(this.settings.axis === "vertical" && + position.bottom > container.top - offsetPrev && + position.top < container.bottom + offsetNext) { + + return true; + } + + return false; + + }; + + DefaultViewManager.prototype.visible = function(){ + // return this.views.displayed(); + var container = this.bounds(); + var views = this.views.displayed(); + var viewsLength = views.length; + var visible = []; + var isVisible; + var view; + + for (var i = 0; i < viewsLength; i++) { + view = views[i]; + isVisible = this.isVisible(view, 0, 0, container); + + if(isVisible === true) { + visible.push(view); + } + + } + return visible; + }; + + DefaultViewManager.prototype.scrollBy = function(x, y, silent){ + if(silent) { + this.ignore = true; + } + + if(this.settings.height) { + + if(x) this.container.scrollLeft += x; + if(y) this.container.scrollTop += y; + + } else { + window.scrollBy(x,y); + } + // console.log("scrollBy", x, y); + this.scrolled = true; + this.onScroll(); + }; + + DefaultViewManager.prototype.scrollTo = function(x, y, silent){ + if(silent) { + this.ignore = true; + } + + if(this.settings.height) { + this.container.scrollLeft = x; + this.container.scrollTop = y; + } else { + window.scrollTo(x,y); + } + // console.log("scrollTo", x, y); + this.scrolled = true; + this.onScroll(); + // if(this.container.scrollLeft != x){ + // setTimeout(function() { + // this.scrollTo(x, y, silent); + // }.bind(this), 10); + // return; + // }; + }; + + DefaultViewManager.prototype.onScroll = function(){ + + }; + + DefaultViewManager.prototype.bounds = function() { + var bounds; + + bounds = this.stage.bounds(); + + return bounds; + }; + + DefaultViewManager.prototype.applyLayout = function(layout) { + + this.layout = layout; + this.updateLayout(); + + this.mapping = new Mapping(this.layout); + // this.manager.layout(this.layout.format); + }; + + DefaultViewManager.prototype.updateLayout = function() { + if (!this.stage) { + return; + } + + this._stageSize = this.stage.size(); + + if(this.settings.axis === "vertical") { + this.layout.calculate(this._stageSize.width, this._stageSize.height); + } else { + this.layout.calculate( + this._stageSize.width, + this._stageSize.height, + this.settings.gap + ); + + // Set the look ahead offset for what is visible + this.settings.offset = this.layout.delta; + + this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]); + + } + + // Set the dimensions for views + this.viewSettings.width = this.layout.width; + this.viewSettings.height = this.layout.height; + + this.setLayout(this.layout); + + }; + + DefaultViewManager.prototype.setLayout = function(layout){ + + this.viewSettings.layout = layout; + + if(this.views) { + + this.views.each(function(view){ + view.setLayout(layout); + }); + + } + + }; + + DefaultViewManager.prototype.updateFlow = function(flow){ + var axis = (flow === "paginated") ? "horizontal" : "vertical"; + + this.settings.axis = axis; + + this.viewSettings.axis = axis; + + this.settings.overflow = (flow === "paginated") ? "hidden" : "auto"; + // this.views.each(function(view){ + // view.setAxis(axis); + // }); + + }; + + //-- Enable binding events to Manager + RSVP.EventTarget.mixin(DefaultViewManager.prototype); + + module.exports = DefaultViewManager; - return deferred.promise; -}; -Unarchive.prototype.revokeUrl = function(url){ - var _URL = window.URL || window.webkitURL || window.mozURL; - var fromCache = this.urlCache[url]; - if(fromCache) _URL.revokeObjectURL(fromCache); -}; +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { -module.exports = Unarchive; - -},{"../libs/mime/mime":1,"./core":10,"./request":26,"jszip":"jszip","rsvp":5,"urijs":7}],"epub":[function(require,module,exports){ -var Book = require('./book'); -var EpubCFI = require('./epubcfi'); -var Rendition = require('./rendition'); -var Contents = require('./contents'); -var RSVP = require('rsvp'); - -function ePub(_url) { - return new Book(_url); -}; - -ePub.VERSION = "0.3.0"; - -ePub.CFI = EpubCFI; -ePub.Rendition = Rendition; -ePub.Contents = Contents; -ePub.RSVP = RSVP; - -ePub.ViewManagers = {}; -ePub.Views = {}; -ePub.register = { - manager : function(name, manager){ - return ePub.ViewManagers[name] = manager; - }, - view : function(name, view){ - return ePub.Views[name] = view; + var core = __webpack_require__(11); + + function Stage(_options) { + this.settings = _options || {}; + this.id = "epubjs-container-" + core.uuid(); + + this.container = this.create(this.settings); + + if(this.settings.hidden) { + this.wrapper = this.wrap(this.container); + } + } -}; + + /** + * Creates an element to render to. + * Resizes to passed width and height or to the elements size + */ + Stage.prototype.create = function(options){ + var height = options.height;// !== false ? options.height : "100%"; + var width = options.width;// !== false ? options.width : "100%"; + var overflow = options.overflow || false; + var axis = options.axis || "vertical"; + + if(options.height && core.isNumber(options.height)) { + height = options.height + "px"; + } + + if(options.width && core.isNumber(options.width)) { + width = options.width + "px"; + } + + // Create new container element + container = document.createElement("div"); + + container.id = this.id; + container.classList.add("epub-container"); + + // Style Element + // container.style.fontSize = "0"; + container.style.wordSpacing = "0"; + container.style.lineHeight = "0"; + container.style.verticalAlign = "top"; + + if(axis === "horizontal") { + container.style.whiteSpace = "nowrap"; + } + + if(width){ + container.style.width = width; + } + + if(height){ + container.style.height = height; + } + + if (overflow) { + container.style.overflow = overflow; + } + + return container; + }; + + Stage.wrap = function(container) { + var wrapper = document.createElement("div"); + + wrapper.style.visibility = "hidden"; + wrapper.style.overflow = "hidden"; + wrapper.style.width = "0"; + wrapper.style.height = "0"; + + wrapper.appendChild(container); + return wrapper; + }; + + + Stage.prototype.getElement = function(_element){ + var element; + + if(core.isElement(_element)) { + element = _element; + } else if (typeof _element === "string") { + element = document.getElementById(_element); + } + + if(!element){ + console.error("Not an Element"); + return; + } + + return element; + }; + + Stage.prototype.attachTo = function(what){ + + var element = this.getElement(what); + var base; + + if(!element){ + return; + } + + if(this.settings.hidden) { + base = this.wrapper; + } else { + base = this.container; + } + + element.appendChild(base); + + this.element = element; + + return element; + + }; + + Stage.prototype.getContainer = function() { + return this.container; + }; + + Stage.prototype.onResize = function(func){ + // Only listen to window for resize event if width and height are not fixed. + // This applies if it is set to a percent or auto. + if(!core.isNumber(this.settings.width) || + !core.isNumber(this.settings.height) ) { + window.addEventListener("resize", func, false); + } + + }; + + Stage.prototype.size = function(width, height){ + var bounds; + // var width = _width || this.settings.width; + // var height = _height || this.settings.height; + + // If width or height are set to false, inherit them from containing element + if(width === null) { + bounds = this.element.getBoundingClientRect(); + + if(bounds.width) { + width = bounds.width; + this.container.style.width = bounds.width + "px"; + } + } + + if(height === null) { + bounds = bounds || this.element.getBoundingClientRect(); + + if(bounds.height) { + height = bounds.height; + this.container.style.height = bounds.height + "px"; + } + + } + + if(!core.isNumber(width)) { + bounds = this.container.getBoundingClientRect(); + width = bounds.width; + //height = bounds.height; + } + + if(!core.isNumber(height)) { + bounds = bounds || this.container.getBoundingClientRect(); + //width = bounds.width; + height = bounds.height; + } + + + this.containerStyles = window.getComputedStyle(this.container); + + this.containerPadding = { + left: parseFloat(this.containerStyles["padding-left"]) || 0, + right: parseFloat(this.containerStyles["padding-right"]) || 0, + top: parseFloat(this.containerStyles["padding-top"]) || 0, + bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0 + }; + + return { + width: width - + this.containerPadding.left - + this.containerPadding.right, + height: height - + this.containerPadding.top - + this.containerPadding.bottom + }; + + }; + + Stage.prototype.bounds = function(){ + + if(!this.container) { + return core.windowBounds(); + } else { + return this.container.getBoundingClientRect(); + } + + } + + Stage.prototype.getSheet = function(){ + var style = document.createElement("style"); + + // WebKit hack --> https://davidwalsh.name/add-rules-stylesheets + style.appendChild(document.createTextNode("")); + + document.head.appendChild(style); + + return style.sheet; + } + + Stage.prototype.addStyleRules = function(selector, rulesArray){ + var scope = "#" + this.id + " "; + var rules = ""; + + if(!this.sheet){ + this.sheet = this.getSheet(); + } + + rulesArray.forEach(function(set) { + for (var prop in set) { + if(set.hasOwnProperty(prop)) { + rules += prop + ":" + set[prop] + ";"; + } + } + }) + + this.sheet.insertRule(scope + selector + " {" + rules + "}", 0); + } + + + + module.exports = Stage; -// Default Views -ePub.register.view("iframe", require('./managers/views/iframe')); -// ePub.register.view("inline", require('./managers/views/inline')); -// Default View Managers -ePub.register.manager("single", require('./managers/default')); -ePub.register.manager("continuous", require('./managers/continuous')); +/***/ }, +/* 34 */ +/***/ function(module, exports) { -module.exports = ePub; + function Views(container) { + this.container = container; + this._views = []; + this.length = 0; + this.hidden = false; + }; + + Views.prototype.all = function() { + return this._views; + }; + + Views.prototype.first = function() { + return this._views[0]; + }; + + Views.prototype.last = function() { + return this._views[this._views.length-1]; + }; + + Views.prototype.indexOf = function(view) { + return this._views.indexOf(view); + }; + + Views.prototype.slice = function() { + return this._views.slice.apply(this._views, arguments); + }; + + Views.prototype.get = function(i) { + return this._views[i]; + }; + + Views.prototype.append = function(view){ + this._views.push(view); + if(this.container){ + this.container.appendChild(view.element); + } + this.length++; + return view; + }; + + Views.prototype.prepend = function(view){ + this._views.unshift(view); + if(this.container){ + this.container.insertBefore(view.element, this.container.firstChild); + } + this.length++; + return view; + }; + + Views.prototype.insert = function(view, index) { + this._views.splice(index, 0, view); + + if(this.container){ + if(index < this.container.children.length){ + this.container.insertBefore(view.element, this.container.children[index]); + } else { + this.container.appendChild(view.element); + } + } + + this.length++; + return view; + }; + + Views.prototype.remove = function(view) { + var index = this._views.indexOf(view); + + if(index > -1) { + this._views.splice(index, 1); + } + + + this.destroy(view); + + this.length--; + }; + + Views.prototype.destroy = function(view) { + view.off("resized"); + + if(view.displayed){ + view.destroy(); + } + + if(this.container){ + this.container.removeChild(view.element); + } + view = null; + }; + + // Iterators + + Views.prototype.each = function() { + return this._views.forEach.apply(this._views, arguments); + }; + + Views.prototype.clear = function(){ + // Remove all views + var view; + var len = this.length; + + if(!this.length) return; + + for (var i = 0; i < len; i++) { + view = this._views[i]; + this.destroy(view); + } + + this._views = []; + this.length = 0; + }; + + Views.prototype.find = function(section){ + + var view; + var len = this.length; + + for (var i = 0; i < len; i++) { + view = this._views[i]; + if(view.displayed && view.section.index == section.index) { + return view; + } + } + + }; + + Views.prototype.displayed = function(){ + var displayed = []; + var view; + var len = this.length; + + for (var i = 0; i < len; i++) { + view = this._views[i]; + if(view.displayed){ + displayed.push(view); + } + } + return displayed; + }; + + Views.prototype.show = function(){ + var view; + var len = this.length; + + for (var i = 0; i < len; i++) { + view = this._views[i]; + if(view.displayed){ + view.show(); + } + } + this.hidden = false; + }; + + Views.prototype.hide = function(){ + var view; + var len = this.length; + + for (var i = 0; i < len; i++) { + view = this._views[i]; + if(view.displayed){ + view.hide(); + } + } + this.hidden = true; + }; + + module.exports = Views; -},{"./book":8,"./contents":9,"./epubcfi":11,"./managers/continuous":15,"./managers/default":16,"./managers/views/iframe":19,"./rendition":24,"rsvp":5}]},{},["epub"])("epub") + +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { + + var RSVP = __webpack_require__(2); + var core = __webpack_require__(11); + var DefaultViewManager = __webpack_require__(32); + + function ContinuousViewManager(options) { + + DefaultViewManager.apply(this, arguments); // call super constructor. + + this.name = "continuous"; + + this.settings = core.extend(this.settings || {}, { + infinite: true, + overflow: "auto", + axis: "vertical", + offset: 500, + offsetDelta: 250, + width: undefined, + height: undefined + }); + + core.extend(this.settings, options.settings || {}); + + // Gap can be 0, byt defaults doesn't handle that + if (options.settings.gap != "undefined" && options.settings.gap === 0) { + this.settings.gap = options.settings.gap; + } + + // this.viewSettings.axis = this.settings.axis; + this.viewSettings = { + ignoreClass: this.settings.ignoreClass, + axis: this.settings.axis, + layout: this.layout, + width: 0, + height: 0 + }; + + this.scrollTop = 0; + this.scrollLeft = 0; + }; + + // subclass extends superclass + ContinuousViewManager.prototype = Object.create(DefaultViewManager.prototype); + ContinuousViewManager.prototype.constructor = ContinuousViewManager; + + ContinuousViewManager.prototype.display = function(section, target){ + return DefaultViewManager.prototype.display.call(this, section, target) + .then(function () { + return this.fill(); + }.bind(this)); + }; + + ContinuousViewManager.prototype.fill = function(_full){ + var full = _full || new RSVP.defer(); + + this.check().then(function(result) { + if (result) { + this.fill(full); + } else { + full.resolve(); + } + }.bind(this)); + + return full.promise; + } + + ContinuousViewManager.prototype.moveTo = function(offset){ + // var bounds = this.stage.bounds(); + // var dist = Math.floor(offset.top / bounds.height) * bounds.height; + var distX = 0, + distY = 0; + + var offsetX = 0, + offsetY = 0; + + if(this.settings.axis === "vertical") { + distY = offset.top; + offsetY = offset.top+this.settings.offset; + } else { + distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta; + offsetX = distX+this.settings.offset; + } + + return this.check(offsetX, offsetY) + .then(function(){ + this.scrollBy(distX, distY); + }.bind(this)); + }; + + /* + ContinuousViewManager.prototype.afterDisplayed = function(currView){ + var next = currView.section.next(); + var prev = currView.section.prev(); + var index = this.views.indexOf(currView); + var prevView, nextView; + + if(index + 1 === this.views.length && next) { + nextView = this.createView(next); + this.q.enqueue(this.append.bind(this), nextView); + } + + if(index === 0 && prev) { + prevView = this.createView(prev, this.viewSettings); + this.q.enqueue(this.prepend.bind(this), prevView); + } + + // this.removeShownListeners(currView); + // currView.onShown = this.afterDisplayed.bind(this); + this.trigger("added", currView.section); + + }; + */ + + ContinuousViewManager.prototype.resize = function(width, height){ + + // Clear the queue + this.q.clear(); + + this._stageSize = this.stage.size(width, height); + this._bounds = this.bounds(); + + // Update for new views + this.viewSettings.width = this._stageSize.width; + this.viewSettings.height = this._stageSize.height; + + // Update for existing views + this.views.each(function(view) { + view.size(this._stageSize.width, this._stageSize.height); + }.bind(this)); + + this.updateLayout(); + + // if(this.location) { + // this.rendition.display(this.location.start); + // } + + this.trigger("resized", { + width: this.stage.width, + height: this.stage.height + }); + + }; + + ContinuousViewManager.prototype.onResized = function(e) { + + // this.views.clear(); + + clearTimeout(this.resizeTimeout); + this.resizeTimeout = setTimeout(function(){ + this.resize(); + }.bind(this), 150); + }; + + ContinuousViewManager.prototype.afterResized = function(view){ + this.trigger("resize", view.section); + }; + + // Remove Previous Listeners if present + ContinuousViewManager.prototype.removeShownListeners = function(view){ + + // view.off("shown", this.afterDisplayed); + // view.off("shown", this.afterDisplayedAbove); + view.onDisplayed = function(){}; + + }; + + + // ContinuousViewManager.prototype.append = function(section){ + // return this.q.enqueue(function() { + // + // this._append(section); + // + // + // }.bind(this)); + // }; + // + // ContinuousViewManager.prototype.prepend = function(section){ + // return this.q.enqueue(function() { + // + // this._prepend(section); + // + // }.bind(this)); + // + // }; + + ContinuousViewManager.prototype.append = function(section){ + var view = this.createView(section); + this.views.append(view); + return view; + }; + + ContinuousViewManager.prototype.prepend = function(section){ + var view = this.createView(section); + + view.on("resized", this.counter.bind(this)); + + this.views.prepend(view); + return view; + }; + + ContinuousViewManager.prototype.counter = function(bounds){ + + if(this.settings.axis === "vertical") { + this.scrollBy(0, bounds.heightDelta, true); + } else { + this.scrollBy(bounds.widthDelta, 0, true); + } + + }; + + ContinuousViewManager.prototype.update = function(_offset){ + var container = this.bounds(); + var views = this.views.all(); + var viewsLength = views.length; + var visible = []; + var offset = typeof _offset != "undefined" ? _offset : (this.settings.offset || 0); + var isVisible; + var view; + + var updating = new RSVP.defer(); + var promises = []; + + for (var i = 0; i < viewsLength; i++) { + view = views[i]; + + isVisible = this.isVisible(view, offset, offset, container); + + if(isVisible === true) { + if (!view.displayed) { + promises.push(view.display(this.request).then(function (view) { + view.show(); + })); + } + visible.push(view); + } else { + this.q.enqueue(view.destroy.bind(view)); + + clearTimeout(this.trimTimeout); + this.trimTimeout = setTimeout(function(){ + this.q.enqueue(this.trim.bind(this)); + }.bind(this), 250); + } + + } + + if(promises.length){ + return RSVP.all(promises); + } else { + updating.resolve(); + return updating.promise; + } + + }; + + ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){ + var last, first, next, prev; + + var checking = new RSVP.defer(); + var newViews = []; + + var horizontal = (this.settings.axis === "horizontal"); + var delta = this.settings.offset || 0; + + if (_offsetLeft && horizontal) { + delta = _offsetLeft; + } + + if (_offsetTop && !horizontal) { + delta = _offsetTop; + } + + var bounds = this._bounds; // bounds saved this until resize + + var offset = horizontal ? this.scrollLeft : this.scrollTop; + var visibleLength = horizontal ? bounds.width : bounds.height; + var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight; + + if (offset + visibleLength + delta >= contentLength) { + last = this.views.last(); + next = last && last.section.next(); + if(next) { + newViews.push(this.append(next)); + } + } + + if (offset - delta < 0 ) { + first = this.views.first(); + prev = first && first.section.prev(); + if(prev) { + newViews.push(this.prepend(prev)); + } + } + + if(newViews.length){ + // RSVP.all(promises) + // .then(function() { + // Check to see if anything new is on screen after rendering + return this.q.enqueue(function(){ + return this.update(delta); + }.bind(this)); + + + // }.bind(this)); + + } else { + checking.resolve(false); + return checking.promise; + } + + + }; + + ContinuousViewManager.prototype.trim = function(){ + var task = new RSVP.defer(); + var displayed = this.views.displayed(); + var first = displayed[0]; + var last = displayed[displayed.length-1]; + var firstIndex = this.views.indexOf(first); + var lastIndex = this.views.indexOf(last); + var above = this.views.slice(0, firstIndex); + var below = this.views.slice(lastIndex+1); + + // Erase all but last above + for (var i = 0; i < above.length-1; i++) { + this.erase(above[i], above); + } + + // Erase all except first below + for (var j = 1; j < below.length; j++) { + this.erase(below[j]); + } + + task.resolve(); + return task.promise; + }; + + ContinuousViewManager.prototype.erase = function(view, above){ //Trim + + var prevTop; + var prevLeft; + + if(this.settings.height) { + prevTop = this.container.scrollTop; + prevLeft = this.container.scrollLeft; + } else { + prevTop = window.scrollY; + prevLeft = window.scrollX; + } + + var bounds = view.bounds(); + + this.views.remove(view); + + if(above) { + + if(this.settings.axis === "vertical") { + this.scrollTo(0, prevTop - bounds.height, true); + } else { + this.scrollTo(prevLeft - bounds.width, 0, true); + } + } + + }; + + ContinuousViewManager.prototype.addEventListeners = function(stage){ + + window.addEventListener('unload', function(e){ + this.ignore = true; + // this.scrollTo(0,0); + this.destroy(); + }.bind(this)); + + this.addScrollListeners(); + }; + + ContinuousViewManager.prototype.addScrollListeners = function() { + var scroller; + + this.tick = core.requestAnimationFrame; + + if(this.settings.height) { + this.prevScrollTop = this.container.scrollTop; + this.prevScrollLeft = this.container.scrollLeft; + } else { + this.prevScrollTop = window.scrollY; + this.prevScrollLeft = window.scrollX; + } + + this.scrollDeltaVert = 0; + this.scrollDeltaHorz = 0; + + if(this.settings.height) { + scroller = this.container; + this.scrollTop = this.container.scrollTop; + this.scrollLeft = this.container.scrollLeft; + } else { + scroller = window; + this.scrollTop = window.scrollY; + this.scrollLeft = window.scrollX; + } + + scroller.addEventListener("scroll", this.onScroll.bind(this)); + + // this.tick.call(window, this.onScroll.bind(this)); + + this.scrolled = false; + + }; + + ContinuousViewManager.prototype.onScroll = function(){ + + // if(!this.ignore) { + + if(this.settings.height) { + scrollTop = this.container.scrollTop; + scrollLeft = this.container.scrollLeft; + } else { + scrollTop = window.scrollY; + scrollLeft = window.scrollX; + } + + this.scrollTop = scrollTop; + this.scrollLeft = scrollLeft; + + if(!this.ignore) { + + if((this.scrollDeltaVert === 0 && + this.scrollDeltaHorz === 0) || + this.scrollDeltaVert > this.settings.offsetDelta || + this.scrollDeltaHorz > this.settings.offsetDelta) { + + this.q.enqueue(function() { + this.check(); + }.bind(this)); + // this.check(); + + this.scrollDeltaVert = 0; + this.scrollDeltaHorz = 0; + + this.trigger("scroll", { + top: scrollTop, + left: scrollLeft + }); + + clearTimeout(this.afterScrolled); + this.afterScrolled = setTimeout(function () { + this.trigger("scrolled", { + top: this.scrollTop, + left: this.scrollLeft + }); + }.bind(this)); + + } + + } else { + this.ignore = false; + } + + this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop); + this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft); + + this.prevScrollTop = scrollTop; + this.prevScrollLeft = scrollLeft; + + clearTimeout(this.scrollTimeout); + this.scrollTimeout = setTimeout(function(){ + this.scrollDeltaVert = 0; + this.scrollDeltaHorz = 0; + }.bind(this), 150); + + + this.scrolled = false; + // } + + // this.tick.call(window, this.onScroll.bind(this)); + + }; + + + // ContinuousViewManager.prototype.resizeView = function(view) { + // + // if(this.settings.axis === "horizontal") { + // view.lock("height", this.stage.width, this.stage.height); + // } else { + // view.lock("width", this.stage.width, this.stage.height); + // } + // + // }; + + ContinuousViewManager.prototype.currentLocation = function(){ + + if (this.settings.axis === "vertical") { + this.location = this.scrolledLocation(); + } else { + this.location = this.paginatedLocation(); + } + + return this.location; + }; + + ContinuousViewManager.prototype.scrolledLocation = function(){ + + var visible = this.visible(); + var startPage, endPage; + + var container = this.container.getBoundingClientRect(); + + if(visible.length === 1) { + return this.mapping.page(visible[0].contents, visible[0].section.cfiBase); + } + + if(visible.length > 1) { + + startPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase); + endPage = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase); + + return { + start: startPage.start, + end: endPage.end + }; + } + + }; + + ContinuousViewManager.prototype.paginatedLocation = function(){ + var visible = this.visible(); + var startA, startB, endA, endB; + var pageLeft, pageRight; + var container = this.container.getBoundingClientRect(); + + if(visible.length === 1) { + startA = container.left - visible[0].position().left; + endA = startA + this.layout.spreadWidth; + + return this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA); + } + + if(visible.length > 1) { + + // Left Col + startA = container.left - visible[0].position().left; + endA = startA + this.layout.columnWidth; + + // Right Col + startB = container.left + this.layout.spreadWidth - visible[visible.length-1].position().left; + endB = startB + this.layout.columnWidth; + + pageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA); + pageRight = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase, startB, endB); + + return { + start: pageLeft.start, + end: pageRight.end + }; + } + }; + + /* + Continuous.prototype.current = function(what){ + var view, top; + var container = this.container.getBoundingClientRect(); + var length = this.views.length - 1; + + if(this.settings.axis === "horizontal") { + + for (var i = length; i >= 0; i--) { + view = this.views[i]; + left = view.position().left; + + if(left < container.right) { + + if(this._current == view) { + break; + } + + this._current = view; + break; + } + } + + } else { + + for (var i = length; i >= 0; i--) { + view = this.views[i]; + top = view.bounds().top; + if(top < container.bottom) { + + if(this._current == view) { + break; + } + + this._current = view; + + break; + } + } + + } + + return this._current; + }; + */ + + ContinuousViewManager.prototype.updateLayout = function() { + + if (!this.stage) { + return; + } + + if(this.settings.axis === "vertical") { + this.layout.calculate(this._stageSize.width, this._stageSize.height); + } else { + this.layout.calculate( + this._stageSize.width, + this._stageSize.height, + this.settings.gap + ); + + // Set the look ahead offset for what is visible + this.settings.offset = this.layout.delta; + + this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]); + + } + + // Set the dimensions for views + this.viewSettings.width = this.layout.width; + this.viewSettings.height = this.layout.height; + + this.setLayout(this.layout); + + }; + + ContinuousViewManager.prototype.next = function(){ + + if(this.settings.axis === "horizontal") { + + this.scrollLeft = this.container.scrollLeft; + + if(this.container.scrollLeft + + this.container.offsetWidth + + this.layout.delta < this.container.scrollWidth) { + this.scrollBy(this.layout.delta, 0); + } else { + this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); + } + + } else { + this.scrollBy(0, this.layout.height); + } + }; + + ContinuousViewManager.prototype.prev = function(){ + if(this.settings.axis === "horizontal") { + this.scrollBy(-this.layout.delta, 0); + } else { + this.scrollBy(0, -this.layout.height); + } + }; + + ContinuousViewManager.prototype.updateFlow = function(flow){ + var axis = (flow === "paginated") ? "horizontal" : "vertical"; + + this.settings.axis = axis; + + this.viewSettings.axis = axis; + + this.settings.overflow = (flow === "paginated") ? "hidden" : "auto"; + + // this.views.each(function(view){ + // view.setAxis(axis); + // }); + + if (this.settings.axis === "vertical") { + this.settings.infinite = true; + } else { + this.settings.infinite = false; + } + + }; + module.exports = ContinuousViewManager; + + +/***/ } +/******/ ]) }); - - -//# sourceMappingURL=epub.js.map +; +//# sourceMappingURL=epub.js.map \ No newline at end of file diff --git a/dist/epub.js.map b/dist/epub.js.map index d809a1e..5f3623b 100644 --- a/dist/epub.js.map +++ b/dist/epub.js.map @@ -1 +1 @@ -{"version":3,"sources":["node_modules/browser-pack/_prelude.js","libs/mime/mime.js","node_modules/base64-js/index.js","node_modules/browserify/lib/_empty.js","node_modules/process/browser.js","node_modules/rsvp/dist/rsvp.js","node_modules/urijs/src/SecondLevelDomains.js","node_modules/urijs/src/URI.js","src/book.js","src/contents.js","src/core.js","src/epubcfi.js","src/hook.js","src/layout.js","src/locations.js","src/managers/continuous/index.js","src/managers/default/index.js","src/managers/helpers/stage.js","src/managers/helpers/views.js","src/managers/views/iframe.js","src/mapping.js","src/navigation.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/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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACh8EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClqEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3VA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5hBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC16BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxqBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/hBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3eA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACxjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // the number of equal signs (place holders)\n // if there are two placeholders, than the two characters before it\n // represent one byte\n // if there is only one, then the three characters before it represent 2 bytes\n // this is just a cheap hack to not do indexOf twice\n return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0\n}\n\nfunction byteLength (b64) {\n // base64 is 4/3 + up to two characters of the original data\n return b64.length * 3 / 4 - placeHoldersCount(b64)\n}\n\nfunction toByteArray (b64) {\n var i, j, l, tmp, placeHolders, arr\n var len = b64.length\n placeHolders = placeHoldersCount(b64)\n\n arr = new Arr(len * 3 / 4 - placeHolders)\n\n // if there are placeholders, only get up to the last complete 4 chars\n l = placeHolders > 0 ? len - 4 : len\n\n var L = 0\n\n for (i = 0, j = 0; i < l; i += 4, j += 3) {\n tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]\n arr[L++] = (tmp >> 16) & 0xFF\n arr[L++] = (tmp >> 8) & 0xFF\n arr[L++] = tmp & 0xFF\n }\n\n if (placeHolders === 2) {\n tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[L++] = tmp & 0xFF\n } else if (placeHolders === 1) {\n tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[L++] = (tmp >> 8) & 0xFF\n arr[L++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var output = ''\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n output += lookup[tmp >> 2]\n output += lookup[(tmp << 4) & 0x3F]\n output += '=='\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + (uint8[len - 1])\n output += lookup[tmp >> 10]\n output += lookup[(tmp >> 4) & 0x3F]\n output += lookup[(tmp << 2) & 0x3F]\n output += '='\n }\n\n parts.push(output)\n\n return parts.join('')\n}\n","","// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 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 runTimeout(drainQueue);\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) 2016 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.3.2\n */\n\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (factory((global.RSVP = global.RSVP || {})));\n}(this, (function (exports) { 'use strict';\n\nfunction indexOf(callbacks, callback) {\n for (var i = 0, l = callbacks.length; i < l; i++) {\n if (callbacks[i] === callback) {\n return i;\n }\n }\n\n return -1;\n}\n\nfunction callbacksFor(object) {\n var callbacks = object._promiseCallbacks;\n\n if (!callbacks) {\n callbacks = object._promiseCallbacks = {};\n }\n\n return callbacks;\n}\n\n/**\n @class RSVP.EventTarget\n*/\nvar EventTarget = {\n\n /**\n `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For\n Example:\n ```javascript\n let object = {};\n RSVP.EventTarget.mixin(object);\n object.on('finished', function(event) {\n // handle event\n });\n object.trigger('finished', { detail: value });\n ```\n `EventTarget.mixin` also works with prototypes:\n ```javascript\n let Person = function() {};\n RSVP.EventTarget.mixin(Person.prototype);\n let yehuda = new Person();\n let tom = new Person();\n yehuda.on('poke', function(event) {\n console.log('Yehuda says OW');\n });\n tom.on('poke', function(event) {\n console.log('Tom says OW');\n });\n yehuda.trigger('poke');\n tom.trigger('poke');\n ```\n @method mixin\n @for RSVP.EventTarget\n @private\n @param {Object} object object to extend with EventTarget methods\n */\n mixin: function mixin(object) {\n object['on'] = this['on'];\n object['off'] = this['off'];\n object['trigger'] = this['trigger'];\n object._promiseCallbacks = undefined;\n return object;\n },\n\n /**\n Registers a callback to be executed when `eventName` is triggered\n ```javascript\n object.on('event', function(eventInfo){\n // handle the event\n });\n object.trigger('event');\n ```\n @method on\n @for RSVP.EventTarget\n @private\n @param {String} eventName name of the event to listen for\n @param {Function} callback function to be called when the event is triggered.\n */\n on: function on(eventName, callback) {\n if (typeof callback !== 'function') {\n throw new TypeError('Callback must be a function');\n }\n\n var allCallbacks = callbacksFor(this),\n callbacks = undefined;\n\n callbacks = allCallbacks[eventName];\n\n if (!callbacks) {\n callbacks = allCallbacks[eventName] = [];\n }\n\n if (indexOf(callbacks, callback) === -1) {\n callbacks.push(callback);\n }\n },\n\n /**\n You can use `off` to stop firing a particular callback for an event:\n ```javascript\n function doStuff() { // do stuff! }\n object.on('stuff', doStuff);\n object.trigger('stuff'); // doStuff will be called\n // Unregister ONLY the doStuff callback\n object.off('stuff', doStuff);\n object.trigger('stuff'); // doStuff will NOT be called\n ```\n If you don't pass a `callback` argument to `off`, ALL callbacks for the\n event will not be executed when the event fires. For example:\n ```javascript\n let callback1 = function(){};\n let callback2 = function(){};\n object.on('stuff', callback1);\n object.on('stuff', callback2);\n object.trigger('stuff'); // callback1 and callback2 will be executed.\n object.off('stuff');\n object.trigger('stuff'); // callback1 and callback2 will not be executed!\n ```\n @method off\n @for RSVP.EventTarget\n @private\n @param {String} eventName event to stop listening to\n @param {Function} callback optional argument. If given, only the function\n given will be removed from the event's callback queue. If no `callback`\n argument is given, all callbacks will be removed from the event's callback\n queue.\n */\n off: function off(eventName, callback) {\n var allCallbacks = callbacksFor(this),\n callbacks = undefined,\n index = undefined;\n\n if (!callback) {\n allCallbacks[eventName] = [];\n return;\n }\n\n callbacks = allCallbacks[eventName];\n\n index = indexOf(callbacks, callback);\n\n if (index !== -1) {\n callbacks.splice(index, 1);\n }\n },\n\n /**\n Use `trigger` to fire custom events. For example:\n ```javascript\n object.on('foo', function(){\n console.log('foo event happened!');\n });\n object.trigger('foo');\n // 'foo event happened!' logged to the console\n ```\n You can also pass a value as a second argument to `trigger` that will be\n passed as an argument to all event listeners for the event:\n ```javascript\n object.on('foo', function(value){\n console.log(value.name);\n });\n object.trigger('foo', { name: 'bar' });\n // 'bar' logged to the console\n ```\n @method trigger\n @for RSVP.EventTarget\n @private\n @param {String} eventName name of the event to be triggered\n @param {*} options optional value to be passed to any event handlers for\n the given `eventName`\n */\n trigger: function trigger(eventName, options, label) {\n var allCallbacks = callbacksFor(this),\n callbacks = undefined,\n callback = undefined;\n\n if (callbacks = allCallbacks[eventName]) {\n // Don't cache the callbacks.length since it may grow\n for (var i = 0; i < callbacks.length; i++) {\n callback = callbacks[i];\n\n callback(options, label);\n }\n }\n }\n};\n\nvar config = {\n instrument: false\n};\n\nEventTarget['mixin'](config);\n\nfunction configure(name, value) {\n if (name === 'onerror') {\n // handle for legacy users that expect the actual\n // error to be passed to their function added via\n // `RSVP.configure('onerror', someFunctionHere);`\n config['on']('error', value);\n return;\n }\n\n if (arguments.length === 2) {\n config[name] = value;\n } else {\n return config[name];\n }\n}\n\nfunction objectOrFunction(x) {\n return typeof x === 'function' || typeof x === 'object' && x !== null;\n}\n\nfunction isFunction(x) {\n return typeof x === 'function';\n}\n\nfunction isMaybeThenable(x) {\n return typeof x === 'object' && x !== null;\n}\n\nvar _isArray = undefined;\nif (!Array.isArray) {\n _isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n} else {\n _isArray = Array.isArray;\n}\n\nvar isArray = _isArray;\n\n// Date.now is not available in browsers < IE9\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility\nvar now = Date.now || function () {\n return new Date().getTime();\n};\n\nfunction F() {}\n\nvar 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 F.prototype = o;\n return new F();\n};\n\nvar queue = [];\n\nfunction scheduleFlush() {\n setTimeout(function () {\n for (var i = 0; i < queue.length; i++) {\n var entry = queue[i];\n\n var payload = entry.payload;\n\n payload.guid = payload.key + payload.id;\n payload.childGuid = payload.key + payload.childId;\n if (payload.error) {\n payload.stack = payload.error.stack;\n }\n\n config['trigger'](entry.name, entry.payload);\n }\n queue.length = 0;\n }, 50);\n}\nfunction instrument(eventName, promise, child) {\n if (1 === queue.push({\n name: eventName,\n payload: {\n key: promise._guidKey,\n id: promise._id,\n eventName: eventName,\n detail: promise._result,\n childId: child && child._id,\n label: promise._label,\n timeStamp: now(),\n error: config[\"instrument-with-stack\"] ? new Error(promise._label) : null\n } })) {\n scheduleFlush();\n }\n}\n\n/**\n `RSVP.Promise.resolve` returns a promise that will become resolved with the\n passed `value`. It is shorthand for the following:\n\n ```javascript\n let promise = new RSVP.Promise(function(resolve, reject){\n resolve(1);\n });\n\n promise.then(function(value){\n // value === 1\n });\n ```\n\n Instead of writing the above, your code now simply becomes the following:\n\n ```javascript\n let promise = RSVP.Promise.resolve(1);\n\n promise.then(function(value){\n // value === 1\n });\n ```\n\n @method resolve\n @static\n @param {*} object value that the returned promise will be resolved with\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise that will become fulfilled with the given\n `value`\n*/\nfunction resolve$1(object, label) {\n /*jshint validthis:true */\n var Constructor = this;\n\n if (object && typeof object === 'object' && object.constructor === Constructor) {\n return object;\n }\n\n var promise = new Constructor(noop, label);\n resolve(promise, object);\n return promise;\n}\n\nfunction withOwnPromise() {\n return new TypeError('A promises callback cannot return that same promise.');\n}\n\nfunction noop() {}\n\nvar PENDING = void 0;\nvar FULFILLED = 1;\nvar REJECTED = 2;\n\nvar GET_THEN_ERROR = new ErrorObject();\n\nfunction getThen(promise) {\n try {\n return promise.then;\n } catch (error) {\n GET_THEN_ERROR.error = error;\n return GET_THEN_ERROR;\n }\n}\n\nfunction tryThen(then, value, fulfillmentHandler, rejectionHandler) {\n try {\n then.call(value, fulfillmentHandler, rejectionHandler);\n } catch (e) {\n return e;\n }\n}\n\nfunction handleForeignThenable(promise, thenable, then) {\n config.async(function (promise) {\n var sealed = false;\n var error = tryThen(then, thenable, function (value) {\n if (sealed) {\n return;\n }\n sealed = true;\n if (thenable !== value) {\n resolve(promise, value, undefined);\n } else {\n fulfill(promise, value);\n }\n }, function (reason) {\n if (sealed) {\n return;\n }\n sealed = true;\n\n reject(promise, reason);\n }, 'Settle: ' + (promise._label || ' unknown promise'));\n\n if (!sealed && error) {\n sealed = true;\n reject(promise, error);\n }\n }, promise);\n}\n\nfunction handleOwnThenable(promise, thenable) {\n if (thenable._state === FULFILLED) {\n fulfill(promise, thenable._result);\n } else if (thenable._state === REJECTED) {\n thenable._onError = null;\n reject(promise, thenable._result);\n } else {\n subscribe(thenable, undefined, function (value) {\n if (thenable !== value) {\n resolve(promise, value, undefined);\n } else {\n fulfill(promise, value);\n }\n }, function (reason) {\n return reject(promise, reason);\n });\n }\n}\n\nfunction handleMaybeThenable(promise, maybeThenable, then$$) {\n if (maybeThenable.constructor === promise.constructor && then$$ === then && promise.constructor.resolve === resolve$1) {\n handleOwnThenable(promise, maybeThenable);\n } else {\n if (then$$ === GET_THEN_ERROR) {\n reject(promise, GET_THEN_ERROR.error);\n } else if (then$$ === undefined) {\n fulfill(promise, maybeThenable);\n } else if (isFunction(then$$)) {\n handleForeignThenable(promise, maybeThenable, then$$);\n } else {\n fulfill(promise, maybeThenable);\n }\n }\n}\n\nfunction resolve(promise, value) {\n if (promise === value) {\n fulfill(promise, value);\n } else if (objectOrFunction(value)) {\n handleMaybeThenable(promise, value, getThen(value));\n } else {\n fulfill(promise, value);\n }\n}\n\nfunction publishRejection(promise) {\n if (promise._onError) {\n promise._onError(promise._result);\n }\n\n publish(promise);\n}\n\nfunction fulfill(promise, value) {\n if (promise._state !== PENDING) {\n return;\n }\n\n promise._result = value;\n promise._state = FULFILLED;\n\n if (promise._subscribers.length === 0) {\n if (config.instrument) {\n instrument('fulfilled', promise);\n }\n } else {\n config.async(publish, promise);\n }\n}\n\nfunction reject(promise, reason) {\n if (promise._state !== PENDING) {\n return;\n }\n promise._state = REJECTED;\n promise._result = reason;\n config.async(publishRejection, promise);\n}\n\nfunction subscribe(parent, child, onFulfillment, onRejection) {\n var subscribers = parent._subscribers;\n var length = subscribers.length;\n\n parent._onError = null;\n\n subscribers[length] = child;\n subscribers[length + FULFILLED] = onFulfillment;\n subscribers[length + REJECTED] = onRejection;\n\n if (length === 0 && parent._state) {\n config.async(publish, parent);\n }\n}\n\nfunction publish(promise) {\n var subscribers = promise._subscribers;\n var settled = promise._state;\n\n if (config.instrument) {\n instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);\n }\n\n if (subscribers.length === 0) {\n return;\n }\n\n var child = undefined,\n callback = undefined,\n detail = promise._result;\n\n for (var i = 0; i < subscribers.length; i += 3) {\n child = subscribers[i];\n callback = subscribers[i + settled];\n\n if (child) {\n invokeCallback(settled, child, callback, detail);\n } else {\n callback(detail);\n }\n }\n\n promise._subscribers.length = 0;\n}\n\nfunction ErrorObject() {\n this.error = null;\n}\n\nvar TRY_CATCH_ERROR = new ErrorObject();\n\nfunction tryCatch(callback, detail) {\n try {\n return callback(detail);\n } catch (e) {\n TRY_CATCH_ERROR.error = e;\n return TRY_CATCH_ERROR;\n }\n}\n\nfunction invokeCallback(settled, promise, callback, detail) {\n var hasCallback = isFunction(callback),\n value = undefined,\n error = undefined,\n succeeded = undefined,\n failed = undefined;\n\n if (hasCallback) {\n value = tryCatch(callback, detail);\n\n if (value === TRY_CATCH_ERROR) {\n failed = true;\n error = value.error;\n value = null;\n } else {\n succeeded = true;\n }\n\n if (promise === value) {\n reject(promise, withOwnPromise());\n return;\n }\n } else {\n value = detail;\n succeeded = true;\n }\n\n if (promise._state !== PENDING) {\n // noop\n } else if (hasCallback && succeeded) {\n resolve(promise, value);\n } else if (failed) {\n reject(promise, error);\n } else if (settled === FULFILLED) {\n fulfill(promise, value);\n } else if (settled === REJECTED) {\n reject(promise, value);\n }\n}\n\nfunction initializePromise(promise, resolver) {\n var resolved = false;\n try {\n resolver(function (value) {\n if (resolved) {\n return;\n }\n resolved = true;\n resolve(promise, value);\n }, function (reason) {\n if (resolved) {\n return;\n }\n resolved = true;\n reject(promise, reason);\n });\n } catch (e) {\n reject(promise, e);\n }\n}\n\nfunction then(onFulfillment, onRejection, label) {\n var _arguments = arguments;\n\n var parent = this;\n var state = parent._state;\n\n if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {\n config.instrument && instrument('chained', parent, parent);\n return parent;\n }\n\n parent._onError = null;\n\n var child = new parent.constructor(noop, label);\n var result = parent._result;\n\n config.instrument && instrument('chained', parent, child);\n\n if (state) {\n (function () {\n var callback = _arguments[state - 1];\n config.async(function () {\n return invokeCallback(state, child, callback, result);\n });\n })();\n } else {\n subscribe(parent, child, onFulfillment, onRejection);\n }\n\n return child;\n}\n\nfunction makeSettledResult(state, position, value) {\n if (state === FULFILLED) {\n return {\n state: 'fulfilled',\n value: value\n };\n } else {\n return {\n state: 'rejected',\n reason: value\n };\n }\n}\n\nfunction Enumerator(Constructor, input, abortOnReject, label) {\n this._instanceConstructor = Constructor;\n this.promise = new Constructor(noop, label);\n this._abortOnReject = abortOnReject;\n\n if (this._validateInput(input)) {\n this._input = input;\n this.length = input.length;\n this._remaining = input.length;\n\n this._init();\n\n if (this.length === 0) {\n fulfill(this.promise, this._result);\n } else {\n this.length = this.length || 0;\n this._enumerate();\n if (this._remaining === 0) {\n fulfill(this.promise, this._result);\n }\n }\n } else {\n reject(this.promise, this._validationError());\n }\n}\n\nEnumerator.prototype._validateInput = function (input) {\n return isArray(input);\n};\n\nEnumerator.prototype._validationError = function () {\n return new Error('Array Methods must be provided an Array');\n};\n\nEnumerator.prototype._init = function () {\n this._result = new Array(this.length);\n};\n\nEnumerator.prototype._enumerate = function () {\n var length = this.length;\n var promise = this.promise;\n var input = this._input;\n\n for (var i = 0; promise._state === PENDING && i < length; i++) {\n this._eachEntry(input[i], i);\n }\n};\n\nEnumerator.prototype._settleMaybeThenable = function (entry, i) {\n var c = this._instanceConstructor;\n var resolve = c.resolve;\n\n if (resolve === resolve$1) {\n var then$$ = getThen(entry);\n\n if (then$$ === then && entry._state !== PENDING) {\n entry._onError = null;\n this._settledAt(entry._state, i, entry._result);\n } else if (typeof then$$ !== 'function') {\n this._remaining--;\n this._result[i] = this._makeResult(FULFILLED, i, entry);\n } else if (c === Promise) {\n var promise = new c(noop);\n handleMaybeThenable(promise, entry, then$$);\n this._willSettleAt(promise, i);\n } else {\n this._willSettleAt(new c(function (resolve) {\n return resolve(entry);\n }), i);\n }\n } else {\n this._willSettleAt(resolve(entry), i);\n }\n};\n\nEnumerator.prototype._eachEntry = function (entry, i) {\n if (isMaybeThenable(entry)) {\n this._settleMaybeThenable(entry, i);\n } else {\n this._remaining--;\n this._result[i] = this._makeResult(FULFILLED, i, entry);\n }\n};\n\nEnumerator.prototype._settledAt = function (state, i, value) {\n var promise = this.promise;\n\n if (promise._state === PENDING) {\n this._remaining--;\n\n if (this._abortOnReject && state === REJECTED) {\n reject(promise, value);\n } else {\n this._result[i] = this._makeResult(state, i, value);\n }\n }\n\n if (this._remaining === 0) {\n fulfill(promise, this._result);\n }\n};\n\nEnumerator.prototype._makeResult = function (state, i, value) {\n return value;\n};\n\nEnumerator.prototype._willSettleAt = function (promise, i) {\n var enumerator = this;\n\n subscribe(promise, undefined, function (value) {\n return enumerator._settledAt(FULFILLED, i, value);\n }, function (reason) {\n return enumerator._settledAt(REJECTED, i, reason);\n });\n};\n\n/**\n `RSVP.Promise.all` accepts an array of promises, and returns a new promise which\n is fulfilled with an array of fulfillment values for the passed promises, or\n rejected with the reason of the first passed promise to be rejected. It casts all\n elements of the passed iterable to promises as it runs this algorithm.\n\n Example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.resolve(2);\n let promise3 = RSVP.resolve(3);\n let promises = [ promise1, promise2, promise3 ];\n\n RSVP.Promise.all(promises).then(function(array){\n // The array here would be [ 1, 2, 3 ];\n });\n ```\n\n If any of the `promises` given to `RSVP.all` are rejected, the first promise\n that is rejected will be given as an argument to the returned promises's\n rejection handler. For example:\n\n Example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.reject(new Error(\"2\"));\n let promise3 = RSVP.reject(new Error(\"3\"));\n let promises = [ promise1, promise2, promise3 ];\n\n RSVP.Promise.all(promises).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(error) {\n // error.message === \"2\"\n });\n ```\n\n @method all\n @static\n @param {Array} entries array of promises\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when all `promises` have been\n fulfilled, or rejected if any of them become rejected.\n @static\n*/\nfunction all(entries, label) {\n return new Enumerator(this, entries, true, /* abort on reject */label).promise;\n}\n\n/**\n `RSVP.Promise.race` returns a new promise which is settled in the same way as the\n first passed promise to settle.\n\n Example:\n\n ```javascript\n let promise1 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 1');\n }, 200);\n });\n\n let promise2 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 2');\n }, 100);\n });\n\n RSVP.Promise.race([promise1, promise2]).then(function(result){\n // result === 'promise 2' because it was resolved before promise1\n // was resolved.\n });\n ```\n\n `RSVP.Promise.race` is deterministic in that only the state of the first\n settled promise matters. For example, even if other promises given to the\n `promises` array argument are resolved, but the first settled promise has\n become rejected before the other promises became fulfilled, the returned\n promise will become rejected:\n\n ```javascript\n let promise1 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 1');\n }, 200);\n });\n\n let promise2 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n reject(new Error('promise 2'));\n }, 100);\n });\n\n RSVP.Promise.race([promise1, promise2]).then(function(result){\n // Code here never runs\n }, function(reason){\n // reason.message === 'promise 2' because promise 2 became rejected before\n // promise 1 became fulfilled\n });\n ```\n\n An example real-world use case is implementing timeouts:\n\n ```javascript\n RSVP.Promise.race([ajax('foo.json'), timeout(5000)])\n ```\n\n @method race\n @static\n @param {Array} entries array of promises to observe\n @param {String} label optional string for describing the promise returned.\n Useful for tooling.\n @return {Promise} a promise which settles in the same way as the first passed\n promise to settle.\n*/\nfunction race(entries, label) {\n /*jshint validthis:true */\n var Constructor = this;\n\n var promise = new Constructor(noop, label);\n\n if (!isArray(entries)) {\n reject(promise, new TypeError('You must pass an array to race.'));\n return promise;\n }\n\n for (var i = 0; promise._state === PENDING && i < entries.length; i++) {\n subscribe(Constructor.resolve(entries[i]), undefined, function (value) {\n return resolve(promise, value);\n }, function (reason) {\n return reject(promise, reason);\n });\n }\n\n return promise;\n}\n\n/**\n `RSVP.Promise.reject` returns a promise rejected with the passed `reason`.\n It is shorthand for the following:\n\n ```javascript\n let promise = new RSVP.Promise(function(resolve, reject){\n reject(new Error('WHOOPS'));\n });\n\n promise.then(function(value){\n // Code here doesn't run because the promise is rejected!\n }, function(reason){\n // reason.message === 'WHOOPS'\n });\n ```\n\n Instead of writing the above, your code now simply becomes the following:\n\n ```javascript\n let promise = RSVP.Promise.reject(new Error('WHOOPS'));\n\n promise.then(function(value){\n // Code here doesn't run because the promise is rejected!\n }, function(reason){\n // reason.message === 'WHOOPS'\n });\n ```\n\n @method reject\n @static\n @param {*} reason value that the returned promise will be rejected with.\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise rejected with the given `reason`.\n*/\nfunction reject$1(reason, label) {\n /*jshint validthis:true */\n var Constructor = this;\n var promise = new Constructor(noop, label);\n reject(promise, reason);\n return promise;\n}\n\nvar guidKey = 'rsvp_' + now() + '-';\nvar counter = 0;\n\nfunction needsResolver() {\n throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');\n}\n\nfunction needsNew() {\n throw new TypeError(\"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.\");\n}\n\n/**\n Promise objects represent the eventual result of an asynchronous operation. The\n primary way of interacting with a promise is through its `then` method, which\n registers callbacks to receive either a promise’s eventual value or the reason\n why the promise cannot be fulfilled.\n\n Terminology\n -----------\n\n - `promise` is an object or function with a `then` method whose behavior conforms to this specification.\n - `thenable` is an object or function that defines a `then` method.\n - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).\n - `exception` is a value that is thrown using the throw statement.\n - `reason` is a value that indicates why a promise was rejected.\n - `settled` the final resting state of a promise, fulfilled or rejected.\n\n A promise can be in one of three states: pending, fulfilled, or rejected.\n\n Promises that are fulfilled have a fulfillment value and are in the fulfilled\n state. Promises that are rejected have a rejection reason and are in the\n rejected state. A fulfillment value is never a thenable.\n\n Promises can also be said to *resolve* a value. If this value is also a\n promise, then the original promise's settled state will match the value's\n settled state. So a promise that *resolves* a promise that rejects will\n itself reject, and a promise that *resolves* a promise that fulfills will\n itself fulfill.\n\n\n Basic Usage:\n ------------\n\n ```js\n let promise = new Promise(function(resolve, reject) {\n // on success\n resolve(value);\n\n // on failure\n reject(reason);\n });\n\n promise.then(function(value) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Advanced Usage:\n ---------------\n\n Promises shine when abstracting away asynchronous interactions such as\n `XMLHttpRequest`s.\n\n ```js\n function getJSON(url) {\n return new Promise(function(resolve, reject){\n let xhr = new XMLHttpRequest();\n\n xhr.open('GET', url);\n xhr.onreadystatechange = handler;\n xhr.responseType = 'json';\n xhr.setRequestHeader('Accept', 'application/json');\n xhr.send();\n\n function handler() {\n if (this.readyState === this.DONE) {\n if (this.status === 200) {\n resolve(this.response);\n } else {\n reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));\n }\n }\n };\n });\n }\n\n getJSON('/posts.json').then(function(json) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Unlike callbacks, promises are great composable primitives.\n\n ```js\n Promise.all([\n getJSON('/posts'),\n getJSON('/comments')\n ]).then(function(values){\n values[0] // => postsJSON\n values[1] // => commentsJSON\n\n return values;\n });\n ```\n\n @class RSVP.Promise\n @param {function} resolver\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @constructor\n*/\nfunction Promise(resolver, label) {\n this._id = counter++;\n this._label = label;\n this._state = undefined;\n this._result = undefined;\n this._subscribers = [];\n\n config.instrument && instrument('created', this);\n\n if (noop !== resolver) {\n typeof resolver !== 'function' && needsResolver();\n this instanceof Promise ? initializePromise(this, resolver) : needsNew();\n }\n}\n\nPromise.cast = resolve$1; // deprecated\nPromise.all = all;\nPromise.race = race;\nPromise.resolve = resolve$1;\nPromise.reject = reject$1;\n\nPromise.prototype = {\n constructor: Promise,\n\n _guidKey: guidKey,\n\n _onError: function _onError(reason) {\n var promise = this;\n config.after(function () {\n if (promise._onError) {\n config['trigger']('error', reason, promise._label);\n }\n });\n },\n\n /**\n The primary way of interacting with a promise is through its `then` method,\n which registers callbacks to receive either a promise's eventual value or the\n reason why the promise cannot be fulfilled.\n \n ```js\n findUser().then(function(user){\n // user is available\n }, function(reason){\n // user is unavailable, and you are given the reason why\n });\n ```\n \n Chaining\n --------\n \n The return value of `then` is itself a promise. This second, 'downstream'\n promise is resolved with the return value of the first promise's fulfillment\n or rejection handler, or rejected if the handler throws an exception.\n \n ```js\n findUser().then(function (user) {\n return user.name;\n }, function (reason) {\n return 'default name';\n }).then(function (userName) {\n // If `findUser` fulfilled, `userName` will be the user's name, otherwise it\n // will be `'default name'`\n });\n \n findUser().then(function (user) {\n throw new Error('Found user, but still unhappy');\n }, function (reason) {\n throw new Error('`findUser` rejected and we\\'re unhappy');\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.\n // If `findUser` rejected, `reason` will be '`findUser` rejected and we\\'re unhappy'.\n });\n ```\n If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.\n \n ```js\n findUser().then(function (user) {\n throw new PedagogicalException('Upstream error');\n }).then(function (value) {\n // never reached\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // The `PedgagocialException` is propagated all the way down to here\n });\n ```\n \n Assimilation\n ------------\n \n Sometimes the value you want to propagate to a downstream promise can only be\n retrieved asynchronously. This can be achieved by returning a promise in the\n fulfillment or rejection handler. The downstream promise will then be pending\n until the returned promise is settled. This is called *assimilation*.\n \n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // The user's comments are now available\n });\n ```\n \n If the assimliated promise rejects, then the downstream promise will also reject.\n \n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // If `findCommentsByAuthor` fulfills, we'll have the value here\n }, function (reason) {\n // If `findCommentsByAuthor` rejects, we'll have the reason here\n });\n ```\n \n Simple Example\n --------------\n \n Synchronous Example\n \n ```javascript\n let result;\n \n try {\n result = findResult();\n // success\n } catch(reason) {\n // failure\n }\n ```\n \n Errback Example\n \n ```js\n findResult(function(result, err){\n if (err) {\n // failure\n } else {\n // success\n }\n });\n ```\n \n Promise Example;\n \n ```javascript\n findResult().then(function(result){\n // success\n }, function(reason){\n // failure\n });\n ```\n \n Advanced Example\n --------------\n \n Synchronous Example\n \n ```javascript\n let author, books;\n \n try {\n author = findAuthor();\n books = findBooksByAuthor(author);\n // success\n } catch(reason) {\n // failure\n }\n ```\n \n Errback Example\n \n ```js\n \n function foundBooks(books) {\n \n }\n \n function failure(reason) {\n \n }\n \n findAuthor(function(author, err){\n if (err) {\n failure(err);\n // failure\n } else {\n try {\n findBoooksByAuthor(author, function(books, err) {\n if (err) {\n failure(err);\n } else {\n try {\n foundBooks(books);\n } catch(reason) {\n failure(reason);\n }\n }\n });\n } catch(error) {\n failure(err);\n }\n // success\n }\n });\n ```\n \n Promise Example;\n \n ```javascript\n findAuthor().\n then(findBooksByAuthor).\n then(function(books){\n // found books\n }).catch(function(reason){\n // something went wrong\n });\n ```\n \n @method then\n @param {Function} onFulfillment\n @param {Function} onRejection\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n then: then,\n\n /**\n `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same\n as the catch block of a try/catch statement.\n \n ```js\n function findAuthor(){\n throw new Error('couldn\\'t find that author');\n }\n \n // synchronous\n try {\n findAuthor();\n } catch(reason) {\n // something went wrong\n }\n \n // async with promises\n findAuthor().catch(function(reason){\n // something went wrong\n });\n ```\n \n @method catch\n @param {Function} onRejection\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'catch': function _catch(onRejection, label) {\n return this.then(undefined, onRejection, label);\n },\n\n /**\n `finally` will be invoked regardless of the promise's fate just as native\n try/catch/finally behaves\n \n Synchronous example:\n \n ```js\n findAuthor() {\n if (Math.random() > 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 _finally(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\nfunction Result() {\n this.value = undefined;\n}\n\nvar ERROR = new Result();\nvar GET_THEN_ERROR$1 = new Result();\n\nfunction getThen$1(obj) {\n try {\n return obj.then;\n } catch (error) {\n ERROR.value = error;\n return ERROR;\n }\n}\n\nfunction tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch (error) {\n ERROR.value = error;\n return ERROR;\n }\n}\n\nfunction makeObject(_, argumentNames) {\n var obj = {};\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 (var i = 0; i < argumentNames.length; i++) {\n var _name = argumentNames[i];\n obj[_name] = args[i + 1];\n }\n\n return obj;\n}\n\nfunction 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\nfunction wrapThenable(_then, promise) {\n return {\n then: function then(onFulFillment, onRejection) {\n return _then.call(promise, onFulFillment, onRejection);\n }\n };\n}\n\n/**\n `RSVP.denodeify` takes a 'node-style' function and returns a function that\n will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the\n browser when you'd prefer to use promises over using callbacks. For example,\n `denodeify` transforms the following:\n\n ```javascript\n let fs = require('fs');\n\n fs.readFile('myfile.txt', function(err, data){\n if (err) return handleError(err);\n handleData(data);\n });\n ```\n\n into:\n\n ```javascript\n let fs = require('fs');\n let readFile = RSVP.denodeify(fs.readFile);\n\n readFile('myfile.txt').then(handleData, handleError);\n ```\n\n If the node function has multiple success parameters, then `denodeify`\n just returns the first one:\n\n ```javascript\n let request = RSVP.denodeify(require('request'));\n\n request('http://example.com').then(function(res) {\n // ...\n });\n ```\n\n However, if you need all success parameters, setting `denodeify`'s\n second parameter to `true` causes it to return all success parameters\n as an array:\n\n ```javascript\n let request = RSVP.denodeify(require('request'), true);\n\n request('http://example.com').then(function(result) {\n // result[0] -> res\n // result[1] -> body\n });\n ```\n\n Or if you pass it an array with names it returns the parameters as a hash:\n\n ```javascript\n let request = RSVP.denodeify(require('request'), ['res', 'body']);\n\n request('http://example.com').then(function(result) {\n // result.res\n // result.body\n });\n ```\n\n Sometimes you need to retain the `this`:\n\n ```javascript\n let app = require('express')();\n let render = RSVP.denodeify(app.render.bind(app));\n ```\n\n The denodified function inherits from the original function. It works in all\n environments, except IE 10 and below. Consequently all properties of the original\n function are available to you. However, any properties you change on the\n denodeified function won't be changed on the original function. Example:\n\n ```javascript\n let request = RSVP.denodeify(require('request')),\n cookieJar = request.jar(); // <- Inheritance is used here\n\n request('http://example.com', {jar: cookieJar}).then(function(res) {\n // cookieJar.cookies holds now the cookies returned by example.com\n });\n ```\n\n Using `denodeify` makes it easier to compose asynchronous operations instead\n of using callbacks. For example, instead of:\n\n ```javascript\n let fs = require('fs');\n\n fs.readFile('myfile.txt', function(err, data){\n if (err) { ... } // Handle error\n fs.writeFile('myfile2.txt', data, function(err){\n if (err) { ... } // Handle error\n console.log('done')\n });\n });\n ```\n\n you can chain the operations together using `then` from the returned promise:\n\n ```javascript\n let fs = require('fs');\n let readFile = RSVP.denodeify(fs.readFile);\n let writeFile = RSVP.denodeify(fs.writeFile);\n\n readFile('myfile.txt').then(function(data){\n return writeFile('myfile2.txt', data);\n }).then(function(){\n console.log('done')\n }).catch(function(error){\n // Handle error\n });\n ```\n\n @method denodeify\n @static\n @for RSVP\n @param {Function} nodeFunc a 'node-style' function that takes a callback as\n its last argument. The callback expects an error to be passed as its first\n argument (if an error occurred, otherwise null), and the value from the\n operation as its second argument ('function(err, value){ }').\n @param {Boolean|Array} [options] An optional paramter that if set\n to `true` causes the promise to fulfill with the callback's success arguments\n as an array. This is useful if the node function has multiple success\n paramters. If you set this paramter to an array with names, the promise will\n fulfill with a hash with these names as keys and the success parameters as\n values.\n @return {Function} a function that wraps `nodeFunc` to return an\n `RSVP.Promise`\n @static\n*/\nfunction denodeify(nodeFunc, options) {\n var fn = function fn() {\n var self = this;\n var l = arguments.length;\n var args = new Array(l + 1);\n var promiseInput = false;\n\n for (var i = 0; i < l; ++i) {\n var arg = arguments[i];\n\n if (!promiseInput) {\n // TODO: clean this up\n promiseInput = needsPromiseInput(arg);\n if (promiseInput === GET_THEN_ERROR$1) {\n var p = new Promise(noop);\n reject(p, GET_THEN_ERROR$1.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new Promise(noop);\n\n args[l] = function (err, val) {\n if (err) reject(promise, err);else if (options === undefined) resolve(promise, val);else if (options === true) resolve(promise, arrayResult(arguments));else if (isArray(options)) resolve(promise, makeObject(arguments, options));else resolve(promise, val);\n };\n\n if (promiseInput) {\n return handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n}\n\nfunction handleValueInput(promise, args, nodeFunc, self) {\n var result = tryApply(nodeFunc, self, args);\n if (result === ERROR) {\n reject(promise, result.value);\n }\n return promise;\n}\n\nfunction handlePromiseInput(promise, args, nodeFunc, self) {\n return Promise.all(args).then(function (args) {\n var result = tryApply(nodeFunc, self, args);\n if (result === ERROR) {\n reject(promise, result.value);\n }\n return promise;\n });\n}\n\nfunction needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === Promise) {\n return true;\n } else {\n return getThen$1(arg);\n }\n } else {\n return false;\n }\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.all`.\n\n @method all\n @static\n @for RSVP\n @param {Array} array Array of promises.\n @param {String} label An optional label. This is useful\n for tooling.\n*/\nfunction all$1(array, label) {\n return Promise.all(array, label);\n}\n\nfunction AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false, /* don't abort on reject */label);\n}\n\nAllSettled.prototype = o_create(Enumerator.prototype);\nAllSettled.prototype._superConstructor = Enumerator;\nAllSettled.prototype._makeResult = makeSettledResult;\nAllSettled.prototype._validationError = function () {\n return new Error('allSettled must be called with an array');\n};\n\n/**\n `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing\n a fail-fast method, it waits until all the promises have returned and\n shows you all the results. This is useful if you want to handle multiple\n promises' failure states together as a set.\n\n Returns a promise that is fulfilled when all the given promises have been\n settled. The return promise is fulfilled with an array of the states of\n the promises passed into the `promises` array argument.\n\n Each state object will either indicate fulfillment or rejection, and\n provide the corresponding value or reason. The states will take one of\n the following formats:\n\n ```javascript\n { state: 'fulfilled', value: value }\n or\n { state: 'rejected', reason: reason }\n ```\n\n Example:\n\n ```javascript\n let promise1 = RSVP.Promise.resolve(1);\n let promise2 = RSVP.Promise.reject(new Error('2'));\n let promise3 = RSVP.Promise.reject(new Error('3'));\n let promises = [ promise1, promise2, promise3 ];\n\n RSVP.allSettled(promises).then(function(array){\n // array == [\n // { state: 'fulfilled', value: 1 },\n // { state: 'rejected', reason: Error },\n // { state: 'rejected', reason: Error }\n // ]\n // Note that for the second item, reason.message will be '2', and for the\n // third item, reason.message will be '3'.\n }, function(error) {\n // Not run. (This block would only be called if allSettled had failed,\n // for instance if passed an incorrect argument type.)\n });\n ```\n\n @method allSettled\n @static\n @for RSVP\n @param {Array} entries\n @param {String} label - optional string that describes the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled with an array of the settled\n states of the constituent promises.\n*/\nfunction allSettled(entries, label) {\n return new AllSettled(Promise, entries, label).promise;\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.race`.\n\n @method race\n @static\n @for RSVP\n @param {Array} array Array of promises.\n @param {String} label An optional label. This is useful\n for tooling.\n */\nfunction race$1(array, label) {\n return Promise.race(array, label);\n}\n\nfunction PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n}\n\nPromiseHash.prototype = o_create(Enumerator.prototype);\nPromiseHash.prototype._superConstructor = Enumerator;\nPromiseHash.prototype._init = function () {\n this._result = {};\n};\n\nPromiseHash.prototype._validateInput = function (input) {\n return input && typeof input === 'object';\n};\n\nPromiseHash.prototype._validationError = function () {\n return new Error('Promise.hash must be called with an object');\n};\n\nPromiseHash.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 === 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 = undefined;\n\n for (var i = 0; promise._state === PENDING && i < length; i++) {\n result = results[i];\n enumerator._eachEntry(result.entry, result.position);\n }\n};\n\n/**\n `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array\n for its `promises` argument.\n\n Returns a promise that is fulfilled when all the given promises have been\n fulfilled, or rejected if any of them become rejected. The returned promise\n is fulfilled with a hash that has the same key names as the `promises` object\n argument. If any of the values in the object are not promises, they will\n simply be copied over to the fulfilled object.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.resolve(1),\n yourPromise: RSVP.resolve(2),\n theirPromise: RSVP.resolve(3),\n notAPromise: 4\n };\n\n RSVP.hash(promises).then(function(hash){\n // hash here is an object that looks like:\n // {\n // myPromise: 1,\n // yourPromise: 2,\n // theirPromise: 3,\n // notAPromise: 4\n // }\n });\n ````\n\n If any of the `promises` given to `RSVP.hash` are rejected, the first promise\n that is rejected will be given as the reason to the rejection handler.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.resolve(1),\n rejectedPromise: RSVP.reject(new Error('rejectedPromise')),\n anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')),\n };\n\n RSVP.hash(promises).then(function(hash){\n // Code here never runs because there are rejected promises!\n }, function(reason) {\n // reason.message === 'rejectedPromise'\n });\n ```\n\n An important note: `RSVP.hash` is intended for plain JavaScript objects that\n are just a set of keys and values. `RSVP.hash` will NOT preserve prototype\n chains.\n\n Example:\n\n ```javascript\n function MyConstructor(){\n this.example = RSVP.resolve('Example');\n }\n\n MyConstructor.prototype = {\n protoProperty: RSVP.resolve('Proto Property')\n };\n\n let myObject = new MyConstructor();\n\n RSVP.hash(myObject).then(function(hash){\n // protoProperty will not be present, instead you will just have an\n // object that looks like:\n // {\n // example: 'Example'\n // }\n //\n // hash.hasOwnProperty('protoProperty'); // false\n // 'undefined' === typeof hash.protoProperty\n });\n ```\n\n @method hash\n @static\n @for RSVP\n @param {Object} object\n @param {String} label optional string that describes the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when all properties of `promises`\n have been fulfilled, or rejected if any of them become rejected.\n*/\nfunction hash(object, label) {\n return new PromiseHash(Promise, object, label).promise;\n}\n\nfunction HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n}\n\nHashSettled.prototype = o_create(PromiseHash.prototype);\nHashSettled.prototype._superConstructor = Enumerator;\nHashSettled.prototype._makeResult = makeSettledResult;\n\nHashSettled.prototype._validationError = function () {\n return new Error('hashSettled must be called with an object');\n};\n\n/**\n `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object\n instead of an array for its `promises` argument.\n\n Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method,\n but like `RSVP.allSettled`, `hashSettled` waits until all the\n constituent promises have returned and then shows you all the results\n with their states and values/reasons. This is useful if you want to\n handle multiple promises' failure states together as a set.\n\n Returns a promise that is fulfilled when all the given promises have been\n settled, or rejected if the passed parameters are invalid.\n\n The returned promise is fulfilled with a hash that has the same key names as\n the `promises` object argument. If any of the values in the object are not\n promises, they will be copied over to the fulfilled object and marked with state\n 'fulfilled'.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.Promise.resolve(1),\n yourPromise: RSVP.Promise.resolve(2),\n theirPromise: RSVP.Promise.resolve(3),\n notAPromise: 4\n };\n\n RSVP.hashSettled(promises).then(function(hash){\n // hash here is an object that looks like:\n // {\n // myPromise: { state: 'fulfilled', value: 1 },\n // yourPromise: { state: 'fulfilled', value: 2 },\n // theirPromise: { state: 'fulfilled', value: 3 },\n // notAPromise: { state: 'fulfilled', value: 4 }\n // }\n });\n ```\n\n If any of the `promises` given to `RSVP.hash` are rejected, the state will\n be set to 'rejected' and the reason for rejection provided.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.Promise.resolve(1),\n rejectedPromise: RSVP.Promise.reject(new Error('rejection')),\n anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')),\n };\n\n RSVP.hashSettled(promises).then(function(hash){\n // hash here is an object that looks like:\n // {\n // myPromise: { state: 'fulfilled', value: 1 },\n // rejectedPromise: { state: 'rejected', reason: Error },\n // anotherRejectedPromise: { state: 'rejected', reason: Error },\n // }\n // Note that for rejectedPromise, reason.message == 'rejection',\n // and for anotherRejectedPromise, reason.message == 'more rejection'.\n });\n ```\n\n An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that\n are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype\n chains.\n\n Example:\n\n ```javascript\n function MyConstructor(){\n this.example = RSVP.Promise.resolve('Example');\n }\n\n MyConstructor.prototype = {\n protoProperty: RSVP.Promise.resolve('Proto Property')\n };\n\n let myObject = new MyConstructor();\n\n RSVP.hashSettled(myObject).then(function(hash){\n // protoProperty will not be present, instead you will just have an\n // object that looks like:\n // {\n // example: { state: 'fulfilled', value: 'Example' }\n // }\n //\n // hash.hasOwnProperty('protoProperty'); // false\n // 'undefined' === typeof hash.protoProperty\n });\n ```\n\n @method hashSettled\n @for RSVP\n @param {Object} object\n @param {String} label optional string that describes the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when when all properties of `promises`\n have been settled.\n @static\n*/\nfunction hashSettled(object, label) {\n return new HashSettled(Promise, object, label).promise;\n}\n\nfunction rethrow(reason) {\n setTimeout(function () {\n throw reason;\n });\n throw reason;\n}\n\n/**\n `RSVP.defer` returns an object similar to jQuery's `$.Deferred`.\n `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s\n interface. New code should use the `RSVP.Promise` constructor instead.\n\n The object returned from `RSVP.defer` is a plain object with three properties:\n\n * promise - an `RSVP.Promise`.\n * reject - a function that causes the `promise` property on this object to\n become rejected\n * resolve - a function that causes the `promise` property on this object to\n become fulfilled.\n\n Example:\n\n ```javascript\n let deferred = RSVP.defer();\n\n deferred.resolve(\"Success!\");\n\n deferred.promise.then(function(value){\n // value here is \"Success!\"\n });\n ```\n\n @method defer\n @static\n @for RSVP\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Object}\n */\nfunction defer(label) {\n var deferred = { resolve: undefined, reject: undefined };\n\n deferred.promise = new Promise(function (resolve, reject) {\n deferred.resolve = resolve;\n deferred.reject = reject;\n }, label);\n\n return deferred;\n}\n\n/**\n `RSVP.map` is similar to JavaScript's native `map` method, except that it\n waits for all promises to become fulfilled before running the `mapFn` on\n each item in given to `promises`. `RSVP.map` returns a promise that will\n become fulfilled with the result of running `mapFn` on the values the promises\n become fulfilled with.\n\n For example:\n\n ```javascript\n\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.resolve(2);\n let promise3 = RSVP.resolve(3);\n let promises = [ promise1, promise2, promise3 ];\n\n let mapFn = function(item){\n return item + 1;\n };\n\n RSVP.map(promises, mapFn).then(function(result){\n // result is [ 2, 3, 4 ]\n });\n ```\n\n If any of the `promises` given to `RSVP.map` are rejected, the first promise\n that is rejected will be given as an argument to the returned promise's\n rejection handler. For example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.reject(new Error('2'));\n let promise3 = RSVP.reject(new Error('3'));\n let promises = [ promise1, promise2, promise3 ];\n\n let mapFn = function(item){\n return item + 1;\n };\n\n RSVP.map(promises, mapFn).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(reason) {\n // reason.message === '2'\n });\n ```\n\n `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,\n say you want to get all comments from a set of blog posts, but you need\n the blog posts first because they contain a url to those comments.\n\n ```javscript\n\n let mapFn = function(blogPost){\n // getComments does some ajax and returns an RSVP.Promise that is fulfilled\n // with some comments data\n return getComments(blogPost.comments_url);\n };\n\n // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled\n // with some blog post data\n RSVP.map(getBlogPosts(), mapFn).then(function(comments){\n // comments is the result of asking the server for the comments\n // of all blog posts returned from getBlogPosts()\n });\n ```\n\n @method map\n @static\n @for RSVP\n @param {Array} promises\n @param {Function} mapFn function to be called on each fulfilled promise.\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled with the result of calling\n `mapFn` on each fulfilled promise or value when they become fulfilled.\n The promise will be rejected if any of the given `promises` become rejected.\n @static\n*/\nfunction map(promises, mapFn, label) {\n return Promise.all(promises, label).then(function (values) {\n if (!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 Promise.all(results, label);\n });\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.resolve`.\n\n @method resolve\n @static\n @for RSVP\n @param {*} value value that the returned promise will be resolved with\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise that will become fulfilled with the given\n `value`\n*/\nfunction resolve$2(value, label) {\n return Promise.resolve(value, label);\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.reject`.\n\n @method reject\n @static\n @for RSVP\n @param {*} reason value that the returned promise will be rejected with.\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise rejected with the given `reason`.\n*/\nfunction reject$2(reason, label) {\n return Promise.reject(reason, label);\n}\n\n/**\n `RSVP.filter` is similar to JavaScript's native `filter` method, except that it\n waits for all promises to become fulfilled before running the `filterFn` on\n each item in given to `promises`. `RSVP.filter` returns a promise that will\n become fulfilled with the result of running `filterFn` on the values the\n promises become fulfilled with.\n\n For example:\n\n ```javascript\n\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.resolve(2);\n let promise3 = RSVP.resolve(3);\n\n let promises = [promise1, promise2, promise3];\n\n let filterFn = function(item){\n return item > 1;\n };\n\n RSVP.filter(promises, filterFn).then(function(result){\n // result is [ 2, 3 ]\n });\n ```\n\n If any of the `promises` given to `RSVP.filter` are rejected, the first promise\n that is rejected will be given as an argument to the returned promise's\n rejection handler. For example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.reject(new Error('2'));\n let promise3 = RSVP.reject(new Error('3'));\n let promises = [ promise1, promise2, promise3 ];\n\n let filterFn = function(item){\n return item > 1;\n };\n\n RSVP.filter(promises, filterFn).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(reason) {\n // reason.message === '2'\n });\n ```\n\n `RSVP.filter` will also wait for any promises returned from `filterFn`.\n For instance, you may want to fetch a list of users then return a subset\n of those users based on some asynchronous operation:\n\n ```javascript\n\n let alice = { name: 'alice' };\n let bob = { name: 'bob' };\n let users = [ alice, bob ];\n\n let promises = users.map(function(user){\n return RSVP.resolve(user);\n });\n\n let filterFn = function(user){\n // Here, Alice has permissions to create a blog post, but Bob does not.\n return getPrivilegesForUser(user).then(function(privs){\n return privs.can_create_blog_post === true;\n });\n };\n RSVP.filter(promises, filterFn).then(function(users){\n // true, because the server told us only Alice can create a blog post.\n users.length === 1;\n // false, because Alice is the only user present in `users`\n users[0] === bob;\n });\n ```\n\n @method filter\n @static\n @for RSVP\n @param {Array} promises\n @param {Function} filterFn - function to be called on each resolved value to\n filter the final results.\n @param {String} label optional string describing the promise. Useful for\n tooling.\n @return {Promise}\n*/\n\nfunction resolveAll(promises, label) {\n return Promise.all(promises, label);\n}\n\nfunction resolveSingle(promise, label) {\n return Promise.resolve(promise, label).then(function (promises) {\n return resolveAll(promises, label);\n });\n}\nfunction filter(promises, filterFn, label) {\n var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label);\n return promise.then(function (values) {\n if (!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 resolveAll(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\nvar len = 0;\nvar vertxNext = undefined;\nfunction asap(callback, arg) {\n queue$1[len] = callback;\n queue$1[len + 1] = arg;\n len += 2;\n if (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 scheduleFlush$1();\n }\n}\n\nvar browserWindow = typeof window !== 'undefined' ? window : undefined;\nvar browserGlobal = browserWindow || {};\nvar BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;\nvar isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';\n\n// test for web worker but not in IE10\nvar isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';\n\n// node\nfunction 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 return nextTick(flush);\n };\n}\n\n// vertx\nfunction useVertxTimer() {\n return function () {\n return vertxNext(flush);\n };\n}\n\nfunction useMutationObserver() {\n var iterations = 0;\n var observer = new BrowserMutationObserver(flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function () {\n return node.data = iterations = ++iterations % 2;\n };\n}\n\n// web worker\nfunction useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = flush;\n return function () {\n return channel.port2.postMessage(0);\n };\n}\n\nfunction useSetTimeout() {\n return function () {\n return setTimeout(flush, 1);\n };\n}\n\nvar queue$1 = new Array(1000);\n\nfunction flush() {\n for (var i = 0; i < len; i += 2) {\n var callback = queue$1[i];\n var arg = queue$1[i + 1];\n\n callback(arg);\n\n queue$1[i] = undefined;\n queue$1[i + 1] = undefined;\n }\n\n len = 0;\n}\n\nfunction attemptVertex() {\n try {\n var r = require;\n var vertx = r('vertx');\n vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return useVertxTimer();\n } catch (e) {\n return useSetTimeout();\n }\n}\n\nvar scheduleFlush$1 = undefined;\n// Decide what async method to use to triggering processing of queued callbacks:\nif (isNode) {\n scheduleFlush$1 = useNextTick();\n} else if (BrowserMutationObserver) {\n scheduleFlush$1 = useMutationObserver();\n} else if (isWorker) {\n scheduleFlush$1 = useMessageChannel();\n} else if (browserWindow === undefined && typeof require === 'function') {\n scheduleFlush$1 = attemptVertex();\n} else {\n scheduleFlush$1 = useSetTimeout();\n}\n\nvar platform = undefined;\n\n/* global self */\nif (typeof self === 'object') {\n platform = self;\n\n /* global global */\n} else if (typeof global === 'object') {\n platform = global;\n } else {\n throw new Error('no global: `self` or `global` found');\n }\n\nvar _async$filter;\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n// defaults\n\n// the default export here is for backwards compat:\n// https://github.com/tildeio/rsvp.js/issues/434\nconfig.async = asap;\nconfig.after = function (cb) {\n return setTimeout(cb, 0);\n};\nvar cast = resolve$2;\n\nvar async = function async(callback, arg) {\n return config.async(callback, arg);\n};\n\nfunction on() {\n config['on'].apply(config, arguments);\n}\n\nfunction off() {\n config['off'].apply(config, arguments);\n}\n\n// Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`\nif (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {\n var callbacks = window['__PROMISE_INSTRUMENTATION__'];\n configure('instrument', true);\n for (var eventName in callbacks) {\n if (callbacks.hasOwnProperty(eventName)) {\n on(eventName, callbacks[eventName]);\n }\n }\n}var rsvp = (_async$filter = {\n cast: cast,\n Promise: Promise,\n EventTarget: EventTarget,\n all: all$1,\n allSettled: allSettled,\n race: race$1,\n hash: hash,\n hashSettled: hashSettled,\n rethrow: rethrow,\n defer: defer,\n denodeify: denodeify,\n configure: configure,\n on: on,\n off: off,\n resolve: resolve$2,\n reject: reject$2,\n map: map\n}, _defineProperty(_async$filter, 'async', async), _defineProperty(_async$filter, 'filter', // babel seems to error if async isn't a computed prop here...\nfilter), _async$filter);\n\nexports['default'] = rsvp;\nexports.cast = cast;\nexports.Promise = Promise;\nexports.EventTarget = EventTarget;\nexports.all = all$1;\nexports.allSettled = allSettled;\nexports.race = race$1;\nexports.hash = hash;\nexports.hashSettled = hashSettled;\nexports.rethrow = rethrow;\nexports.defer = defer;\nexports.denodeify = denodeify;\nexports.configure = configure;\nexports.on = on;\nexports.off = off;\nexports.resolve = resolve$2;\nexports.reject = reject$2;\nexports.map = map;\nexports.async = async;\nexports.filter = filter;\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceMappingURL=rsvp.map","/*!\n * URI.js - Mutating URLs\n * Second Level Domain (SLD) Support\n *\n * Version: 1.18.1\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 *\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();\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory);\n } else {\n // Browser globals (root is window)\n root.SecondLevelDomains = factory(root);\n }\n}(this, function (root) {\n 'use strict';\n\n // save current SecondLevelDomains variable, if any\n var _SecondLevelDomains = root && root.SecondLevelDomains;\n\n var SLD = {\n // list of known Second Level Domains\n // converted list of SLDs from https://github.com/gavingmiller/second-level-domains\n // ----\n // publicsuffix.org is more current and actually used by a couple of browsers internally.\n // downside is it also contains domains like \"dyndns.org\" - which is fine for the security\n // issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js\n // ----\n list: {\n 'ac':' com gov mil net org ',\n 'ae':' ac co gov mil name net org pro sch ',\n 'af':' com edu gov net org ',\n 'al':' com edu gov mil net org ',\n 'ao':' co ed gv it og pb ',\n 'ar':' com edu gob gov int mil net org tur ',\n 'at':' ac co gv or ',\n 'au':' asn com csiro edu gov id net org ',\n 'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ',\n 'bb':' biz co com edu gov info net org store tv ',\n 'bh':' biz cc com edu gov info net org ',\n 'bn':' com edu gov net org ',\n 'bo':' com edu gob gov int mil net org tv ',\n 'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ',\n 'bs':' com edu gov net org ',\n 'bz':' du et om ov rg ',\n 'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ',\n 'ck':' biz co edu gen gov info net org ',\n 'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ',\n 'co':' com edu gov mil net nom org ',\n 'cr':' ac c co ed fi go or sa ',\n 'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ',\n 'do':' art com edu gob gov mil net org sld web ',\n 'dz':' art asso com edu gov net org pol ',\n 'ec':' com edu fin gov info med mil net org pro ',\n 'eg':' com edu eun gov mil name net org sci ',\n 'er':' com edu gov ind mil net org rochest w ',\n 'es':' com edu gob nom org ',\n 'et':' biz com edu gov info name net org ',\n 'fj':' ac biz com info mil name net org pro ',\n 'fk':' ac co gov net nom org ',\n 'fr':' asso com f gouv nom prd presse tm ',\n 'gg':' co net org ',\n 'gh':' com edu gov mil org ',\n 'gn':' ac com gov net org ',\n 'gr':' com edu gov mil net org ',\n 'gt':' com edu gob ind mil net org ',\n 'gu':' com edu gov net org ',\n 'hk':' com edu gov idv net org ',\n 'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ',\n 'id':' ac co go mil net or sch web ',\n 'il':' ac co gov idf k12 muni net org ',\n 'in':' ac co edu ernet firm gen gov i ind mil net nic org res ',\n 'iq':' com edu gov i mil net org ',\n 'ir':' ac co dnssec gov i id net org sch ',\n 'it':' edu gov ',\n 'je':' co net org ',\n 'jo':' com edu gov mil name net org sch ',\n 'jp':' ac ad co ed go gr lg ne or ',\n 'ke':' ac co go info me mobi ne or sc ',\n 'kh':' com edu gov mil net org per ',\n 'ki':' biz com de edu gov info mob net org tel ',\n 'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ',\n 'kn':' edu gov net org ',\n 'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ',\n 'kw':' com edu gov net org ',\n 'ky':' com edu gov net org ',\n 'kz':' com edu gov mil net org ',\n 'lb':' com edu gov net org ',\n 'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ',\n 'lr':' com edu gov net org ',\n 'lv':' asn com conf edu gov id mil net org ',\n 'ly':' com edu gov id med net org plc sch ',\n 'ma':' ac co gov m net org press ',\n 'mc':' asso tm ',\n 'me':' ac co edu gov its net org priv ',\n 'mg':' com edu gov mil nom org prd tm ',\n 'mk':' com edu gov inf name net org pro ',\n 'ml':' com edu gov net org presse ',\n 'mn':' edu gov org ',\n 'mo':' com edu gov net org ',\n 'mt':' com edu gov net org ',\n 'mv':' aero biz com coop edu gov info int mil museum name net org pro ',\n 'mw':' ac co com coop edu gov int museum net org ',\n 'mx':' com edu gob net org ',\n 'my':' com edu gov mil name net org sch ',\n 'nf':' arts com firm info net other per rec store web ',\n 'ng':' biz com edu gov mil mobi name net org sch ',\n 'ni':' ac co com edu gob mil net nom org ',\n 'np':' com edu gov mil net org ',\n 'nr':' biz com edu gov info net org ',\n 'om':' ac biz co com edu gov med mil museum net org pro sch ',\n 'pe':' com edu gob mil net nom org sld ',\n 'ph':' com edu gov i mil net ngo org ',\n 'pk':' biz com edu fam gob gok gon gop gos gov net org web ',\n 'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ',\n 'pr':' ac biz com edu est gov info isla name net org pro prof ',\n 'ps':' com edu gov net org plo sec ',\n 'pw':' belau co ed go ne or ',\n 'ro':' arts com firm info nom nt org rec store tm www ',\n 'rs':' ac co edu gov in org ',\n 'sb':' com edu gov net org ',\n 'sc':' com edu gov net org ',\n 'sh':' co com edu gov net nom org ',\n 'sl':' com edu gov net org ',\n 'st':' co com consulado edu embaixada gov mil net org principe saotome store ',\n 'sv':' com edu gob org red ',\n 'sz':' ac co org ',\n 'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ',\n 'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ',\n 'tw':' club com ebiz edu game gov idv mil net org ',\n 'mu':' ac co com gov net or org ',\n 'mz':' ac co edu gov org ',\n 'na':' co com ',\n 'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ',\n 'pa':' abo ac com edu gob ing med net nom org sld ',\n 'pt':' com edu gov int net nome org publ ',\n 'py':' com edu gov mil net org ',\n 'qa':' com edu gov mil net org ',\n 're':' asso com nom ',\n 'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ',\n 'rw':' ac co com edu gouv gov int mil net ',\n 'sa':' com edu gov med net org pub sch ',\n 'sd':' com edu gov info med net org tv ',\n 'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ',\n 'sg':' com edu gov idn net org per ',\n 'sn':' art com edu gouv org perso univ ',\n 'sy':' com edu gov mil net news org ',\n 'th':' ac co go in mi net or ',\n 'tj':' ac biz co com edu go gov info int mil name net nic org test web ',\n 'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ',\n 'tz':' ac co go ne or ',\n 'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ',\n 'ug':' ac co go ne or org sc ',\n 'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ',\n 'us':' dni fed isa kids nsn ',\n 'uy':' com edu gub mil net org ',\n 've':' co com edu gob info mil net org web ',\n 'vi':' co com k12 net org ',\n 'vn':' ac biz com edu gov health info int name net org pro ',\n 'ye':' co com gov ltd me net org plc ',\n 'yu':' ac co edu gov org ',\n 'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ',\n 'zm':' ac co com edu gov net org sch '\n },\n // gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost\n // in both performance and memory footprint. No initialization required.\n // http://jsperf.com/uri-js-sld-regex-vs-binary-search/4\n // Following methods use lastIndexOf() rather than array.split() in order\n // to avoid any memory allocations.\n has: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return false;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {\n return false;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return false;\n }\n return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0;\n },\n is: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return false;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset >= 0) {\n return false;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return false;\n }\n return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0;\n },\n get: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return null;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {\n return null;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return null;\n }\n if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) {\n return null;\n }\n return domain.slice(sldOffset+1);\n },\n noConflict: function(){\n if (root.SecondLevelDomains === this) {\n root.SecondLevelDomains = _SecondLevelDomains;\n }\n return this;\n }\n };\n\n return SLD;\n}));\n","/*!\n * URI.js - Mutating URLs\n *\n * Version: 1.18.1\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 *\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.18.1';\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\n if (parts.password) {\n t += ':' + URI.encode(parts.password);\n }\n\n if (t) {\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 switch (getType(name)) {\n case 'String':\n // Nothing to do here\n break;\n\n case 'RegExp':\n for (var key in data) {\n if (hasOwn.call(data, key)) {\n if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) {\n return true;\n }\n }\n }\n\n return false;\n\n case '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\n default:\n throw new TypeError('URI.hasQuery() accepts a string, regular expression or object 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.joinPaths = function() {\n var input = [];\n var segments = [];\n var nonEmptySegments = 0;\n\n for (var i = 0; i < arguments.length; i++) {\n var url = new URI(arguments[i]);\n input.push(url);\n var _segments = url.segment();\n for (var s = 0; s < _segments.length; s++) {\n if (typeof _segments[s] === 'string') {\n segments.push(_segments[s]);\n }\n\n if (_segments[s]) {\n nonEmptySegments++;\n }\n }\n }\n\n if (!segments.length || !nonEmptySegments) {\n return new URI('');\n }\n\n var uri = new URI('').segment(segments);\n\n if (input[0].path() === '' || input[0].path().slice(0, 1) === '/') {\n uri.path('/' + uri.path());\n }\n\n return uri.normalize();\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 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) {\n return '';\n }\n\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 var t = URI.buildUserinfo(this._parts);\n return t ? t.substring(0, t.length -1) : t;\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 _path = URI.recodePath(_path);\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.search(/\\/\\.\\.(\\/|$)/);\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 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 Unarchive = require('./unarchive');\nvar request = require('./request');\nvar EpubCFI = require('./epubcfi');\n\nfunction Book(_url, options){\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\trequestMethod: this.requestMethod\n\t});\n\n\tcore.extend(this.settings, options);\n\n\n\t// Promises\n\tthis.opening = new RSVP.defer();\n\tthis.opened = this.opening.promise;\n\tthis.isOpen = false;\n\n\tthis.url = undefined;\n\n\tthis.loading = {\n\t\tmanifest: new RSVP.defer(),\n\t\tspine: new RSVP.defer(),\n\t\tmetadata: new RSVP.defer(),\n\t\tcover: new RSVP.defer(),\n\t\tnavigation: new RSVP.defer(),\n\t\tpageList: new RSVP.defer()\n\t};\n\n\tthis.loaded = {\n\t\tmanifest: this.loading.manifest.promise,\n\t\tspine: this.loading.spine.promise,\n\t\tmetadata: this.loading.metadata.promise,\n\t\tcover: this.loading.cover.promise,\n\t\tnavigation: this.loading.navigation.promise,\n\t\tpageList: this.loading.pageList.promise\n\t};\n\n\tthis.ready = RSVP.hash(this.loaded);\n\n\t// Queue for methods used before opening\n\tthis.isRendered = false;\n\t// this._q = core.queue(this);\n\n\tthis.request = this.settings.requestMethod.bind(this);\n\n\tthis.spine = new Spine(this.request);\n\tthis.locations = new Locations(this.spine, this.request);\n\n\tif(_url) {\n\t\tthis.open(_url).catch(function (error) {\n\t\t\tvar err = new Error(\"Cannot load book at \"+ _url );\n\t\t\tconsole.error(err);\n\n\t\t\tthis.trigger(\"loadFailed\", error);\n\t\t}.bind(this));\n\t}\n};\n\nBook.prototype.open = function(_url, options){\n\tvar uri;\n\tvar parse = new Parser();\n\tvar epubPackage;\n\tvar epubContainer;\n\tvar book = this;\n\tvar containerPath = \"META-INF/container.xml\";\n\tvar location;\n\tvar absoluteUri;\n\tvar isArrayBuffer = false;\n\tvar isBase64 = options && options.base64;\n\n\tif(!_url) {\n\t\tthis.opening.resolve(this);\n\t\treturn this.opened;\n\t}\n\n\t// Reuse parsed url or create a new uri object\n\t// if(typeof(_url) === \"object\") {\n\t// uri = _url;\n\t// } else {\n\t// uri = core.uri(_url);\n\t// }\n\tif (_url instanceof ArrayBuffer || isBase64) {\n\t\tisArrayBuffer = true;\n\t\tthis.url = '/';\n\t} else {\n\t\turi = URI(_url);\n\t}\n\n\tif (window && window.location && uri) {\n\t\tabsoluteUri = uri.absoluteTo(window.location.href);\n\t\tthis.url = absoluteUri.toString();\n\t} else if (window && window.location) {\n\t\tthis.url = window.location.href;\n\t} else {\n\t\tthis.url = _url;\n\t}\n\n\t// Find path to the Container\n\tif(uri && uri.suffix() === \"opf\") {\n\t\t// Direct link to package, no container\n\t\tthis.packageUrl = _url;\n\t\tthis.containerUrl = '';\n\n\t\tif(uri.origin()) {\n\t\t\tthis.baseUrl = uri.origin() + \"/\" + uri.directory() + \"/\";\n\t\t} else if(absoluteUri){\n\t\t\tthis.baseUrl = absoluteUri.origin();\n\t\t\tthis.baseUrl += absoluteUri.directory() + \"/\";\n\t\t} else {\n\t\t\tthis.baseUrl = uri.directory() + \"/\";\n\t\t}\n\n\t\tepubPackage = this.request(this.packageUrl)\n\t\t\t.catch(function(error) {\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\n\t} else if(isArrayBuffer || isBase64 || this.isArchivedUrl(uri)) {\n\t\t// Book is archived\n\t\tthis.url = '/';\n\t\tthis.containerUrl = URI(containerPath).absoluteTo(this.url).toString();\n\n\t\tepubContainer = this.unarchive(_url, isBase64).\n\t\t\tthen(function() {\n\t\t\t\treturn this.request(this.containerUrl);\n\t\t\t}.bind(this))\n\t\t\t.catch(function(error) {\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\t}\n\t// Find the path to the Package from the container\n\telse if (!uri.suffix()) {\n\n\t\tthis.containerUrl = this.url + containerPath;\n\n\t\tepubContainer = this.request(this.containerUrl)\n\t\t\t.catch(function(error) {\n\t\t\t\t// handle errors in loading container\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\t}\n\n\tif (epubContainer) {\n\t\tepubPackage = epubContainer.\n\t\t\tthen(function(containerXml){\n\t\t\t\treturn parse.container(containerXml); // Container has path to content\n\t\t\t}).\n\t\t\tthen(function(paths){\n\t\t\t\tvar packageUri = URI(paths.packagePath);\n\t\t\t\tvar absPackageUri = packageUri.absoluteTo(book.url);\n\t\t\t\tvar absWindowUri;\n\n\t\t\t\tbook.packageUrl = absPackageUri.toString();\n\t\t\t\tbook.encoding = paths.encoding;\n\n\t\t\t\t// Set Url relative to the content\n\t\t\t\tif(absPackageUri.origin()) {\n\t\t\t\t\tbook.baseUrl = absPackageUri.origin() + absPackageUri.directory() + \"/\";\n\t\t\t\t} else {\n\t\t\t\t\tif(packageUri.directory()) {\n\t\t\t\t\t\tbook.baseUrl = \"/\" + packageUri.directory() + \"/\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbook.baseUrl = \"/\"\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn book.request(book.packageUrl);\n\t\t\t}).catch(function(error) {\n\t\t\t\t// handle errors in either of the two requests\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\t}\n\n\tepubPackage.then(function(packageXml) {\n\n\t\tif (!packageXml) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get package information from epub opf\n\t\tbook.unpack(packageXml);\n\n\t\t// Resolve promises\n\t\tbook.loading.manifest.resolve(book.package.manifest);\n\t\tbook.loading.metadata.resolve(book.package.metadata);\n\t\tbook.loading.spine.resolve(book.spine);\n\t\tbook.loading.cover.resolve(book.cover);\n\n\t\tbook.isOpen = true;\n\n\t\t// Clear queue of any waiting book request\n\n\t\t// Resolve book opened promise\n\t\tbook.opening.resolve(book);\n\n\t}).catch(function(error) {\n\t\t// handle errors in parsing the book\n\t\t// console.error(error.message, error.stack);\n\t\tbook.opening.reject(error);\n\t});\n\n\treturn this.opened;\n};\n\nBook.prototype.unpack = function(packageXml){\n\tvar book = this,\n\t\t\tparse = new Parser();\n\n\tbook.package = parse.packageContents(packageXml); // Extract info from contents\n\tif(!book.package) {\n\t\treturn;\n\t}\n\n\tbook.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths\n\n\tthis.spine.load(book.package);\n\n\tbook.navigation = new Navigation(book.package, this.request);\n\tbook.navigation.load().then(function(toc){\n\t\tbook.toc = toc;\n\t\tbook.loading.navigation.resolve(book.toc);\n\t});\n\n\t// //-- Set Global Layout setting based on metadata\n\t// MOVE TO RENDER\n\t// book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);\n\n\tbook.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();\n};\n\n// Alias for book.spine.get\nBook.prototype.section = function(target) {\n\treturn this.spine.get(target);\n};\n\n// Sugar to render a book\nBook.prototype.renderTo = function(element, options) {\n\t// var renderMethod = (options && options.method) ?\n\t// options.method :\n\t// \"single\";\n\n\tthis.rendition = new Rendition(this, options);\n\tthis.rendition.attachTo(element);\n\n\treturn this.rendition;\n};\n\nBook.prototype.requestMethod = function(_url) {\n\t// Switch request methods\n\tif(this.unarchived) {\n\t\treturn this.unarchived.request(_url);\n\t} else {\n\t\treturn request(_url, null, this.requestCredentials, this.requestHeaders);\n\t}\n\n};\n\nBook.prototype.setRequestCredentials = function(_credentials) {\n\tthis.requestCredentials = _credentials;\n};\n\nBook.prototype.setRequestHeaders = function(_headers) {\n\tthis.requestHeaders = _headers;\n};\n\nBook.prototype.unarchive = function(bookUrl, isBase64){\n\tthis.unarchived = new Unarchive();\n\treturn this.unarchived.open(bookUrl, isBase64);\n};\n\n//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)\nBook.prototype.isArchivedUrl = function(bookUrl){\n\tvar uri;\n\tvar extension;\n\n\tif (bookUrl instanceof ArrayBuffer) {\n\t\treturn true;\n\t}\n\n\t// Reuse parsed url or create a new uri object\n\t// if(typeof(bookUrl) === \"object\") {\n\t// uri = bookUrl;\n\t// } else {\n\t// uri = core.uri(bookUrl);\n\t// }\n\turi = URI(bookUrl);\n\textension = 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.unarchived) {\n\t\t\t\treturn this.unarchived.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\nBook.prototype.range = function(cfiRange) {\n\tvar cfi = new EpubCFI(cfiRange);\n\tvar item = this.spine.get(cfi.spinePos);\n\n\treturn item.load().then(function (contents) {\n\t\tvar range = cfi.toRange(item.document);\n\t\treturn range;\n\t})\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\tconsole.error(event);\n});\n\nRSVP.configure('instrument', false); //-- 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\tconsole.error(event.detail.message, event.detail.stack);\n});\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Mapping = require('./mapping');\n\n\nfunction Contents(doc, content, cfiBase) {\n\t// Blank Cfi for Parsing\n\tthis.epubcfi = new EpubCFI();\n\n\tthis.document = doc;\n\tthis.documentElement = this.document.documentElement;\n\tthis.content = content || this.document.body;\n\tthis.window = this.document.defaultView;\n\t// Dom events to listen for\n\tthis.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n\n\tthis._size = {\n\t\twidth: 0,\n\t\theight: 0\n\t}\n\n\tthis.cfiBase = cfiBase || \"\";\n\n\tthis.listeners();\n};\n\nContents.prototype.width = function(w) {\n\t// var frame = this.documentElement;\n\tvar frame = this.content;\n\n\tif (w && core.isNumber(w)) {\n\t\tw = w + \"px\";\n\t}\n\n\tif (w) {\n\t\tframe.style.width = w;\n\t\t// this.content.style.width = w;\n\t}\n\n\treturn this.window.getComputedStyle(frame)['width'];\n\n\n};\n\nContents.prototype.height = function(h) {\n\t// var frame = this.documentElement;\n\tvar frame = this.content;\n\n\tif (h && core.isNumber(h)) {\n\t\th = h + \"px\";\n\t}\n\n\tif (h) {\n\t\tframe.style.height = h;\n\t\t// this.content.style.height = h;\n\t}\n\n\treturn this.window.getComputedStyle(frame)['height'];\n\n};\n\nContents.prototype.contentWidth = function(w) {\n\n\tvar content = this.content || this.document.body;\n\n\tif (w && core.isNumber(w)) {\n\t\tw = w + \"px\";\n\t}\n\n\tif (w) {\n\t\tcontent.style.width = w;\n\t}\n\n\treturn this.window.getComputedStyle(content)['width'];\n\n\n};\n\nContents.prototype.contentHeight = function(h) {\n\n\tvar content = this.content || this.document.body;\n\n\tif (h && core.isNumber(h)) {\n\t\th = h + \"px\";\n\t}\n\n\tif (h) {\n\t\tcontent.style.height = h;\n\t}\n\n\treturn this.window.getComputedStyle(content)['height'];\n\n};\n\nContents.prototype.textWidth = function() {\n\tvar width;\n\tvar range = this.document.createRange();\n\tvar content = this.content || this.document.body;\n\n\t// Select the contents of frame\n\trange.selectNodeContents(content);\n\n\t// get the width of the text content\n\twidth = range.getBoundingClientRect().width;\n\n\treturn width;\n\n};\n\nContents.prototype.textHeight = function() {\n\tvar height;\n\tvar range = this.document.createRange();\n\tvar content = this.content || this.document.body;\n\n\trange.selectNodeContents(content);\n\n\theight = range.getBoundingClientRect().height;\n\n\treturn height;\n};\n\nContents.prototype.scrollWidth = function() {\n\tvar width = this.documentElement.scrollWidth;\n\n\treturn width;\n};\n\nContents.prototype.scrollHeight = function() {\n\tvar height = this.documentElement.scrollHeight;\n\n\treturn height;\n};\n\nContents.prototype.overflow = function(overflow) {\n\n\tif (overflow) {\n\t\tthis.documentElement.style.overflow = overflow;\n\t}\n\n\treturn this.window.getComputedStyle(this.documentElement)['overflow'];\n};\n\nContents.prototype.overflowX = function(overflow) {\n\n\tif (overflow) {\n\t\tthis.documentElement.style.overflowX = overflow;\n\t}\n\n\treturn this.window.getComputedStyle(this.documentElement)['overflowX'];\n};\n\nContents.prototype.overflowY = function(overflow) {\n\n\tif (overflow) {\n\t\tthis.documentElement.style.overflowY = overflow;\n\t}\n\n\treturn this.window.getComputedStyle(this.documentElement)['overflowY'];\n};\n\nContents.prototype.css = function(property, value) {\n\tvar content = this.content || this.document.body;\n\n\tif (value) {\n\t\tcontent.style[property] = value;\n\t}\n\n\treturn this.window.getComputedStyle(content)[property];\n};\n\nContents.prototype.viewport = function(options) {\n\tvar width, height, scale, scalable;\n\tvar $viewport = this.document.querySelector(\"meta[name='viewport']\");\n\tvar newContent = '';\n\n\t/**\n\t* check for the viewport size\n\t* \n\t*/\n\tif($viewport && $viewport.hasAttribute(\"content\")) {\n\t\tcontent = $viewport.getAttribute(\"content\");\n\t\tcontents = content.split(/\\s*,\\s*/);\n\t\tif(contents[0]){\n\t\t\twidth = contents[0].replace(\"width=\", '').trim();\n\t\t}\n\t\tif(contents[1]){\n\t\t\theight = contents[1].replace(\"height=\", '').trim();\n\t\t}\n\t\tif(contents[2]){\n\t\t\tscale = contents[2].replace(\"initial-scale=\", '').trim();\n\t\t}\n\t\tif(contents[3]){\n\t\t\tscalable = contents[3].replace(\"user-scalable=\", '').trim();\n\t\t}\n\t}\n\n\tif (options) {\n\n\t\tnewContent += \"width=\" + (options.width || width);\n\t\tnewContent += \", height=\" + (options.height || height);\n\t\tif (options.scale || scale) {\n\t\t\tnewContent += \", initial-scale=\" + (options.scale || scale);\n\t\t}\n\t\tif (options.scalable || scalable) {\n\t\t\tnewContent += \", user-scalable=\" + (options.scalable || scalable);\n\t\t}\n\n\t\tif (!$viewport) {\n\t\t\t$viewport = this.document.createElement(\"meta\");\n\t\t\t$viewport.setAttribute(\"name\", \"viewport\");\n\t\t\tthis.document.querySelector('head').appendChild($viewport);\n\t\t}\n\n\t\t$viewport.setAttribute(\"content\", newContent);\n\t}\n\n\n\treturn {\n\t\twidth: parseInt(width),\n\t\theight: parseInt(height)\n\t};\n};\n\n\n// Contents.prototype.layout = function(layoutFunc) {\n//\n// this.iframe.style.display = \"inline-block\";\n//\n// // Reset Body Styles\n// this.content.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//\n// Contents.prototype.onLayout = function(view) {\n// // stub\n// };\n\nContents.prototype.expand = function() {\n\tthis.trigger(\"expand\");\n};\n\nContents.prototype.listeners = function() {\n\n\tthis.imageLoadListeners();\n\n\tthis.mediaQueryListeners();\n\n\t// this.fontLoadListeners();\n\n\tthis.addEventListeners();\n\n\tthis.addSelectionListeners();\n\n\tthis.resizeListeners();\n\n};\n\nContents.prototype.removeListeners = function() {\n\n\tthis.removeEventListeners();\n\n\tthis.removeSelectionListeners();\n};\n\nContents.prototype.resizeListeners = function() {\n\tvar width, height;\n\t// Test size again\n\tclearTimeout(this.expanding);\n\n\twidth = this.scrollWidth();\n\theight = this.scrollHeight();\n\n\tif (width != this._size.width || height != this._size.height) {\n\n\t\tthis._size = {\n\t\t\twidth: width,\n\t\t\theight: height\n\t\t}\n\n\t\tthis.trigger(\"resize\", this._size);\n\t}\n\n\tthis.expanding = setTimeout(this.resizeListeners.bind(this), 350);\n};\n\n//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js\nContents.prototype.mediaQueryListeners = function() {\n\t\tvar sheets = this.document.styleSheets;\n\t\tvar mediaChangeHandler = function(m){\n\t\t\tif(m.matches && !this._expanding) {\n\t\t\t\tsetTimeout(this.expand.bind(this), 1);\n\t\t\t\t// this.expand();\n\t\t\t}\n\t\t}.bind(this);\n\n\t\tfor (var i = 0; i < sheets.length; i += 1) {\n\t\t\t\tvar rules = sheets[i].cssRules;\n\t\t\t\tif(!rules) return; // Stylesheets changed\n\t\t\t\tfor (var j = 0; j < rules.length; j += 1) {\n\t\t\t\t\t\t//if (rules[j].constructor === CSSMediaRule) {\n\t\t\t\t\t\tif(rules[j].media){\n\t\t\t\t\t\t\t\tvar mql = this.window.matchMedia(rules[j].media.mediaText);\n\t\t\t\t\t\t\t\tmql.addListener(mediaChangeHandler);\n\t\t\t\t\t\t\t\t//mql.onchange = mediaChangeHandler;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n};\n\nContents.prototype.observe = function(target) {\n\tvar renderer = this;\n\n\t// create an observer instance\n\tvar observer = new MutationObserver(function(mutations) {\n\t\tif(renderer._expanding) {\n\t\t\trenderer.expand();\n\t\t}\n\t\t// mutations.forEach(function(mutation) {\n\t\t// console.log(mutation);\n\t\t// });\n\t});\n\n\t// configuration of the observer:\n\tvar config = { attributes: true, childList: true, characterData: true, subtree: true };\n\n\t// pass in the target node, as well as the observer options\n\tobserver.observe(target, config);\n\n\treturn observer;\n};\n\nContents.prototype.imageLoadListeners = function(target) {\n\tvar images = this.document.querySelectorAll(\"img\");\n\tvar img;\n\tfor (var i = 0; i < images.length; i++) {\n\t\timg = images[i];\n\n\t\tif (typeof img.naturalWidth !== \"undefined\" &&\n\t\t\t\timg.naturalWidth === 0) {\n\t\t\timg.onload = this.expand.bind(this);\n\t\t}\n\t}\n};\n\nContents.prototype.fontLoadListeners = function(target) {\n\tif (!this.document || !this.document.fonts) {\n\t\treturn;\n\t}\n\n\tthis.document.fonts.ready.then(function () {\n\t\tthis.expand();\n\t}.bind(this));\n\n};\n\nContents.prototype.root = function() {\n\tif(!this.document) return null;\n\treturn this.document.documentElement;\n};\n\nContents.prototype.locationOf = function(target, ignoreClass) {\n\tvar position;\n\tvar targetPos = {\"left\": 0, \"top\": 0};\n\n\tif(!this.document) return;\n\n\tif(this.epubcfi.isCfiString(target)) {\n\t\trange = new EpubCFI(target).toRange(this.document, ignoreClass);\n\n\t\tif(range) {\n\t\t\tif (range.startContainer.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\tposition = range.startContainer.getBoundingClientRect();\n\t\t\t\ttargetPos.left = position.left;\n\t\t\t\ttargetPos.top = position.top;\n\t\t\t} else {\n\t\t\t\tposition = range.getBoundingClientRect();\n\t\t\t\ttargetPos.left = position.left;\n\t\t\t\ttargetPos.top = position.top;\n\t\t\t}\n\t\t}\n\n\t} else if(typeof target === \"string\" &&\n\t\ttarget.indexOf(\"#\") > -1) {\n\n\t\tid = target.substring(target.indexOf(\"#\")+1);\n\t\tel = this.document.getElementById(id);\n\n\t\tif(el) {\n\t\t\tposition = el.getBoundingClientRect();\n\t\t\ttargetPos.left = position.left;\n\t\t\ttargetPos.top = position.top;\n\t\t}\n\t}\n\n\treturn targetPos;\n};\n\nContents.prototype.addStylesheet = function(src) {\n\treturn new RSVP.Promise(function(resolve, reject){\n\t\tvar $stylesheet;\n\t\tvar ready = false;\n\n\t\tif(!this.document) {\n\t\t\tresolve(false);\n\t\t\treturn;\n\t\t}\n\n\t\t$stylesheet = this.document.createElement('link');\n\t\t$stylesheet.type = 'text/css';\n\t\t$stylesheet.rel = \"stylesheet\";\n\t\t$stylesheet.href = src;\n\t\t$stylesheet.onload = $stylesheet.onreadystatechange = function() {\n\t\t\tif ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n\t\t\t\tready = true;\n\t\t\t\t// Let apply\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tresolve(true);\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t};\n\n\t\tthis.document.head.appendChild($stylesheet);\n\n\t}.bind(this));\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule\nContents.prototype.addStylesheetRules = function(rules) {\n\tvar styleEl;\n\tvar styleSheet;\n\n\tif(!this.document) return;\n\n\tstyleEl = this.document.createElement('style');\n\n\t// Append style element to head\n\tthis.document.head.appendChild(styleEl);\n\n\t// Grab style sheet\n\tstyleSheet = styleEl.sheet;\n\n\tfor (var i = 0, rl = rules.length; i < rl; i++) {\n\t\tvar j = 1, rule = rules[i], selector = rules[i][0], propStr = '';\n\t\t// If the second argument of a rule is an array of arrays, correct our variables.\n\t\tif (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {\n\t\t\trule = rule[1];\n\t\t\tj = 0;\n\t\t}\n\n\t\tfor (var pl = rule.length; j < pl; j++) {\n\t\t\tvar prop = rule[j];\n\t\t\tpropStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\\n';\n\t\t}\n\n\t\t// Insert CSS Rule\n\t\tstyleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);\n\t}\n};\n\nContents.prototype.addScript = function(src) {\n\n\treturn new RSVP.Promise(function(resolve, reject){\n\t\tvar $script;\n\t\tvar ready = false;\n\n\t\tif(!this.document) {\n\t\t\tresolve(false);\n\t\t\treturn;\n\t\t}\n\n\t\t$script = this.document.createElement('script');\n\t\t$script.type = 'text/javascript';\n\t\t$script.async = true;\n\t\t$script.src = src;\n\t\t$script.onload = $script.onreadystatechange = function() {\n\t\t\tif ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n\t\t\t\tready = true;\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tresolve(true);\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t};\n\n\t\tthis.document.head.appendChild($script);\n\n\t}.bind(this));\n};\n\nContents.prototype.addEventListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.listenedEvents.forEach(function(eventName){\n\t\tthis.document.addEventListener(eventName, this.triggerEvent.bind(this), false);\n\t}, this);\n\n};\n\nContents.prototype.removeEventListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.listenedEvents.forEach(function(eventName){\n\t\tthis.document.removeEventListener(eventName, this.triggerEvent, false);\n\t}, this);\n\n};\n\n// Pass browser events\nContents.prototype.triggerEvent = function(e){\n\tthis.trigger(e.type, e);\n};\n\nContents.prototype.addSelectionListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.document.addEventListener(\"selectionchange\", this.onSelectionChange.bind(this), false);\n};\n\nContents.prototype.removeSelectionListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.document.removeEventListener(\"selectionchange\", this.onSelectionChange, false);\n};\n\nContents.prototype.onSelectionChange = function(e){\n\tif (this.selectionEndTimeout) {\n\t\tclearTimeout(this.selectionEndTimeout);\n\t}\n\tthis.selectionEndTimeout = setTimeout(function() {\n\t\tvar selection = this.window.getSelection();\n\t\tthis.triggerSelectedEvent(selection);\n\t}.bind(this), 500);\n};\n\nContents.prototype.triggerSelectedEvent = function(selection){\n\tvar range, cfirange;\n\n\tif (selection && selection.rangeCount > 0) {\n\t\trange = selection.getRangeAt(0);\n\t\tif(!range.collapsed) {\n\t\t\t// cfirange = this.section.cfiFromRange(range);\n\t\t\tcfirange = new EpubCFI(range, this.cfiBase).toString();\n\t\t\tthis.trigger(\"selected\", cfirange);\n\t\t\tthis.trigger(\"selectedRange\", range);\n\t\t}\n\t}\n};\n\nContents.prototype.range = function(_cfi, ignoreClass){\n\tvar cfi = new EpubCFI(_cfi);\n\treturn cfi.toRange(this.document, ignoreClass);\n};\n\nContents.prototype.map = function(layout){\n\tvar map = new Mapping(layout);\n\treturn map.section();\n};\n\nContents.prototype.size = function(width, height){\n\n\tif (width >= 0) {\n\t\tthis.width(width);\n\t}\n\n\tif (height >= 0) {\n\t\tthis.height(height);\n\t}\n\n\tthis.css(\"margin\", \"0\");\n\tthis.css(\"boxSizing\", \"border-box\");\n\n};\n\nContents.prototype.columns = function(width, height, columnWidth, gap){\n\tvar COLUMN_AXIS = core.prefixed('columnAxis');\n\tvar COLUMN_GAP = core.prefixed('columnGap');\n\tvar COLUMN_WIDTH = core.prefixed('columnWidth');\n\tvar COLUMN_FILL = core.prefixed('columnFill');\n\tvar textWidth;\n\n\tthis.width(width);\n\tthis.height(height);\n\n\t// Deal with Mobile trying to scale to viewport\n\tthis.viewport({ width: width, height: height, scale: 1.0 });\n\n\t// this.overflowY(\"hidden\");\n\tthis.css(\"overflowY\", \"hidden\");\n\tthis.css(\"margin\", \"0\");\n\tthis.css(\"boxSizing\", \"border-box\");\n\tthis.css(\"maxWidth\", \"inherit\");\n\n\tthis.css(COLUMN_AXIS, \"horizontal\");\n\tthis.css(COLUMN_FILL, \"auto\");\n\n\tthis.css(COLUMN_GAP, gap+\"px\");\n\tthis.css(COLUMN_WIDTH, columnWidth+\"px\");\n};\n\nContents.prototype.scale = function(scale, offsetX, offsetY){\n\tvar scale = \"scale(\" + scale + \")\";\n\tvar translate = '';\n\t// this.css(\"position\", \"absolute\"));\n\tthis.css(\"transformOrigin\", \"top left\");\n\n\tif (offsetX >= 0 || offsetY >= 0) {\n\t\ttranslate = \" translate(\" + (offsetX || 0 )+ \"px, \" + (offsetY || 0 )+ \"px )\";\n\t}\n\n\tthis.css(\"transform\", scale + translate);\n};\n\nContents.prototype.fit = function(width, height){\n\tvar viewport = this.viewport();\n\tvar widthScale = width / viewport.width;\n\tvar heightScale = height / viewport.height;\n\tvar scale = widthScale < heightScale ? widthScale : heightScale;\n\n\tvar offsetY = (height - (viewport.height * scale)) / 2;\n\n\tthis.width(width);\n\tthis.height(height);\n\tthis.overflow(\"hidden\");\n\n\t// Deal with Mobile trying to scale to viewport\n\tthis.viewport({ scale: 1.0 });\n\n\t// Scale to the correct size\n\tthis.scale(scale, 0, offsetY);\n\n\tthis.css(\"backgroundColor\", \"transparent\");\n};\n\nContents.prototype.mapPage = function(cfiBase, start, end) {\n\tvar mapping = new Mapping();\n\n\treturn mapping.page(this, cfiBase, start, end);\n};\n\nContents.prototype.destroy = function() {\n\t// Stop observing\n\tif(this.observer) {\n\t\tthis.observer.disconnect();\n\t}\n\n\tthis.removeListeners();\n\n};\n\nRSVP.EventTarget.mixin(Contents.prototype);\n\nmodule.exports = Contents;\n","var RSVP = require('rsvp');\nvar base64 = require('base64-js');\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\tvar uri = {\n\t\t\t\tprotocol : '',\n\t\t\t\thost : '',\n\t\t\t\tpath : '',\n\t\t\t\torigin : '',\n\t\t\t\tdirectory : '',\n\t\t\t\tbase : '',\n\t\t\t\tfilename : '',\n\t\t\t\textension : '',\n\t\t\t\tfragment : '',\n\t\t\t\thref : url\n\t\t\t},\n\t\t\tdoubleSlash = url.indexOf('://'),\n\t\t\tsearch = url.indexOf('?'),\n\t\t\tfragment = url.indexOf(\"#\"),\n\t\t\twithoutProtocol,\n\t\t\tdot,\n\t\t\tfirstSlash;\n\n\tif(fragment != -1) {\n\t\turi.fragment = url.slice(fragment + 1);\n\t\turl = url.slice(0, fragment);\n\t}\n\n\tif(search != -1) {\n\t\turi.search = url.slice(search + 1);\n\t\turl = url.slice(0, search);\n\t\thref = url;\n\t}\n\n\tif(doubleSlash != -1) {\n\t\turi.protocol = url.slice(0, doubleSlash);\n\t\twithoutProtocol = url.slice(doubleSlash+3);\n\t\tfirstSlash = withoutProtocol.indexOf('/');\n\n\t\tif(firstSlash === -1) {\n\t\t\turi.host = uri.path;\n\t\t\turi.path = \"\";\n\t\t} else {\n\t\t\turi.host = withoutProtocol.slice(0, firstSlash);\n\t\t\turi.path = withoutProtocol.slice(firstSlash);\n\t\t}\n\n\n\t\turi.origin = uri.protocol + \"://\" + uri.host;\n\n\t\turi.directory = folder(uri.path);\n\n\t\turi.base = uri.origin + uri.directory;\n\t\t// return origin;\n\t} else {\n\t\turi.path = url;\n\t\turi.directory = folder(url);\n\t\turi.base = uri.directory;\n\t}\n\n\t//-- Filename\n\turi.filename = url.replace(uri.base, '');\n\tdot = uri.filename.lastIndexOf('.');\n\tif(dot != -1) {\n\t\turi.extension = uri.filename.slice(dot+1);\n\t}\n\treturn uri;\n};\n\n//-- Parse out the folder, will return everything before the last slash\nfunction folder(url){\n\n\tvar lastSlash = url.lastIndexOf('/');\n\n\tif(lastSlash == -1) var folder = '';\n\n\tfolder = url.slice(0, lastSlash + 1);\n\n\treturn folder;\n\n};\n*/\nfunction isElement(obj) {\n\t\treturn !!(obj && obj.nodeType == 1);\n};\n\n// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\nfunction uuid() {\n\tvar d = new Date().getTime();\n\tvar uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n\t\t\tvar r = (d + Math.random()*16)%16 | 0;\n\t\t\td = Math.floor(d/16);\n\t\t\treturn (c=='x' ? r : (r&0x7|0x8)).toString(16);\n\t});\n\treturn uuid;\n};\n\n// From Lodash\nfunction values(object) {\n\tvar index = -1,\n\t\t\tprops = Object.keys(object),\n\t\t\tlength = props.length,\n\t\t\tresult = Array(length);\n\n\twhile (++index < length) {\n\t\tresult[index] = object[props[index]];\n\t}\n\treturn result;\n};\n\nfunction resolveUrl(base, path) {\n\tvar url = [],\n\t\tsegments = [],\n\t\tbaseUri = uri(base),\n\t\tpathUri = uri(path),\n\t\tbaseDirectory = baseUri.directory,\n\t\tpathDirectory = pathUri.directory,\n\t\tdirectories = [],\n\t\t// folders = base.split(\"/\"),\n\t\tpaths;\n\n\t// if(uri.host) {\n\t// return path;\n\t// }\n\n\tif(baseDirectory[0] === \"/\") {\n\t\tbaseDirectory = baseDirectory.substring(1);\n\t}\n\n\tif(pathDirectory[pathDirectory.length-1] === \"/\") {\n\t\tbaseDirectory = baseDirectory.substring(0, baseDirectory.length-1);\n\t}\n\n\tif(pathDirectory[0] === \"/\") {\n\t\tpathDirectory = pathDirectory.substring(1);\n\t}\n\n\tif(pathDirectory[pathDirectory.length-1] === \"/\") {\n\t\tpathDirectory = pathDirectory.substring(0, pathDirectory.length-1);\n\t}\n\n\tif(baseDirectory) {\n\t\tdirectories = baseDirectory.split(\"/\");\n\t}\n\n\tpaths = pathDirectory.split(\"/\");\n\n\tpaths.reverse().forEach(function(part, index){\n\t\tif(part === \"..\"){\n\t\t\tdirectories.pop();\n\t\t} else if(part === directories[directories.length-1]) {\n\t\t\tdirectories.pop();\n\t\t\tsegments.unshift(part);\n\t\t} else {\n\t\t\tsegments.unshift(part);\n\t\t}\n\t});\n\n\turl = [baseUri.origin];\n\n\tif(directories.length) {\n\t\turl = url.concat(directories);\n\t}\n\n\tif(segments) {\n\t\turl = url.concat(segments);\n\t}\n\n\turl = url.concat(pathUri.filename);\n\n\treturn url.join(\"/\");\n};\n\nfunction documentHeight() {\n\treturn Math.max(\n\t\t\tdocument.documentElement.clientHeight,\n\t\t\tdocument.body.scrollHeight,\n\t\t\tdocument.documentElement.scrollHeight,\n\t\t\tdocument.body.offsetHeight,\n\t\t\tdocument.documentElement.offsetHeight\n\t);\n};\n\nfunction isNumber(n) {\n\treturn !isNaN(parseFloat(n)) && isFinite(n);\n};\n\nfunction prefixed(unprefixed) {\n\tvar vendors = [\"Webkit\", \"Moz\", \"O\", \"ms\" ],\n\t\tprefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],\n\t\tupper = unprefixed[0].toUpperCase() + unprefixed.slice(1),\n\t\tlength = vendors.length;\n\n\tif (typeof(document) === 'undefined' || typeof(document.body.style[unprefixed]) != 'undefined') {\n\t\treturn unprefixed;\n\t}\n\n\tfor ( var i=0; i < length; i++ ) {\n\t\tif (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {\n\t\t\treturn vendors[i] + upper;\n\t\t}\n\t}\n\n\treturn unprefixed;\n};\n\nfunction defaults(obj) {\n\tfor (var i = 1, length = arguments.length; i < length; i++) {\n\t\tvar source = arguments[i];\n\t\tfor (var prop in source) {\n\t\t\tif (obj[prop] === void 0) obj[prop] = source[prop];\n\t\t}\n\t}\n\treturn obj;\n};\n\nfunction extend(target) {\n\t\tvar sources = [].slice.call(arguments, 1);\n\t\tsources.forEach(function (source) {\n\t\t\tif(!source) return;\n\t\t\tObject.getOwnPropertyNames(source).forEach(function(propName) {\n\t\t\t\tObject.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));\n\t\t\t});\n\t\t});\n\t\treturn 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\tvar location = locationOf(item, array, compareFunction);\n\tarray.splice(location, 0, item);\n\n\treturn location;\n};\n// Returns where something would fit in\nfunction locationOf(item, array, compareFunction, _start, _end) {\n\tvar start = _start || 0;\n\tvar end = _end || array.length;\n\tvar pivot = parseInt(start + (end - start) / 2);\n\tvar compared;\n\tif(!compareFunction){\n\t\tcompareFunction = function(a, b) {\n\t\t\tif(a > b) return 1;\n\t\t\tif(a < b) return -1;\n\t\t\tif(a = b) return 0;\n\t\t};\n\t}\n\tif(end-start <= 0) {\n\t\treturn pivot;\n\t}\n\n\tcompared = compareFunction(array[pivot], item);\n\tif(end-start === 1) {\n\t\treturn compared > 0 ? pivot : pivot + 1;\n\t}\n\n\tif(compared === 0) {\n\t\treturn pivot;\n\t}\n\tif(compared === -1) {\n\t\treturn locationOf(item, array, compareFunction, pivot, end);\n\t} else{\n\t\treturn locationOf(item, array, compareFunction, start, pivot);\n\t}\n};\n// Returns -1 of mpt found\nfunction indexOfSorted(item, array, compareFunction, _start, _end) {\n\tvar start = _start || 0;\n\tvar end = _end || array.length;\n\tvar pivot = parseInt(start + (end - start) / 2);\n\tvar compared;\n\tif(!compareFunction){\n\t\tcompareFunction = function(a, b) {\n\t\t\tif(a > b) return 1;\n\t\t\tif(a < b) return -1;\n\t\t\tif(a = b) return 0;\n\t\t};\n\t}\n\tif(end-start <= 0) {\n\t\treturn -1; // Not found\n\t}\n\n\tcompared = compareFunction(array[pivot], item);\n\tif(end-start === 1) {\n\t\treturn compared === 0 ? pivot : -1;\n\t}\n\tif(compared === 0) {\n\t\treturn pivot; // Found\n\t}\n\tif(compared === -1) {\n\t\treturn indexOfSorted(item, array, compareFunction, pivot, end);\n\t} else{\n\t\treturn indexOfSorted(item, array, compareFunction, start, pivot);\n\t}\n};\n\nfunction bounds(el) {\n\n\tvar style = window.getComputedStyle(el);\n\tvar widthProps = [\"width\", \"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n\tvar heightProps = [\"height\", \"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n\tvar width = 0;\n\tvar height = 0;\n\n\twidthProps.forEach(function(prop){\n\t\twidth += parseFloat(style[prop]) || 0;\n\t});\n\n\theightProps.forEach(function(prop){\n\t\theight += parseFloat(style[prop]) || 0;\n\t});\n\n\treturn {\n\t\theight: height,\n\t\twidth: width\n\t};\n\n};\n\nfunction borders(el) {\n\n\tvar style = window.getComputedStyle(el);\n\tvar widthProps = [\"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n\tvar heightProps = [\"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n\tvar width = 0;\n\tvar height = 0;\n\n\twidthProps.forEach(function(prop){\n\t\twidth += parseFloat(style[prop]) || 0;\n\t});\n\n\theightProps.forEach(function(prop){\n\t\theight += parseFloat(style[prop]) || 0;\n\t});\n\n\treturn {\n\t\theight: height,\n\t\twidth: width\n\t};\n\n};\n\nfunction windowBounds() {\n\n\tvar width = window.innerWidth;\n\tvar height = window.innerHeight;\n\n\treturn {\n\t\ttop: 0,\n\t\tleft: 0,\n\t\tright: width,\n\t\tbottom: height,\n\t\twidth: width,\n\t\theight: height\n\t};\n\n};\n\n//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496\nfunction cleanStringForXpath(str) {\n\t\tvar parts = str.match(/[^'\"]+|['\"]/g);\n\t\tparts = parts.map(function(part){\n\t\t\t\tif (part === \"'\") {\n\t\t\t\t\t\treturn '\\\"\\'\\\"'; // output \"'\"\n\t\t\t\t}\n\n\t\t\t\tif (part === '\"') {\n\t\t\t\t\t\treturn \"\\'\\\"\\'\"; // output '\"'\n\t\t\t\t}\n\t\t\t\treturn \"\\'\" + part + \"\\'\";\n\t\t});\n\t\treturn \"concat(\\'\\',\" + parts.join(\",\") + \")\";\n};\n\nfunction indexOfTextNode(textNode){\n\tvar parent = textNode.parentNode;\n\tvar children = parent.childNodes;\n\tvar sib;\n\tvar index = -1;\n\tfor (var i = 0; i < children.length; i++) {\n\t\tsib = children[i];\n\t\tif(sib.nodeType === Node.TEXT_NODE){\n\t\t\tindex++;\n\t\t}\n\t\tif(sib == textNode) break;\n\t}\n\n\treturn index;\n};\n\nfunction isXml(ext) {\n\treturn ['xml', 'opf', 'ncx'].indexOf(ext) > -1;\n}\n\nfunction createBlob(content, mime){\n\tvar blob = new Blob([content], {type : mime });\n\n\treturn blob;\n};\n\nfunction createBlobUrl(content, mime){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob = this.createBlob(content, mime);\n\n\ttempUrl = _URL.createObjectURL(blob);\n\n\treturn tempUrl;\n};\n\nfunction createBase64Url(content, mime){\n\tvar string;\n\tvar data;\n\tvar datauri;\n\n\tif (typeof(content) !== \"string\") {\n\t\t// Only handles strings\n\t\treturn;\n\t}\n\n\tdata = btoa(content);\n\n\tdatauri = \"data:\" + mime + \";base64,\" + data;\n\n\treturn datauri;\n};\n\nfunction type(obj){\n\treturn Object.prototype.toString.call(obj).slice(8, -1);\n}\n\nfunction parse(markup, mime) {\n\tvar doc;\n\t// console.log(\"parse\", markup);\n\n\tif (typeof DOMParser === \"undefined\") {\n\t\tDOMParser = require('xmldom').DOMParser;\n\t}\n\n\n\tdoc = new DOMParser().parseFromString(markup, mime);\n\n\treturn doc;\n}\n\nfunction qs(el, sel) {\n\tvar elements;\n\n\tif (typeof el.querySelector != \"undefined\") {\n\t\treturn el.querySelector(sel);\n\t} else {\n\t\telements = el.getElementsByTagName(sel);\n\t\tif (elements.length) {\n\t\t\treturn elements[0];\n\t\t}\n\t}\n}\n\nfunction qsa(el, sel) {\n\n\tif (typeof el.querySelector != \"undefined\") {\n\t\treturn el.querySelectorAll(sel);\n\t} else {\n\t\treturn el.getElementsByTagName(sel);\n\t}\n}\n\nfunction qsp(el, sel, props) {\n\tvar q, filtered;\n\tif (typeof el.querySelector != \"undefined\") {\n\t\tsel += '[';\n\t\tfor (var prop in props) {\n\t\t\tsel += prop + \"='\" + props[prop] + \"'\";\n\t\t}\n\t\tsel += ']';\n\t\treturn el.querySelector(sel);\n\t} else {\n\t\tq = el.getElementsByTagName(sel);\n\t\tfiltered = Array.prototype.slice.call(q, 0).filter(function(el) {\n\t\t\tfor (var prop in props) {\n\t\t\t\tif(el.getAttribute(prop) === props[prop]){\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\n\t\tif (filtered) {\n\t\t\treturn filtered[0];\n\t\t}\n\t}\n}\n\nfunction blob2base64(blob, cb) {\n\tvar reader = new FileReader();\n\treader.readAsDataURL(blob);\n\treader.onloadend = function() {\n\t\tcb(reader.result);\n\t}\n}\n\nmodule.exports = {\n\t// 'uri': uri,\n\t// 'folder': folder,\n\t'isElement': isElement,\n\t'uuid': uuid,\n\t'values': values,\n\t'resolveUrl': resolveUrl,\n\t'indexOfSorted': indexOfSorted,\n\t'documentHeight': documentHeight,\n\t'isNumber': isNumber,\n\t'prefixed': prefixed,\n\t'defaults': defaults,\n\t'extend': extend,\n\t'insert': insert,\n\t'locationOf': locationOf,\n\t'indexOfSorted': indexOfSorted,\n\t'requestAnimationFrame': requestAnimationFrame,\n\t'bounds': bounds,\n\t'borders': borders,\n\t'windowBounds': windowBounds,\n\t'cleanStringForXpath': cleanStringForXpath,\n\t'indexOfTextNode': indexOfTextNode,\n\t'isXml': isXml,\n\t'createBlob': createBlob,\n\t'createBlobUrl': createBlobUrl,\n\t'type': type,\n\t'parse' : parse,\n\t'qs' : qs,\n\t'qsa' : qsa,\n\t'qsp' : qsp,\n\t'blob2base64' : blob2base64,\n\t'createBase64Url': createBase64Url\n};\n","var URI = require('urijs');\nvar core = require('./core');\n\n/**\n\tEPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html\n\n\tImplements:\n\t- Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)\n\t- Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)\n\n\tDoes Not Implement:\n\t- Temporal Offset (~)\n\t- Spatial Offset (@)\n\t- Temporal-Spatial Offset (~ + @)\n\t- Text Location Assertion ([)\n*/\n\nfunction EpubCFI(cfiFrom, base, ignoreClass){\n\tvar type;\n\n\tthis.str = '';\n\n\tthis.base = {};\n\tthis.spinePos = 0; // For compatibility\n\n\tthis.range = false; // true || false;\n\n\tthis.path = {};\n\tthis.start = null;\n\tthis.end = null;\n\n\t// Allow instantiation without the 'new' keyword\n\tif (!(this instanceof EpubCFI)) {\n\t\treturn new EpubCFI(cfiFrom, base, ignoreClass);\n\t}\n\n\tif(typeof base === 'string') {\n\t\tthis.base = this.parseComponent(base);\n\t} else if(typeof base === 'object' && base.steps) {\n\t\tthis.base = base;\n\t}\n\n\ttype = this.checkType(cfiFrom);\n\n\n\tif(type === 'string') {\n\t\tthis.str = cfiFrom;\n\t\treturn core.extend(this, this.parse(cfiFrom));\n\t} else if (type === 'range') {\n\t\treturn core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));\n\t} else if (type === 'node') {\n\t\treturn core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));\n\t} else if (type === 'EpubCFI' && cfiFrom.path) {\n\t\treturn cfiFrom;\n\t} else if (!cfiFrom) {\n\t\treturn this;\n\t} else {\n\t\tthrow new TypeError('not a valid argument for EpubCFI');\n\t}\n\n};\n\nEpubCFI.prototype.checkType = function(cfi) {\n\n\tif (this.isCfiString(cfi)) {\n\t\treturn 'string';\n\t// Is a range object\n\t} else if (typeof cfi === 'object' && core.type(cfi) === \"Range\"){\n\t\treturn 'range';\n\t} else if (typeof cfi === 'object' && typeof(cfi.nodeType) != \"undefined\" ){ // || typeof cfi === 'function'\n\t\treturn 'node';\n\t} else if (typeof cfi === 'object' && cfi instanceof EpubCFI){\n\t\treturn 'EpubCFI';\n\t} else {\n\t\treturn false;\n\t}\n};\n\nEpubCFI.prototype.parse = function(cfiStr) {\n\tvar cfi = {\n\t\t\tspinePos: -1,\n\t\t\trange: false,\n\t\t\tbase: {},\n\t\t\tpath: {},\n\t\t\tstart: null,\n\t\t\tend: null\n\t\t};\n\tvar baseComponent, pathComponent, range;\n\n\tif(typeof cfiStr !== \"string\") {\n\t\treturn {spinePos: -1};\n\t}\n\n\tif(cfiStr.indexOf(\"epubcfi(\") === 0 && cfiStr[cfiStr.length-1] === \")\") {\n\t\t// Remove intial epubcfi( and ending )\n\t\tcfiStr = cfiStr.slice(8, cfiStr.length-1);\n\t}\n\n\tbaseComponent = this.getChapterComponent(cfiStr);\n\n\t// Make sure this is a valid cfi or return\n\tif(!baseComponent) {\n\t\treturn {spinePos: -1};\n\t}\n\n\tcfi.base = this.parseComponent(baseComponent);\n\n\tpathComponent = this.getPathComponent(cfiStr);\n\tcfi.path = this.parseComponent(pathComponent);\n\n\trange = this.getRange(cfiStr);\n\n\tif(range) {\n\t\tcfi.range = true;\n\t\tcfi.start = this.parseComponent(range[0]);\n\t\tcfi.end = this.parseComponent(range[1]);\n\t}\n\n\t// Get spine node position\n\t// cfi.spineSegment = cfi.base.steps[1];\n\n\t// Chapter segment is always the second step\n\tcfi.spinePos = cfi.base.steps[1].index;\n\n\treturn cfi;\n};\n\nEpubCFI.prototype.parseComponent = function(componentStr){\n\tvar component = {\n\t\tsteps: [],\n\t\tterminal: {\n\t\t\toffset: null,\n\t\t\tassertion: null\n\t\t}\n\t};\n\tvar parts = componentStr.split(':');\n\tvar steps = parts[0].split('/');\n\tvar terminal;\n\n\tif(parts.length > 1) {\n\t\tterminal = parts[1];\n\t\tcomponent.terminal = this.parseTerminal(terminal);\n\t}\n\n\tif (steps[0] === '') {\n\t\tsteps.shift(); // Ignore the first slash\n\t}\n\n\tcomponent.steps = steps.map(function(step){\n\t\treturn this.parseStep(step);\n\t}.bind(this));\n\n\treturn component;\n};\n\nEpubCFI.prototype.parseStep = function(stepStr){\n\tvar type, num, index, has_brackets, id;\n\n\thas_brackets = stepStr.match(/\\[(.*)\\]/);\n\tif(has_brackets && has_brackets[1]){\n\t\tid = has_brackets[1];\n\t}\n\n\t//-- Check if step is a text node or element\n\tnum = parseInt(stepStr);\n\n\tif(isNaN(num)) {\n\t\treturn;\n\t}\n\n\tif(num % 2 === 0) { // Even = is an element\n\t\ttype = \"element\";\n\t\tindex = num / 2 - 1;\n\t} else {\n\t\ttype = \"text\";\n\t\tindex = (num - 1 ) / 2;\n\t}\n\n\treturn {\n\t\t\"type\" : type,\n\t\t'index' : index,\n\t\t'id' : id || null\n\t};\n};\n\nEpubCFI.prototype.parseTerminal = function(termialStr){\n\tvar characterOffset, textLocationAssertion;\n\tvar assertion = termialStr.match(/\\[(.*)\\]/);\n\n\tif(assertion && assertion[1]){\n\t\tcharacterOffset = parseInt(termialStr.split('[')[0]) || null;\n\t\ttextLocationAssertion = assertion[1];\n\t} else {\n\t\tcharacterOffset = parseInt(termialStr) || null;\n\t}\n\n\treturn {\n\t\t'offset': characterOffset,\n\t\t'assertion': textLocationAssertion\n\t};\n\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n\tvar indirection = cfiStr.split(\"!\");\n\n\treturn indirection[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n\tvar indirection = cfiStr.split(\"!\");\n\n\tif(indirection[1]) {\n\t\tranges = indirection[1].split(',');\n\t\treturn ranges[0];\n\t}\n\n};\n\nEpubCFI.prototype.getRange = function(cfiStr) {\n\n\tvar ranges = cfiStr.split(\",\");\n\n\tif(ranges.length === 3){\n\t\treturn [\n\t\t\tranges[1],\n\t\t\tranges[2]\n\t\t];\n\t}\n\n\treturn false;\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n\tvar splitStr = cfiStr.split(\":\");\n\treturn splitStr[1] || '';\n};\n\nEpubCFI.prototype.joinSteps = function(steps) {\n\tif(!steps) {\n\t\treturn \"\";\n\t}\n\n\treturn steps.map(function(part){\n\t\tvar segment = '';\n\n\t\tif(part.type === 'element') {\n\t\t\tsegment += (part.index + 1) * 2;\n\t\t}\n\n\t\tif(part.type === 'text') {\n\t\t\tsegment += 1 + (2 * part.index); // TODO: double check that this is odd\n\t\t}\n\n\t\tif(part.id) {\n\t\t\tsegment += \"[\" + part.id + \"]\";\n\t\t}\n\n\t\treturn segment;\n\n\t}).join('/');\n\n};\n\nEpubCFI.prototype.segmentString = function(segment) {\n\tvar segmentString = '/';\n\n\tsegmentString += this.joinSteps(segment.steps);\n\n\tif(segment.terminal && segment.terminal.offset != null){\n\t\tsegmentString += ':' + segment.terminal.offset;\n\t}\n\n\tif(segment.terminal && segment.terminal.assertion != null){\n\t\tsegmentString += '[' + segment.terminal.assertion + ']';\n\t}\n\n\treturn segmentString;\n};\n\nEpubCFI.prototype.toString = function() {\n\tvar cfiString = 'epubcfi(';\n\n\tcfiString += this.segmentString(this.base);\n\n\tcfiString += '!';\n\tcfiString += this.segmentString(this.path);\n\n\t// Add Range, if present\n\tif(this.start) {\n\t\tcfiString += ',';\n\t\tcfiString += this.segmentString(this.start);\n\t}\n\n\tif(this.end) {\n\t\tcfiString += ',';\n\t\tcfiString += this.segmentString(this.end);\n\t}\n\n\tcfiString += \")\";\n\n\treturn cfiString;\n};\n\nEpubCFI.prototype.compare = function(cfiOne, cfiTwo) {\n\tif(typeof cfiOne === 'string') {\n\t\tcfiOne = new EpubCFI(cfiOne);\n\t}\n\tif(typeof cfiTwo === 'string') {\n\t\tcfiTwo = new EpubCFI(cfiTwo);\n\t}\n\t// Compare Spine Positions\n\tif(cfiOne.spinePos > cfiTwo.spinePos) {\n\t\treturn 1;\n\t}\n\tif(cfiOne.spinePos < cfiTwo.spinePos) {\n\t\treturn -1;\n\t}\n\n\n\t// Compare Each Step in the First item\n\tfor (var i = 0; i < cfiOne.path.steps.length; i++) {\n\t\tif(!cfiTwo.path.steps[i]) {\n\t\t\treturn 1;\n\t\t}\n\t\tif(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {\n\t\t\treturn 1;\n\t\t}\n\t\tif(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {\n\t\t\treturn -1;\n\t\t}\n\t\t// Otherwise continue checking\n\t}\n\n\t// All steps in First equal to Second and First is Less Specific\n\tif(cfiOne.path.steps.length < cfiTwo.path.steps.length) {\n\t\treturn 1;\n\t}\n\n\t// Compare the charecter offset of the text node\n\tif(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {\n\t\treturn 1;\n\t}\n\tif(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {\n\t\treturn -1;\n\t}\n\n\t// TODO: compare ranges\n\n\t// CFI's are equal\n\treturn 0;\n};\n\nEpubCFI.prototype.step = function(node) {\n\tvar nodeType = (node.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n\treturn {\n\t\t'id' : node.id,\n\t\t'tagName' : node.tagName,\n\t\t'type' : nodeType,\n\t\t'index' : this.position(node)\n\t};\n};\n\nEpubCFI.prototype.filteredStep = function(node, ignoreClass) {\n\tvar filteredNode = this.filter(node, ignoreClass);\n\tvar nodeType;\n\n\t// Node filtered, so ignore\n\tif (!filteredNode) {\n\t\treturn;\n\t}\n\n\t// Otherwise add the filter node in\n\tnodeType = (filteredNode.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n\treturn {\n\t\t'id' : filteredNode.id,\n\t\t'tagName' : filteredNode.tagName,\n\t\t'type' : nodeType,\n\t\t'index' : this.filteredPosition(filteredNode, ignoreClass)\n\t};\n};\n\nEpubCFI.prototype.pathTo = function(node, offset, ignoreClass) {\n\tvar segment = {\n\t\tsteps: [],\n\t\tterminal: {\n\t\t\toffset: null,\n\t\t\tassertion: null\n\t\t}\n\t};\n\tvar currentNode = node;\n\tvar step;\n\n\twhile(currentNode && currentNode.parentNode &&\n\t\t\t\tcurrentNode.parentNode.nodeType != Node.DOCUMENT_NODE) {\n\n\t\tif (ignoreClass) {\n\t\t\tstep = this.filteredStep(currentNode, ignoreClass);\n\t\t} else {\n\t\t\tstep = this.step(currentNode);\n\t\t}\n\n\t\tif (step) {\n\t\t\tsegment.steps.unshift(step);\n\t\t}\n\n\t\tcurrentNode = currentNode.parentNode;\n\n\t}\n\n\tif (offset != null && offset >= 0) {\n\n\t\tsegment.terminal.offset = offset;\n\n\t\t// Make sure we are getting to a textNode if there is an offset\n\t\tif(segment.steps[segment.steps.length-1].type != \"text\") {\n\t\t\tsegment.steps.push({\n\t\t\t\t'type' : \"text\",\n\t\t\t\t'index' : 0\n\t\t\t});\n\t\t}\n\n\t}\n\n\n\treturn segment;\n}\n\nEpubCFI.prototype.equalStep = function(stepA, stepB) {\n\tif (!stepA || !stepB) {\n\t\treturn false;\n\t}\n\n\tif(stepA.index === stepB.index &&\n\t\t stepA.id === stepB.id &&\n\t\t stepA.type === stepB.type) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\nEpubCFI.prototype.fromRange = function(range, base, ignoreClass) {\n\tvar cfi = {\n\t\t\trange: false,\n\t\t\tbase: {},\n\t\t\tpath: {},\n\t\t\tstart: null,\n\t\t\tend: null\n\t\t};\n\n\tvar start = range.startContainer;\n\tvar end = range.endContainer;\n\n\tvar startOffset = range.startOffset;\n\tvar endOffset = range.endOffset;\n\n\tvar needsIgnoring = false;\n\n\tif (ignoreClass) {\n\t\t// Tell pathTo if / what to ignore\n\t\tneedsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null);\n\t}\n\n\n\tif (typeof base === 'string') {\n\t\tcfi.base = this.parseComponent(base);\n\t\tcfi.spinePos = cfi.base.steps[1].index;\n\t} else if (typeof base === 'object') {\n\t\tcfi.base = base;\n\t}\n\n\tif (range.collapsed) {\n\t\tif (needsIgnoring) {\n\t\t\tstartOffset = this.patchOffset(start, startOffset, ignoreClass);\n\t\t}\n\t\tcfi.path = this.pathTo(start, startOffset, ignoreClass);\n\t} else {\n\t\tcfi.range = true;\n\n\t\tif (needsIgnoring) {\n\t\t\tstartOffset = this.patchOffset(start, startOffset, ignoreClass);\n\t\t}\n\n\t\tcfi.start = this.pathTo(start, startOffset, ignoreClass);\n\n\t\tif (needsIgnoring) {\n\t\t\tendOffset = this.patchOffset(end, endOffset, ignoreClass);\n\t\t}\n\n\t\tcfi.end = this.pathTo(end, endOffset, ignoreClass);\n\n\t\t// Create a new empty path\n\t\tcfi.path = {\n\t\t\tsteps: [],\n\t\t\tterminal: null\n\t\t};\n\n\t\t// Push steps that are shared between start and end to the common path\n\t\tvar len = cfi.start.steps.length;\n\t\tvar i;\n\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tif (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {\n\t\t\t\tif(i == len-1) {\n\t\t\t\t\t// Last step is equal, check terminals\n\t\t\t\t\tif(cfi.start.terminal === cfi.end.terminal) {\n\t\t\t\t\t\t// CFI's are equal\n\t\t\t\t\t\tcfi.path.steps.push(cfi.start.steps[i]);\n\t\t\t\t\t\t// Not a range\n\t\t\t\t\t\tcfi.range = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcfi.path.steps.push(cfi.start.steps[i]);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t};\n\n\t\tcfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);\n\t\tcfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length);\n\n\t\t// TODO: Add Sanity check to make sure that the end if greater than the start\n\t}\n\n\treturn cfi;\n}\n\nEpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) {\n\tvar cfi = {\n\t\t\trange: false,\n\t\t\tbase: {},\n\t\t\tpath: {},\n\t\t\tstart: null,\n\t\t\tend: null\n\t\t};\n\n\tvar needsIgnoring = false;\n\n\tif (ignoreClass) {\n\t\t// Tell pathTo if / what to ignore\n\t\tneedsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null);\n\t}\n\n\tif (typeof base === 'string') {\n\t\tcfi.base = this.parseComponent(base);\n\t\tcfi.spinePos = cfi.base.steps[1].index;\n\t} else if (typeof base === 'object') {\n\t\tcfi.base = base;\n\t}\n\n\tcfi.path = this.pathTo(anchor, null, ignoreClass);\n\n\treturn cfi;\n};\n\n\nEpubCFI.prototype.filter = function(anchor, ignoreClass) {\n\tvar needsIgnoring;\n\tvar sibling; // to join with\n\tvar parent, prevSibling, nextSibling;\n\tvar isText = false;\n\n\tif (anchor.nodeType === Node.TEXT_NODE) {\n\t\tisText = true;\n\t\tparent = anchor.parentNode;\n\t\tneedsIgnoring = anchor.parentNode.classList.contains(ignoreClass);\n\t} else {\n\t\tisText = false;\n\t\tneedsIgnoring = anchor.classList.contains(ignoreClass);\n\t}\n\n\tif (needsIgnoring && isText) {\n\t\tpreviousSibling = parent.previousSibling;\n\t\tnextSibling = parent.nextSibling;\n\n\t\t// If the sibling is a text node, join the nodes\n\t\tif (previousSibling && previousSibling.nodeType === Node.TEXT_NODE) {\n\t\t\tsibling = previousSibling;\n\t\t} else if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n\t\t\tsibling = nextSibling;\n\t\t}\n\n\t\tif (sibling) {\n\t\t\treturn sibling;\n\t\t} else {\n\t\t\t// Parent will be ignored on next step\n\t\t\treturn anchor;\n\t\t}\n\n\t} else if (needsIgnoring && !isText) {\n\t\t// Otherwise just skip the element node\n\t\treturn false;\n\t} else {\n\t\t// No need to filter\n\t\treturn anchor;\n\t}\n\n};\n\nEpubCFI.prototype.patchOffset = function(anchor, offset, ignoreClass) {\n\tvar needsIgnoring;\n\tvar sibling;\n\n\tif (anchor.nodeType != Node.TEXT_NODE) {\n\t\tconsole.error(\"Anchor must be a text node\");\n\t\treturn;\n\t}\n\n\tvar curr = anchor;\n\tvar totalOffset = offset;\n\n\t// If the parent is a ignored node, get offset from it's start\n\tif (anchor.parentNode.classList.contains(ignoreClass)) {\n\t\tcurr = anchor.parentNode;\n\t}\n\n\twhile (curr.previousSibling) {\n\t\tif(curr.previousSibling.nodeType === Node.ELEMENT_NODE) {\n\t\t\t// Originally a text node, so join\n\t\t\tif(curr.previousSibling.classList.contains(ignoreClass)){\n\t\t\t\ttotalOffset += curr.previousSibling.textContent.length;\n\t\t\t} else {\n\t\t\t\tbreak; // Normal node, dont join\n\t\t\t}\n\t\t} else {\n\t\t\t// If the previous sibling is a text node, join the nodes\n\t\t\ttotalOffset += curr.previousSibling.textContent.length;\n\t\t}\n\n\t\tcurr = curr.previousSibling;\n\t}\n\n\treturn totalOffset;\n\n};\n\nEpubCFI.prototype.normalizedMap = function(children, nodeType, ignoreClass) {\n\tvar output = {};\n\tvar prevIndex = -1;\n\tvar i, len = children.length;\n\tvar currNodeType;\n\tvar prevNodeType;\n\n\tfor (i = 0; i < len; i++) {\n\n\t\tcurrNodeType = children[i].nodeType;\n\n\t\t// Check if needs ignoring\n\t\tif (currNodeType === Node.ELEMENT_NODE &&\n\t\t\t\tchildren[i].classList.contains(ignoreClass)) {\n\t\t\tcurrNodeType = Node.TEXT_NODE;\n\t\t}\n\n\t\tif (i > 0 &&\n\t\t\t\tcurrNodeType === Node.TEXT_NODE &&\n\t\t\t\tprevNodeType === Node.TEXT_NODE) {\n\t\t\t// join text nodes\n\t\t\toutput[i] = prevIndex;\n\t\t} else if (nodeType === currNodeType){\n\t\t\tprevIndex = prevIndex + 1;\n\t\t\toutput[i] = prevIndex;\n\t\t}\n\n\t\tprevNodeType = currNodeType;\n\n\t}\n\n\treturn output;\n};\n\nEpubCFI.prototype.position = function(anchor) {\n\tvar children, index, map;\n\n\tif (anchor.nodeType === Node.ELEMENT_NODE) {\n\t\tchildren = anchor.parentNode.children;\n\t\tindex = Array.prototype.indexOf.call(children, anchor);\n\t} else {\n\t\tchildren = this.textNodes(anchor.parentNode);\n\t\tindex = children.indexOf(anchor);\n\t}\n\n\treturn index;\n};\n\nEpubCFI.prototype.filteredPosition = function(anchor, ignoreClass) {\n\tvar children, index, map;\n\n\tif (anchor.nodeType === Node.ELEMENT_NODE) {\n\t\tchildren = anchor.parentNode.children;\n\t\tmap = this.normalizedMap(children, Node.ELEMENT_NODE, ignoreClass);\n\t} else {\n\t\tchildren = anchor.parentNode.childNodes;\n\t\t// Inside an ignored node\n\t\tif(anchor.parentNode.classList.contains(ignoreClass)) {\n\t\t\tanchor = anchor.parentNode;\n\t\t\tchildren = anchor.parentNode.childNodes;\n\t\t}\n\t\tmap = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n\t}\n\n\n\tindex = Array.prototype.indexOf.call(children, anchor);\n\n\treturn map[index];\n};\n\nEpubCFI.prototype.stepsToXpath = function(steps) {\n\tvar xpath = [\".\", \"*\"];\n\n\tsteps.forEach(function(step){\n\t\tvar position = step.index + 1;\n\n\t\tif(step.id){\n\t\t\txpath.push(\"*[position()=\" + position + \" and @id='\" + step.id + \"']\");\n\t\t} else if(step.type === \"text\") {\n\t\t\txpath.push(\"text()[\" + position + \"]\");\n\t\t} else {\n\t\t\txpath.push(\"*[\" + position + \"]\");\n\t\t}\n\t});\n\n\treturn xpath.join(\"/\");\n};\n\n\n/*\n\nTo get the last step if needed:\n\n// Get the terminal step\nlastStep = steps[steps.length-1];\n// Get the query string\nquery = this.stepsToQuery(steps);\n// Find the containing element\nstartContainerParent = doc.querySelector(query);\n// Find the text node within that element\nif(startContainerParent && lastStep.type == \"text\") {\n\tcontainer = startContainerParent.childNodes[lastStep.index];\n}\n*/\nEpubCFI.prototype.stepsToQuerySelector = function(steps) {\n\tvar query = [\"html\"];\n\n\tsteps.forEach(function(step){\n\t\tvar position = step.index + 1;\n\n\t\tif(step.id){\n\t\t\tquery.push(\"#\" + step.id);\n\t\t} else if(step.type === \"text\") {\n\t\t\t// unsupported in querySelector\n\t\t\t// query.push(\"text()[\" + position + \"]\");\n\t\t} else {\n\t\t\tquery.push(\"*:nth-child(\" + position + \")\");\n\t\t}\n\t});\n\n\treturn query.join(\">\");\n\n};\n\nEpubCFI.prototype.textNodes = function(container, ignoreClass) {\n\treturn Array.prototype.slice.call(container.childNodes).\n\t\tfilter(function (node) {\n\t\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\treturn true;\n\t\t\t} else if (ignoreClass && node.classList.contains(ignoreClass)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n};\n\nEpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) {\n\tvar doc = _doc || document;\n\tvar container = doc.documentElement;\n\tvar step;\n\tvar len = steps.length;\n\tvar i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tstep = steps[i];\n\n\t\tif(step.type === \"element\") {\n\t\t\tcontainer = container.children[step.index];\n\t\t} else if(step.type === \"text\"){\n\t\t\tcontainer = this.textNodes(container, ignoreClass)[step.index];\n\t\t}\n\n\t};\n\n\treturn container;\n};\n\nEpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) {\n\tvar doc = _doc || document;\n\tvar container;\n\tvar xpath;\n\n\tif(!ignoreClass && typeof doc.evaluate != 'undefined') {\n\t\txpath = this.stepsToXpath(steps);\n\t\tcontainer = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n\t} else if(ignoreClass) {\n\t\tcontainer = this.walkToNode(steps, doc, ignoreClass);\n\t} else {\n\t\tcontainer = this.walkToNode(steps, doc);\n\t}\n\n\treturn container;\n};\n\nEpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {\n\tvar container = this.findNode(steps.slice(0,-1), _doc, ignoreClass);\n\tvar children = container.childNodes;\n\tvar map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n\tvar i;\n\tvar child;\n\tvar len;\n\tvar childIndex;\n\tvar lastStepIndex = steps[steps.length-1].index;\n\n\tfor (var childIndex in map) {\n\t\tif (!map.hasOwnProperty(childIndex)) return;\n\n\t\tif(map[childIndex] === lastStepIndex) {\n\t\t\tchild = children[childIndex];\n\t\t\tlen = child.textContent.length;\n\t\t\tif(offset > len) {\n\t\t\t\toffset = offset - len;\n\t\t\t} else {\n\t\t\t\tif (child.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\tcontainer = child.childNodes[0];\n\t\t\t\t} else {\n\t\t\t\t\tcontainer = child;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tcontainer: container,\n\t\toffset: offset\n\t};\n\n};\n\nEpubCFI.prototype.toRange = function(_doc, ignoreClass) {\n\tvar doc = _doc || document;\n\tvar range = doc.createRange();\n\tvar start, end, startContainer, endContainer;\n\tvar cfi = this;\n\tvar startSteps, endSteps;\n\tvar needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false;\n\tvar missed;\n\n\tif (cfi.range) {\n\t\tstart = cfi.start;\n\t\tstartSteps = cfi.path.steps.concat(start.steps);\n\t\tstartContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);\n\t\tend = cfi.end;\n\t\tendSteps = cfi.path.steps.concat(end.steps);\n\t\tendContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);\n\t} else {\n\t\tstart = cfi.path;\n\t\tstartSteps = cfi.path.steps;\n\t\tstartContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);\n\t}\n\n\tif(startContainer) {\n\t\ttry {\n\n\t\t\tif(start.terminal.offset != null) {\n\t\t\t\trange.setStart(startContainer, start.terminal.offset);\n\t\t\t} else {\n\t\t\t\trange.setStart(startContainer, 0);\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\tmissed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n\t\t\trange.setStart(missed.container, missed.offset);\n\t\t}\n\t} else {\n\t\t// No start found\n\t\treturn null;\n\t}\n\n\tif (endContainer) {\n\t\ttry {\n\n\t\t\tif(end.terminal.offset != null) {\n\t\t\t\trange.setEnd(endContainer, end.terminal.offset);\n\t\t\t} else {\n\t\t\t\trange.setEnd(endContainer, 0);\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\tmissed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n\t\t\trange.setEnd(missed.container, missed.offset);\n\t\t}\n\t}\n\n\n\t// doc.defaultView.getSelection().addRange(range);\n\treturn range;\n};\n\n// is a cfi string, should be wrapped with \"epubcfi()\"\nEpubCFI.prototype.isCfiString = function(str) {\n\tif(typeof str === 'string' &&\n\t\t\tstr.indexOf(\"epubcfi(\") === 0 &&\n\t\t\tstr[str.length-1] === \")\") {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nEpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {\n\tvar pos = parseInt(_pos),\n\t\tspineNodeIndex = _spineNodeIndex + 1,\n\t\tcfi = '/'+spineNodeIndex+'/';\n\n\tcfi += (pos + 1) * 2;\n\n\tif(id) {\n\t\tcfi += \"[\" + id + \"]\";\n\t}\n\n\treturn cfi;\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\tthis.context = context || this;\n\tthis.hooks = [];\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.register = function(){\n\tfor(var i = 0; i < arguments.length; ++i) {\n\t\tif (typeof arguments[i] === \"function\") {\n\t\t\tthis.hooks.push(arguments[i]);\n\t\t} else {\n\t\t\t// unpack array\n\t\t\tfor(var j = 0; j < arguments[i].length; ++j) {\n\t\t\t\tthis.hooks.push(arguments[i][j]);\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Triggers a hook to run all functions\nHook.prototype.trigger = function(){\n\tvar args = arguments;\n\tvar context = this.context;\n\tvar promises = [];\n\n\tthis.hooks.forEach(function(task, i) {\n\t\tvar executing = task.apply(context, args);\n\n\t\tif(executing && typeof executing[\"then\"] === \"function\") {\n\t\t\t// Task is a function that returns a promise\n\t\t\tpromises.push(executing);\n\t\t}\n\t\t// Otherwise Task resolves immediately, continue\n\t});\n\n\n\treturn RSVP.all(promises);\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.list = function(){\n\treturn this.hooks;\n};\n\nHook.prototype.clear = function(){\n\treturn this.hooks = [];\n};\n\nmodule.exports = Hook;\n","var core = require('./core');\nvar RSVP = require('rsvp');\n\nfunction Layout(settings){\n\tthis.name = settings.layout || \"reflowable\";\n\tthis._spread = (settings.spread === \"none\") ? false : true;\n\tthis._minSpreadWidth = settings.spread || 800;\n\tthis._evenSpreads = settings.evenSpreads || false;\n\n\tif (settings.flow === \"scrolled-continuous\" ||\n\t\t\tsettings.flow === \"scrolled-doc\") {\n\t\tthis._flow = \"scrolled\";\n\t} else {\n\t\tthis._flow = \"paginated\";\n\t}\n\n\n\tthis.width = 0;\n\tthis.height = 0;\n\tthis.spreadWidth = 0;\n\tthis.delta = 0;\n\n\tthis.columnWidth = 0;\n\tthis.gap = 0;\n\tthis.divisor = 1;\n};\n\n// paginated | scrolled\nLayout.prototype.flow = function(flow) {\n\tthis._flow = (flow === \"paginated\") ? \"paginated\" : \"scrolled\";\n}\n\n// true | false\nLayout.prototype.spread = function(spread, min) {\n\n\tthis._spread = (spread === \"none\") ? false : true;\n\n\tif (min >= 0) {\n\t\tthis._minSpreadWidth = min;\n\t}\n}\n\nLayout.prototype.calculate = function(_width, _height, _gap){\n\n\tvar divisor = 1;\n\tvar gap = _gap || 0;\n\n\t//-- Check the width and create even width columns\n\tvar fullWidth = Math.floor(_width);\n\tvar width = _width;\n\n\tvar section = Math.floor(width / 8);\n\n\tvar colWidth;\n\tvar spreadWidth;\n\tvar delta;\n\n\tif (this._spread && width >= this._minSpreadWidth) {\n\t\tdivisor = 2;\n\t} else {\n\t\tdivisor = 1;\n\t}\n\n\tif (this.name === \"reflowable\" && this._flow === \"paginated\" && !(_gap >= 0)) {\n\t\tgap = ((section % 2 === 0) ? section : section - 1);\n\t}\n\n\tif (this.name === \"pre-paginated\" ) {\n\t\tgap = 0;\n\t}\n\n\t//-- Double Page\n\tif(divisor > 1) {\n\t\tcolWidth = Math.floor((width - gap) / divisor);\n\t} else {\n\t\tcolWidth = width;\n\t}\n\n\tif (this.name === \"pre-paginated\" && divisor > 1) {\n\t\twidth = colWidth;\n\t}\n\n\tspreadWidth = colWidth * divisor;\n\n\tdelta = (colWidth + gap) * divisor;\n\n\tthis.width = width;\n\tthis.height = _height;\n\tthis.spreadWidth = spreadWidth;\n\tthis.delta = delta;\n\n\tthis.columnWidth = colWidth;\n\tthis.gap = gap;\n\tthis.divisor = divisor;\n};\n\nLayout.prototype.format = function(contents){\n\tvar formating;\n\n\tif (this.name === \"pre-paginated\") {\n\t\tformating = contents.fit(this.columnWidth, this.height);\n\t} else if (this._flow === \"paginated\") {\n\t\tformating = contents.columns(this.width, this.height, this.columnWidth, this.gap);\n\t} else { // scrolled\n\t\tformating = contents.size(this.width, null);\n\t}\n\n\treturn formating; // might be a promise in some View Managers\n};\n\nLayout.prototype.count = function(totalWidth) {\n\t// var totalWidth = contents.scrollWidth();\n\tvar spreads = Math.ceil( totalWidth / this.spreadWidth);\n\n\treturn {\n\t\tspreads : spreads,\n\t\tpages : spreads * this.divisor\n\t};\n};\n\nmodule.exports = Layout;\n","var core = require('./core');\nvar Queue = require('./queue');\nvar EpubCFI = require('./epubcfi');\nvar RSVP = require('rsvp');\n\nfunction Locations(spine, request) {\n\tthis.spine = spine;\n\tthis.request = request;\n\n\tthis.q = new Queue(this);\n\tthis.epubcfi = new EpubCFI();\n\n\tthis._locations = [];\n\tthis.total = 0;\n\n\tthis.break = 150;\n\n\tthis._current = 0;\n\n};\n\n// Load all of sections in the book\nLocations.prototype.generate = function(chars) {\n\n\tif (chars) {\n\t\tthis.break = chars;\n\t}\n\n\tthis.q.pause();\n\n\tthis.spine.each(function(section) {\n\n\t\tthis.q.enqueue(this.process, section);\n\n\t}.bind(this));\n\n\treturn this.q.run().then(function() {\n\t\tthis.total = this._locations.length-1;\n\n\t\tif (this._currentCfi) {\n\t\t\tthis.currentLocation = this._currentCfi;\n\t\t}\n\n\t\treturn this._locations;\n\t\t// console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));\n\t}.bind(this));\n\n};\n\nLocations.prototype.process = function(section) {\n\n\treturn section.load(this.request)\n\t\t.then(function(contents) {\n\n\t\t\tvar range;\n\t\t\tvar doc = contents.ownerDocument;\n\t\t\tvar counter = 0;\n\n\t\t\tthis.sprint(contents, function(node) {\n\t\t\t\tvar len = node.length;\n\t\t\t\tvar dist;\n\t\t\t\tvar pos = 0;\n\n\t\t\t\t// Start range\n\t\t\t\tif (counter == 0) {\n\t\t\t\t\trange = doc.createRange();\n\t\t\t\t\trange.setStart(node, 0);\n\t\t\t\t}\n\n\t\t\t\tdist = this.break - counter;\n\n\t\t\t\t// Node is smaller than a break\n\t\t\t\tif(dist > len){\n\t\t\t\t\tcounter += len;\n\t\t\t\t\tpos = len;\n\t\t\t\t}\n\n\t\t\t\twhile (pos < len) {\n\t\t\t\t\tcounter = this.break;\n\t\t\t\t\tpos += this.break;\n\n\t\t\t\t\t// Gone over\n\t\t\t\t\tif(pos >= len){\n\t\t\t\t\t\t// Continue counter for next node\n\t\t\t\t\t\tcounter = len - (pos - this.break);\n\n\t\t\t\t\t// At End\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// End the previous range\n\t\t\t\t\t\trange.setEnd(node, pos);\n\t\t\t\t\t\tcfi = section.cfiFromRange(range);\n\t\t\t\t\t\tthis._locations.push(cfi);\n\t\t\t\t\t\tcounter = 0;\n\n\t\t\t\t\t\t// Start new range\n\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\trange = doc.createRange();\n\t\t\t\t\t\trange.setStart(node, pos);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\n\t\t\t}.bind(this));\n\n\t\t\t// Close remaining\n\t\t\tif (range) {\n\t\t\t\trange.setEnd(prev, prev.length);\n\t\t\t\tcfi = section.cfiFromRange(range);\n\t\t\t\tthis._locations.push(cfi)\n\t\t\t\tcounter = 0;\n\t\t\t}\n\n\t\t}.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\t// Check if the location has not been set yet\n\tif(this._locations.length === 0) {\n\t\treturn -1;\n\t}\n\n\treturn core.locationOf(cfi, this._locations, this.epubcfi.compare);\n};\n\nLocations.prototype.precentageFromCfi = function(cfi) {\n\t// Find closest cfi\n\tvar loc = this.locationFromCfi(cfi);\n\t// Get percentage in total\n\treturn this.precentageFromLocation(loc);\n};\n\nLocations.prototype.percentageFromLocation = function(loc) {\n\tif (!loc || !this.total) {\n\t\treturn 0;\n\t}\n\treturn (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\tvar 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\tthis.total = this._locations.length-1;\n\treturn 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\tvar loc;\n\n\tif(typeof curr == \"string\"){\n\t\tthis._currentCfi = curr;\n\t} else if (typeof curr == \"number\") {\n\t\tthis._current = curr;\n\t} else {\n\t\treturn;\n\t}\n\n\tif(this._locations.length === 0) {\n\t\treturn;\n\t}\n\n\tif(typeof curr == \"string\"){\n\t\tloc = this.locationFromCfi(curr);\n\t\tthis._current = loc;\n\t} else {\n\t\tloc = curr;\n\t}\n\n\tthis.trigger(\"changed\", {\n\t\tpercentage: this.precentageFromLocation(loc)\n\t});\n};\n\nObject.defineProperty(Locations.prototype, 'currentLocation', {\n\tget: function () {\n\t\treturn this._current;\n\t},\n\tset: function (curr) {\n\t\tthis.setCurrent(curr);\n\t}\n});\n\nRSVP.EventTarget.mixin(Locations.prototype);\n\nmodule.exports = Locations;\n","var RSVP = require('rsvp');\nvar core = require('../../core');\nvar DefaultViewManager = require('../default');\n\nfunction ContinuousViewManager(options) {\n\n\tDefaultViewManager.apply(this, arguments); // call super constructor.\n\n\tthis.name = \"continuous\";\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\twidth: undefined,\n\t\theight: undefined\n\t});\n\n\tcore.extend(this.settings, options.settings || {});\n\n\t// Gap can be 0, byt defaults doesn't handle that\n\tif (options.settings.gap != \"undefined\" && options.settings.gap === 0) {\n\t\tthis.settings.gap = options.settings.gap;\n\t}\n\n\t// this.viewSettings.axis = this.settings.axis;\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass,\n\t\taxis: this.settings.axis,\n\t\tlayout: this.layout,\n\t\twidth: 0,\n\t\theight: 0\n\t};\n\n\tthis.scrollTop = 0;\n\tthis.scrollLeft = 0;\n};\n\n// subclass extends superclass\nContinuousViewManager.prototype = Object.create(DefaultViewManager.prototype);\nContinuousViewManager.prototype.constructor = ContinuousViewManager;\n\nContinuousViewManager.prototype.display = function(section, target){\n\treturn DefaultViewManager.prototype.display.call(this, section, target)\n\t\t.then(function () {\n\t\t\treturn this.fill();\n\t\t}.bind(this));\n};\n\nContinuousViewManager.prototype.fill = function(_full){\n\tvar full = _full || new RSVP.defer();\n\n\tthis.check().then(function(result) {\n\t\tif (result) {\n\t\t\tthis.fill(full);\n\t\t} else {\n\t\t\tfull.resolve();\n\t\t}\n\t}.bind(this));\n\n\treturn full.promise;\n}\n\nContinuousViewManager.prototype.moveTo = function(offset){\n\t// var bounds = this.stage.bounds();\n\t// var dist = Math.floor(offset.top / bounds.height) * bounds.height;\n\tvar distX = 0,\n\t\t\tdistY = 0;\n\n\tvar offsetX = 0,\n\t\t\toffsetY = 0;\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tdistY = offset.top;\n\t\toffsetY = offset.top+this.settings.offset;\n\t} else {\n\t\tdistX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n\t\toffsetX = distX+this.settings.offset;\n\t}\n\n\treturn this.check(offsetX, offsetY)\n\t\t.then(function(){\n\t\t\tthis.scrollBy(distX, distY);\n\t\t}.bind(this));\n};\n\n/*\nContinuousViewManager.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.bind(this), nextView);\n\t}\n\n\tif(index === 0 && prev) {\n\t\tprevView = this.createView(prev, this.viewSettings);\n\t\tthis.q.enqueue(this.prepend.bind(this), 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\nContinuousViewManager.prototype.resize = function(width, height){\n\n\t// Clear the queue\n\tthis.q.clear();\n\n\tthis._stageSize = this.stage.size(width, height);\n\tthis._bounds = this.bounds();\n\n\t// Update for new views\n\tthis.viewSettings.width = this._stageSize.width;\n\tthis.viewSettings.height = this._stageSize.height;\n\n\t// Update for existing views\n\tthis.views.each(function(view) {\n\t\tview.size(this._stageSize.width, this._stageSize.height);\n\t}.bind(this));\n\n\tthis.updateLayout();\n\n\t// if(this.location) {\n\t// this.rendition.display(this.location.start);\n\t// }\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nContinuousViewManager.prototype.onResized = function(e) {\n\n\t// this.views.clear();\n\n\tclearTimeout(this.resizeTimeout);\n\tthis.resizeTimeout = setTimeout(function(){\n\t\tthis.resize();\n\t}.bind(this), 150);\n};\n\nContinuousViewManager.prototype.afterResized = function(view){\n\tthis.trigger(\"resize\", view.section);\n};\n\n// Remove Previous Listeners if present\nContinuousViewManager.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\n\n// ContinuousViewManager.prototype.append = function(section){\n// \treturn this.q.enqueue(function() {\n//\n// \t\tthis._append(section);\n//\n//\n// \t}.bind(this));\n// };\n//\n// ContinuousViewManager.prototype.prepend = function(section){\n// \treturn this.q.enqueue(function() {\n//\n// \t\tthis._prepend(section);\n//\n// \t}.bind(this));\n//\n// };\n\nContinuousViewManager.prototype.append = function(section){\n\tvar view = this.createView(section);\n\tthis.views.append(view);\n\treturn view;\n};\n\nContinuousViewManager.prototype.prepend = function(section){\n\tvar view = this.createView(section);\n\n\tview.on(\"resized\", this.counter.bind(this));\n\n\tthis.views.prepend(view);\n\treturn view;\n};\n\nContinuousViewManager.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\nContinuousViewManager.prototype.update = function(_offset){\n\tvar container = this.bounds();\n\tvar views = this.views.all();\n\tvar viewsLength = views.length;\n\tvar visible = [];\n\tvar offset = typeof _offset != \"undefined\" ? _offset : (this.settings.offset || 0);\n\tvar isVisible;\n\tvar view;\n\n\tvar updating = new RSVP.defer();\n\tvar promises = [];\n\n\tfor (var i = 0; i < viewsLength; i++) {\n\t\tview = views[i];\n\n\t\tisVisible = this.isVisible(view, offset, offset, container);\n\n\t\tif(isVisible === true) {\n\t\t\tif (!view.displayed) {\n\t\t\t\tpromises.push(view.display(this.request).then(function (view) {\n\t\t\t\t\tview.show();\n\t\t\t\t}));\n\t\t\t}\n\t\t\tvisible.push(view);\n\t\t} else {\n\t\t\tthis.q.enqueue(view.destroy.bind(view));\n\n\t\t\tclearTimeout(this.trimTimeout);\n\t\t\tthis.trimTimeout = setTimeout(function(){\n\t\t\t\tthis.q.enqueue(this.trim.bind(this));\n\t\t\t}.bind(this), 250);\n\t\t}\n\n\t}\n\n\tif(promises.length){\n\t\treturn RSVP.all(promises);\n\t} else {\n\t\tupdating.resolve();\n\t\treturn updating.promise;\n\t}\n\n};\n\nContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){\n\tvar last, first, next, prev;\n\n\tvar checking = new RSVP.defer();\n\tvar newViews = [];\n\n\tvar horizontal = (this.settings.axis === \"horizontal\");\n\tvar delta = this.settings.offset || 0;\n\n\tif (_offsetLeft && horizontal) {\n\t\tdelta = _offsetLeft;\n\t}\n\n\tif (_offsetTop && !horizontal) {\n\t\tdelta = _offsetTop;\n\t}\n\n\tvar bounds = this._bounds; // bounds saved this until resize\n\n\tvar offset = horizontal ? this.scrollLeft : this.scrollTop;\n\tvar visibleLength = horizontal ? bounds.width : bounds.height;\n\tvar contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;\n\n\tif (offset + visibleLength + delta >= contentLength) {\n\t\tlast = this.views.last();\n\t\tnext = last && last.section.next();\n\t\tif(next) {\n\t\t\tnewViews.push(this.append(next));\n\t\t}\n\t}\n\n\tif (offset - delta < 0 ) {\n\t\tfirst = this.views.first();\n\t\tprev = first && first.section.prev();\n\t\tif(prev) {\n\t\t\tnewViews.push(this.prepend(prev));\n\t\t}\n\t}\n\n\tif(newViews.length){\n\t\t// RSVP.all(promises)\n\t\t\t// .then(function() {\n\t\t\t\t// Check to see if anything new is on screen after rendering\n\t\t\t\treturn this.q.enqueue(function(){\n\t\t\t\t\treturn this.update(delta);\n\t\t\t\t}.bind(this));\n\n\n\t\t\t// }.bind(this));\n\n\t} else {\n\t\tchecking.resolve(false);\n\t\treturn checking.promise;\n\t}\n\n\n};\n\nContinuousViewManager.prototype.trim = function(){\n\tvar task = new RSVP.defer();\n\tvar displayed = this.views.displayed();\n\tvar first = displayed[0];\n\tvar last = displayed[displayed.length-1];\n\tvar firstIndex = this.views.indexOf(first);\n\tvar lastIndex = this.views.indexOf(last);\n\tvar above = this.views.slice(0, firstIndex);\n\tvar below = this.views.slice(lastIndex+1);\n\n\t// Erase all but last above\n\tfor (var i = 0; i < above.length-1; i++) {\n\t\tthis.erase(above[i], above);\n\t}\n\n\t// Erase all except first below\n\tfor (var j = 1; j < below.length; j++) {\n\t\tthis.erase(below[j]);\n\t}\n\n\ttask.resolve();\n\treturn task.promise;\n};\n\nContinuousViewManager.prototype.erase = function(view, above){ //Trim\n\n\tvar prevTop;\n\tvar prevLeft;\n\n\tif(this.settings.height) {\n\t\tprevTop = this.container.scrollTop;\n\t\tprevLeft = this.container.scrollLeft;\n\t} else {\n\t\tprevTop = window.scrollY;\n\t\tprevLeft = window.scrollX;\n\t}\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\nContinuousViewManager.prototype.addEventListeners = function(stage){\n\n\twindow.addEventListener('unload', function(e){\n\t\tthis.ignore = true;\n\t\t// this.scrollTo(0,0);\n\t\tthis.destroy();\n\t}.bind(this));\n\n\tthis.addScrollListeners();\n};\n\nContinuousViewManager.prototype.addScrollListeners = function() {\n\tvar scroller;\n\n\tthis.tick = core.requestAnimationFrame;\n\n\tif(this.settings.height) {\n\t\tthis.prevScrollTop = this.container.scrollTop;\n\t\tthis.prevScrollLeft = this.container.scrollLeft;\n\t} else {\n\t\tthis.prevScrollTop = window.scrollY;\n\t\tthis.prevScrollLeft = window.scrollX;\n\t}\n\n\tthis.scrollDeltaVert = 0;\n\tthis.scrollDeltaHorz = 0;\n\n\tif(this.settings.height) {\n\t\tscroller = this.container;\n\t\tthis.scrollTop = this.container.scrollTop;\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\t} else {\n\t\tscroller = window;\n\t\tthis.scrollTop = window.scrollY;\n\t\tthis.scrollLeft = window.scrollX;\n\t}\n\n\tscroller.addEventListener(\"scroll\", this.onScroll.bind(this));\n\n\t// this.tick.call(window, this.onScroll.bind(this));\n\n\tthis.scrolled = false;\n\n};\n\nContinuousViewManager.prototype.onScroll = function(){\n\n\t// if(!this.ignore) {\n\n\t\tif(this.settings.height) {\n\t\t\tscrollTop = this.container.scrollTop;\n\t\t\tscrollLeft = this.container.scrollLeft;\n\t\t} else {\n\t\t\tscrollTop = window.scrollY;\n\t\t\tscrollLeft = window.scrollX;\n\t\t}\n\n\t\tthis.scrollTop = scrollTop;\n\t\tthis.scrollLeft = scrollLeft;\n\n\t\tif(!this.ignore) {\n\n\t\t\tif((this.scrollDeltaVert === 0 &&\n\t\t\t\t this.scrollDeltaHorz === 0) ||\n\t\t\t\t this.scrollDeltaVert > this.settings.offsetDelta ||\n\t\t\t\t this.scrollDeltaHorz > this.settings.offsetDelta) {\n\n\t\t\t\tthis.q.enqueue(function() {\n\t\t\t\t\tthis.check();\n\t\t\t\t}.bind(this));\n\t\t\t\t// this.check();\n\n\t\t\t\tthis.scrollDeltaVert = 0;\n\t\t\t\tthis.scrollDeltaHorz = 0;\n\n\t\t\t\tthis.trigger(\"scroll\", {\n\t\t\t\t\ttop: scrollTop,\n\t\t\t\t\tleft: scrollLeft\n\t\t\t\t});\n\n\t\t\t\tclearTimeout(this.afterScrolled);\n\t\t\t\tthis.afterScrolled = setTimeout(function () {\n\t\t\t\t\tthis.trigger(\"scrolled\", {\n\t\t\t\t\t\ttop: this.scrollTop,\n\t\t\t\t\t\tleft: this.scrollLeft\n\t\t\t\t\t});\n\t\t\t\t}.bind(this));\n\n\t\t\t}\n\n\t\t} else {\n\t\t\tthis.ignore = false;\n\t\t}\n\n\t\tthis.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);\n\t\tthis.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);\n\n\t\tthis.prevScrollTop = scrollTop;\n\t\tthis.prevScrollLeft = scrollLeft;\n\n\t\tclearTimeout(this.scrollTimeout);\n\t\tthis.scrollTimeout = setTimeout(function(){\n\t\t\tthis.scrollDeltaVert = 0;\n\t\t\tthis.scrollDeltaHorz = 0;\n\t\t}.bind(this), 150);\n\n\n\t\tthis.scrolled = false;\n\t// }\n\n\t// this.tick.call(window, this.onScroll.bind(this));\n\n};\n\n\n// ContinuousViewManager.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\nContinuousViewManager.prototype.currentLocation = function(){\n\n\tif (this.settings.axis === \"vertical\") {\n\t\tthis.location = this.scrolledLocation();\n\t} else {\n\t\tthis.location = this.paginatedLocation();\n\t}\n\n\treturn this.location;\n};\n\nContinuousViewManager.prototype.scrolledLocation = function(){\n\n\tvar visible = this.visible();\n\tvar startPage, endPage;\n\n\tvar container = this.container.getBoundingClientRect();\n\n\tif(visible.length === 1) {\n\t\treturn this.mapping.page(visible[0].contents, visible[0].section.cfiBase);\n\t}\n\n\tif(visible.length > 1) {\n\n\t\tstartPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase);\n\t\tendPage = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase);\n\n\t\treturn {\n\t\t\tstart: startPage.start,\n\t\t\tend: endPage.end\n\t\t};\n\t}\n\n};\n\nContinuousViewManager.prototype.paginatedLocation = function(){\n\tvar visible = this.visible();\n\tvar startA, startB, endA, endB;\n\tvar pageLeft, pageRight;\n\tvar container = this.container.getBoundingClientRect();\n\n\tif(visible.length === 1) {\n\t\tstartA = container.left - visible[0].position().left;\n\t\tendA = startA + this.layout.spreadWidth;\n\n\t\treturn this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);\n\t}\n\n\tif(visible.length > 1) {\n\n\t\t// Left Col\n\t\tstartA = container.left - visible[0].position().left;\n\t\tendA = startA + this.layout.columnWidth;\n\n\t\t// Right Col\n\t\tstartB = container.left + this.layout.spreadWidth - visible[visible.length-1].position().left;\n\t\tendB = startB + this.layout.columnWidth;\n\n\t\tpageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);\n\t\tpageRight = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase, startB, endB);\n\n\t\treturn {\n\t\t\tstart: pageLeft.start,\n\t\t\tend: pageRight.end\n\t\t};\n\t}\n};\n\n/*\nContinuous.prototype.current = function(what){\n\tvar view, top;\n\tvar container = this.container.getBoundingClientRect();\n\tvar length = this.views.length - 1;\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tfor (var i = length; i >= 0; i--) {\n\t\t\tview = this.views[i];\n\t\t\tleft = view.position().left;\n\n\t\t\tif(left < container.right) {\n\n\t\t\t\tif(this._current == view) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._current = view;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tfor (var i = length; i >= 0; i--) {\n\t\t\tview = this.views[i];\n\t\t\ttop = view.bounds().top;\n\t\t\tif(top < container.bottom) {\n\n\t\t\t\tif(this._current == view) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._current = view;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t}\n\n\treturn this._current;\n};\n*/\n\nContinuousViewManager.prototype.updateLayout = function() {\n\n\tif (!this.stage) {\n\t\treturn;\n\t}\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.layout.calculate(this._stageSize.width, this._stageSize.height);\n\t} else {\n\t\tthis.layout.calculate(\n\t\t\tthis._stageSize.width,\n\t\t\tthis._stageSize.height,\n\t\t\tthis.settings.gap\n\t\t);\n\n\t\t// Set the look ahead offset for what is visible\n\t\tthis.settings.offset = this.layout.delta;\n\n\t\tthis.stage.addStyleRules(\"iframe\", [{\"margin-right\" : this.layout.gap + \"px\"}]);\n\n\t}\n\n\t// Set the dimensions for views\n\tthis.viewSettings.width = this.layout.width;\n\tthis.viewSettings.height = this.layout.height;\n\n\tthis.setLayout(this.layout);\n\n};\n\nContinuousViewManager.prototype.next = function(){\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\n\t\tif(this.container.scrollLeft +\n\t\t\t this.container.offsetWidth +\n\t\t\t this.layout.delta < this.container.scrollWidth) {\n\t\t\tthis.scrollBy(this.layout.delta, 0);\n\t\t} else {\n\t\t\tthis.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n\t\t}\n\n\t} else {\n\t\tthis.scrollBy(0, this.layout.height);\n\t}\n};\n\nContinuousViewManager.prototype.prev = function(){\n\tif(this.settings.axis === \"horizontal\") {\n\t\tthis.scrollBy(-this.layout.delta, 0);\n\t} else {\n\t\tthis.scrollBy(0, -this.layout.height);\n\t}\n};\n\nContinuousViewManager.prototype.updateFlow = function(flow){\n\tvar axis = (flow === \"paginated\") ? \"horizontal\" : \"vertical\";\n\n\tthis.settings.axis = axis;\n\n\tthis.viewSettings.axis = axis;\n\n\tthis.settings.overflow = (flow === \"paginated\") ? \"hidden\" : \"auto\";\n\n\t// this.views.each(function(view){\n\t// \tview.setAxis(axis);\n\t// });\n\n\tif (this.settings.axis === \"vertical\") {\n\t\tthis.settings.infinite = true;\n\t} else {\n\t\tthis.settings.infinite = false;\n\t}\n\n};\nmodule.exports = ContinuousViewManager;\n","var RSVP = require('rsvp');\nvar core = require('../../core');\nvar EpubCFI = require('../../epubcfi');\nvar Mapping = require('../../mapping');\nvar Queue = require('../../queue');\nvar Stage = require('../helpers/stage');\nvar Views = require('../helpers/views');\n\nfunction DefaultViewManager(options) {\n\n\tthis.name = \"default\";\n\tthis.View = options.view;\n\tthis.request = options.request;\n\tthis.renditionQueue = options.queue;\n\tthis.q = new Queue(this);\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\thidden: false,\n\t\twidth: undefined,\n\t\theight: undefined,\n\t\t// globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'},\n\t\t// layout: null,\n\t\taxis: \"vertical\",\n\t\tignoreClass: ''\n\t});\n\n\tcore.extend(this.settings, options.settings || {});\n\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass,\n\t\taxis: this.settings.axis,\n\t\tlayout: this.layout,\n\t\twidth: 0,\n\t\theight: 0\n\t};\n\n}\n\nDefaultViewManager.prototype.render = function(element, size){\n\n\t// Save the stage\n\tthis.stage = new Stage({\n\t\twidth: size.width,\n\t\theight: size.height,\n\t\toverflow: this.settings.overflow,\n\t\thidden: this.settings.hidden,\n\t\taxis: this.settings.axis\n\t});\n\n\tthis.stage.attachTo(element);\n\n\t// Get this stage container div\n\tthis.container = this.stage.getContainer();\n\n\t// Views array methods\n\tthis.views = new Views(this.container);\n\n\t// Calculate Stage Size\n\tthis._bounds = this.bounds();\n\tthis._stageSize = this.stage.size();\n\n\t// Set the dimensions for views\n\tthis.viewSettings.width = this._stageSize.width;\n\tthis.viewSettings.height = this._stageSize.height;\n\n\t// Function to handle a resize event.\n\t// Will only attach if width and height are both fixed.\n\tthis.stage.onResize(this.onResized.bind(this));\n\n\t// Add Event Listeners\n\tthis.addEventListeners();\n\n\t// Add Layout method\n\t// this.applyLayoutMethod();\n\tif (this.layout) {\n\t\tthis.updateLayout();\n\t}\n};\n\nDefaultViewManager.prototype.addEventListeners = function(){\n\twindow.addEventListener('unload', function(e){\n\t\tthis.destroy();\n\t}.bind(this));\n};\n\nDefaultViewManager.prototype.destroy = function(){\n\t// this.views.each(function(view){\n\t// \tview.destroy();\n\t// });\n\n\t/*\n\n\t\tclearTimeout(this.trimTimeout);\n\t\tif(this.settings.hidden) {\n\t\t\tthis.element.removeChild(this.wrapper);\n\t\t} else {\n\t\t\tthis.element.removeChild(this.container);\n\t\t}\n\t*/\n};\n\nDefaultViewManager.prototype.onResized = function(e) {\n\tclearTimeout(this.resizeTimeout);\n\tthis.resizeTimeout = setTimeout(function(){\n\t\tthis.resize();\n\t}.bind(this), 150);\n};\n\nDefaultViewManager.prototype.resize = function(width, height){\n\n\t// Clear the queue\n\tthis.q.clear();\n\n\tthis._stageSize = this.stage.size(width, height);\n\tthis._bounds = this.bounds();\n\n\t// Update for new views\n\tthis.viewSettings.width = this._stageSize.width;\n\tthis.viewSettings.height = this._stageSize.height;\n\n\t// Update for existing views\n\tthis.views.each(function(view) {\n\t\tview.size(this._stageSize.width, this._stageSize.height);\n\t}.bind(this));\n\n\tthis.updateLayout();\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nDefaultViewManager.prototype.createView = function(section) {\n\treturn new this.View(section, this.viewSettings);\n};\n\nDefaultViewManager.prototype.display = function(section, target){\n\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\n\t// Check to make sure the section we want isn't already shown\n\tvar visible = this.views.find(section);\n\n\t// View is already shown, just move to correct location\n\tif(visible && target) {\n\t\toffset = visible.locationOf(target);\n\t\tthis.moveTo(offset);\n\t\tdisplaying.resolve();\n\t\treturn displayed;\n\t}\n\n\t// Hide all current views\n\tthis.views.hide();\n\n\tthis.views.clear();\n\n\tthis.add(section)\n\t\t.then(function(){\n\t\t\tvar next;\n\t\t\tif (this.layout.name === \"pre-paginated\" &&\n\t\t\t\t\tthis.layout.divisor > 1) {\n\t\t\t\tnext = section.next();\n\t\t\t\tif (next) {\n\t\t\t\t\treturn this.add(next);\n\t\t\t\t}\n\t\t\t}\n\t\t}.bind(this))\n\t\t.then(function(view){\n\n\t\t\t// Move to correct place within the section, if needed\n\t\t\tif(target) {\n\t\t\t\toffset = view.locationOf(target);\n\t\t\t\tthis.moveTo(offset);\n\t\t\t}\n\n\t\t\tthis.views.show();\n\n\t\t\tdisplaying.resolve();\n\n\t\t}.bind(this))\n\t\t// .then(function(){\n\t\t// \treturn this.hooks.display.trigger(view);\n\t\t// }.bind(this))\n\t\t// .then(function(){\n\t\t// \tthis.views.show();\n\t\t// }.bind(this));\n\t\treturn displayed;\n};\n\nDefaultViewManager.prototype.afterDisplayed = function(view){\n\tthis.trigger(\"added\", view);\n};\n\nDefaultViewManager.prototype.afterResized = function(view){\n\tthis.trigger(\"resize\", view.section);\n};\n\n// DefaultViewManager.prototype.moveTo = function(offset){\n// \tthis.scrollTo(offset.left, offset.top);\n// };\n\nDefaultViewManager.prototype.moveTo = function(offset){\n\tvar distX = 0,\n\t\t\tdistY = 0;\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tdistY = offset.top;\n\t} else {\n\t\tdistX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n\n\t\tif (distX + this.layout.delta > this.container.scrollWidth) {\n\t\t\tdistX = this.container.scrollWidth - this.layout.delta;\n\t\t}\n\t}\n\n\tthis.scrollTo(distX, distY);\n};\n\nDefaultViewManager.prototype.add = function(section){\n\tvar view = this.createView(section);\n\n\tthis.views.append(view);\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\tview.onResize = this.afterResized.bind(this);\n\n\treturn view.display(this.request);\n\n};\n\nDefaultViewManager.prototype.append = function(section){\n\tvar view = this.createView(section);\n\tthis.views.append(view);\n\treturn view.display(this.request);\n};\n\nDefaultViewManager.prototype.prepend = function(section){\n\tvar view = this.createView(section);\n\n\tthis.views.prepend(view);\n\treturn view.display(this.request);\n};\n// DefaultViewManager.prototype.resizeView = function(view) {\n//\n// \tif(this.settings.globalLayoutProperties.layout === \"pre-paginated\") {\n// \t\tview.lock(\"both\", this.bounds.width, this.bounds.height);\n// \t} else {\n// \t\tview.lock(\"width\", this.bounds.width, this.bounds.height);\n// \t}\n//\n// };\n\nDefaultViewManager.prototype.next = function(){\n\tvar next;\n\tvar view;\n\tvar left;\n\n\tif(!this.views.length) return;\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\n\t\tleft = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;\n\n\t\tif(left < this.container.scrollWidth) {\n\t\t\tthis.scrollBy(this.layout.delta, 0);\n\t\t} else if (left - this.layout.columnWidth === this.container.scrollWidth) {\n\t\t\tthis.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n\t\t} else {\n\t\t\tnext = this.views.last().section.next();\n\t\t}\n\n\n\t} else {\n\n\t\tnext = this.views.last().section.next();\n\n\t}\n\n\tif(next) {\n\t\tthis.views.clear();\n\n\t\treturn this.append(next)\n\t\t\t.then(function(){\n\t\t\t\tvar right;\n\t\t\t\tif (this.layout.name && this.layout.divisor > 1) {\n\t\t\t\t\tright = next.next();\n\t\t\t\t\tif (right) {\n\t\t\t\t\t\treturn this.append(right);\n\t\t\t\t\t}\n\t\t\t\t}\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\n};\n\nDefaultViewManager.prototype.prev = function(){\n\tvar prev;\n\tvar view;\n\tvar left;\n\n\tif(!this.views.length) return;\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\n\t\tleft = this.container.scrollLeft;\n\n\t\tif(left > 0) {\n\t\t\tthis.scrollBy(-this.layout.delta, 0);\n\t\t} else {\n\t\t\tprev = this.views.first().section.prev();\n\t\t}\n\n\n\t} else {\n\n\t\tprev = this.views.first().section.prev();\n\n\t}\n\n\tif(prev) {\n\t\tthis.views.clear();\n\n\t\treturn this.prepend(prev)\n\t\t\t.then(function(){\n\t\t\t\tvar left;\n\t\t\t\tif (this.layout.name && this.layout.divisor > 1) {\n\t\t\t\t\tleft = prev.prev();\n\t\t\t\t\tif (left) {\n\t\t\t\t\t\treturn this.prepend(left);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tif(this.settings.axis === \"horizontal\") {\n\t\t\t\t\tthis.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n\t\t\t\t}\n\t\t\t\tthis.views.show();\n\t\t\t}.bind(this));\n\t}\n};\n\nDefaultViewManager.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\treturn null;\n};\n\nDefaultViewManager.prototype.currentLocation = function(){\n\tvar view;\n\tvar start, end;\n\n\tif(this.views.length) {\n\t\tview = this.views.first();\n\t\tstart = container.left - view.position().left;\n\t\tend = start + this.layout.spread;\n\n\t\treturn this.mapping.page(view, view.section.cfiBase);\n\t}\n\n};\n\nDefaultViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){\n\tvar position = view.position();\n\tvar container = _container || this.bounds();\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\t} else if(this.settings.axis === \"vertical\" &&\n\t\tposition.bottom > container.top - offsetPrev &&\n\t\tposition.top < container.bottom + offsetNext) {\n\n\t\treturn true;\n\t}\n\n\treturn false;\n\n};\n\nDefaultViewManager.prototype.visible = function(){\n\t// return this.views.displayed();\n\tvar container = this.bounds();\n\tvar views = this.views.displayed();\n\tvar viewsLength = views.length;\n\tvar visible = [];\n\tvar isVisible;\n\tvar view;\n\n\tfor (var i = 0; i < viewsLength; i++) {\n\t\tview = views[i];\n\t\tisVisible = this.isVisible(view, 0, 0, container);\n\n\t\tif(isVisible === true) {\n\t\t\tvisible.push(view);\n\t\t}\n\n\t}\n\treturn visible;\n};\n\nDefaultViewManager.prototype.scrollBy = function(x, y, silent){\n\tif(silent) {\n\t\tthis.ignore = true;\n\t}\n\n\tif(this.settings.height) {\n\n\t\tif(x) this.container.scrollLeft += x;\n\t\tif(y) this.container.scrollTop += y;\n\n\t} else {\n\t\twindow.scrollBy(x,y);\n\t}\n\t// console.log(\"scrollBy\", x, y);\n\tthis.scrolled = true;\n\tthis.onScroll();\n};\n\nDefaultViewManager.prototype.scrollTo = function(x, y, silent){\n\tif(silent) {\n\t\tthis.ignore = true;\n\t}\n\n\tif(this.settings.height) {\n\t\tthis.container.scrollLeft = x;\n\t\tthis.container.scrollTop = y;\n\t} else {\n\t\twindow.scrollTo(x,y);\n\t}\n\t// console.log(\"scrollTo\", x, y);\n\tthis.scrolled = true;\n\tthis.onScroll();\n\t// if(this.container.scrollLeft != x){\n\t// setTimeout(function() {\n\t// this.scrollTo(x, y, silent);\n\t// }.bind(this), 10);\n\t// return;\n\t// };\n };\n\nDefaultViewManager.prototype.onScroll = function(){\n\n};\n\nDefaultViewManager.prototype.bounds = function() {\n\tvar bounds;\n\n\tbounds = this.stage.bounds();\n\n\treturn bounds;\n};\n\nDefaultViewManager.prototype.applyLayout = function(layout) {\n\n\tthis.layout = layout;\n\tthis.updateLayout();\n\n\tthis.mapping = new Mapping(this.layout);\n\t // this.manager.layout(this.layout.format);\n};\n\nDefaultViewManager.prototype.updateLayout = function() {\n\tif (!this.stage) {\n\t\treturn;\n\t}\n\n\tthis._stageSize = this.stage.size();\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.layout.calculate(this._stageSize.width, this._stageSize.height);\n\t} else {\n\t\tthis.layout.calculate(\n\t\t\tthis._stageSize.width,\n\t\t\tthis._stageSize.height,\n\t\t\tthis.settings.gap\n\t\t);\n\n\t\t// Set the look ahead offset for what is visible\n\t\tthis.settings.offset = this.layout.delta;\n\n\t\tthis.stage.addStyleRules(\"iframe\", [{\"margin-right\" : this.layout.gap + \"px\"}]);\n\n\t}\n\n\t// Set the dimensions for views\n\tthis.viewSettings.width = this.layout.width;\n\tthis.viewSettings.height = this.layout.height;\n\n\tthis.setLayout(this.layout);\n\n};\n\nDefaultViewManager.prototype.setLayout = function(layout){\n\n\tthis.viewSettings.layout = layout;\n\n\tif(this.views) {\n\n\t\tthis.views.each(function(view){\n\t\t\tview.setLayout(layout);\n\t\t});\n\n\t}\n\n};\n\nDefaultViewManager.prototype.updateFlow = function(flow){\n\tvar axis = (flow === \"paginated\") ? \"horizontal\" : \"vertical\";\n\n\tthis.settings.axis = axis;\n\n\tthis.viewSettings.axis = axis;\n\n\tthis.settings.overflow = (flow === \"paginated\") ? \"hidden\" : \"auto\";\n\t// this.views.each(function(view){\n\t// \tview.setAxis(axis);\n\t// });\n\n};\n\n //-- Enable binding events to Manager\n RSVP.EventTarget.mixin(DefaultViewManager.prototype);\n\n module.exports = DefaultViewManager;\n","var core = require('../../core');\n\nfunction Stage(_options) {\n\tthis.settings = _options || {};\n\tthis.id = \"epubjs-container-\" + core.uuid();\n\n\tthis.container = this.create(this.settings);\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t}\n\n}\n\n/**\n* Creates an element to render to.\n* Resizes to passed width and height or to the elements size\n*/\nStage.prototype.create = function(options){\n\tvar height = options.height;// !== false ? options.height : \"100%\";\n\tvar width = options.width;// !== false ? options.width : \"100%\";\n\tvar overflow = options.overflow || false;\n\tvar axis = options.axis || \"vertical\";\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 = this.id;\n\tcontainer.classList.add(\"epub-container\");\n\n\t// Style Element\n\t// container.style.fontSize = \"0\";\n\tcontainer.style.wordSpacing = \"0\";\n\tcontainer.style.lineHeight = \"0\";\n\tcontainer.style.verticalAlign = \"top\";\n\n\tif(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\tif (overflow) {\n\t\tcontainer.style.overflow = overflow;\n\t}\n\n\treturn container;\n};\n\nStage.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\nStage.prototype.getElement = function(_element){\n\tvar element;\n\n\tif(core.isElement(_element)) {\n\t\telement = _element;\n\t} else if (typeof _element === \"string\") {\n\t\telement = document.getElementById(_element);\n\t}\n\n\tif(!element){\n\t\tconsole.error(\"Not an Element\");\n\t\treturn;\n\t}\n\n\treturn element;\n};\n\nStage.prototype.attachTo = function(what){\n\n\tvar element = this.getElement(what);\n\tvar base;\n\n\tif(!element){\n\t\treturn;\n\t}\n\n\tif(this.settings.hidden) {\n\t\tbase = this.wrapper;\n\t} else {\n\t\tbase = this.container;\n\t}\n\n\telement.appendChild(base);\n\n\tthis.element = element;\n\n\treturn element;\n\n};\n\nStage.prototype.getContainer = function() {\n\treturn this.container;\n};\n\nStage.prototype.onResize = function(func){\n\t// Only listen to window for resize event if width and height are not fixed.\n\t// This applies if it is set to a percent or auto.\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", func, false);\n\t}\n\n};\n\nStage.prototype.size = function(width, height){\n\tvar bounds;\n\t// var width = _width || this.settings.width;\n\t// var height = _height || this.settings.height;\n\n\t// If width or height are set to false, inherit them from containing element\n\tif(width === null) {\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 === null) {\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(!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(!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\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\treturn {\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};\n\nStage.prototype.bounds = function(){\n\n\tif(!this.container) {\n\t\treturn core.windowBounds();\n\t} else {\n\t\treturn this.container.getBoundingClientRect();\n\t}\n\n}\n\nStage.prototype.getSheet = function(){\n\tvar style = document.createElement(\"style\");\n\n\t// WebKit hack --> https://davidwalsh.name/add-rules-stylesheets\n\tstyle.appendChild(document.createTextNode(\"\"));\n\n\tdocument.head.appendChild(style);\n\n\treturn style.sheet;\n}\n\nStage.prototype.addStyleRules = function(selector, rulesArray){\n\tvar scope = \"#\" + this.id + \" \";\n\tvar rules = \"\";\n\n\tif(!this.sheet){\n\t\tthis.sheet = this.getSheet();\n\t}\n\n\trulesArray.forEach(function(set) {\n\t\tfor (var prop in set) {\n\t\t\tif(set.hasOwnProperty(prop)) {\n\t\t\t\trules += prop + \":\" + set[prop] + \";\";\n\t\t\t}\n\t\t}\n\t})\n\n\tthis.sheet.insertRule(scope + selector + \" {\" + rules + \"}\", 0);\n}\n\n\n\nmodule.exports = Stage;\n","function Views(container) {\n\tthis.container = container;\n\tthis._views = [];\n\tthis.length = 0;\n\tthis.hidden = false;\n};\n\nViews.prototype.all = function() {\n\treturn this._views;\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.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\tif(this.container){\n\t\tthis.container.appendChild(view.element);\n\t}\n\tthis.length++;\n\treturn view;\n};\n\nViews.prototype.prepend = function(view){\n\tthis._views.unshift(view);\n\tif(this.container){\n\t\tthis.container.insertBefore(view.element, this.container.firstChild);\n\t}\n\tthis.length++;\n\treturn view;\n};\n\nViews.prototype.insert = function(view, index) {\n\tthis._views.splice(index, 0, view);\n\n\tif(this.container){\n\t\tif(index < this.container.children.length){\n\t\t\tthis.container.insertBefore(view.element, this.container.children[index]);\n\t\t} else {\n\t\t\tthis.container.appendChild(view.element);\n\t\t}\n\t}\n\n\tthis.length++;\n\treturn 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\tthis.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\tif(this.container){\n\t\t this.container.removeChild(view.element);\n\t}\n\tview = null;\n};\n\n// Iterators\n\nViews.prototype.each = function() {\n\treturn this._views.forEach.apply(this._views, arguments);\n};\n\nViews.prototype.clear = function(){\n\t// Remove all views\n\tvar view;\n\tvar len = this.length;\n\n\tif(!this.length) return;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tthis.destroy(view);\n\t}\n\n\tthis._views = [];\n\tthis.length = 0;\n};\n\nViews.prototype.find = function(section){\n\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed && view.section.index == section.index) {\n\t\t\treturn view;\n\t\t}\n\t}\n\n};\n\nViews.prototype.displayed = function(){\n\tvar displayed = [];\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed){\n\t\t\tdisplayed.push(view);\n\t\t}\n\t}\n\treturn displayed;\n};\n\nViews.prototype.show = function(){\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed){\n\t\t\tview.show();\n\t\t}\n\t}\n\tthis.hidden = false;\n};\n\nViews.prototype.hide = function(){\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed){\n\t\t\tview.hide();\n\t\t}\n\t}\n\tthis.hidden = true;\n};\n\nmodule.exports = Views;\n","var RSVP = require('rsvp');\nvar core = require('../../core');\nvar EpubCFI = require('../../epubcfi');\nvar Contents = require('../../contents');\n\nfunction IframeView(section, options) {\n\tthis.settings = core.extend({\n\t\tignoreClass : '',\n\t\taxis: 'vertical',\n\t\twidth: 0,\n\t\theight: 0,\n\t\tlayout: undefined,\n\t\tglobalLayoutProperties: {},\n\t}, options || {});\n\n\tthis.id = \"epubjs-view-\" + core.uuid();\n\tthis.section = section;\n\tthis.index = section.index;\n\n\tthis.element = this.container(this.settings.axis);\n\n\tthis.added = false;\n\tthis.displayed = false;\n\tthis.rendered = false;\n\n\tthis.width = this.settings.width;\n\tthis.height = this.settings.height;\n\n\tthis.fixedWidth = 0;\n\tthis.fixedHeight = 0;\n\n\t// Blank Cfi for Parsing\n\tthis.epubcfi = new EpubCFI();\n\n\tthis.layout = this.settings.layout;\n\t// Dom events to listen for\n\t// this.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n};\n\nIframeView.prototype.container = function(axis) {\n\tvar element = document.createElement('div');\n\n\telement.classList.add(\"epub-view\");\n\n\t// this.element.style.minHeight = \"100px\";\n\telement.style.height = \"0px\";\n\telement.style.width = \"0px\";\n\telement.style.overflow = \"hidden\";\n\n\tif(axis && axis == \"horizontal\"){\n\t\telement.style.display = \"inline-block\";\n\t} else {\n\t\telement.style.display = \"block\";\n\t}\n\n\treturn element;\n};\n\nIframeView.prototype.create = function() {\n\n\tif(this.iframe) {\n\t\treturn this.iframe;\n\t}\n\n\tif(!this.element) {\n\t\tthis.element = this.createContainer();\n\t}\n\n\tthis.iframe = document.createElement('iframe');\n\tthis.iframe.id = this.id;\n\tthis.iframe.scrolling = \"no\"; // Might need to be removed: breaks ios width calculations\n\tthis.iframe.style.overflow = \"hidden\";\n\tthis.iframe.seamless = \"seamless\";\n\t// Back up if seamless isn't supported\n\tthis.iframe.style.border = \"none\";\n\n\tthis.resizing = true;\n\n\t// this.iframe.style.display = \"none\";\n\tthis.element.style.visibility = \"hidden\";\n\tthis.iframe.style.visibility = \"hidden\";\n\n\tthis.iframe.style.width = \"0\";\n\tthis.iframe.style.height = \"0\";\n\tthis._width = 0;\n\tthis._height = 0;\n\n\tthis.element.appendChild(this.iframe);\n\tthis.added = true;\n\n\tthis.elementBounds = core.bounds(this.element);\n\n\t// if(width || height){\n\t// this.resize(width, height);\n\t// } else if(this.width && this.height){\n\t// this.resize(this.width, this.height);\n\t// } else {\n\t// this.iframeBounds = core.bounds(this.iframe);\n\t// }\n\n\t// Firefox has trouble with baseURI and srcdoc\n\t// TODO: Disable for now in firefox\n\n\tif(!!(\"srcdoc\" in this.iframe)) {\n\t\tthis.supportsSrcdoc = true;\n\t} else {\n\t\tthis.supportsSrcdoc = false;\n\t}\n\n\treturn this.iframe;\n};\n\nIframeView.prototype.render = function(request, show) {\n\n\t// view.onLayout = this.layout.format.bind(this.layout);\n\tthis.create();\n\n\t// Fit to size of the container, apply padding\n\tthis.size();\n\n\tif(!this.sectionRender) {\n\t\tthis.sectionRender = this.section.render(request);\n\t}\n\n\t// Render Chain\n\treturn this.sectionRender\n\t\t.then(function(contents){\n\t\t\treturn this.load(contents);\n\t\t}.bind(this))\n\t\t// .then(function(doc){\n\t\t// \treturn this.hooks.content.trigger(view, this);\n\t\t// }.bind(this))\n\t\t.then(function(){\n\t\t\t// this.settings.layout.format(view.contents);\n\t\t\t// return this.hooks.layout.trigger(view, this);\n\t\t}.bind(this))\n\t\t// .then(function(){\n\t\t// \treturn this.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\n\t\t\t// apply the layout function to the contents\n\t\t\tthis.settings.layout.format(this.contents);\n\n\t\t\t// Expand the iframe to the full size of the content\n\t\t\tthis.expand();\n\n\t\t\t// Listen for events that require an expansion of the iframe\n\t\t\tthis.addListeners();\n\n\t\t\tif(show !== false) {\n\t\t\t\t//this.q.enqueue(function(view){\n\t\t\t\t\t// this.show();\n\t\t\t\t//}, view);\n\t\t\t}\n\t\t\t// this.map = new Map(view, this.layout);\n\t\t\t//this.hooks.show.trigger(view, this);\n\t\t\tthis.trigger(\"rendered\", this.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// Determine locks base on settings\nIframeView.prototype.size = function(_width, _height) {\n\tvar width = _width || this.settings.width;\n\tvar height = _height || this.settings.height;\n\n\tif(this.layout.name === \"pre-paginated\") {\n\t\tthis.lock(\"both\", width, height);\n\t} else if(this.settings.axis === \"horizontal\") {\n\t\tthis.lock(\"height\", width, height);\n\t} else {\n\t\tthis.lock(\"width\", width, height);\n\t}\n\n};\n\n// Lock an axis to element dimensions, taking borders into account\nIframeView.prototype.lock = function(what, width, height) {\n\tvar elBorders = core.borders(this.element);\n\tvar iframeBorders;\n\n\tif(this.iframe) {\n\t\tiframeBorders = core.borders(this.iframe);\n\t} else {\n\t\tiframeBorders = {width: 0, height: 0};\n\t}\n\n\tif(what == \"width\" && core.isNumber(width)){\n\t\tthis.lockedWidth = width - elBorders.width - iframeBorders.width;\n\t\tthis.resize(this.lockedWidth, width); // width keeps ratio correct\n\t}\n\n\tif(what == \"height\" && core.isNumber(height)){\n\t\tthis.lockedHeight = height - elBorders.height - iframeBorders.height;\n\t\tthis.resize(width, this.lockedHeight);\n\t}\n\n\tif(what === \"both\" &&\n\t\t core.isNumber(width) &&\n\t\t core.isNumber(height)){\n\n\t\tthis.lockedWidth = width - elBorders.width - iframeBorders.width;\n\t\tthis.lockedHeight = height - elBorders.height - iframeBorders.height;\n\n\t\tthis.resize(this.lockedWidth, this.lockedHeight);\n\t}\n\n\tif(this.displayed && this.iframe) {\n\n\t\t\t// this.contents.layout();\n\t\t\tthis.expand();\n\n\t}\n\n\n\n};\n\n// Resize a single axis based on content dimensions\nIframeView.prototype.expand = function(force) {\n\tvar width = this.lockedWidth;\n\tvar height = this.lockedHeight;\n\tvar columns;\n\n\tvar textWidth, textHeight;\n\n\tif(!this.iframe || this._expanding) return;\n\n\tthis._expanding = true;\n\n\t// Expand Horizontally\n\t// if(height && !width) {\n\tif(this.settings.axis === \"horizontal\") {\n\t\t// Get the width of the text\n\t\ttextWidth = this.contents.textWidth();\n\t\t// Check if the textWidth has changed\n\t\tif(textWidth != this._textWidth){\n\t\t\t// Get the contentWidth by resizing the iframe\n\t\t\t// Check with a min reset of the textWidth\n\t\t\twidth = this.contentWidth(textWidth);\n\n\t\t\tcolumns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap));\n\n\t\t\tif ( this.settings.layout.divisor > 1 &&\n\t\t\t\t\t this.settings.layout.name === \"reflowable\" &&\n\t\t\t\t\t(columns % 2 > 0)) {\n\t\t\t\t\t// add a blank page\n\t\t\t\t\twidth += this.settings.layout.gap + this.settings.layout.columnWidth;\n\t\t\t}\n\n\t\t\t// Save the textWdith\n\t\t\tthis._textWidth = textWidth;\n\t\t\t// Save the contentWidth\n\t\t\tthis._contentWidth = width;\n\t\t} else {\n\t\t\t// Otherwise assume content height hasn't changed\n\t\t\twidth = this._contentWidth;\n\t\t}\n\t} // Expand Vertically\n\telse if(this.settings.axis === \"vertical\") {\n\t\ttextHeight = this.contents.textHeight();\n\t\tif(textHeight != this._textHeight){\n\t\t\theight = this.contentHeight(textHeight);\n\t\t\tthis._textHeight = textHeight;\n\t\t\tthis._contentHeight = height;\n\t\t} else {\n\t\t\theight = this._contentHeight;\n\t\t}\n\n\t}\n\n\t// Only Resize if dimensions have changed or\n\t// if Frame is still hidden, so needs reframing\n\tif(this._needsReframe || width != this._width || height != this._height){\n\t\tthis.resize(width, height);\n\t}\n\n\tthis._expanding = false;\n};\n\nIframeView.prototype.contentWidth = function(min) {\n\tvar prev;\n\tvar width;\n\n\t// Save previous width\n\tprev = this.iframe.style.width;\n\t// Set the iframe size to min, width will only ever be greater\n\t// Will preserve the aspect ratio\n\tthis.iframe.style.width = (min || 0) + \"px\";\n\t// Get the scroll overflow width\n\twidth = this.contents.scrollWidth();\n\t// Reset iframe size back\n\tthis.iframe.style.width = prev;\n\treturn width;\n};\n\nIframeView.prototype.contentHeight = function(min) {\n\tvar prev;\n\tvar height;\n\n\tprev = this.iframe.style.height;\n\tthis.iframe.style.height = (min || 0) + \"px\";\n\theight = this.contents.scrollHeight();\n\n\tthis.iframe.style.height = prev;\n\treturn height;\n};\n\n\nIframeView.prototype.resize = function(width, height) {\n\n\tif(!this.iframe) return;\n\n\tif(core.isNumber(width)){\n\t\tthis.iframe.style.width = width + \"px\";\n\t\tthis._width = width;\n\t}\n\n\tif(core.isNumber(height)){\n\t\tthis.iframe.style.height = height + \"px\";\n\t\tthis._height = height;\n\t}\n\n\tthis.iframeBounds = core.bounds(this.iframe);\n\n\tthis.reframe(this.iframeBounds.width, this.iframeBounds.height);\n\n};\n\nIframeView.prototype.reframe = function(width, height) {\n\tvar size;\n\n\t// if(!this.displayed) {\n\t// this._needsReframe = true;\n\t// return;\n\t// }\n\tif(core.isNumber(width)){\n\t\tthis.element.style.width = width + \"px\";\n\t}\n\n\tif(core.isNumber(height)){\n\t\tthis.element.style.height = height + \"px\";\n\t}\n\n\tthis.prevBounds = this.elementBounds;\n\n\tthis.elementBounds = core.bounds(this.element);\n\n\tsize = {\n\t\twidth: this.elementBounds.width,\n\t\theight: this.elementBounds.height,\n\t\twidthDelta: this.elementBounds.width - this.prevBounds.width,\n\t\theightDelta: this.elementBounds.height - this.prevBounds.height,\n\t};\n\n\tthis.onResize(this, size);\n\n\tthis.trigger(\"resized\", size);\n\n};\n\n\nIframeView.prototype.load = function(contents) {\n\tvar loading = new RSVP.defer();\n\tvar loaded = loading.promise;\n\n\tif(!this.iframe) {\n\t\tloading.reject(new Error(\"No Iframe Available\"));\n\t\treturn loaded;\n\t}\n\n\tthis.iframe.onload = function(event) {\n\n\t\tthis.onLoad(event, loading);\n\n\t}.bind(this);\n\n\tif(this.supportsSrcdoc){\n\t\tthis.iframe.srcdoc = contents;\n\t} else {\n\n\t\tthis.document = this.iframe.contentDocument;\n\n\t\tif(!this.document) {\n\t\t\tloading.reject(new Error(\"No Document Available\"));\n\t\t\treturn loaded;\n\t\t}\n\n\t\tthis.iframe.contentDocument.open();\n\t\tthis.iframe.contentDocument.write(contents);\n\t\tthis.iframe.contentDocument.close();\n\n\t}\n\n\treturn loaded;\n};\n\nIframeView.prototype.onLoad = function(event, promise) {\n\n\t\tthis.window = this.iframe.contentWindow;\n\t\tthis.document = this.iframe.contentDocument;\n\n\t\tthis.contents = new Contents(this.document, this.document.body, this.section.cfiBase);\n\n\t\tthis.rendering = false;\n\n\t\tvar link = this.document.querySelector(\"link[rel='canonical']\");\n\t\tif (link) {\n\t\t\tlink.setAttribute(\"href\", this.section.url);\n\t\t} else {\n\t\t\tlink = this.document.createElement(\"link\");\n\t\t\tlink.setAttribute(\"rel\", \"canonical\");\n\t\t\tlink.setAttribute(\"href\", this.section.url);\n\t\t\tthis.document.querySelector(\"head\").appendChild(link);\n\t\t}\n\n\t\tthis.contents.on(\"expand\", function () {\n\t\t\tif(this.displayed && this.iframe) {\n\t\t\t\t\tthis.expand();\n\t\t\t}\n\t\t});\n\n\t\tpromise.resolve(this.contents);\n};\n\n\n\n// IframeView.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// this.layoutFunc = layoutFunc;\n// }\n//\n// this.contents.layout(this.layoutFunc);\n//\n// };\n//\n// IframeView.prototype.onLayout = function(view) {\n// // stub\n// };\n\nIframeView.prototype.setLayout = function(layout) {\n\tthis.layout = layout;\n};\n\nIframeView.prototype.setAxis = function(axis) {\n\tthis.settings.axis = axis;\n};\n\nIframeView.prototype.resizeListenters = function() {\n\t// Test size again\n\tclearTimeout(this.expanding);\n\tthis.expanding = setTimeout(this.expand.bind(this), 350);\n};\n\nIframeView.prototype.addListeners = function() {\n\t//TODO: Add content listeners for expanding\n};\n\nIframeView.prototype.removeListeners = function(layoutFunc) {\n\t//TODO: remove content listeners for expanding\n};\n\nIframeView.prototype.display = function(request) {\n\tvar displayed = new RSVP.defer();\n\n\tif (!this.displayed) {\n\n\t\tthis.render(request).then(function () {\n\n\t\t\tthis.trigger(\"displayed\", this);\n\t\t\tthis.onDisplayed(this);\n\n\t\t\tthis.displayed = true;\n\t\t\tdisplayed.resolve(this);\n\n\t\t}.bind(this));\n\n\t} else {\n\t\tdisplayed.resolve(this);\n\t}\n\n\n\treturn displayed.promise;\n};\n\nIframeView.prototype.show = function() {\n\n\tthis.element.style.visibility = \"visible\";\n\n\tif(this.iframe){\n\t\tthis.iframe.style.visibility = \"visible\";\n\t}\n\n\tthis.trigger(\"shown\", this);\n};\n\nIframeView.prototype.hide = function() {\n\t// this.iframe.style.display = \"none\";\n\tthis.element.style.visibility = \"hidden\";\n\tthis.iframe.style.visibility = \"hidden\";\n\n\tthis.stopExpanding = true;\n\tthis.trigger(\"hidden\", this);\n};\n\nIframeView.prototype.position = function() {\n\treturn this.element.getBoundingClientRect();\n};\n\nIframeView.prototype.locationOf = function(target) {\n\tvar parentPos = this.iframe.getBoundingClientRect();\n\tvar targetPos = this.contents.locationOf(target, this.settings.ignoreClass);\n\n\treturn {\n\t\t\"left\": window.scrollX + parentPos.left + targetPos.left,\n\t\t\"top\": window.scrollY + parentPos.top + targetPos.top\n\t};\n};\n\nIframeView.prototype.onDisplayed = function(view) {\n\t// Stub, override with a custom functions\n};\n\nIframeView.prototype.onResize = function(view, e) {\n\t// Stub, override with a custom functions\n};\n\nIframeView.prototype.bounds = function() {\n\tif(!this.elementBounds) {\n\t\tthis.elementBounds = core.bounds(this.element);\n\t}\n\treturn this.elementBounds;\n};\n\nIframeView.prototype.destroy = function() {\n\n\tif(this.displayed){\n\t\tthis.displayed = false;\n\n\t\tthis.removeListeners();\n\n\t\tthis.stopExpanding = true;\n\t\tthis.element.removeChild(this.iframe);\n\t\tthis.displayed = false;\n\t\tthis.iframe = null;\n\n\t\tthis._textWidth = null;\n\t\tthis._textHeight = null;\n\t\tthis._width = null;\n\t\tthis._height = null;\n\t}\n\t// this.element.style.height = \"0px\";\n\t// this.element.style.width = \"0px\";\n};\n\nRSVP.EventTarget.mixin(IframeView.prototype);\n\nmodule.exports = IframeView;\n","var EpubCFI = require('./epubcfi');\n\nfunction Mapping(layout){\n\tthis.layout = layout;\n};\n\nMapping.prototype.section = function(view) {\n\tvar ranges = this.findRanges(view);\n\tvar map = this.rangeListToCfiList(view.section.cfiBase, ranges);\n\n\treturn map;\n};\n\nMapping.prototype.page = function(contents, cfiBase, start, end) {\n\tvar root = contents && contents.document ? contents.document.body : false;\n\n\tif (!root) {\n\t\treturn;\n\t}\n\n\treturn this.rangePairToCfiPair(cfiBase, {\n\t\tstart: this.findStart(root, start, end),\n\t\tend: this.findEnd(root, start, end)\n\t});\n};\n\nMapping.prototype.walk = function(root, func) {\n\t//var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);\n\tvar treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n\t\t\tacceptNode: function (node) {\n\t\t\t\t\tif ( node.data.trim().length > 0 ) {\n\t\t\t\t\t\treturn NodeFilter.FILTER_ACCEPT;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn NodeFilter.FILTER_REJECT;\n\t\t\t\t\t}\n\t\t\t}\n\t}, false);\n\tvar node;\n\tvar result;\n\twhile ((node = treeWalker.nextNode())) {\n\t\tresult = func(node);\n\t\tif(result) break;\n\t}\n\n\treturn result;\n};\n\nMapping.prototype.findRanges = function(view){\n\tvar columns = [];\n\tvar scrollWidth = view.contents.scrollWidth();\n\tvar count = this.layout.count(scrollWidth);\n\tvar column = this.layout.column;\n\tvar gap = this.layout.gap;\n\tvar start, end;\n\n\tfor (var i = 0; i < count.pages; i++) {\n\t\tstart = (column + gap) * i;\n\t\tend = (column * (i+1)) + (gap * i);\n\t\tcolumns.push({\n\t\t\tstart: this.findStart(view.document.body, start, end),\n\t\t\tend: this.findEnd(view.document.body, start, end)\n\t\t});\n\t}\n\n\treturn columns;\n};\n\nMapping.prototype.findStart = function(root, start, end){\n\tvar stack = [root];\n\tvar $el;\n\tvar found;\n\tvar $prev = root;\n\twhile (stack.length) {\n\n\t\t$el = stack.shift();\n\n\t\tfound = this.walk($el, function(node){\n\t\t\tvar left, right;\n\t\t\tvar elPos;\n\t\t\tvar elRange;\n\n\n\t\t\tif(node.nodeType == Node.TEXT_NODE){\n\t\t\t\telRange = document.createRange();\n\t\t\t\telRange.selectNodeContents(node);\n\t\t\t\telPos = elRange.getBoundingClientRect();\n\t\t\t} else {\n\t\t\t\telPos = node.getBoundingClientRect();\n\t\t\t}\n\n\t\t\tleft = elPos.left;\n\t\t\tright = elPos.right;\n\n\t\t\tif( left >= start && left <= end ) {\n\t\t\t\treturn node;\n\t\t\t} else if (right > start) {\n\t\t\t\treturn node;\n\t\t\t} else {\n\t\t\t\t$prev = node;\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t});\n\n\t\tif(found) {\n\t\t\treturn this.findTextStartRange(found, start, end);\n\t\t}\n\n\t}\n\n\t// Return last element\n\treturn this.findTextStartRange($prev, start, end);\n};\n\nMapping.prototype.findEnd = function(root, start, end){\n\tvar stack = [root];\n\tvar $el;\n\tvar $prev = root;\n\tvar found;\n\n\twhile (stack.length) {\n\n\t\t$el = stack.shift();\n\n\t\tfound = this.walk($el, function(node){\n\n\t\t\tvar left, right;\n\t\t\tvar elPos;\n\t\t\tvar elRange;\n\n\n\t\t\tif(node.nodeType == Node.TEXT_NODE){\n\t\t\t\telRange = document.createRange();\n\t\t\t\telRange.selectNodeContents(node);\n\t\t\t\telPos = elRange.getBoundingClientRect();\n\t\t\t} else {\n\t\t\t\telPos = node.getBoundingClientRect();\n\t\t\t}\n\n\t\t\tleft = elPos.left;\n\t\t\tright = elPos.right;\n\n\t\t\tif(left > end && $prev) {\n\t\t\t\treturn $prev;\n\t\t\t} else if(right > end) {\n\t\t\t\treturn node;\n\t\t\t} else {\n\t\t\t\t$prev = node;\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t});\n\n\n\t\tif(found){\n\t\t\treturn this.findTextEndRange(found, start, end);\n\t\t}\n\n\t}\n\n\t// end of chapter\n\treturn this.findTextEndRange($prev, start, end);\n};\n\n\nMapping.prototype.findTextStartRange = function(node, start, end){\n\tvar ranges = this.splitTextNodeIntoRanges(node);\n\tvar prev;\n\tvar range;\n\tvar pos;\n\n\tfor (var i = 0; i < ranges.length; i++) {\n\t\trange = ranges[i];\n\n\t\tpos = range.getBoundingClientRect();\n\n\t\tif( pos.left >= start ) {\n\t\t\treturn range;\n\t\t}\n\n\t\tprev = range;\n\n\t}\n\n\treturn ranges[0];\n};\n\nMapping.prototype.findTextEndRange = function(node, start, end){\n\tvar ranges = this.splitTextNodeIntoRanges(node);\n\tvar prev;\n\tvar range;\n\tvar pos;\n\n\tfor (var i = 0; i < ranges.length; i++) {\n\t\trange = ranges[i];\n\n\t\tpos = range.getBoundingClientRect();\n\n\t\tif(pos.left > end && prev) {\n\t\t\treturn prev;\n\t\t} else if(pos.right > end) {\n\t\t\treturn range;\n\t\t}\n\n\t\tprev = range;\n\n\t}\n\n\t// Ends before limit\n\treturn ranges[ranges.length-1];\n\n};\n\nMapping.prototype.splitTextNodeIntoRanges = function(node, _splitter){\n\tvar ranges = [];\n\tvar textContent = node.textContent || \"\";\n\tvar text = textContent.trim();\n\tvar range;\n\tvar rect;\n\tvar list;\n\tvar doc = node.ownerDocument;\n\tvar splitter = _splitter || \" \";\n\n\tpos = text.indexOf(splitter);\n\n\tif(pos === -1 || node.nodeType != Node.TEXT_NODE) {\n\t\trange = doc.createRange();\n\t\trange.selectNodeContents(node);\n\t\treturn [range];\n\t}\n\n\trange = doc.createRange();\n\trange.setStart(node, 0);\n\trange.setEnd(node, pos);\n\tranges.push(range);\n\trange = false;\n\n\twhile ( pos != -1 ) {\n\n\t\tpos = text.indexOf(splitter, pos + 1);\n\t\tif(pos > 0) {\n\n\t\t\tif(range) {\n\t\t\t\trange.setEnd(node, pos);\n\t\t\t\tranges.push(range);\n\t\t\t}\n\n\t\t\trange = doc.createRange();\n\t\t\trange.setStart(node, pos+1);\n\t\t}\n\t}\n\n\tif(range) {\n\t\trange.setEnd(node, text.length);\n\t\tranges.push(range);\n\t}\n\n\treturn ranges;\n};\n\n\n\nMapping.prototype.rangePairToCfiPair = function(cfiBase, rangePair){\n\n\tvar startRange = rangePair.start;\n\tvar endRange = rangePair.end;\n\n\tstartRange.collapse(true);\n\tendRange.collapse(true);\n\n\t// startCfi = section.cfiFromRange(startRange);\n\t// endCfi = section.cfiFromRange(endRange);\n\tstartCfi = new EpubCFI(startRange, cfiBase).toString();\n\tendCfi = new EpubCFI(endRange, cfiBase).toString();\n\n\treturn {\n\t\tstart: startCfi,\n\t\tend: endCfi\n\t};\n\n};\n\nMapping.prototype.rangeListToCfiList = function(cfiBase, columns){\n\tvar map = [];\n\tvar rangePair, cifPair;\n\n\tfor (var i = 0; i < columns.length; i++) {\n\t\tcifPair = this.rangePairToCfiPair(cfiBase, columns[i]);\n\n\t\tmap.push(cifPair);\n\n\t}\n\n\treturn map;\n};\n\nmodule.exports = Mapping;\n","var core = require('./core');\nvar Parser = require('./parser');\nvar RSVP = require('rsvp');\nvar URI = require('urijs');\n\nfunction Navigation(_package, _request){\n\tvar navigation = this;\n\tvar parse = new Parser();\n\tvar request = _request || require('./request');\n\n\tthis.package = _package;\n\tthis.toc = [];\n\tthis.tocByHref = {};\n\tthis.tocById = {};\n\n\tif(_package.navPath) {\n\t\tthis.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();\n\t\tthis.nav = {};\n\n\t\tthis.nav.load = function(_request){\n\t\t\tvar loading = new RSVP.defer();\n\t\t\tvar loaded = loading.promise;\n\n\t\t\trequest(navigation.navUrl, 'xml').then(function(xml){\n\t\t\t\tnavigation.toc = parse.nav(xml);\n\t\t\t\tnavigation.loaded(navigation.toc);\n\t\t\t\tloading.resolve(navigation.toc);\n\t\t\t});\n\n\t\t\treturn loaded;\n\t\t};\n\n\t}\n\n\tif(_package.ncxPath) {\n\t\tthis.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();\n\t\tthis.ncx = {};\n\n\t\tthis.ncx.load = function(_request){\n\t\t\tvar loading = new RSVP.defer();\n\t\t\tvar loaded = loading.promise;\n\n\t\t\trequest(navigation.ncxUrl, 'xml').then(function(xml){\n\t\t\t\tnavigation.toc = parse.toc(xml);\n\t\t\t\tnavigation.loaded(navigation.toc);\n\t\t\t\tloading.resolve(navigation.toc);\n\t\t\t});\n\n\t\t\treturn loaded;\n\t\t};\n\n\t}\n};\n\n// Load the navigation\nNavigation.prototype.load = function(_request) {\n\tvar request = _request || require('./request');\n\tvar loading, loaded;\n\n\tif(this.nav) {\n\t\tloading = this.nav.load();\n\t} else if(this.ncx) {\n\t\tloading = this.ncx.load();\n\t} else {\n\t\tloaded = new RSVP.defer();\n\t\tloaded.resolve([]);\n\t\tloading = loaded.promise;\n\t}\n\n\treturn loading;\n\n};\n\nNavigation.prototype.loaded = function(toc) {\n\tvar item;\n\n\tfor (var i = 0; i < toc.length; i++) {\n\t\titem = toc[i];\n\t\tthis.tocByHref[item.href] = i;\n\t\tthis.tocById[item.id] = i;\n\t}\n\n};\n\n// Get an item from the navigation\nNavigation.prototype.get = function(target) {\n\tvar index;\n\n\tif(!target) {\n\t\treturn this.toc;\n\t}\n\n\tif(target.indexOf(\"#\") === 0) {\n\t\tindex = this.tocById[target.substring(1)];\n\t} else if(target in this.tocByHref){\n\t\tindex = this.tocByHref[target];\n\t}\n\n\treturn this.toc[index];\n};\n\nmodule.exports = Navigation;\n","var URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\n\nfunction Parser(){};\n\nParser.prototype.container = function(containerXml){\n\t\t//-- \n\t\tvar rootfile, fullpath, folder, encoding;\n\n\t\tif(!containerXml) {\n\t\t\tconsole.error(\"Container File Not Found\");\n\t\t\treturn;\n\t\t}\n\n\t\trootfile = core.qs(containerXml, \"rootfile\");\n\n\t\tif(!rootfile) {\n\t\t\tconsole.error(\"No RootFile Found\");\n\t\t\treturn;\n\t\t}\n\n\t\tfullpath = rootfile.getAttribute('full-path');\n\t\tfolder = URI(fullpath).directory();\n\t\tencoding = containerXml.xmlEncoding;\n\n\t\t//-- Now that we have the path we can parse the contents\n\t\treturn {\n\t\t\t'packagePath' : fullpath,\n\t\t\t'basePath' : folder,\n\t\t\t'encoding' : encoding\n\t\t};\n};\n\nParser.prototype.identifier = function(packageXml){\n\tvar metadataNode;\n\n\tif(!packageXml) {\n\t\tconsole.error(\"Package File Not Found\");\n\t\treturn;\n\t}\n\n\tmetadataNode = core.qs(packageXml, \"metadata\");\n\n\tif(!metadataNode) {\n\t\tconsole.error(\"No Metadata Found\");\n\t\treturn;\n\t}\n\n\treturn this.getElementText(metadataNode, \"identifier\");\n};\n\nParser.prototype.packageContents = function(packageXml){\n\tvar parse = this;\n\tvar metadataNode, manifestNode, spineNode;\n\tvar manifest, navPath, ncxPath, coverPath;\n\tvar spineNodeIndex;\n\tvar spine;\n\tvar spineIndexByURL;\n\tvar metadata;\n\n\tif(!packageXml) {\n\t\tconsole.error(\"Package File Not Found\");\n\t\treturn;\n\t}\n\n\tmetadataNode = core.qs(packageXml, \"metadata\");\n\tif(!metadataNode) {\n\t\tconsole.error(\"No Metadata Found\");\n\t\treturn;\n\t}\n\n\tmanifestNode = core.qs(packageXml, \"manifest\");\n\tif(!manifestNode) {\n\t\tconsole.error(\"No Manifest Found\");\n\t\treturn;\n\t}\n\n\tspineNode = core.qs(packageXml, \"spine\");\n\tif(!spineNode) {\n\t\tconsole.error(\"No Spine Found\");\n\t\treturn;\n\t}\n\n\tmanifest = parse.manifest(manifestNode);\n\tnavPath = parse.findNavPath(manifestNode);\n\tncxPath = parse.findNcxPath(manifestNode, spineNode);\n\tcoverPath = parse.findCoverPath(packageXml);\n\n\tspineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);\n\n\tspine = parse.spine(spineNode, manifest);\n\n\tmetadata = parse.metadata(metadataNode);\n\n\tmetadata.direction = spineNode.getAttribute(\"page-progression-direction\");\n\n\treturn {\n\t\t'metadata' : metadata,\n\t\t'spine' : spine,\n\t\t'manifest' : manifest,\n\t\t'navPath' : navPath,\n\t\t'ncxPath' : ncxPath,\n\t\t'coverPath': coverPath,\n\t\t'spineNodeIndex' : spineNodeIndex\n\t};\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\t// var node = manifestNode.querySelector(\"item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']\");\n\tvar node = core.qsp(manifestNode, \"item\", {\"properties\":\"nav\"});\n\treturn 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\t// var node = manifestNode.querySelector(\"item[media-type='application/x-dtbncx+xml']\");\n\tvar node = core.qsp(manifestNode, \"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\t// node = manifestNode.querySelector(\"item[id='\" + tocId + \"']\");\n\t\t\tnode = manifestNode.getElementById(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\tvar metadata = {},\n\t\t\tp = this;\n\n\tmetadata.title = p.getElementText(xml, 'title');\n\tmetadata.creator = p.getElementText(xml, 'creator');\n\tmetadata.description = p.getElementText(xml, 'description');\n\n\tmetadata.pubdate = p.getElementText(xml, 'date');\n\n\tmetadata.publisher = p.getElementText(xml, 'publisher');\n\n\tmetadata.identifier = p.getElementText(xml, \"identifier\");\n\tmetadata.language = p.getElementText(xml, \"language\");\n\tmetadata.rights = p.getElementText(xml, \"rights\");\n\n\tmetadata.modified_date = p.getPropertyText(xml, 'dcterms:modified');\n\n\tmetadata.layout = p.getPropertyText(xml, \"rendition:layout\");\n\tmetadata.orientation = p.getPropertyText(xml, 'rendition:orientation');\n\tmetadata.flow = p.getPropertyText(xml, 'rendition:flow');\n\tmetadata.viewport = p.getPropertyText(xml, 'rendition:viewport');\n\t// metadata.page_prog_dir = packageXml.querySelector(\"spine\").getAttribute(\"page-progression-direction\");\n\n\treturn metadata;\n};\n\n//-- Find Cover: \n//-- Fallback for Epub 2.0\nParser.prototype.findCoverPath = function(packageXml){\n\tvar pkg = core.qs(packageXml, \"package\");\n\tvar epubVersion = pkg.getAttribute('version');\n\n\tif (epubVersion === '2.0') {\n\t\tvar metaCover = core.qsp(packageXml, 'meta', {'name':'cover'});\n\t\tif (metaCover) {\n\t\t\tvar coverId = metaCover.getAttribute('content');\n\t\t\t// var cover = packageXml.querySelector(\"item[id='\" + coverId + \"']\");\n\t\t\tvar cover = packageXml.getElementById(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\t// var node = packageXml.querySelector(\"item[properties='cover-image']\");\n\t\tvar node = core.qsp(packageXml, 'item', {'properties':'cover-image'});\n\t\treturn node ? node.getAttribute('href') : false;\n\t}\n};\n\nParser.prototype.getElementText = function(xml, tag){\n\tvar found = xml.getElementsByTagNameNS(\"http://purl.org/dc/elements/1.1/\", tag),\n\t\tel;\n\n\tif(!found || found.length === 0) return '';\n\n\tel = found[0];\n\n\tif(el.childNodes.length){\n\t\treturn el.childNodes[0].nodeValue;\n\t}\n\n\treturn '';\n\n};\n\nParser.prototype.getPropertyText = function(xml, property){\n\tvar el = core.qsp(xml, \"meta\", {\"property\":property});\n\n\tif(el && el.childNodes.length){\n\t\treturn el.childNodes[0].nodeValue;\n\t}\n\n\treturn '';\n};\n\nParser.prototype.querySelectorText = function(xml, q){\n\tvar el = xml.querySelector(q);\n\n\tif(el && el.childNodes.length){\n\t\treturn el.childNodes[0].nodeValue;\n\t}\n\n\treturn '';\n};\n\nParser.prototype.manifest = function(manifestXml){\n\tvar manifest = {};\n\n\t//-- Turn items into an array\n\t// var selected = manifestXml.querySelectorAll(\"item\");\n\tvar selected = core.qsa(manifestXml, \"item\");\n\tvar items = Array.prototype.slice.call(selected);\n\n\t//-- Create an object with the id as key\n\titems.forEach(function(item){\n\t\tvar id = item.getAttribute('id'),\n\t\t\t\thref = item.getAttribute('href') || '',\n\t\t\t\ttype = item.getAttribute('media-type') || '',\n\t\t\t\tproperties = item.getAttribute('properties') || '';\n\n\t\tmanifest[id] = {\n\t\t\t'href' : href,\n\t\t\t// 'url' : href,\n\t\t\t'type' : type,\n\t\t\t'properties' : properties.length ? properties.split(' ') : []\n\t\t};\n\n\t});\n\n\treturn manifest;\n\n};\n\nParser.prototype.spine = function(spineXml, manifest){\n\tvar spine = [];\n\n\tvar selected = spineXml.getElementsByTagName(\"itemref\"),\n\t\t\titems = Array.prototype.slice.call(selected);\n\n\tvar epubcfi = new EpubCFI();\n\n\t//-- Add to array to mantain ordering and cross reference with manifest\n\titems.forEach(function(item, index){\n\t\tvar idref = item.getAttribute('idref');\n\t\t// var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);\n\t\tvar props = item.getAttribute('properties') || '';\n\t\tvar propArray = props.length ? props.split(' ') : [];\n\t\t// var manifestProps = manifest[Id].properties;\n\t\t// var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];\n\n\t\tvar itemref = {\n\t\t\t'idref' : idref,\n\t\t\t'linear' : item.getAttribute('linear') || '',\n\t\t\t'properties' : propArray,\n\t\t\t// 'href' : manifest[Id].href,\n\t\t\t// 'url' : manifest[Id].url,\n\t\t\t'index' : index\n\t\t\t// 'cfiBase' : cfiBase\n\t\t};\n\t\tspine.push(itemref);\n\t});\n\n\treturn spine;\n};\n\nParser.prototype.querySelectorByType = function(html, element, type){\n\tvar query;\n\tif (typeof html.querySelector != \"undefined\") {\n\t\tquery = html.querySelector(element+'[*|type=\"'+type+'\"]');\n\t}\n\t// Handle IE not supporting namespaced epub:type in querySelector\n\tif(!query || query.length === 0) {\n\t\tquery = core.qsa(html, 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\t// var navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar navItems = navElement ? core.qsa(navElement, \"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\t// content = item.querySelector(\"a, span\"),\n\t\t\tcontent = core.qs(item, \"a\"),\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\t/*\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\t*/\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.ncx = function(tocXml, spineIndexByURL, bookSpine){\n\t// var navPoints = tocXml.querySelectorAll(\"navMap navPoint\");\n\tvar navPoints = core.qsa(tocXml, \"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.ncxItem(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.ncxItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\t// content = item.querySelector(\"content\"),\n\t\t\tcontent = core.qs(item, \"content\"),\n\t\t\tsrc = content.getAttribute('src'),\n\t\t\t// navLabel = item.querySelector(\"navLabel\"),\n\t\t\tnavLabel = core.qs(item, \"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\t/*\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\t*/\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\t// var navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar navItems = navElement ? core.qsa(navElement, \"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\t// content = item.querySelector(\"a\"),\n\t\tcontent = core.qs(item, \"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\tthis._q = [];\n\tthis.context = _context;\n\tthis.tick = core.requestAnimationFrame;\n\tthis.running = false;\n\tthis.paused = false;\n};\n\n// Add an item to the queue\nQueue.prototype.enqueue = function() {\n\tvar deferred, promise;\n\tvar queued;\n\tvar task = [].shift.call(arguments);\n\tvar args = arguments;\n\n\t// Handle single args without context\n\t// if(args && !Array.isArray(args)) {\n\t// args = [args];\n\t// }\n\tif(!task) {\n\t\treturn console.error(\"No Task Provided\");\n\t}\n\n\tif(typeof task === \"function\"){\n\n\t\tdeferred = new RSVP.defer();\n\t\tpromise = deferred.promise;\n\n\t\tqueued = {\n\t\t\t\"task\" : task,\n\t\t\t\"args\" : args,\n\t\t\t//\"context\" : context,\n\t\t\t\"deferred\" : deferred,\n\t\t\t\"promise\" : promise\n\t\t};\n\n\t} else {\n\t\t// Task is a promise\n\t\tqueued = {\n\t\t\t\"promise\" : task\n\t\t};\n\n\t}\n\n\tthis._q.push(queued);\n\n\t// Wait to start queue flush\n\tif (this.paused == false && !this.running) {\n\t\t// setTimeout(this.flush.bind(this), 0);\n\t\t// this.tick.call(window, this.run.bind(this));\n\t\tthis.run();\n\t}\n\n\treturn queued.promise;\n};\n\n// Run one item\nQueue.prototype.dequeue = function(){\n\tvar inwait, task, result;\n\n\tif(this._q.length) {\n\t\tinwait = this._q.shift();\n\t\ttask = inwait.task;\n\t\tif(task){\n\t\t\t// console.log(task)\n\n\t\t\tresult = task.apply(this.context, inwait.args);\n\n\t\t\tif(result && typeof result[\"then\"] === \"function\") {\n\t\t\t\t// Task is a function that returns a promise\n\t\t\t\treturn result.then(function(){\n\t\t\t\t\tinwait.deferred.resolve.apply(this.context, arguments);\n\t\t\t\t}.bind(this));\n\t\t\t} else {\n\t\t\t\t// Task resolves immediately\n\t\t\t\tinwait.deferred.resolve.apply(this.context, result);\n\t\t\t\treturn inwait.promise;\n\t\t\t}\n\n\n\n\t\t} else if(inwait.promise) {\n\t\t\t// Task is a promise\n\t\t\treturn inwait.promise;\n\t\t}\n\n\t} else {\n\t\tinwait = new RSVP.defer();\n\t\tinwait.deferred.resolve();\n\t\treturn inwait.promise;\n\t}\n\n};\n\n// Run All Immediately\nQueue.prototype.dump = function(){\n\twhile(this._q.length) {\n\t\tthis.dequeue();\n\t}\n};\n\n// Run all sequentially, at convince\n\nQueue.prototype.run = function(){\n\n\tif(!this.running){\n\t\tthis.running = true;\n\t\tthis.defered = new RSVP.defer();\n\t}\n\n\tthis.tick.call(window, function() {\n\n\t\tif(this._q.length) {\n\n\t\t\tthis.dequeue()\n\t\t\t\t.then(function(){\n\t\t\t\t\tthis.run();\n\t\t\t\t}.bind(this));\n\n\t\t} else {\n\t\t\tthis.defered.resolve();\n\t\t\tthis.running = undefined;\n\t\t}\n\n\t}.bind(this));\n\n\t// Unpause\n\tif(this.paused == true) {\n\t\tthis.paused = false;\n\t}\n\n\treturn this.defered.promise;\n};\n\n// Flush all, as quickly as possible\nQueue.prototype.flush = function(){\n\n\tif(this.running){\n\t\treturn this.running;\n\t}\n\n\tif(this._q.length) {\n\t\tthis.running = this.dequeue()\n\t\t\t.then(function(){\n\t\t\t\tthis.running = undefined;\n\t\t\t\treturn this.flush();\n\t\t\t}.bind(this));\n\n\t\treturn this.running;\n\t}\n\n};\n\n// Clear all items in wait\nQueue.prototype.clear = function(){\n\tthis._q = [];\n\tthis.running = false;\n};\n\nQueue.prototype.length = function(){\n\treturn this._q.length;\n};\n\nQueue.prototype.pause = function(){\n\tthis.paused = true;\n};\n\n// Create a new task from a callback\nfunction Task(task, args, context){\n\n\treturn function(){\n\t\tvar toApply = arguments || [];\n\n\t\treturn new RSVP.Promise(function(resolve, reject) {\n\t\t\tvar callback = function(value){\n\t\t\t\tresolve(value);\n\t\t\t};\n\t\t\t// Add the callback to the arguments list\n\t\t\ttoApply.push(callback);\n\n\t\t\t// Apply all arguments to the functions\n\t\t\ttask.apply(this, toApply);\n\n\t}.bind(this));\n\n\t};\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 Layout = require('./layout');\nvar Mapping = require('./mapping');\n\nfunction Rendition(book, options) {\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\twidth: null,\n\t\theight: null,\n\t\tignoreClass: '',\n\t\tmanager: \"single\",\n\t\tview: \"iframe\",\n\t\tflow: null,\n\t\tlayout: null,\n\t\tspread: null,\n\t\tminSpreadWidth: 800, //-- overridden by spread: none (never) / both (always),\n\t\tuseBase64: true\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass\n\t};\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\tthis.epubcfi = new EpubCFI();\n\n\tthis.q = new Queue(this);\n\n\tthis.q.enqueue(this.book.opened);\n\n\t// Block the queue until rendering is started\n\t// this.starting = new RSVP.defer();\n\t// this.started = this.starting.promise;\n\tthis.q.enqueue(this.start);\n\n\tif(this.book.unarchived) {\n\t\tthis.q.enqueue(this.replacements.bind(this));\n\t}\n\n};\n\nRendition.prototype.setManager = function(manager) {\n\tthis.manager = manager;\n};\n\nRendition.prototype.requireManager = function(manager) {\n\tvar viewManager;\n\n\t// If manager is a string, try to load from register managers,\n\t// or require included managers directly\n\tif (typeof manager === \"string\") {\n\t\t// Use global or require\n\t\tviewManager = typeof ePub != \"undefined\" ? ePub.ViewManagers[manager] : undefined; //require('./managers/'+manager);\n\t} else {\n\t\t// otherwise, assume we were passed a function\n\t\tviewManager = manager\n\t}\n\n\treturn viewManager;\n};\n\nRendition.prototype.requireView = function(view) {\n\tvar View;\n\n\tif (typeof view == \"string\") {\n\t\tView = typeof ePub != \"undefined\" ? ePub.Views[view] : undefined; //require('./views/'+view);\n\t} else {\n\t\t// otherwise, assume we were passed a function\n\t\tView = view\n\t}\n\n\treturn View;\n};\n\nRendition.prototype.start = function(){\n\n\tif(!this.manager) {\n\t\tthis.ViewManager = this.requireManager(this.settings.manager);\n\t\tthis.View = this.requireView(this.settings.view);\n\n\t\tthis.manager = new this.ViewManager({\n\t\t\tview: this.View,\n\t\t\tqueue: this.q,\n\t\t\trequest: this.book.request,\n\t\t\tsettings: this.settings\n\t\t});\n\t}\n\n\t// Parse metadata to get layout props\n\tthis.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata);\n\n\tthis.flow(this.settings.globalLayoutProperties.flow);\n\n\tthis.layout(this.settings.globalLayoutProperties);\n\n\t// Listen for displayed views\n\tthis.manager.on(\"added\", this.afterDisplayed.bind(this));\n\n\t// Listen for resizing\n\tthis.manager.on(\"resized\", this.onResized.bind(this));\n\n\t// Listen for scroll changes\n\tthis.manager.on(\"scroll\", this.reportLocation.bind(this));\n\n\n\tthis.on('displayed', this.reportLocation.bind(this));\n\n\t// Trigger that rendering has started\n\tthis.trigger(\"started\");\n\n\t// Start processing queue\n\t// this.starting.resolve();\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\n\treturn this.q.enqueue(function () {\n\n\t\t// Start rendering\n\t\tthis.manager.render(element, {\n\t\t\t\"width\" : this.settings.width,\n\t\t\t\"height\" : this.settings.height\n\t\t});\n\n\t\t// Trigger Attached\n\t\tthis.trigger(\"attached\");\n\n\t}.bind(this));\n\n};\n\nRendition.prototype.display = function(target){\n\n\t// if (!this.book.spine.spineItems.length > 0) {\n\t\t// Book isn't open yet\n\t\t// return this.q.enqueue(this.display, target);\n\t// }\n\n\treturn this.q.enqueue(this._display, target);\n\n};\n\nRendition.prototype._display = function(target){\n\tvar isCfiString = this.epubcfi.isCfiString(target);\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\tvar section;\n\tvar moveTo;\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// Trim the target fragment\n\t// removing the chapter\n\tif(!isCfiString && typeof target === \"string\" &&\n\t\ttarget.indexOf(\"#\") > -1) {\n\t\t\tmoveTo = target.substring(target.indexOf(\"#\")+1);\n\t}\n\n\tif (isCfiString) {\n\t\tmoveTo = target;\n\t}\n\n\treturn this.manager.display(section, moveTo)\n\t\t.then(function(){\n\t\t\tthis.trigger(\"displayed\", section);\n\t\t}.bind(this));\n\n};\n\n/*\nRendition.prototype.render = function(view, show) {\n\n\t// view.onLayout = this.layout.format.bind(this.layout);\n\tview.create();\n\n\t// Fit to size of the container, apply padding\n\tthis.manager.resizeView(view);\n\n\t// Render Chain\n\treturn view.section.render(this.book.request)\n\t\t.then(function(contents){\n\t\t\treturn view.load(contents);\n\t\t}.bind(this))\n\t\t.then(function(doc){\n\t\t\treturn this.hooks.content.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\tthis.layout.format(view.contents);\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) {\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\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.hooks.content.trigger(view, this);\n\tthis.trigger(\"rendered\", view.section);\n\tthis.reportLocation();\n};\n\nRendition.prototype.onResized = function(size){\n\n\tif(this.location) {\n\t\tthis.display(this.location.start);\n\t}\n\n\tthis.trigger(\"resized\", {\n\t\twidth: size.width,\n\t\theight: size.height\n\t});\n\n};\n\nRendition.prototype.moveTo = function(offset){\n\tthis.manager.moveTo(offset);\n};\n\nRendition.prototype.next = function(){\n\treturn this.q.enqueue(this.manager.next.bind(this.manager))\n\t\t.then(this.reportLocation.bind(this));\n};\n\nRendition.prototype.prev = function(){\n\treturn this.q.enqueue(this.manager.prev.bind(this.manager))\n\t\t.then(this.reportLocation.bind(this));\n};\n\n//-- http://www.idpf.org/epub/301/spec/epub-publications.html#meta-properties-rendering\nRendition.prototype.determineLayoutProperties = function(metadata){\n\tvar settings;\n\tvar layout = this.settings.layout || metadata.layout || \"reflowable\";\n\tvar spread = this.settings.spread || metadata.spread || \"auto\";\n\tvar orientation = this.settings.orientation || metadata.orientation || \"auto\";\n\tvar flow = this.settings.flow || metadata.flow || \"auto\";\n\tvar viewport = metadata.viewport || \"\";\n\tvar minSpreadWidth = this.settings.minSpreadWidth || metadata.minSpreadWidth || 800;\n\n\tif (this.settings.width >= 0 && this.settings.height >= 0) {\n\t\tviewport = \"width=\"+this.settings.width+\", height=\"+this.settings.height+\"\";\n\t}\n\n\tsettings = {\n\t\tlayout : layout,\n\t\tspread : spread,\n\t\torientation : orientation,\n\t\tflow : flow,\n\t\tviewport : viewport,\n\t\tminSpreadWidth : minSpreadWidth\n\t};\n\n\treturn settings;\n};\n\n// Rendition.prototype.applyLayoutProperties = function(){\n// \tvar settings = this.determineLayoutProperties(this.book.package.metadata);\n//\n// \tthis.flow(settings.flow);\n//\n// \tthis.layout(settings);\n// };\n\n// paginated | scrolled\n// (scrolled-continuous vs scrolled-doc are handled by different view managers)\nRendition.prototype.flow = function(_flow){\n\tvar flow;\n\tif (_flow === \"scrolled-doc\" || _flow === \"scrolled-continuous\") {\n\t\tflow = \"scrolled\";\n\t}\n\n\tif (_flow === \"auto\" || _flow === \"paginated\") {\n\t\tflow = \"paginated\";\n\t}\n\n\tif (this._layout) {\n\t\tthis._layout.flow(flow);\n\t}\n\n\tif (this.manager) {\n\t\tthis.manager.updateFlow(flow);\n\t}\n};\n\n// reflowable | pre-paginated\nRendition.prototype.layout = function(settings){\n\tif (settings) {\n\t\tthis._layout = new Layout(settings);\n\t\tthis._layout.spread(settings.spread, this.settings.minSpreadWidth);\n\n\t\tthis.mapping = new Mapping(this._layout);\n\t}\n\n\tif (this.manager && this._layout) {\n\t\tthis.manager.applyLayout(this._layout);\n\t}\n\n\treturn this._layout;\n};\n\n// none | auto (TODO: implement landscape, portrait, both)\nRendition.prototype.spread = function(spread, min){\n\n\tthis._layout.spread(spread, min);\n\n\tif (this.manager.isRendered()) {\n\t\tthis.manager.updateLayout();\n\t}\n};\n\n\nRendition.prototype.reportLocation = function(){\n\treturn this.q.enqueue(function(){\n\t\tvar location = this.manager.currentLocation();\n\t\tif (location && location.then && typeof location.then === 'function') {\n\t\t\tlocation.then(function(result) {\n\t\t\t\tthis.location = result;\n\t\t\t\tthis.trigger(\"locationChanged\", this.location);\n\t\t\t}.bind(this));\n\t\t} else if (location) {\n\t\t\tthis.location = location;\n\t\t\tthis.trigger(\"locationChanged\", this.location);\n\t\t}\n\n\t}.bind(this));\n};\n\n\nRendition.prototype.destroy = function(){\n\t// Clear the queue\n\tthis.q.clear();\n\n\tthis.manager.destroy();\n};\n\nRendition.prototype.passViewEvents = function(view){\n\tview.contents.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\tthis.trigger(e.type, e);\n};\n\nRendition.prototype.triggerSelectedEvent = function(cfirange){\n\tthis.trigger(\"selected\", cfirange);\n};\n\nRendition.prototype.replacements = function(){\n\t// Wait for loading\n\t// return this.q.enqueue(function () {\n\t\t// Get thes books manifest\n\t\tvar manifest = this.book.package.manifest;\n\t\tvar manifestArray = Object.keys(manifest).\n\t\t\tmap(function (key){\n\t\t\t\treturn manifest[key];\n\t\t\t});\n\n\t\t// Exclude HTML\n\t\tvar items = manifestArray.\n\t\t\tfilter(function (item){\n\t\t\t\tif (item.type != \"application/xhtml+xml\" &&\n\t\t\t\t\t\titem.type != \"text/html\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t});\n\n\t\t// Only CSS\n\t\tvar css = items.\n\t\t\tfilter(function (item){\n\t\t\t\tif (item.type === \"text/css\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\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\tvar urls = items.\n\t\t\tmap(function(item) {\n\t\t\t\treturn item.href;\n\t\t\t}.bind(this));\n\n\t\t// Create blob urls for all the assets\n\t\tvar processing = urls.\n\t\t\tmap(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\t\t\treturn this.book.unarchived.createUrl(absolute, {\"base64\": this.settings.useBase64});\n\t\t\t}.bind(this));\n\n\t\tvar replacementUrls;\n\n\t\t// After all the urls are created\n\t\treturn RSVP.all(processing)\n\t\t\t.then(function(_replacementUrls) {\n\t\t\t\tvar replaced = [];\n\n\t\t\t\treplacementUrls = _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\treplaced.push(this.replaceCss(href, urls, replacementUrls));\n\t\t\t\t}.bind(this));\n\n\t\t\t\treturn RSVP.all(replaced);\n\n\t\t\t}.bind(this))\n\t\t\t.then(function () {\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\t\t\tthis.book.spine.hooks.serialize.register(function(output, section) {\n\n\t\t\t\t\tthis.replaceAssets(section, urls, replacementUrls);\n\n\t\t\t\t}.bind(this));\n\n\t\t\t}.bind(this))\n\t\t\t.catch(function(reason){\n\t\t\t\tconsole.error(reason);\n\t\t\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 textResponse = this.book.unarchived.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\treturn textResponse.then(function (text) {\n\t\t\t// Replacements in the css text\n\t\t\ttext = replace.substitute(text, relUrls, replacementUrls);\n\n\t\t\t// Get the new url\n\t\t\tif (this.settings.useBase64) {\n\t\t\t\tnewUrl = core.createBase64Url(text, 'text/css');\n\t\t\t} else {\n\t\t\t\tnewUrl = core.createBlobUrl(text, 'text/css');\n\t\t\t}\n\n\t\t\t// switch the url in the replacementUrls\n\t\t\tindexInUrls = urls.indexOf(href);\n\t\t\tif (indexInUrls > -1) {\n\t\t\t\treplacementUrls[indexInUrls] = newUrl;\n\t\t\t}\n\n\t\t\treturn new RSVP.Promise(function(resolve, reject){\n\t\t\t\tresolve(urls, replacementUrls);\n\t\t\t});\n\n\t\t}.bind(this));\n\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\nRendition.prototype.range = function(_cfi, ignoreClass){\n\tvar cfi = new EpubCFI(_cfi);\n\tvar found = this.visible().filter(function (view) {\n\t\tif(cfi.spinePos === view.index) return true;\n\t});\n\n\t// Should only every return 1 item\n\tif (found.length) {\n\t\treturn found[0].range(cfi, ignoreClass);\n\t}\n};\n\nRendition.prototype.adjustImages = function(view) {\n\n\tview.addStylesheetRules([\n\t\t\t[\"img\",\n\t\t\t\t[\"max-width\", (view.layout.spreadWidth) + \"px\"],\n\t\t\t\t[\"max-height\", (view.layout.height) + \"px\"]\n\t\t\t]\n\t]);\n\treturn new RSVP.Promise(function(resolve, reject){\n\t\t// Wait to apply\n\t\tsetTimeout(function() {\n\t\t\tresolve();\n\t\t}, 1);\n\t});\n};\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\tvar base;\n\tvar head;\n\n\tif(!doc){\n\t\treturn;\n\t}\n\n\t// head = doc.querySelector(\"head\");\n\t// base = head.querySelector(\"base\");\n\thead = core.qs(doc, \"head\");\n\tbase = core.qs(head, \"base\");\n\n\tif(!base) {\n\t\tbase = doc.createElement(\"base\");\n\t\thead.insertBefore(base, head.firstChild);\n\t}\n\n\tbase.setAttribute(\"href\", section.url);\n}\n\nfunction canonical(doc, section){\n\tvar head;\n\tvar link;\n\tvar url = section.url; // window.location.origin + window.location.pathname + \"?loc=\" + encodeURIComponent(section.url);\n\n\tif(!doc){\n\t\treturn;\n\t}\n\n\thead = core.qs(doc, \"head\");\n\tlink = core.qs(head, \"link[rel='canonical']\");\n\n\tif (link) {\n\t\tlink.setAttribute(\"href\", url);\n\t} else {\n\t\tlink = doc.createElement(\"link\");\n\t\tlink.setAttribute(\"rel\", \"canonical\");\n\t\tlink.setAttribute(\"href\", url);\n\t\thead.appendChild(link);\n\t}\n}\n\nfunction links(view, renderer) {\n\n\tvar links = view.document.querySelectorAll(\"a[href]\");\n\tvar replaceLinks = function(link){\n\t\tvar href = link.getAttribute(\"href\");\n\n\t\tif(href.indexOf(\"mailto:\") === 0){\n\t\t\treturn;\n\t\t}\n\n\t\tvar linkUri = URI(href);\n\t\tvar absolute = linkUri.absoluteTo(view.section.url);\n\t\tvar relative = absolute.relativeTo(this.book.baseUrl).toString();\n\n\t\tif(linkUri.protocol()){\n\n\t\t\tlink.setAttribute(\"target\", \"_blank\");\n\n\t\t}else{\n\t\t\t/*\n\t\t\tif(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\t\t\t*/\n\n\t\t\tif(linkUri.fragment()) {\n\t\t\t\t// do nothing with fragment yet\n\t\t\t} else {\n\t\t\t\tlink.onclick = function(){\n\t\t\t\t\trenderer.display(relative);\n\t\t\t\t\treturn false;\n\t\t\t\t};\n\t\t\t}\n\n\t\t}\n\t}.bind(this);\n\n\tfor (var i = 0; i < links.length; i++) {\n\t\treplaceLinks(links[i]);\n\t}\n\n\n};\n\nfunction substitute(content, urls, replacements) {\n\turls.forEach(function(url, i){\n\t\tif (url && replacements[i]) {\n\t\t\tcontent = content.replace(new RegExp(url, 'g'), replacements[i]);\n\t\t}\n\t});\n\treturn content;\n}\nmodule.exports = {\n\t'base': base,\n\t'canonical' : canonical,\n\t'links': links,\n\t'substitute': substitute\n};\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\n\nfunction request(url, type, withCredentials, headers) {\n\tvar supportsURL = (typeof window != \"undefined\") ? window.URL : false; // TODO: fallback for url if window isn't defined\n\tvar BLOB_RESPONSE = supportsURL ? \"blob\" : \"arraybuffer\";\n\tvar uri;\n\n\tvar deferred = new RSVP.defer();\n\n\tvar xhr = new XMLHttpRequest();\n\n\t//-- Check from PDF.js:\n\t// https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js\n\tvar xhrPrototype = XMLHttpRequest.prototype;\n\n\tvar header;\n\n\tif (!('overrideMimeType' in xhrPrototype)) {\n\t\t// IE10 might have response, but not overrideMimeType\n\t\tObject.defineProperty(xhrPrototype, 'overrideMimeType', {\n\t\t\tvalue: function xmlHttpRequestOverrideMimeType(mimeType) {}\n\t\t});\n\t}\n\tif(withCredentials) {\n\t\txhr.withCredentials = true;\n\t}\n\n\txhr.onreadystatechange = handler;\n\txhr.onerror = err;\n\n\txhr.open(\"GET\", url, true);\n\n\tfor(header in headers) {\n\t\txhr.setRequestHeader(header, headers[header]);\n\t}\n\n\tif(type == \"json\") {\n\t\txhr.setRequestHeader(\"Accept\", \"application/json\");\n\t}\n\n\t// 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\tif(type == 'blob'){\n\t\txhr.responseType = BLOB_RESPONSE;\n\t}\n\n\n\tif(core.isXml(type)) {\n\t\t// xhr.responseType = \"document\";\n\t\txhr.overrideMimeType('text/xml'); // for OPF parsing\n\t}\n\n\tif(type == 'xhtml') {\n\t\t// xhr.responseType = \"document\";\n\t}\n\n\tif(type == 'html' || type == 'htm') {\n\t\t// xhr.responseType = \"document\";\n\t }\n\n\tif(type == \"binary\") {\n\t\txhr.responseType = \"arraybuffer\";\n\t}\n\n\txhr.send();\n\n\tfunction err(e) {\n\t\tconsole.error(e);\n\t\tdeferred.reject(e);\n\t}\n\n\tfunction handler() {\n\t\tif (this.readyState === XMLHttpRequest.DONE) {\n\n\t\t\tif (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls\n\t\t\t\tvar r;\n\n\t\t\t\tif (!this.response && !this.responseXML) {\n\t\t\t\t\tdeferred.reject({\n\t\t\t\t\t\tstatus: this.status,\n\t\t\t\t\t\tmessage : \"Empty Response\",\n\t\t\t\t\t\tstack : new Error().stack\n\t\t\t\t\t});\n\t\t\t\t\treturn deferred.promise;\n\t\t\t\t}\n\n\t\t\t\tif (this.status === 403) {\n\t\t\t\t\tdeferred.reject({\n\t\t\t\t\t\tstatus: this.status,\n\t\t\t\t\t\tresponse: this.response,\n\t\t\t\t\t\tmessage : \"Forbidden\",\n\t\t\t\t\t\tstack : new Error().stack\n\t\t\t\t\t});\n\t\t\t\t\treturn deferred.promise;\n\t\t\t\t}\n\n\t\t\t\tif((this.responseType == '' || this.responseType == 'document')\n\t\t\t\t\t\t&& this.responseXML){\n\t\t\t\t\tr = this.responseXML;\n\t\t\t\t} else\n\t\t\t\tif(core.isXml(type)){\n\t\t\t\t\t// xhr.overrideMimeType('text/xml'); // for OPF parsing\n\t\t\t\t\t// If this.responseXML wasn't set, try to parse using a DOMParser from text\n\t\t\t\t\tr = core.parse(this.response, \"text/xml\");\n\t\t\t\t}else\n\t\t\t\tif(type == 'xhtml'){\n\t\t\t\t\tr = core.parse(this.response, \"application/xhtml+xml\");\n\t\t\t\t}else\n\t\t\t\tif(type == 'html' || type == 'htm'){\n\t\t\t\t\tr = core.parse(this.response, \"text/html\");\n\t\t\t\t}else\n\t\t\t\tif(type == 'json'){\n\t\t\t\t\tr = JSON.parse(this.response);\n\t\t\t\t}else\n\t\t\t\tif(type == 'blob'){\n\n\t\t\t\t\tif(supportsURL) {\n\t\t\t\t\t\tr = this.response;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//-- Safari doesn't support responseType blob, so create a blob from arraybuffer\n\t\t\t\t\t\tr = new Blob([this.response]);\n\t\t\t\t\t}\n\n\t\t\t\t}else{\n\t\t\t\t\tr = this.response;\n\t\t\t\t}\n\n\t\t\t\tdeferred.resolve(r);\n\t\t\t} else {\n\n\t\t\t\tdeferred.reject({\n\t\t\t\t\tstatus: this.status,\n\t\t\t\t\tmessage : this.response,\n\t\t\t\t\tstack : new Error().stack\n\t\t\t\t});\n\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 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');\n\nfunction Section(item, hooks){\n\t\tthis.idref = item.idref;\n\t\tthis.linear = item.linear;\n\t\tthis.properties = item.properties;\n\t\tthis.index = item.index;\n\t\tthis.href = item.href;\n\t\tthis.url = item.url;\n\t\tthis.next = item.next;\n\t\tthis.prev = item.prev;\n\n\t\tthis.cfiBase = item.cfiBase;\n\n\t\tif (hooks) {\n\t\t\tthis.hooks = hooks;\n\t\t} else {\n\t\t\tthis.hooks = {};\n\t\t\tthis.hooks.serialize = new Hook(this);\n\t\t\tthis.hooks.content = new Hook(this);\n\t\t}\n\n};\n\n\nSection.prototype.load = function(_request){\n\tvar request = _request || this.request || require('./request');\n\tvar loading = new RSVP.defer();\n\tvar loaded = loading.promise;\n\n\tif(this.contents) {\n\t\tloading.resolve(this.contents);\n\t} else {\n\t\trequest(this.url)\n\t\t\t.then(function(xml){\n\t\t\t\tvar base;\n\t\t\t\tvar directory = URI(this.url).directory();\n\n\t\t\t\tthis.document = xml;\n\t\t\t\tthis.contents = xml.documentElement;\n\n\t\t\t\treturn this.hooks.content.trigger(this.document, this);\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tloading.resolve(this.contents);\n\t\t\t}.bind(this))\n\t\t\t.catch(function(error){\n\t\t\t\tloading.reject(error);\n\t\t\t});\n\t}\n\n\treturn loaded;\n};\n\nSection.prototype.base = function(_document){\n\t\tvar task = new RSVP.defer();\n\t\tvar base = _document.createElement(\"base\"); // TODO: check if exists\n\t\tvar head;\n\t\tconsole.log(window.location.origin + \"/\" +this.url);\n\n\t\tbase.setAttribute(\"href\", window.location.origin + \"/\" +this.url);\n\n\t\tif(_document) {\n\t\t\thead = _document.querySelector(\"head\");\n\t\t}\n\t\tif(head) {\n\t\t\thead.insertBefore(base, head.firstChild);\n\t\t\ttask.resolve();\n\t\t} else {\n\t\t\ttask.reject(new Error(\"No head to insert into\"));\n\t\t}\n\n\n\t\treturn task.promise;\n};\n\nSection.prototype.beforeSectionLoad = function(){\n\t// Stub for a hook - replace me for now\n};\n\nSection.prototype.render = function(_request){\n\tvar rendering = new RSVP.defer();\n\tvar rendered = rendering.promise;\n\tthis.output; // TODO: better way to return this from hooks?\n\n\tthis.load(_request).\n\t\tthen(function(contents){\n\t\t\tvar serializer;\n\n\t\t\tif (typeof XMLSerializer === \"undefined\") {\n\t\t\t\tXMLSerializer = require('xmldom').XMLSerializer;\n\t\t\t}\n\t\t\tserializer = new XMLSerializer();\n\t\t\tthis.output = serializer.serializeToString(contents);\n\t\t\treturn this.output;\n\t\t}.bind(this)).\n\t\tthen(function(){\n\t\t\treturn this.hooks.serialize.trigger(this.output, this);\n\t\t}.bind(this)).\n\t\tthen(function(){\n\t\t\trendering.resolve(this.output);\n\t\t}.bind(this))\n\t\t.catch(function(error){\n\t\t\trendering.reject(error);\n\t\t});\n\n\treturn 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\t//-- Get the global defaults\n\tvar settings = {\n\t\tlayout : global.layout,\n\t\tspread : global.spread,\n\t\torientation : global.orientation\n\t};\n\n\t//-- Get the chapter's display type\n\tthis.properties.forEach(function(prop){\n\t\tvar rendition = prop.replace(\"rendition:\", '');\n\t\tvar split = rendition.indexOf(\"-\");\n\t\tvar property, value;\n\n\t\tif(split != -1){\n\t\t\tproperty = rendition.slice(0, split);\n\t\t\tvalue = rendition.slice(split+1);\n\n\t\t\tsettings[property] = value;\n\t\t}\n\t});\n return settings;\n};\n\nSection.prototype.cfiFromRange = function(_range) {\n\treturn new EpubCFI(_range, this.cfiBase).toString();\n};\n\nSection.prototype.cfiFromElement = function(el) {\n\treturn new EpubCFI(el, this.cfiBase).toString();\n};\n\nmodule.exports = Section;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\nvar Section = require('./section');\nvar replacements = require('./replacements');\n\nfunction Spine(_request){\n\tthis.request = _request;\n\tthis.spineItems = [];\n\tthis.spineByHref = {};\n\tthis.spineById = {};\n\n\tthis.hooks = {};\n\tthis.hooks.serialize = new Hook();\n\tthis.hooks.content = new Hook();\n\n\t// Register replacements\n\tthis.hooks.content.register(replacements.base);\n\tthis.hooks.content.register(replacements.canonical);\n\n\tthis.epubcfi = new EpubCFI();\n\n\tthis.loaded = false;\n};\n\nSpine.prototype.load = function(_package) {\n\n\tthis.items = _package.spine;\n\tthis.manifest = _package.manifest;\n\tthis.spineNodeIndex = _package.spineNodeIndex;\n\tthis.baseUrl = _package.baseUrl || '';\n\tthis.length = this.items.length;\n\n\tthis.items.forEach(function(item, index){\n\t\tvar href, url;\n\t\tvar manifestItem = this.manifest[item.idref];\n\t\tvar spineItem;\n\n\t\titem.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);\n\n\t\tif(manifestItem) {\n\t\t\titem.href = manifestItem.href;\n\t\t\titem.url = this.baseUrl + item.href;\n\n\t\t\tif(manifestItem.properties.length){\n\t\t\t\titem.properties.push.apply(item.properties, manifestItem.properties);\n\t\t\t}\n\t\t}\n\n\t\t// if(index > 0) {\n\t\t\titem.prev = function(){ return this.get(index-1); }.bind(this);\n\t\t// }\n\n\t\t// if(index+1 < this.items.length) {\n\t\t\titem.next = function(){ return this.get(index+1); }.bind(this);\n\t\t// }\n\n\t\tspineItem = new Section(item, this.hooks);\n\n\t\tthis.append(spineItem);\n\n\n\t}.bind(this));\n\n\tthis.loaded = true;\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\tvar index = 0;\n\n\tif(this.epubcfi.isCfiString(target)) {\n\t\tcfi = new EpubCFI(target);\n\t\tindex = cfi.spinePos;\n\t} else if(target && (typeof target === \"number\" || isNaN(target) === false)){\n\t\tindex = target;\n\t} else if(target && target.indexOf(\"#\") === 0) {\n\t\tindex = this.spineById[target.substring(1)];\n\t} else if(target) {\n\t\t// Remove fragments\n\t\ttarget = target.split(\"#\")[0];\n\t\tindex = this.spineByHref[target];\n\t}\n\n\treturn this.spineItems[index] || null;\n};\n\nSpine.prototype.append = function(section) {\n\tvar index = this.spineItems.length;\n\tsection.index = index;\n\n\tthis.spineItems.push(section);\n\n\tthis.spineByHref[section.href] = index;\n\tthis.spineById[section.idref] = index;\n\n\treturn index;\n};\n\nSpine.prototype.prepend = function(section) {\n\tvar index = this.spineItems.unshift(section);\n\tthis.spineByHref[section.href] = 0;\n\tthis.spineById[section.idref] = 0;\n\n\t// Re-index\n\tthis.spineItems.forEach(function(item, index){\n\t\titem.index = index;\n\t});\n\n\treturn 0;\n};\n\nSpine.prototype.insert = function(section, index) {\n\n};\n\nSpine.prototype.remove = function(section) {\n\tvar index = this.spineItems.indexOf(section);\n\n\tif(index > -1) {\n\t\tdelete this.spineByHref[section.href];\n\t\tdelete this.spineById[section.idref];\n\n\t\treturn this.spineItems.splice(index, 1);\n\t}\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\tthis.checkRequirements();\n\tthis.urlCache = {};\n\n}\n\nUnarchive.prototype.checkRequirements = function(callback){\n\ttry {\n\t\tif (typeof JSZip !== 'undefined') {\n\t\t\tthis.zip = new JSZip();\n\t\t} else {\n\t\t\tJSZip = require('jszip');\n\t\t\tthis.zip = new JSZip();\n\t\t}\n\t} catch (e) {\n\t\tconsole.error(\"JSZip lib not loaded\");\n\t}\n};\n\nUnarchive.prototype.open = function(zipUrl, isBase64){\n\tif (zipUrl instanceof ArrayBuffer || isBase64) {\n\t\treturn this.zip.loadAsync(zipUrl, {\"base64\": isBase64});\n\t} else {\n\t\treturn request(zipUrl, \"binary\")\n\t\t\t.then(function(data){\n\t\t\t\treturn this.zip.loadAsync(data);\n\t\t\t}.bind(this));\n\t}\n};\n\nUnarchive.prototype.request = function(url, type){\n\tvar deferred = new RSVP.defer();\n\tvar response;\n\tvar r;\n\n\t// 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\tif(type == 'blob'){\n\t\tresponse = this.getBlob(url);\n\t} else {\n\t\tresponse = this.getText(url);\n\t}\n\n\tif (response) {\n\t\tresponse.then(function (r) {\n\t\t\tresult = this.handleResponse(r, type);\n\t\t\tdeferred.resolve(result);\n\t\t}.bind(this));\n\t} else {\n\t\tdeferred.reject({\n\t\t\tmessage : \"File not found in the epub: \" + url,\n\t\t\tstack : new Error().stack\n\t\t});\n\t}\n\treturn deferred.promise;\n};\n\nUnarchive.prototype.handleResponse = function(response, type){\n\tvar r;\n\n\tif(type == \"json\") {\n\t\tr = JSON.parse(response);\n\t}\n\telse\n\tif(core.isXml(type)) {\n\t\tr = core.parse(response, \"text/xml\");\n\t}\n\telse\n\tif(type == 'xhtml') {\n\t\tr = core.parse(response, \"application/xhtml+xml\");\n\t}\n\telse\n\tif(type == 'html' || type == 'htm') {\n\t\tr = core.parse(response, \"text/html\");\n\t } else {\n\t\t r = response;\n\t }\n\n\treturn 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\tvar mimeType;\n\n\tif(entry) {\n\t\tmimeType = _mimeType || mime.lookup(entry.name);\n\t\treturn entry.async(\"uint8array\").then(function(uint8array) {\n\t\t\treturn new Blob([uint8array], {type : mimeType});\n\t\t});\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\t\treturn entry.async(\"string\").then(function(text) {\n\t\t\treturn text;\n\t\t});\n\t}\n};\n\nUnarchive.prototype.getBase64 = function(url, _mimeType){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n\tvar mimeType;\n\n\tif(entry) {\n\t\tmimeType = _mimeType || mime.lookup(entry.name);\n\t\treturn entry.async(\"base64\").then(function(data) {\n\t\t\treturn \"data:\" + mimeType + \";base64,\" + data;\n\t\t});\n\t}\n};\n\nUnarchive.prototype.createUrl = function(url, options){\n\tvar deferred = new RSVP.defer();\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob;\n\tvar response;\n\tvar useBase64 = options && options.base64;\n\n\tif(url in this.urlCache) {\n\t\tdeferred.resolve(this.urlCache[url]);\n\t\treturn deferred.promise;\n\t}\n\n\tif (useBase64) {\n\t\tresponse = this.getBase64(url);\n\n\t\tif (response) {\n\t\t\tresponse.then(function(tempUrl) {\n\n\t\t\t\tthis.urlCache[url] = tempUrl;\n\t\t\t\tdeferred.resolve(tempUrl);\n\n\t\t\t}.bind(this));\n\n\t\t}\n\n\t} else {\n\n\t\tresponse = this.getBlob(url);\n\n\t\tif (response) {\n\t\t\tresponse.then(function(blob) {\n\n\t\t\t\ttempUrl = _URL.createObjectURL(blob);\n\t\t\t\tthis.urlCache[url] = tempUrl;\n\t\t\t\tdeferred.resolve(tempUrl);\n\n\t\t\t}.bind(this));\n\n\t\t}\n\t}\n\n\n\tif (!response) {\n\t\tdeferred.reject({\n\t\t\tmessage : \"File not found in the epub: \" + url,\n\t\t\tstack : new Error().stack\n\t\t});\n\t}\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 Book = require('./book');\nvar EpubCFI = require('./epubcfi');\nvar Rendition = require('./rendition');\nvar Contents = require('./contents');\nvar RSVP = require('rsvp');\n\nfunction ePub(_url) {\n\treturn new Book(_url);\n};\n\nePub.VERSION = \"0.3.0\";\n\nePub.CFI = EpubCFI;\nePub.Rendition = Rendition;\nePub.Contents = Contents;\nePub.RSVP = RSVP;\n\nePub.ViewManagers = {};\nePub.Views = {};\nePub.register = {\n\tmanager : function(name, manager){\n\t\treturn ePub.ViewManagers[name] = manager;\n\t},\n\tview : function(name, view){\n\t\treturn ePub.Views[name] = view;\n\t}\n};\n\n// Default Views\nePub.register.view(\"iframe\", require('./managers/views/iframe'));\n// ePub.register.view(\"inline\", require('./managers/views/inline'));\n\n// Default View Managers\nePub.register.manager(\"single\", require('./managers/default'));\nePub.register.manager(\"continuous\", require('./managers/continuous'));\n\nmodule.exports = ePub;\n"]} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 357e8a8caf94859fd255","webpack:///./src/epub.js","webpack:///./src/book.js","webpack:///./~/rsvp/dist/rsvp.js","webpack:///./~/process/browser.js","webpack:///./~/timers-browserify/main.js","webpack:///vertx (ignored)","webpack:///./~/urijs/src/URI.js","webpack:///./~/urijs/src/punycode.js","webpack:///(webpack)/buildin/module.js","webpack:///./~/urijs/src/IPv6.js","webpack:///./~/urijs/src/SecondLevelDomains.js","webpack:///./src/core.js","webpack:///./~/base64-js/index.js","webpack:///external \"xmldom\"","webpack:///./src/spine.js","webpack:///./src/epubcfi.js","webpack:///./src/hook.js","webpack:///./src/section.js","webpack:///./src/request.js","webpack:///./src/replacements.js","webpack:///./src/locations.js","webpack:///./src/queue.js","webpack:///./src/parser.js","webpack:///./src/navigation.js","webpack:///./src/rendition.js","webpack:///./src/layout.js","webpack:///./src/mapping.js","webpack:///./src/unarchive.js","webpack:///./libs/mime/mime.js","webpack:///external \"JSZip\"","webpack:///./src/contents.js","webpack:///./src/managers/views/iframe.js","webpack:///./src/managers/default/index.js","webpack:///./src/managers/helpers/stage.js","webpack:///./src/managers/helpers/views.js","webpack:///./src/managers/continuous/index.js"],"names":[],"mappings":"AAAA;AACA;AACA,6FAA6F,MAAM,yBAAyB,EAAE,YAAY,EAAE;AAC5I;AACA;AACA;AACA,8FAA8F,MAAM,yBAAyB,EAAE,YAAY,EAAE;AAC7I;AACA;AACA,CAAC;AACD,O;ACVA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;ACtCA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;ACnCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,iDAAgD;AAChD;AACA,GAAE;;AAEF;;;AAGA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA,KAAI;;AAEJ,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,KAAI;AACJ;;AAEA;AACA;AACA;AACA,0CAAyC;AACzC,KAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,OAAM;AACN;AACA;AACA;;AAEA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA,GAAE;AACF;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;;AAEA,mDAAkD;AAClD;AACA;AACA;;AAEA,sCAAqC;;AAErC;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,IAAG;;;;AAIH;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,EAAC;;AAED,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA,EAAC;;;;;;;aC1VD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,4CAA2C;AAC3C,EAAC,4BAA4B;;AAE7B;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL,kCAAiC,gBAAgB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,aAAY,SAAS;AACrB;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,yBAAwB;AACxB;AACA,8BAA6B;AAC7B;AACA;AACA,6BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA6B;AAC7B;AACA,6BAA4B;AAC5B;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,aAAY,SAAS;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL,6BAA4B,cAAc;AAC1C;AACA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,aAAY,EAAE;AACd;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,sBAAqB,sBAAsB;AAC3C;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,qDAAoD;AACpD;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,oBAAmB,kBAAkB;AACrC;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK,EAAE;AACP;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA,WAAU,EAAE;AACZ,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,QAAO;AACP;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,kBAAiB,wBAAwB;AACzC;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL,IAAG;AACH;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP,MAAK;AACL,IAAG;AACH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,kBAAiB,0CAA0C;AAC3D;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,QAAO;AACP;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL,IAAG;;AAEH;AACA;AACA;AACA,MAAK;AACL,IAAG;;AAEH;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL,IAAG;;AAEH;AACA;AACA;AACA,MAAK;AACL,IAAG;;AAEH;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA,kBAAiB,kDAAkD;AACnE;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA,WAAU,EAAE;AACZ,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW;AACX;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,IAAG;AACH;;AAEA;AACA,WAAU,SAAS;AACnB,WAAU,OAAO;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,0BAAyB;AACzB;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL,IAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA,MAAK;;AAEL;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA,MAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA,gBAAe;AACf;AACA;AACA;AACA,YAAW;AACX,UAAS;AACT;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA,aAAY,SAAS;AACrB,aAAY,SAAS;AACrB,aAAY,OAAO;AACnB;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA,aAAY,SAAS;AACrB,aAAY,OAAO;AACnB;AACA,cAAa;AACb;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,2BAA0B;AAC1B,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;;AAEA;AACA,aAAY,SAAS;AACrB,aAAY,OAAO;AACnB;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,QAAO;AACP,MAAK;AACL;AACA;AACA,QAAO;AACP,MAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,kBAAiB,YAAY;AAC7B;AACA;;AAEA,kBAAiB,0BAA0B;AAC3C;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,kBAAiB,YAAY;AAC7B;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,iCAAgC;;AAEhC,kCAAiC,eAAe;AAChD;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,eAAc,MAAM;AACpB;AACA,iBAAgB,MAAM;AACtB;AACA,MAAK;AACL,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,WAAU,SAAS;AACnB;AACA;AACA,2DAA0D,EAAE;AAC5D,WAAU,cAAc;AACxB;AACA;AACA;AACA;AACA;AACA,YAAW,SAAS;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,oBAAmB,OAAO;AAC1B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,qCAAoC,sDAAsD,oEAAoE,4EAA4E;AAC1O;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,OAAO;AACjB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAU,+BAA+B;AACzC,WAAU,mCAAmC;AAC7C,WAAU;AACV;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,OAAO;AACjB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;;AAEA;AACA;AACA;;AAEA,kBAAiB,0CAA0C;AAC3D;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6CAA4C;AAC5C;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,WAAU,OAAO;AACjB,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,sBAAqB,+BAA+B;AACpD,wBAAuB,+BAA+B;AACtD,yBAAwB,+BAA+B;AACvD,wBAAuB;AACvB;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mCAAkC,+BAA+B;AACjE,mCAAkC,mCAAmC;AACrE,mCAAkC,mCAAmC;AACrE;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;AACA;AACA,6CAA4C;AAC5C;AACA,IAAG;AACH;;AAEA;AACA;AACA,WAAU,OAAO;AACjB,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,KAAI;AACJ;;AAEA;AACA;AACA;AACA,WAAU,OAAO;AACjB;AACA,YAAW;AACX;AACA;AACA,mBAAkB;;AAElB;AACA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,SAAS;AACnB,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,oBAAmB,YAAY;AAC/B;AACA;;AAEA;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;AACA;AACA;AACA,WAAU,EAAE;AACZ,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,WAAU,EAAE;AACZ,WAAU,OAAO;AACjB;AACA,YAAW,QAAQ;AACnB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;;AAEA;AACA;AACA;;AAEA;;AAEA,gBAAe;AACf,gBAAe;AACf;;AAEA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,WAAU,MAAM;AAChB,WAAU,SAAS;AACnB;AACA,WAAU,OAAO;AACjB;AACA,YAAW;AACX;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,oBAAmB,YAAY;AAC/B;AACA;;AAEA;AACA;AACA;;AAEA,sBAAqB,YAAY;AACjC;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,MAAK;AACL,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kFAAiF;;AAEjF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,2BAA0B,sBAAsB;;AAEhD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,kBAAiB,SAAS;AAC1B;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA,EAAC;AACD;AACA,EAAC;AACD;AACA,EAAC;AACD;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA,EAAC;AACD;AACA,IAAG;AACH;AACA;;AAEA;;AAEA,4CAA2C,kBAAkB,kCAAkC,qEAAqE,EAAE,EAAE,OAAO,kBAAkB,EAAE,YAAY;;AAE/M;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,+CAA8C,cAAc;;AAE5D,EAAC;AACD,8B;;;;;;;ACh8EA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB,sBAAsB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,4BAA2B;AAC3B;AACA;AACA;AACA,6BAA4B,UAAU;;;;;;;ACnLtC;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C,iBAAiB;;AAE5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;AACA,G;;;;;;;AC3EA,gB;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,QAAO;AACP;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,yCAAwC;AACxC;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL,yCAAwC,YAAY;AACpD;AACA;AACA,MAAK;AACL;AACA;;AAEA,sCAAqC,YAAY;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,yCAAwC,YAAY;AACpD;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,sCAAqC,YAAY;AACjD;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA4B,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AAC3D;AACA;AACA;AACA,4CAA2C,IAAI,GAAG,EAAE,aAAa,IAAI,mBAAmB,IAAI,GAAG,EAAE,cAAc,IAAI,yEAAyE,EAAE,oBAAoB,IAAI,GAAG,EAAE,gBAAgB,IAAI,EAAE,IAAI,2EAA2E,EAAE,oBAAoB,IAAI,GAAG,EAAE,gBAAgB,IAAI,EAAE,IAAI,iBAAiB,IAAI,2EAA2E,EAAE,qBAAqB,IAAI,GAAG,EAAE,gBAAgB,IAAI,EAAE,IAAI,iBAAiB,IAAI,EAAE,IAAI,yEAAyE,EAAE,qBAAqB,IAAI,GAAG,EAAE,gBAAgB,IAAI,EAAE,IAAI,iBAAiB,IAAI,EAAE,IAAI,yEAAyE,EAAE,qBAAqB,IAAI,GAAG,EAAE,gBAAgB,IAAI,EAAE,IAAI,iBAAiB,IAAI,EAAE,IAAI,yEAAyE,EAAE,yBAAyB,IAAI,EAAE,IAAI,iBAAiB,IAAI,EAAE,IAAI,yEAAyE,EAAE;AAC9jC;AACA;AACA;AACA;AACA,sDAAqD,IAAI,kBAAkB,IAAI,yBAAyB,IAAI,0GAA0G;AACtN;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB;AACvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wEAAuE;AACvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,4EAA2E;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;;AAEA;;AAEA,gDAA+C,YAAY;AAC3D;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,QAAO;AACP;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,6BAA4B;AAC5B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAgD,YAAY;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,QAAO;AACP;AACA;;AAEA;AACA;AACA;;AAEA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA,wCAAuC,YAAY;AACnD;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,YAAW;AACX;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA,QAAO;AACP;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,6BAA4B;;AAE5B;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;;AAEA,oBAAmB,sBAAsB;AACzC;AACA;AACA;AACA,sBAAqB,sBAAsB;AAC3C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kBAAiB,cAAc;AAC/B;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,6BAA4B;AAC5B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;AAEA;AACA;AACA,QAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,MAAK;AACL;;AAEA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,QAAO;AACP;AACA,QAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,MAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,QAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,QAAO;AACP;AACA,QAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,kCAAiC,OAAO;AACxC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,QAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,QAAO;AACP,yCAAwC,OAAO;AAC/C;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,MAAK;AACL,gCAA+B,OAAO;AACtC;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,GAAG;;AAEtB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,uEAAsE,OAAO;AAC7E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,gBAAe,qBAAqB;AACpC;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,EAAC;;;;;;;mCCjqED;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,aAAY,OAAO;AACnB,eAAc,MAAM;AACpB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAY,MAAM;AAClB,aAAY,SAAS;AACrB;AACA,eAAc,MAAM;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,aAAY,SAAS;AACrB;AACA,eAAc,MAAM;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,eAAc,MAAM;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC;AACrC;AACA,MAAK;AACL,6BAA4B;AAC5B;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAY,MAAM;AAClB,eAAc,OAAO;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,eAAc,OAAO;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,eAAc,OAAO;AACrB;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gCAA+B,mCAAmC;AAClE;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,eAAc,OAAO;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,cAAa,WAAW;AACxB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,yBAAwB;;AAExB,0CAAyC,qBAAqB;;AAE9D;AACA;AACA;AACA;AACA;AACA,mCAAkC,oBAAoB;;AAEtD;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB,eAAc,OAAO;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,cAAa,iBAAiB;AAC9B;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,2BAA0B,iBAAiB;AAC3C;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,eAAc,iBAAiB;AAC/B;;AAEA;AACA;AACA;;AAEA;AACA;AACA,+BAA8B,oBAAoB;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB;AACA,eAAc,OAAO;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY,OAAO;AACnB;AACA,eAAc,OAAO;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,OAEA;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;AACF;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA,EAAC;;;;;;;;ACphBD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kBAAiB,cAAc;AAC/B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA,sBAAqB,QAAQ;AAC7B;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;;AAET,gBAAe,WAAW;AAC1B;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,gBAAe,YAAY;AAC3B;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,EAAC;;;;;;;ACxLD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,EAAC;;;;;;;AC/OD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;;AAGA;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,gBAAe,YAAY;AAC3B;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,4CAA2C,YAAY;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAe;AACf;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,uBAAsB;AACtB;;AAEA;AACA,uBAAsB;AACtB;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,iBAAgB,qBAAqB;AACrC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kCAAiC,aAAa;;AAE9C;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA,+BAA8B;;AAE9B;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AC3hBA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,mCAAkC,SAAS;AAC3C;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA,qBAAoB,OAAO;AAC3B;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,sBAAqB,SAAS;AAC9B;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,2CAA0C,UAAU;AACpD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;;;;;;ACjHA,iD;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,2BAA0B,0BAA0B,EAAE;AACtD;;AAEA;AACA,2BAA0B,0BAA0B,EAAE;AACtD;;AAEA;;AAEA;;;AAGA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;ACvIA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA,oBAAmB;;AAEnB,qBAAoB;;AAEpB;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;;;AAGA;AACA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA,GAAE,2EAA2E;AAC7E;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,YAAW;AACX,YAAW;AACX;AACA;AACA;AACA;;AAEA;AACA,WAAU;AACV;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,WAAU;AACV;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,iBAAgB;AAChB;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,qBAAoB;AACpB;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oCAAmC;AACnC;;AAEA;AACA;AACA;;AAEA;;AAEA,GAAE;;AAEF;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA,iBAAgB,8BAA8B;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;;AAEA;;;AAGA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,YAAW;AACX,YAAW;AACX;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,cAAa,SAAS;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,YAAW;AACX,YAAW;AACX;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;AACA;;;AAGA;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA,GAAE;AACF;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,WAAU;AACV;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,aAAY,SAAS;;AAErB;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;AACA;;;AAGA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,aAAY,SAAS;AACrB;;AAEA;AACA;AACA,IAAG;AACH;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAI;AACJ;AACA;;AAEA,IAAG;AACH;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAI;AACJ;AACA;;AAEA,IAAG;AACH;AACA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACz6BA;;AAEA;AACA;AACA;;AAEA;AACA,sCAAqC;AACrC,gDAA+C;;AAE/C;AACA;AACA;AACA;;AAEA;AACA;AACA,gBAAe,sBAAsB;AACrC;AACA;AACA,IAAG;AACH;AACA,kBAAiB,yBAAyB;AAC1C;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;;AAGF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;AC1DA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;;AAEA;AACA;;AAEA;AACA;AACA,8CAA6C;AAC7C;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;;AAGA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;AC3JA;AACA;AACA;;AAEA;AACA,wEAAuE;AACvE;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA,oCAAmC;AACnC;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,mDAAkD;AAClD;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA,0CAAyC;AACzC;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA,OAAM;AACN;AACA;AACA;;AAEA,MAAK;AACL;AACA;;AAEA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;ACrJA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB;;AAEvB;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAE;;AAEF,iBAAgB,kBAAkB;AAClC;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACjHA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;;AAIA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,IAAG;;AAEH;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,qDAAoD;AACpD;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED;;AAEA;;;;;;;AC9NA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,GAAE;AACF;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL,KAAI;AACJ;AACA;AACA;AACA;;;;AAIA,IAAG;AACH;AACA;AACA;;AAEA,GAAE;AACF;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,MAAK;;AAEL,IAAG;AACH;AACA;AACA;;AAEA,GAAE;;AAEF;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,GAAE;;AAEF;;AAEA;;AAEA;;;;;;;AChMA;AACA;AACA;;;AAGA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,6CAA4C,mBAAmB;AAC/D;AACA;;AAEA;AACA;AACA;AACA,6CAA4C,wCAAwC;AACpF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,mBAAkB;AAClB;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,iDAAgD,eAAe;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C,2BAA2B;AACtE;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA,kCAAiC,oBAAoB;;AAErD;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,GAAE;;AAEF;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,kBAAkB;AACnC;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,aAAY,YAAY;AACxB;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,aAAY,YAAY;AACxB;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,aAAY,YAAY;AACxB;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC1eA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA,iBAAgB,gBAAgB;AAChC;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;;AAEA;;;;;;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,iDAAgD;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,qFAAoF;AACpF,GAAE;AACF;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,oEAAmE;AACnE,GAAE;AACF;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA,GAAE;;AAEF;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA,IAAG;AACH;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,IAAG;AACH;AACA;AACA;;AAEA,GAAE;AACF;;;AAGA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA,sDAAqD,kCAAkC;AACvF,KAAI;;AAEJ;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,MAAK;;AAEL;;AAEA,KAAI;AACJ;AACA;AACA;AACA;;AAEA;;AAEA,MAAK;;AAEL,KAAI;AACJ;AACA;AACA,KAAI;AACJ,MAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAI;;AAEJ,IAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;;AAGH;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;AACF;;AAEA;AACA;;AAEA;;;;;;;ACvjBA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;;;AAGA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA,GAAE,OAAO;AACT;AACA;;AAEA,mBAAkB;AAClB;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACxHA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,iBAAgB,iBAAiB;AACjC;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;;AAEA,IAAG;;AAEH;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;;AAEA,IAAG;;;AAGH;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;;AAEA,iBAAgB,mBAAmB;AACnC;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,iBAAgB,mBAAmB;AACnC;;AAEA;;AAEA;AACA;AACA,IAAG;AACH;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;;AAIA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA,iBAAgB,oBAAoB;AACpC;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;;;;;;ACxSA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA,sCAAqC,mBAAmB;AACxD,GAAE;AACF;AACA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;AACF;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;;AAEA;AACA,8DAA6D;AAC7D;AACA;;AAEA;AACA;AACA;AACA,mCAAkC,gBAAgB;AAClD,IAAG;AACH;AACA;;AAEA;AACA,8DAA6D;AAC7D;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA,8DAA6D;AAC7D;AACA;;AAEA;AACA;AACA;AACA,kCAAiC;AACjC,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,KAAI;;AAEJ;;AAEA,GAAE;;AAEF;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,KAAI;;AAEJ;AACA;;;AAGA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC5LA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN,sBAAqB,oBAAoB;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED,iCAAgC;;AAEhC;AACA;AACA;;AAEA;AACA;AACA;;;;;;;AC1KA,4DAA2D,kDAAkD,6BAA6B;AAC1I,iD;;;;;;ACDA;AACA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;;AAGA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;AAGA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH,kBAAiB,mBAAmB;AACpC;AACA,uBAAsB;AACtB,oBAAmB,kBAAkB;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN,GAAE;;AAEF;AACA,gBAAe;;AAEf;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,iBAAgB,mBAAmB;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,mBAAkB;;AAElB;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA,GAAE;AACF;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;;AAEA,GAAE;AACF;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA,oCAAmC,QAAQ;AAC3C;AACA;AACA;AACA;AACA;AACA;;AAEA,6BAA4B,QAAQ;AACpC;AACA,4EAA2E;AAC3E;;AAEA;AACA,sCAAqC,gBAAgB;AACrD;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;;AAEA,GAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,iBAAgB,2CAA2C;;AAE3D;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA,iBAAgB,aAAa;;AAE7B;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;;;;;;ACvpBA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA4B;AAC5B,GAAE,eAAe;;AAEjB;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,+BAA8B;AAC9B;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,OAAM;AACN;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,OAAM;AACN;AACA;AACA,OAAM;AACN;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;;AAEA,IAAG;AACH;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF,oBAAmB;AACnB;;AAEA;AACA;AACA,wCAAuC;AACvC;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;;;AAIA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA,IAAG;;AAEH,GAAE;AACF;AACA;;;AAGA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;;;;;;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,iDAAgD;AAChD;AACA;AACA;AACA;AACA,gCAA+B,2DAA2D;AAC1F;AACA;AACA;AACA,GAAE;;AAEF,mDAAkD;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA,MAAK;;AAEL;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA,IAAG;AACH;AACA;AACA,OAAM;AACN;AACA;AACA,OAAM;AACN;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;;;AAGA,GAAE;;AAEF;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;;;AAGA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,IAAG;AACH;AACA;;;AAGA,GAAE;;AAEF;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA,GAAE;AACF;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,iBAAgB,iBAAiB;AACjC;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,wCAAuC,wCAAwC;;AAE/E;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,IAAG;;AAEH;;AAEA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,MAAK;;AAEL;;AAEA;AACA;;AAEA;;;;;;;AC9hBA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,+BAA8B;AAC9B,8BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,yCAAwC;AACxC;AACA;AACA,GAAE;;AAEF,8CAA6C,cAAc;AAC3D;;;;AAIA;;;;;;;ACtOA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA,iBAAgB,SAAS;AACzB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA,iBAAgB,SAAS;AACzB;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA,iBAAgB,SAAS;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,iBAAgB,SAAS;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,iBAAgB,SAAS;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACtKA;AACA;AACA;;AAEA;;AAEA,4CAA2C;;AAE3C;;AAEA,iDAAgD;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF,mDAAkD;;AAElD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,iBAAgB,iBAAiB;AACjC;;AAEA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA,KAAI;AACJ;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,4BAA2B;;AAE3B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;;AAGL,QAAO;;AAEP,GAAE;AACF;AACA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAgB,oBAAoB;AACpC;AACA;;AAEA;AACA,iBAAgB,kBAAkB;AAClC;AACA;;AAEA;AACA;AACA;;AAEA,+DAA8D;;AAE9D;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,OAAM;AACN,MAAK;;AAEL;;AAEA,IAAG;AACH;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;;;AAGH;AACA;;AAEA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,uBAAsB,QAAQ;AAC9B;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,GAAE;;AAEF,uBAAsB,QAAQ;AAC9B;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,wCAAuC,wCAAwC;;AAE/E;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,MAAK;;AAEL;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA","file":"epub.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"xmldom\"), (function webpackLoadOptionalExternalModule() { try { return require(\"JSZip\"); } catch(e) {} }()));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"xmldom\", \"JSZip\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ePub\"] = factory(require(\"xmldom\"), (function webpackLoadOptionalExternalModule() { try { return require(\"JSZip\"); } catch(e) {} }()));\n\telse\n\t\troot[\"ePub\"] = factory(root[\"xmldom\"], root[\"JSZip\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_13__, __WEBPACK_EXTERNAL_MODULE_29__) {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 357e8a8caf94859fd255\n **/","var Book = require('./book');\nvar EpubCFI = require('./epubcfi');\nvar Rendition = require('./rendition');\nvar Contents = require('./contents');\nvar RSVP = require('rsvp');\n\nfunction ePub(_url) {\n\treturn new Book(_url);\n};\n\nePub.VERSION = \"0.3.0\";\n\nePub.CFI = EpubCFI;\nePub.Rendition = Rendition;\nePub.Contents = Contents;\nePub.RSVP = RSVP;\n\nePub.ViewManagers = {};\nePub.Views = {};\nePub.register = {\n\tmanager : function(name, manager){\n\t\treturn ePub.ViewManagers[name] = manager;\n\t},\n\tview : function(name, view){\n\t\treturn ePub.Views[name] = view;\n\t}\n};\n\n// Default Views\nePub.register.view(\"iframe\", require('./managers/views/iframe'));\n\n// Default View Managers\nePub.register.manager(\"single\", require('./managers/default'));\nePub.register.manager(\"continuous\", require('./managers/continuous'));\n\nmodule.exports = ePub;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/epub.js\n ** module id = 0\n ** module chunks = 0\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 Unarchive = require('./unarchive');\nvar request = require('./request');\nvar EpubCFI = require('./epubcfi');\n\nfunction Book(_url, options){\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\trequestMethod: this.requestMethod\n\t});\n\n\tcore.extend(this.settings, options);\n\n\n\t// Promises\n\tthis.opening = new RSVP.defer();\n\tthis.opened = this.opening.promise;\n\tthis.isOpen = false;\n\n\tthis.url = undefined;\n\n\tthis.loading = {\n\t\tmanifest: new RSVP.defer(),\n\t\tspine: new RSVP.defer(),\n\t\tmetadata: new RSVP.defer(),\n\t\tcover: new RSVP.defer(),\n\t\tnavigation: new RSVP.defer(),\n\t\tpageList: new RSVP.defer()\n\t};\n\n\tthis.loaded = {\n\t\tmanifest: this.loading.manifest.promise,\n\t\tspine: this.loading.spine.promise,\n\t\tmetadata: this.loading.metadata.promise,\n\t\tcover: this.loading.cover.promise,\n\t\tnavigation: this.loading.navigation.promise,\n\t\tpageList: this.loading.pageList.promise\n\t};\n\n\tthis.ready = RSVP.hash(this.loaded);\n\n\t// Queue for methods used before opening\n\tthis.isRendered = false;\n\t// this._q = core.queue(this);\n\n\tthis.request = this.settings.requestMethod.bind(this);\n\n\tthis.spine = new Spine(this.request);\n\tthis.locations = new Locations(this.spine, this.request);\n\n\tif(_url) {\n\t\tthis.open(_url).catch(function (error) {\n\t\t\tvar err = new Error(\"Cannot load book at \"+ _url );\n\t\t\tconsole.error(err);\n\n\t\t\tthis.trigger(\"loadFailed\", error);\n\t\t}.bind(this));\n\t}\n};\n\nBook.prototype.open = function(_url, options){\n\tvar uri;\n\tvar parse = new Parser();\n\tvar epubPackage;\n\tvar epubContainer;\n\tvar book = this;\n\tvar containerPath = \"META-INF/container.xml\";\n\tvar location;\n\tvar absoluteUri;\n\tvar isArrayBuffer = false;\n\tvar isBase64 = options && options.base64;\n\n\tif(!_url) {\n\t\tthis.opening.resolve(this);\n\t\treturn this.opened;\n\t}\n\n\t// Reuse parsed url or create a new uri object\n\t// if(typeof(_url) === \"object\") {\n\t// uri = _url;\n\t// } else {\n\t// uri = core.uri(_url);\n\t// }\n\tif (_url instanceof ArrayBuffer || isBase64) {\n\t\tisArrayBuffer = true;\n\t\tthis.url = '/';\n\t} else {\n\t\turi = URI(_url);\n\t}\n\n\tif (window && window.location && uri) {\n\t\tabsoluteUri = uri.absoluteTo(window.location.href);\n\t\tthis.url = absoluteUri.toString();\n\t} else if (window && window.location) {\n\t\tthis.url = window.location.href;\n\t} else {\n\t\tthis.url = _url;\n\t}\n\n\t// Find path to the Container\n\tif(uri && uri.suffix() === \"opf\") {\n\t\t// Direct link to package, no container\n\t\tthis.packageUrl = _url;\n\t\tthis.containerUrl = '';\n\n\t\tif(uri.origin()) {\n\t\t\tthis.baseUrl = uri.origin() + \"/\" + uri.directory() + \"/\";\n\t\t} else if(absoluteUri){\n\t\t\tthis.baseUrl = absoluteUri.origin();\n\t\t\tthis.baseUrl += absoluteUri.directory() + \"/\";\n\t\t} else {\n\t\t\tthis.baseUrl = uri.directory() + \"/\";\n\t\t}\n\n\t\tepubPackage = this.request(this.packageUrl)\n\t\t\t.catch(function(error) {\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\n\t} else if(isArrayBuffer || isBase64 || this.isArchivedUrl(uri)) {\n\t\t// Book is archived\n\t\tthis.url = '/';\n\t\tthis.containerUrl = URI(containerPath).absoluteTo(this.url).toString();\n\n\t\tepubContainer = this.unarchive(_url, isBase64).\n\t\t\tthen(function() {\n\t\t\t\treturn this.request(this.containerUrl);\n\t\t\t}.bind(this))\n\t\t\t.catch(function(error) {\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\t}\n\t// Find the path to the Package from the container\n\telse if (!uri.suffix()) {\n\n\t\tthis.containerUrl = this.url + containerPath;\n\n\t\tepubContainer = this.request(this.containerUrl)\n\t\t\t.catch(function(error) {\n\t\t\t\t// handle errors in loading container\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\t}\n\n\tif (epubContainer) {\n\t\tepubPackage = epubContainer.\n\t\t\tthen(function(containerXml){\n\t\t\t\treturn parse.container(containerXml); // Container has path to content\n\t\t\t}).\n\t\t\tthen(function(paths){\n\t\t\t\tvar packageUri = URI(paths.packagePath);\n\t\t\t\tvar absPackageUri = packageUri.absoluteTo(book.url);\n\t\t\t\tvar absWindowUri;\n\n\t\t\t\tbook.packageUrl = absPackageUri.toString();\n\t\t\t\tbook.encoding = paths.encoding;\n\n\t\t\t\t// Set Url relative to the content\n\t\t\t\tif(absPackageUri.origin()) {\n\t\t\t\t\tbook.baseUrl = absPackageUri.origin() + absPackageUri.directory() + \"/\";\n\t\t\t\t} else {\n\t\t\t\t\tif(packageUri.directory()) {\n\t\t\t\t\t\tbook.baseUrl = \"/\" + packageUri.directory() + \"/\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbook.baseUrl = \"/\"\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn book.request(book.packageUrl);\n\t\t\t}).catch(function(error) {\n\t\t\t\t// handle errors in either of the two requests\n\t\t\t\tbook.opening.reject(error);\n\t\t\t});\n\t}\n\n\tepubPackage.then(function(packageXml) {\n\n\t\tif (!packageXml) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get package information from epub opf\n\t\tbook.unpack(packageXml);\n\n\t\t// Resolve promises\n\t\tbook.loading.manifest.resolve(book.package.manifest);\n\t\tbook.loading.metadata.resolve(book.package.metadata);\n\t\tbook.loading.spine.resolve(book.spine);\n\t\tbook.loading.cover.resolve(book.cover);\n\n\t\tbook.isOpen = true;\n\n\t\t// Clear queue of any waiting book request\n\n\t\t// Resolve book opened promise\n\t\tbook.opening.resolve(book);\n\n\t}).catch(function(error) {\n\t\t// handle errors in parsing the book\n\t\t// console.error(error.message, error.stack);\n\t\tbook.opening.reject(error);\n\t});\n\n\treturn this.opened;\n};\n\nBook.prototype.unpack = function(packageXml){\n\tvar book = this,\n\t\t\tparse = new Parser();\n\n\tbook.package = parse.packageContents(packageXml); // Extract info from contents\n\tif(!book.package) {\n\t\treturn;\n\t}\n\n\tbook.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths\n\n\tthis.spine.load(book.package);\n\n\tbook.navigation = new Navigation(book.package, this.request);\n\tbook.navigation.load().then(function(toc){\n\t\tbook.toc = toc;\n\t\tbook.loading.navigation.resolve(book.toc);\n\t});\n\n\t// //-- Set Global Layout setting based on metadata\n\t// MOVE TO RENDER\n\t// book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);\n\n\tbook.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();\n};\n\n// Alias for book.spine.get\nBook.prototype.section = function(target) {\n\treturn this.spine.get(target);\n};\n\n// Sugar to render a book\nBook.prototype.renderTo = function(element, options) {\n\t// var renderMethod = (options && options.method) ?\n\t// options.method :\n\t// \"single\";\n\n\tthis.rendition = new Rendition(this, options);\n\tthis.rendition.attachTo(element);\n\n\treturn this.rendition;\n};\n\nBook.prototype.requestMethod = function(_url) {\n\t// Switch request methods\n\tif(this.unarchived) {\n\t\treturn this.unarchived.request(_url);\n\t} else {\n\t\treturn request(_url, null, this.requestCredentials, this.requestHeaders);\n\t}\n\n};\n\nBook.prototype.setRequestCredentials = function(_credentials) {\n\tthis.requestCredentials = _credentials;\n};\n\nBook.prototype.setRequestHeaders = function(_headers) {\n\tthis.requestHeaders = _headers;\n};\n\nBook.prototype.unarchive = function(bookUrl, isBase64){\n\tthis.unarchived = new Unarchive();\n\treturn this.unarchived.open(bookUrl, isBase64);\n};\n\n//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)\nBook.prototype.isArchivedUrl = function(bookUrl){\n\tvar uri;\n\tvar extension;\n\n\tif (bookUrl instanceof ArrayBuffer) {\n\t\treturn true;\n\t}\n\n\t// Reuse parsed url or create a new uri object\n\t// if(typeof(bookUrl) === \"object\") {\n\t// uri = bookUrl;\n\t// } else {\n\t// uri = core.uri(bookUrl);\n\t// }\n\turi = URI(bookUrl);\n\textension = 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.unarchived) {\n\t\t\t\treturn this.unarchived.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\nBook.prototype.range = function(cfiRange) {\n\tvar cfi = new EpubCFI(cfiRange);\n\tvar item = this.spine.get(cfi.spinePos);\n\n\treturn item.load().then(function (contents) {\n\t\tvar range = cfi.toRange(item.document);\n\t\treturn range;\n\t})\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\tconsole.error(event);\n});\n\nRSVP.configure('instrument', false); //-- 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\tconsole.error(event.detail.message, event.detail.stack);\n});\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/book.js\n ** module id = 1\n ** module chunks = 0\n **/","/*!\n * @overview RSVP - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2016 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.3.2\n */\n\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (factory((global.RSVP = global.RSVP || {})));\n}(this, (function (exports) { 'use strict';\n\nfunction indexOf(callbacks, callback) {\n for (var i = 0, l = callbacks.length; i < l; i++) {\n if (callbacks[i] === callback) {\n return i;\n }\n }\n\n return -1;\n}\n\nfunction callbacksFor(object) {\n var callbacks = object._promiseCallbacks;\n\n if (!callbacks) {\n callbacks = object._promiseCallbacks = {};\n }\n\n return callbacks;\n}\n\n/**\n @class RSVP.EventTarget\n*/\nvar EventTarget = {\n\n /**\n `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For\n Example:\n ```javascript\n let object = {};\n RSVP.EventTarget.mixin(object);\n object.on('finished', function(event) {\n // handle event\n });\n object.trigger('finished', { detail: value });\n ```\n `EventTarget.mixin` also works with prototypes:\n ```javascript\n let Person = function() {};\n RSVP.EventTarget.mixin(Person.prototype);\n let yehuda = new Person();\n let tom = new Person();\n yehuda.on('poke', function(event) {\n console.log('Yehuda says OW');\n });\n tom.on('poke', function(event) {\n console.log('Tom says OW');\n });\n yehuda.trigger('poke');\n tom.trigger('poke');\n ```\n @method mixin\n @for RSVP.EventTarget\n @private\n @param {Object} object object to extend with EventTarget methods\n */\n mixin: function mixin(object) {\n object['on'] = this['on'];\n object['off'] = this['off'];\n object['trigger'] = this['trigger'];\n object._promiseCallbacks = undefined;\n return object;\n },\n\n /**\n Registers a callback to be executed when `eventName` is triggered\n ```javascript\n object.on('event', function(eventInfo){\n // handle the event\n });\n object.trigger('event');\n ```\n @method on\n @for RSVP.EventTarget\n @private\n @param {String} eventName name of the event to listen for\n @param {Function} callback function to be called when the event is triggered.\n */\n on: function on(eventName, callback) {\n if (typeof callback !== 'function') {\n throw new TypeError('Callback must be a function');\n }\n\n var allCallbacks = callbacksFor(this),\n callbacks = undefined;\n\n callbacks = allCallbacks[eventName];\n\n if (!callbacks) {\n callbacks = allCallbacks[eventName] = [];\n }\n\n if (indexOf(callbacks, callback) === -1) {\n callbacks.push(callback);\n }\n },\n\n /**\n You can use `off` to stop firing a particular callback for an event:\n ```javascript\n function doStuff() { // do stuff! }\n object.on('stuff', doStuff);\n object.trigger('stuff'); // doStuff will be called\n // Unregister ONLY the doStuff callback\n object.off('stuff', doStuff);\n object.trigger('stuff'); // doStuff will NOT be called\n ```\n If you don't pass a `callback` argument to `off`, ALL callbacks for the\n event will not be executed when the event fires. For example:\n ```javascript\n let callback1 = function(){};\n let callback2 = function(){};\n object.on('stuff', callback1);\n object.on('stuff', callback2);\n object.trigger('stuff'); // callback1 and callback2 will be executed.\n object.off('stuff');\n object.trigger('stuff'); // callback1 and callback2 will not be executed!\n ```\n @method off\n @for RSVP.EventTarget\n @private\n @param {String} eventName event to stop listening to\n @param {Function} callback optional argument. If given, only the function\n given will be removed from the event's callback queue. If no `callback`\n argument is given, all callbacks will be removed from the event's callback\n queue.\n */\n off: function off(eventName, callback) {\n var allCallbacks = callbacksFor(this),\n callbacks = undefined,\n index = undefined;\n\n if (!callback) {\n allCallbacks[eventName] = [];\n return;\n }\n\n callbacks = allCallbacks[eventName];\n\n index = indexOf(callbacks, callback);\n\n if (index !== -1) {\n callbacks.splice(index, 1);\n }\n },\n\n /**\n Use `trigger` to fire custom events. For example:\n ```javascript\n object.on('foo', function(){\n console.log('foo event happened!');\n });\n object.trigger('foo');\n // 'foo event happened!' logged to the console\n ```\n You can also pass a value as a second argument to `trigger` that will be\n passed as an argument to all event listeners for the event:\n ```javascript\n object.on('foo', function(value){\n console.log(value.name);\n });\n object.trigger('foo', { name: 'bar' });\n // 'bar' logged to the console\n ```\n @method trigger\n @for RSVP.EventTarget\n @private\n @param {String} eventName name of the event to be triggered\n @param {*} options optional value to be passed to any event handlers for\n the given `eventName`\n */\n trigger: function trigger(eventName, options, label) {\n var allCallbacks = callbacksFor(this),\n callbacks = undefined,\n callback = undefined;\n\n if (callbacks = allCallbacks[eventName]) {\n // Don't cache the callbacks.length since it may grow\n for (var i = 0; i < callbacks.length; i++) {\n callback = callbacks[i];\n\n callback(options, label);\n }\n }\n }\n};\n\nvar config = {\n instrument: false\n};\n\nEventTarget['mixin'](config);\n\nfunction configure(name, value) {\n if (name === 'onerror') {\n // handle for legacy users that expect the actual\n // error to be passed to their function added via\n // `RSVP.configure('onerror', someFunctionHere);`\n config['on']('error', value);\n return;\n }\n\n if (arguments.length === 2) {\n config[name] = value;\n } else {\n return config[name];\n }\n}\n\nfunction objectOrFunction(x) {\n return typeof x === 'function' || typeof x === 'object' && x !== null;\n}\n\nfunction isFunction(x) {\n return typeof x === 'function';\n}\n\nfunction isMaybeThenable(x) {\n return typeof x === 'object' && x !== null;\n}\n\nvar _isArray = undefined;\nif (!Array.isArray) {\n _isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n} else {\n _isArray = Array.isArray;\n}\n\nvar isArray = _isArray;\n\n// Date.now is not available in browsers < IE9\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility\nvar now = Date.now || function () {\n return new Date().getTime();\n};\n\nfunction F() {}\n\nvar 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 F.prototype = o;\n return new F();\n};\n\nvar queue = [];\n\nfunction scheduleFlush() {\n setTimeout(function () {\n for (var i = 0; i < queue.length; i++) {\n var entry = queue[i];\n\n var payload = entry.payload;\n\n payload.guid = payload.key + payload.id;\n payload.childGuid = payload.key + payload.childId;\n if (payload.error) {\n payload.stack = payload.error.stack;\n }\n\n config['trigger'](entry.name, entry.payload);\n }\n queue.length = 0;\n }, 50);\n}\nfunction instrument(eventName, promise, child) {\n if (1 === queue.push({\n name: eventName,\n payload: {\n key: promise._guidKey,\n id: promise._id,\n eventName: eventName,\n detail: promise._result,\n childId: child && child._id,\n label: promise._label,\n timeStamp: now(),\n error: config[\"instrument-with-stack\"] ? new Error(promise._label) : null\n } })) {\n scheduleFlush();\n }\n}\n\n/**\n `RSVP.Promise.resolve` returns a promise that will become resolved with the\n passed `value`. It is shorthand for the following:\n\n ```javascript\n let promise = new RSVP.Promise(function(resolve, reject){\n resolve(1);\n });\n\n promise.then(function(value){\n // value === 1\n });\n ```\n\n Instead of writing the above, your code now simply becomes the following:\n\n ```javascript\n let promise = RSVP.Promise.resolve(1);\n\n promise.then(function(value){\n // value === 1\n });\n ```\n\n @method resolve\n @static\n @param {*} object value that the returned promise will be resolved with\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise that will become fulfilled with the given\n `value`\n*/\nfunction resolve$1(object, label) {\n /*jshint validthis:true */\n var Constructor = this;\n\n if (object && typeof object === 'object' && object.constructor === Constructor) {\n return object;\n }\n\n var promise = new Constructor(noop, label);\n resolve(promise, object);\n return promise;\n}\n\nfunction withOwnPromise() {\n return new TypeError('A promises callback cannot return that same promise.');\n}\n\nfunction noop() {}\n\nvar PENDING = void 0;\nvar FULFILLED = 1;\nvar REJECTED = 2;\n\nvar GET_THEN_ERROR = new ErrorObject();\n\nfunction getThen(promise) {\n try {\n return promise.then;\n } catch (error) {\n GET_THEN_ERROR.error = error;\n return GET_THEN_ERROR;\n }\n}\n\nfunction tryThen(then, value, fulfillmentHandler, rejectionHandler) {\n try {\n then.call(value, fulfillmentHandler, rejectionHandler);\n } catch (e) {\n return e;\n }\n}\n\nfunction handleForeignThenable(promise, thenable, then) {\n config.async(function (promise) {\n var sealed = false;\n var error = tryThen(then, thenable, function (value) {\n if (sealed) {\n return;\n }\n sealed = true;\n if (thenable !== value) {\n resolve(promise, value, undefined);\n } else {\n fulfill(promise, value);\n }\n }, function (reason) {\n if (sealed) {\n return;\n }\n sealed = true;\n\n reject(promise, reason);\n }, 'Settle: ' + (promise._label || ' unknown promise'));\n\n if (!sealed && error) {\n sealed = true;\n reject(promise, error);\n }\n }, promise);\n}\n\nfunction handleOwnThenable(promise, thenable) {\n if (thenable._state === FULFILLED) {\n fulfill(promise, thenable._result);\n } else if (thenable._state === REJECTED) {\n thenable._onError = null;\n reject(promise, thenable._result);\n } else {\n subscribe(thenable, undefined, function (value) {\n if (thenable !== value) {\n resolve(promise, value, undefined);\n } else {\n fulfill(promise, value);\n }\n }, function (reason) {\n return reject(promise, reason);\n });\n }\n}\n\nfunction handleMaybeThenable(promise, maybeThenable, then$$) {\n if (maybeThenable.constructor === promise.constructor && then$$ === then && promise.constructor.resolve === resolve$1) {\n handleOwnThenable(promise, maybeThenable);\n } else {\n if (then$$ === GET_THEN_ERROR) {\n reject(promise, GET_THEN_ERROR.error);\n } else if (then$$ === undefined) {\n fulfill(promise, maybeThenable);\n } else if (isFunction(then$$)) {\n handleForeignThenable(promise, maybeThenable, then$$);\n } else {\n fulfill(promise, maybeThenable);\n }\n }\n}\n\nfunction resolve(promise, value) {\n if (promise === value) {\n fulfill(promise, value);\n } else if (objectOrFunction(value)) {\n handleMaybeThenable(promise, value, getThen(value));\n } else {\n fulfill(promise, value);\n }\n}\n\nfunction publishRejection(promise) {\n if (promise._onError) {\n promise._onError(promise._result);\n }\n\n publish(promise);\n}\n\nfunction fulfill(promise, value) {\n if (promise._state !== PENDING) {\n return;\n }\n\n promise._result = value;\n promise._state = FULFILLED;\n\n if (promise._subscribers.length === 0) {\n if (config.instrument) {\n instrument('fulfilled', promise);\n }\n } else {\n config.async(publish, promise);\n }\n}\n\nfunction reject(promise, reason) {\n if (promise._state !== PENDING) {\n return;\n }\n promise._state = REJECTED;\n promise._result = reason;\n config.async(publishRejection, promise);\n}\n\nfunction subscribe(parent, child, onFulfillment, onRejection) {\n var subscribers = parent._subscribers;\n var length = subscribers.length;\n\n parent._onError = null;\n\n subscribers[length] = child;\n subscribers[length + FULFILLED] = onFulfillment;\n subscribers[length + REJECTED] = onRejection;\n\n if (length === 0 && parent._state) {\n config.async(publish, parent);\n }\n}\n\nfunction publish(promise) {\n var subscribers = promise._subscribers;\n var settled = promise._state;\n\n if (config.instrument) {\n instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);\n }\n\n if (subscribers.length === 0) {\n return;\n }\n\n var child = undefined,\n callback = undefined,\n detail = promise._result;\n\n for (var i = 0; i < subscribers.length; i += 3) {\n child = subscribers[i];\n callback = subscribers[i + settled];\n\n if (child) {\n invokeCallback(settled, child, callback, detail);\n } else {\n callback(detail);\n }\n }\n\n promise._subscribers.length = 0;\n}\n\nfunction ErrorObject() {\n this.error = null;\n}\n\nvar TRY_CATCH_ERROR = new ErrorObject();\n\nfunction tryCatch(callback, detail) {\n try {\n return callback(detail);\n } catch (e) {\n TRY_CATCH_ERROR.error = e;\n return TRY_CATCH_ERROR;\n }\n}\n\nfunction invokeCallback(settled, promise, callback, detail) {\n var hasCallback = isFunction(callback),\n value = undefined,\n error = undefined,\n succeeded = undefined,\n failed = undefined;\n\n if (hasCallback) {\n value = tryCatch(callback, detail);\n\n if (value === TRY_CATCH_ERROR) {\n failed = true;\n error = value.error;\n value = null;\n } else {\n succeeded = true;\n }\n\n if (promise === value) {\n reject(promise, withOwnPromise());\n return;\n }\n } else {\n value = detail;\n succeeded = true;\n }\n\n if (promise._state !== PENDING) {\n // noop\n } else if (hasCallback && succeeded) {\n resolve(promise, value);\n } else if (failed) {\n reject(promise, error);\n } else if (settled === FULFILLED) {\n fulfill(promise, value);\n } else if (settled === REJECTED) {\n reject(promise, value);\n }\n}\n\nfunction initializePromise(promise, resolver) {\n var resolved = false;\n try {\n resolver(function (value) {\n if (resolved) {\n return;\n }\n resolved = true;\n resolve(promise, value);\n }, function (reason) {\n if (resolved) {\n return;\n }\n resolved = true;\n reject(promise, reason);\n });\n } catch (e) {\n reject(promise, e);\n }\n}\n\nfunction then(onFulfillment, onRejection, label) {\n var _arguments = arguments;\n\n var parent = this;\n var state = parent._state;\n\n if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {\n config.instrument && instrument('chained', parent, parent);\n return parent;\n }\n\n parent._onError = null;\n\n var child = new parent.constructor(noop, label);\n var result = parent._result;\n\n config.instrument && instrument('chained', parent, child);\n\n if (state) {\n (function () {\n var callback = _arguments[state - 1];\n config.async(function () {\n return invokeCallback(state, child, callback, result);\n });\n })();\n } else {\n subscribe(parent, child, onFulfillment, onRejection);\n }\n\n return child;\n}\n\nfunction makeSettledResult(state, position, value) {\n if (state === FULFILLED) {\n return {\n state: 'fulfilled',\n value: value\n };\n } else {\n return {\n state: 'rejected',\n reason: value\n };\n }\n}\n\nfunction Enumerator(Constructor, input, abortOnReject, label) {\n this._instanceConstructor = Constructor;\n this.promise = new Constructor(noop, label);\n this._abortOnReject = abortOnReject;\n\n if (this._validateInput(input)) {\n this._input = input;\n this.length = input.length;\n this._remaining = input.length;\n\n this._init();\n\n if (this.length === 0) {\n fulfill(this.promise, this._result);\n } else {\n this.length = this.length || 0;\n this._enumerate();\n if (this._remaining === 0) {\n fulfill(this.promise, this._result);\n }\n }\n } else {\n reject(this.promise, this._validationError());\n }\n}\n\nEnumerator.prototype._validateInput = function (input) {\n return isArray(input);\n};\n\nEnumerator.prototype._validationError = function () {\n return new Error('Array Methods must be provided an Array');\n};\n\nEnumerator.prototype._init = function () {\n this._result = new Array(this.length);\n};\n\nEnumerator.prototype._enumerate = function () {\n var length = this.length;\n var promise = this.promise;\n var input = this._input;\n\n for (var i = 0; promise._state === PENDING && i < length; i++) {\n this._eachEntry(input[i], i);\n }\n};\n\nEnumerator.prototype._settleMaybeThenable = function (entry, i) {\n var c = this._instanceConstructor;\n var resolve = c.resolve;\n\n if (resolve === resolve$1) {\n var then$$ = getThen(entry);\n\n if (then$$ === then && entry._state !== PENDING) {\n entry._onError = null;\n this._settledAt(entry._state, i, entry._result);\n } else if (typeof then$$ !== 'function') {\n this._remaining--;\n this._result[i] = this._makeResult(FULFILLED, i, entry);\n } else if (c === Promise) {\n var promise = new c(noop);\n handleMaybeThenable(promise, entry, then$$);\n this._willSettleAt(promise, i);\n } else {\n this._willSettleAt(new c(function (resolve) {\n return resolve(entry);\n }), i);\n }\n } else {\n this._willSettleAt(resolve(entry), i);\n }\n};\n\nEnumerator.prototype._eachEntry = function (entry, i) {\n if (isMaybeThenable(entry)) {\n this._settleMaybeThenable(entry, i);\n } else {\n this._remaining--;\n this._result[i] = this._makeResult(FULFILLED, i, entry);\n }\n};\n\nEnumerator.prototype._settledAt = function (state, i, value) {\n var promise = this.promise;\n\n if (promise._state === PENDING) {\n this._remaining--;\n\n if (this._abortOnReject && state === REJECTED) {\n reject(promise, value);\n } else {\n this._result[i] = this._makeResult(state, i, value);\n }\n }\n\n if (this._remaining === 0) {\n fulfill(promise, this._result);\n }\n};\n\nEnumerator.prototype._makeResult = function (state, i, value) {\n return value;\n};\n\nEnumerator.prototype._willSettleAt = function (promise, i) {\n var enumerator = this;\n\n subscribe(promise, undefined, function (value) {\n return enumerator._settledAt(FULFILLED, i, value);\n }, function (reason) {\n return enumerator._settledAt(REJECTED, i, reason);\n });\n};\n\n/**\n `RSVP.Promise.all` accepts an array of promises, and returns a new promise which\n is fulfilled with an array of fulfillment values for the passed promises, or\n rejected with the reason of the first passed promise to be rejected. It casts all\n elements of the passed iterable to promises as it runs this algorithm.\n\n Example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.resolve(2);\n let promise3 = RSVP.resolve(3);\n let promises = [ promise1, promise2, promise3 ];\n\n RSVP.Promise.all(promises).then(function(array){\n // The array here would be [ 1, 2, 3 ];\n });\n ```\n\n If any of the `promises` given to `RSVP.all` are rejected, the first promise\n that is rejected will be given as an argument to the returned promises's\n rejection handler. For example:\n\n Example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.reject(new Error(\"2\"));\n let promise3 = RSVP.reject(new Error(\"3\"));\n let promises = [ promise1, promise2, promise3 ];\n\n RSVP.Promise.all(promises).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(error) {\n // error.message === \"2\"\n });\n ```\n\n @method all\n @static\n @param {Array} entries array of promises\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when all `promises` have been\n fulfilled, or rejected if any of them become rejected.\n @static\n*/\nfunction all(entries, label) {\n return new Enumerator(this, entries, true, /* abort on reject */label).promise;\n}\n\n/**\n `RSVP.Promise.race` returns a new promise which is settled in the same way as the\n first passed promise to settle.\n\n Example:\n\n ```javascript\n let promise1 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 1');\n }, 200);\n });\n\n let promise2 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 2');\n }, 100);\n });\n\n RSVP.Promise.race([promise1, promise2]).then(function(result){\n // result === 'promise 2' because it was resolved before promise1\n // was resolved.\n });\n ```\n\n `RSVP.Promise.race` is deterministic in that only the state of the first\n settled promise matters. For example, even if other promises given to the\n `promises` array argument are resolved, but the first settled promise has\n become rejected before the other promises became fulfilled, the returned\n promise will become rejected:\n\n ```javascript\n let promise1 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 1');\n }, 200);\n });\n\n let promise2 = new RSVP.Promise(function(resolve, reject){\n setTimeout(function(){\n reject(new Error('promise 2'));\n }, 100);\n });\n\n RSVP.Promise.race([promise1, promise2]).then(function(result){\n // Code here never runs\n }, function(reason){\n // reason.message === 'promise 2' because promise 2 became rejected before\n // promise 1 became fulfilled\n });\n ```\n\n An example real-world use case is implementing timeouts:\n\n ```javascript\n RSVP.Promise.race([ajax('foo.json'), timeout(5000)])\n ```\n\n @method race\n @static\n @param {Array} entries array of promises to observe\n @param {String} label optional string for describing the promise returned.\n Useful for tooling.\n @return {Promise} a promise which settles in the same way as the first passed\n promise to settle.\n*/\nfunction race(entries, label) {\n /*jshint validthis:true */\n var Constructor = this;\n\n var promise = new Constructor(noop, label);\n\n if (!isArray(entries)) {\n reject(promise, new TypeError('You must pass an array to race.'));\n return promise;\n }\n\n for (var i = 0; promise._state === PENDING && i < entries.length; i++) {\n subscribe(Constructor.resolve(entries[i]), undefined, function (value) {\n return resolve(promise, value);\n }, function (reason) {\n return reject(promise, reason);\n });\n }\n\n return promise;\n}\n\n/**\n `RSVP.Promise.reject` returns a promise rejected with the passed `reason`.\n It is shorthand for the following:\n\n ```javascript\n let promise = new RSVP.Promise(function(resolve, reject){\n reject(new Error('WHOOPS'));\n });\n\n promise.then(function(value){\n // Code here doesn't run because the promise is rejected!\n }, function(reason){\n // reason.message === 'WHOOPS'\n });\n ```\n\n Instead of writing the above, your code now simply becomes the following:\n\n ```javascript\n let promise = RSVP.Promise.reject(new Error('WHOOPS'));\n\n promise.then(function(value){\n // Code here doesn't run because the promise is rejected!\n }, function(reason){\n // reason.message === 'WHOOPS'\n });\n ```\n\n @method reject\n @static\n @param {*} reason value that the returned promise will be rejected with.\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise rejected with the given `reason`.\n*/\nfunction reject$1(reason, label) {\n /*jshint validthis:true */\n var Constructor = this;\n var promise = new Constructor(noop, label);\n reject(promise, reason);\n return promise;\n}\n\nvar guidKey = 'rsvp_' + now() + '-';\nvar counter = 0;\n\nfunction needsResolver() {\n throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');\n}\n\nfunction needsNew() {\n throw new TypeError(\"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.\");\n}\n\n/**\n Promise objects represent the eventual result of an asynchronous operation. The\n primary way of interacting with a promise is through its `then` method, which\n registers callbacks to receive either a promise’s eventual value or the reason\n why the promise cannot be fulfilled.\n\n Terminology\n -----------\n\n - `promise` is an object or function with a `then` method whose behavior conforms to this specification.\n - `thenable` is an object or function that defines a `then` method.\n - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).\n - `exception` is a value that is thrown using the throw statement.\n - `reason` is a value that indicates why a promise was rejected.\n - `settled` the final resting state of a promise, fulfilled or rejected.\n\n A promise can be in one of three states: pending, fulfilled, or rejected.\n\n Promises that are fulfilled have a fulfillment value and are in the fulfilled\n state. Promises that are rejected have a rejection reason and are in the\n rejected state. A fulfillment value is never a thenable.\n\n Promises can also be said to *resolve* a value. If this value is also a\n promise, then the original promise's settled state will match the value's\n settled state. So a promise that *resolves* a promise that rejects will\n itself reject, and a promise that *resolves* a promise that fulfills will\n itself fulfill.\n\n\n Basic Usage:\n ------------\n\n ```js\n let promise = new Promise(function(resolve, reject) {\n // on success\n resolve(value);\n\n // on failure\n reject(reason);\n });\n\n promise.then(function(value) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Advanced Usage:\n ---------------\n\n Promises shine when abstracting away asynchronous interactions such as\n `XMLHttpRequest`s.\n\n ```js\n function getJSON(url) {\n return new Promise(function(resolve, reject){\n let xhr = new XMLHttpRequest();\n\n xhr.open('GET', url);\n xhr.onreadystatechange = handler;\n xhr.responseType = 'json';\n xhr.setRequestHeader('Accept', 'application/json');\n xhr.send();\n\n function handler() {\n if (this.readyState === this.DONE) {\n if (this.status === 200) {\n resolve(this.response);\n } else {\n reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));\n }\n }\n };\n });\n }\n\n getJSON('/posts.json').then(function(json) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Unlike callbacks, promises are great composable primitives.\n\n ```js\n Promise.all([\n getJSON('/posts'),\n getJSON('/comments')\n ]).then(function(values){\n values[0] // => postsJSON\n values[1] // => commentsJSON\n\n return values;\n });\n ```\n\n @class RSVP.Promise\n @param {function} resolver\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @constructor\n*/\nfunction Promise(resolver, label) {\n this._id = counter++;\n this._label = label;\n this._state = undefined;\n this._result = undefined;\n this._subscribers = [];\n\n config.instrument && instrument('created', this);\n\n if (noop !== resolver) {\n typeof resolver !== 'function' && needsResolver();\n this instanceof Promise ? initializePromise(this, resolver) : needsNew();\n }\n}\n\nPromise.cast = resolve$1; // deprecated\nPromise.all = all;\nPromise.race = race;\nPromise.resolve = resolve$1;\nPromise.reject = reject$1;\n\nPromise.prototype = {\n constructor: Promise,\n\n _guidKey: guidKey,\n\n _onError: function _onError(reason) {\n var promise = this;\n config.after(function () {\n if (promise._onError) {\n config['trigger']('error', reason, promise._label);\n }\n });\n },\n\n /**\n The primary way of interacting with a promise is through its `then` method,\n which registers callbacks to receive either a promise's eventual value or the\n reason why the promise cannot be fulfilled.\n \n ```js\n findUser().then(function(user){\n // user is available\n }, function(reason){\n // user is unavailable, and you are given the reason why\n });\n ```\n \n Chaining\n --------\n \n The return value of `then` is itself a promise. This second, 'downstream'\n promise is resolved with the return value of the first promise's fulfillment\n or rejection handler, or rejected if the handler throws an exception.\n \n ```js\n findUser().then(function (user) {\n return user.name;\n }, function (reason) {\n return 'default name';\n }).then(function (userName) {\n // If `findUser` fulfilled, `userName` will be the user's name, otherwise it\n // will be `'default name'`\n });\n \n findUser().then(function (user) {\n throw new Error('Found user, but still unhappy');\n }, function (reason) {\n throw new Error('`findUser` rejected and we\\'re unhappy');\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.\n // If `findUser` rejected, `reason` will be '`findUser` rejected and we\\'re unhappy'.\n });\n ```\n If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.\n \n ```js\n findUser().then(function (user) {\n throw new PedagogicalException('Upstream error');\n }).then(function (value) {\n // never reached\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // The `PedgagocialException` is propagated all the way down to here\n });\n ```\n \n Assimilation\n ------------\n \n Sometimes the value you want to propagate to a downstream promise can only be\n retrieved asynchronously. This can be achieved by returning a promise in the\n fulfillment or rejection handler. The downstream promise will then be pending\n until the returned promise is settled. This is called *assimilation*.\n \n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // The user's comments are now available\n });\n ```\n \n If the assimliated promise rejects, then the downstream promise will also reject.\n \n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // If `findCommentsByAuthor` fulfills, we'll have the value here\n }, function (reason) {\n // If `findCommentsByAuthor` rejects, we'll have the reason here\n });\n ```\n \n Simple Example\n --------------\n \n Synchronous Example\n \n ```javascript\n let result;\n \n try {\n result = findResult();\n // success\n } catch(reason) {\n // failure\n }\n ```\n \n Errback Example\n \n ```js\n findResult(function(result, err){\n if (err) {\n // failure\n } else {\n // success\n }\n });\n ```\n \n Promise Example;\n \n ```javascript\n findResult().then(function(result){\n // success\n }, function(reason){\n // failure\n });\n ```\n \n Advanced Example\n --------------\n \n Synchronous Example\n \n ```javascript\n let author, books;\n \n try {\n author = findAuthor();\n books = findBooksByAuthor(author);\n // success\n } catch(reason) {\n // failure\n }\n ```\n \n Errback Example\n \n ```js\n \n function foundBooks(books) {\n \n }\n \n function failure(reason) {\n \n }\n \n findAuthor(function(author, err){\n if (err) {\n failure(err);\n // failure\n } else {\n try {\n findBoooksByAuthor(author, function(books, err) {\n if (err) {\n failure(err);\n } else {\n try {\n foundBooks(books);\n } catch(reason) {\n failure(reason);\n }\n }\n });\n } catch(error) {\n failure(err);\n }\n // success\n }\n });\n ```\n \n Promise Example;\n \n ```javascript\n findAuthor().\n then(findBooksByAuthor).\n then(function(books){\n // found books\n }).catch(function(reason){\n // something went wrong\n });\n ```\n \n @method then\n @param {Function} onFulfillment\n @param {Function} onRejection\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n then: then,\n\n /**\n `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same\n as the catch block of a try/catch statement.\n \n ```js\n function findAuthor(){\n throw new Error('couldn\\'t find that author');\n }\n \n // synchronous\n try {\n findAuthor();\n } catch(reason) {\n // something went wrong\n }\n \n // async with promises\n findAuthor().catch(function(reason){\n // something went wrong\n });\n ```\n \n @method catch\n @param {Function} onRejection\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'catch': function _catch(onRejection, label) {\n return this.then(undefined, onRejection, label);\n },\n\n /**\n `finally` will be invoked regardless of the promise's fate just as native\n try/catch/finally behaves\n \n Synchronous example:\n \n ```js\n findAuthor() {\n if (Math.random() > 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 _finally(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\nfunction Result() {\n this.value = undefined;\n}\n\nvar ERROR = new Result();\nvar GET_THEN_ERROR$1 = new Result();\n\nfunction getThen$1(obj) {\n try {\n return obj.then;\n } catch (error) {\n ERROR.value = error;\n return ERROR;\n }\n}\n\nfunction tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch (error) {\n ERROR.value = error;\n return ERROR;\n }\n}\n\nfunction makeObject(_, argumentNames) {\n var obj = {};\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 (var i = 0; i < argumentNames.length; i++) {\n var _name = argumentNames[i];\n obj[_name] = args[i + 1];\n }\n\n return obj;\n}\n\nfunction 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\nfunction wrapThenable(_then, promise) {\n return {\n then: function then(onFulFillment, onRejection) {\n return _then.call(promise, onFulFillment, onRejection);\n }\n };\n}\n\n/**\n `RSVP.denodeify` takes a 'node-style' function and returns a function that\n will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the\n browser when you'd prefer to use promises over using callbacks. For example,\n `denodeify` transforms the following:\n\n ```javascript\n let fs = require('fs');\n\n fs.readFile('myfile.txt', function(err, data){\n if (err) return handleError(err);\n handleData(data);\n });\n ```\n\n into:\n\n ```javascript\n let fs = require('fs');\n let readFile = RSVP.denodeify(fs.readFile);\n\n readFile('myfile.txt').then(handleData, handleError);\n ```\n\n If the node function has multiple success parameters, then `denodeify`\n just returns the first one:\n\n ```javascript\n let request = RSVP.denodeify(require('request'));\n\n request('http://example.com').then(function(res) {\n // ...\n });\n ```\n\n However, if you need all success parameters, setting `denodeify`'s\n second parameter to `true` causes it to return all success parameters\n as an array:\n\n ```javascript\n let request = RSVP.denodeify(require('request'), true);\n\n request('http://example.com').then(function(result) {\n // result[0] -> res\n // result[1] -> body\n });\n ```\n\n Or if you pass it an array with names it returns the parameters as a hash:\n\n ```javascript\n let request = RSVP.denodeify(require('request'), ['res', 'body']);\n\n request('http://example.com').then(function(result) {\n // result.res\n // result.body\n });\n ```\n\n Sometimes you need to retain the `this`:\n\n ```javascript\n let app = require('express')();\n let render = RSVP.denodeify(app.render.bind(app));\n ```\n\n The denodified function inherits from the original function. It works in all\n environments, except IE 10 and below. Consequently all properties of the original\n function are available to you. However, any properties you change on the\n denodeified function won't be changed on the original function. Example:\n\n ```javascript\n let request = RSVP.denodeify(require('request')),\n cookieJar = request.jar(); // <- Inheritance is used here\n\n request('http://example.com', {jar: cookieJar}).then(function(res) {\n // cookieJar.cookies holds now the cookies returned by example.com\n });\n ```\n\n Using `denodeify` makes it easier to compose asynchronous operations instead\n of using callbacks. For example, instead of:\n\n ```javascript\n let fs = require('fs');\n\n fs.readFile('myfile.txt', function(err, data){\n if (err) { ... } // Handle error\n fs.writeFile('myfile2.txt', data, function(err){\n if (err) { ... } // Handle error\n console.log('done')\n });\n });\n ```\n\n you can chain the operations together using `then` from the returned promise:\n\n ```javascript\n let fs = require('fs');\n let readFile = RSVP.denodeify(fs.readFile);\n let writeFile = RSVP.denodeify(fs.writeFile);\n\n readFile('myfile.txt').then(function(data){\n return writeFile('myfile2.txt', data);\n }).then(function(){\n console.log('done')\n }).catch(function(error){\n // Handle error\n });\n ```\n\n @method denodeify\n @static\n @for RSVP\n @param {Function} nodeFunc a 'node-style' function that takes a callback as\n its last argument. The callback expects an error to be passed as its first\n argument (if an error occurred, otherwise null), and the value from the\n operation as its second argument ('function(err, value){ }').\n @param {Boolean|Array} [options] An optional paramter that if set\n to `true` causes the promise to fulfill with the callback's success arguments\n as an array. This is useful if the node function has multiple success\n paramters. If you set this paramter to an array with names, the promise will\n fulfill with a hash with these names as keys and the success parameters as\n values.\n @return {Function} a function that wraps `nodeFunc` to return an\n `RSVP.Promise`\n @static\n*/\nfunction denodeify(nodeFunc, options) {\n var fn = function fn() {\n var self = this;\n var l = arguments.length;\n var args = new Array(l + 1);\n var promiseInput = false;\n\n for (var i = 0; i < l; ++i) {\n var arg = arguments[i];\n\n if (!promiseInput) {\n // TODO: clean this up\n promiseInput = needsPromiseInput(arg);\n if (promiseInput === GET_THEN_ERROR$1) {\n var p = new Promise(noop);\n reject(p, GET_THEN_ERROR$1.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new Promise(noop);\n\n args[l] = function (err, val) {\n if (err) reject(promise, err);else if (options === undefined) resolve(promise, val);else if (options === true) resolve(promise, arrayResult(arguments));else if (isArray(options)) resolve(promise, makeObject(arguments, options));else resolve(promise, val);\n };\n\n if (promiseInput) {\n return handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n}\n\nfunction handleValueInput(promise, args, nodeFunc, self) {\n var result = tryApply(nodeFunc, self, args);\n if (result === ERROR) {\n reject(promise, result.value);\n }\n return promise;\n}\n\nfunction handlePromiseInput(promise, args, nodeFunc, self) {\n return Promise.all(args).then(function (args) {\n var result = tryApply(nodeFunc, self, args);\n if (result === ERROR) {\n reject(promise, result.value);\n }\n return promise;\n });\n}\n\nfunction needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === Promise) {\n return true;\n } else {\n return getThen$1(arg);\n }\n } else {\n return false;\n }\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.all`.\n\n @method all\n @static\n @for RSVP\n @param {Array} array Array of promises.\n @param {String} label An optional label. This is useful\n for tooling.\n*/\nfunction all$1(array, label) {\n return Promise.all(array, label);\n}\n\nfunction AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false, /* don't abort on reject */label);\n}\n\nAllSettled.prototype = o_create(Enumerator.prototype);\nAllSettled.prototype._superConstructor = Enumerator;\nAllSettled.prototype._makeResult = makeSettledResult;\nAllSettled.prototype._validationError = function () {\n return new Error('allSettled must be called with an array');\n};\n\n/**\n `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing\n a fail-fast method, it waits until all the promises have returned and\n shows you all the results. This is useful if you want to handle multiple\n promises' failure states together as a set.\n\n Returns a promise that is fulfilled when all the given promises have been\n settled. The return promise is fulfilled with an array of the states of\n the promises passed into the `promises` array argument.\n\n Each state object will either indicate fulfillment or rejection, and\n provide the corresponding value or reason. The states will take one of\n the following formats:\n\n ```javascript\n { state: 'fulfilled', value: value }\n or\n { state: 'rejected', reason: reason }\n ```\n\n Example:\n\n ```javascript\n let promise1 = RSVP.Promise.resolve(1);\n let promise2 = RSVP.Promise.reject(new Error('2'));\n let promise3 = RSVP.Promise.reject(new Error('3'));\n let promises = [ promise1, promise2, promise3 ];\n\n RSVP.allSettled(promises).then(function(array){\n // array == [\n // { state: 'fulfilled', value: 1 },\n // { state: 'rejected', reason: Error },\n // { state: 'rejected', reason: Error }\n // ]\n // Note that for the second item, reason.message will be '2', and for the\n // third item, reason.message will be '3'.\n }, function(error) {\n // Not run. (This block would only be called if allSettled had failed,\n // for instance if passed an incorrect argument type.)\n });\n ```\n\n @method allSettled\n @static\n @for RSVP\n @param {Array} entries\n @param {String} label - optional string that describes the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled with an array of the settled\n states of the constituent promises.\n*/\nfunction allSettled(entries, label) {\n return new AllSettled(Promise, entries, label).promise;\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.race`.\n\n @method race\n @static\n @for RSVP\n @param {Array} array Array of promises.\n @param {String} label An optional label. This is useful\n for tooling.\n */\nfunction race$1(array, label) {\n return Promise.race(array, label);\n}\n\nfunction PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n}\n\nPromiseHash.prototype = o_create(Enumerator.prototype);\nPromiseHash.prototype._superConstructor = Enumerator;\nPromiseHash.prototype._init = function () {\n this._result = {};\n};\n\nPromiseHash.prototype._validateInput = function (input) {\n return input && typeof input === 'object';\n};\n\nPromiseHash.prototype._validationError = function () {\n return new Error('Promise.hash must be called with an object');\n};\n\nPromiseHash.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 === 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 = undefined;\n\n for (var i = 0; promise._state === PENDING && i < length; i++) {\n result = results[i];\n enumerator._eachEntry(result.entry, result.position);\n }\n};\n\n/**\n `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array\n for its `promises` argument.\n\n Returns a promise that is fulfilled when all the given promises have been\n fulfilled, or rejected if any of them become rejected. The returned promise\n is fulfilled with a hash that has the same key names as the `promises` object\n argument. If any of the values in the object are not promises, they will\n simply be copied over to the fulfilled object.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.resolve(1),\n yourPromise: RSVP.resolve(2),\n theirPromise: RSVP.resolve(3),\n notAPromise: 4\n };\n\n RSVP.hash(promises).then(function(hash){\n // hash here is an object that looks like:\n // {\n // myPromise: 1,\n // yourPromise: 2,\n // theirPromise: 3,\n // notAPromise: 4\n // }\n });\n ````\n\n If any of the `promises` given to `RSVP.hash` are rejected, the first promise\n that is rejected will be given as the reason to the rejection handler.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.resolve(1),\n rejectedPromise: RSVP.reject(new Error('rejectedPromise')),\n anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')),\n };\n\n RSVP.hash(promises).then(function(hash){\n // Code here never runs because there are rejected promises!\n }, function(reason) {\n // reason.message === 'rejectedPromise'\n });\n ```\n\n An important note: `RSVP.hash` is intended for plain JavaScript objects that\n are just a set of keys and values. `RSVP.hash` will NOT preserve prototype\n chains.\n\n Example:\n\n ```javascript\n function MyConstructor(){\n this.example = RSVP.resolve('Example');\n }\n\n MyConstructor.prototype = {\n protoProperty: RSVP.resolve('Proto Property')\n };\n\n let myObject = new MyConstructor();\n\n RSVP.hash(myObject).then(function(hash){\n // protoProperty will not be present, instead you will just have an\n // object that looks like:\n // {\n // example: 'Example'\n // }\n //\n // hash.hasOwnProperty('protoProperty'); // false\n // 'undefined' === typeof hash.protoProperty\n });\n ```\n\n @method hash\n @static\n @for RSVP\n @param {Object} object\n @param {String} label optional string that describes the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when all properties of `promises`\n have been fulfilled, or rejected if any of them become rejected.\n*/\nfunction hash(object, label) {\n return new PromiseHash(Promise, object, label).promise;\n}\n\nfunction HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n}\n\nHashSettled.prototype = o_create(PromiseHash.prototype);\nHashSettled.prototype._superConstructor = Enumerator;\nHashSettled.prototype._makeResult = makeSettledResult;\n\nHashSettled.prototype._validationError = function () {\n return new Error('hashSettled must be called with an object');\n};\n\n/**\n `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object\n instead of an array for its `promises` argument.\n\n Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method,\n but like `RSVP.allSettled`, `hashSettled` waits until all the\n constituent promises have returned and then shows you all the results\n with their states and values/reasons. This is useful if you want to\n handle multiple promises' failure states together as a set.\n\n Returns a promise that is fulfilled when all the given promises have been\n settled, or rejected if the passed parameters are invalid.\n\n The returned promise is fulfilled with a hash that has the same key names as\n the `promises` object argument. If any of the values in the object are not\n promises, they will be copied over to the fulfilled object and marked with state\n 'fulfilled'.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.Promise.resolve(1),\n yourPromise: RSVP.Promise.resolve(2),\n theirPromise: RSVP.Promise.resolve(3),\n notAPromise: 4\n };\n\n RSVP.hashSettled(promises).then(function(hash){\n // hash here is an object that looks like:\n // {\n // myPromise: { state: 'fulfilled', value: 1 },\n // yourPromise: { state: 'fulfilled', value: 2 },\n // theirPromise: { state: 'fulfilled', value: 3 },\n // notAPromise: { state: 'fulfilled', value: 4 }\n // }\n });\n ```\n\n If any of the `promises` given to `RSVP.hash` are rejected, the state will\n be set to 'rejected' and the reason for rejection provided.\n\n Example:\n\n ```javascript\n let promises = {\n myPromise: RSVP.Promise.resolve(1),\n rejectedPromise: RSVP.Promise.reject(new Error('rejection')),\n anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')),\n };\n\n RSVP.hashSettled(promises).then(function(hash){\n // hash here is an object that looks like:\n // {\n // myPromise: { state: 'fulfilled', value: 1 },\n // rejectedPromise: { state: 'rejected', reason: Error },\n // anotherRejectedPromise: { state: 'rejected', reason: Error },\n // }\n // Note that for rejectedPromise, reason.message == 'rejection',\n // and for anotherRejectedPromise, reason.message == 'more rejection'.\n });\n ```\n\n An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that\n are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype\n chains.\n\n Example:\n\n ```javascript\n function MyConstructor(){\n this.example = RSVP.Promise.resolve('Example');\n }\n\n MyConstructor.prototype = {\n protoProperty: RSVP.Promise.resolve('Proto Property')\n };\n\n let myObject = new MyConstructor();\n\n RSVP.hashSettled(myObject).then(function(hash){\n // protoProperty will not be present, instead you will just have an\n // object that looks like:\n // {\n // example: { state: 'fulfilled', value: 'Example' }\n // }\n //\n // hash.hasOwnProperty('protoProperty'); // false\n // 'undefined' === typeof hash.protoProperty\n });\n ```\n\n @method hashSettled\n @for RSVP\n @param {Object} object\n @param {String} label optional string that describes the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when when all properties of `promises`\n have been settled.\n @static\n*/\nfunction hashSettled(object, label) {\n return new HashSettled(Promise, object, label).promise;\n}\n\nfunction rethrow(reason) {\n setTimeout(function () {\n throw reason;\n });\n throw reason;\n}\n\n/**\n `RSVP.defer` returns an object similar to jQuery's `$.Deferred`.\n `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s\n interface. New code should use the `RSVP.Promise` constructor instead.\n\n The object returned from `RSVP.defer` is a plain object with three properties:\n\n * promise - an `RSVP.Promise`.\n * reject - a function that causes the `promise` property on this object to\n become rejected\n * resolve - a function that causes the `promise` property on this object to\n become fulfilled.\n\n Example:\n\n ```javascript\n let deferred = RSVP.defer();\n\n deferred.resolve(\"Success!\");\n\n deferred.promise.then(function(value){\n // value here is \"Success!\"\n });\n ```\n\n @method defer\n @static\n @for RSVP\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Object}\n */\nfunction defer(label) {\n var deferred = { resolve: undefined, reject: undefined };\n\n deferred.promise = new Promise(function (resolve, reject) {\n deferred.resolve = resolve;\n deferred.reject = reject;\n }, label);\n\n return deferred;\n}\n\n/**\n `RSVP.map` is similar to JavaScript's native `map` method, except that it\n waits for all promises to become fulfilled before running the `mapFn` on\n each item in given to `promises`. `RSVP.map` returns a promise that will\n become fulfilled with the result of running `mapFn` on the values the promises\n become fulfilled with.\n\n For example:\n\n ```javascript\n\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.resolve(2);\n let promise3 = RSVP.resolve(3);\n let promises = [ promise1, promise2, promise3 ];\n\n let mapFn = function(item){\n return item + 1;\n };\n\n RSVP.map(promises, mapFn).then(function(result){\n // result is [ 2, 3, 4 ]\n });\n ```\n\n If any of the `promises` given to `RSVP.map` are rejected, the first promise\n that is rejected will be given as an argument to the returned promise's\n rejection handler. For example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.reject(new Error('2'));\n let promise3 = RSVP.reject(new Error('3'));\n let promises = [ promise1, promise2, promise3 ];\n\n let mapFn = function(item){\n return item + 1;\n };\n\n RSVP.map(promises, mapFn).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(reason) {\n // reason.message === '2'\n });\n ```\n\n `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,\n say you want to get all comments from a set of blog posts, but you need\n the blog posts first because they contain a url to those comments.\n\n ```javscript\n\n let mapFn = function(blogPost){\n // getComments does some ajax and returns an RSVP.Promise that is fulfilled\n // with some comments data\n return getComments(blogPost.comments_url);\n };\n\n // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled\n // with some blog post data\n RSVP.map(getBlogPosts(), mapFn).then(function(comments){\n // comments is the result of asking the server for the comments\n // of all blog posts returned from getBlogPosts()\n });\n ```\n\n @method map\n @static\n @for RSVP\n @param {Array} promises\n @param {Function} mapFn function to be called on each fulfilled promise.\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled with the result of calling\n `mapFn` on each fulfilled promise or value when they become fulfilled.\n The promise will be rejected if any of the given `promises` become rejected.\n @static\n*/\nfunction map(promises, mapFn, label) {\n return Promise.all(promises, label).then(function (values) {\n if (!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 Promise.all(results, label);\n });\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.resolve`.\n\n @method resolve\n @static\n @for RSVP\n @param {*} value value that the returned promise will be resolved with\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise that will become fulfilled with the given\n `value`\n*/\nfunction resolve$2(value, label) {\n return Promise.resolve(value, label);\n}\n\n/**\n This is a convenient alias for `RSVP.Promise.reject`.\n\n @method reject\n @static\n @for RSVP\n @param {*} reason value that the returned promise will be rejected with.\n @param {String} label optional string for identifying the returned promise.\n Useful for tooling.\n @return {Promise} a promise rejected with the given `reason`.\n*/\nfunction reject$2(reason, label) {\n return Promise.reject(reason, label);\n}\n\n/**\n `RSVP.filter` is similar to JavaScript's native `filter` method, except that it\n waits for all promises to become fulfilled before running the `filterFn` on\n each item in given to `promises`. `RSVP.filter` returns a promise that will\n become fulfilled with the result of running `filterFn` on the values the\n promises become fulfilled with.\n\n For example:\n\n ```javascript\n\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.resolve(2);\n let promise3 = RSVP.resolve(3);\n\n let promises = [promise1, promise2, promise3];\n\n let filterFn = function(item){\n return item > 1;\n };\n\n RSVP.filter(promises, filterFn).then(function(result){\n // result is [ 2, 3 ]\n });\n ```\n\n If any of the `promises` given to `RSVP.filter` are rejected, the first promise\n that is rejected will be given as an argument to the returned promise's\n rejection handler. For example:\n\n ```javascript\n let promise1 = RSVP.resolve(1);\n let promise2 = RSVP.reject(new Error('2'));\n let promise3 = RSVP.reject(new Error('3'));\n let promises = [ promise1, promise2, promise3 ];\n\n let filterFn = function(item){\n return item > 1;\n };\n\n RSVP.filter(promises, filterFn).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(reason) {\n // reason.message === '2'\n });\n ```\n\n `RSVP.filter` will also wait for any promises returned from `filterFn`.\n For instance, you may want to fetch a list of users then return a subset\n of those users based on some asynchronous operation:\n\n ```javascript\n\n let alice = { name: 'alice' };\n let bob = { name: 'bob' };\n let users = [ alice, bob ];\n\n let promises = users.map(function(user){\n return RSVP.resolve(user);\n });\n\n let filterFn = function(user){\n // Here, Alice has permissions to create a blog post, but Bob does not.\n return getPrivilegesForUser(user).then(function(privs){\n return privs.can_create_blog_post === true;\n });\n };\n RSVP.filter(promises, filterFn).then(function(users){\n // true, because the server told us only Alice can create a blog post.\n users.length === 1;\n // false, because Alice is the only user present in `users`\n users[0] === bob;\n });\n ```\n\n @method filter\n @static\n @for RSVP\n @param {Array} promises\n @param {Function} filterFn - function to be called on each resolved value to\n filter the final results.\n @param {String} label optional string describing the promise. Useful for\n tooling.\n @return {Promise}\n*/\n\nfunction resolveAll(promises, label) {\n return Promise.all(promises, label);\n}\n\nfunction resolveSingle(promise, label) {\n return Promise.resolve(promise, label).then(function (promises) {\n return resolveAll(promises, label);\n });\n}\nfunction filter(promises, filterFn, label) {\n var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label);\n return promise.then(function (values) {\n if (!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 resolveAll(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\nvar len = 0;\nvar vertxNext = undefined;\nfunction asap(callback, arg) {\n queue$1[len] = callback;\n queue$1[len + 1] = arg;\n len += 2;\n if (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 scheduleFlush$1();\n }\n}\n\nvar browserWindow = typeof window !== 'undefined' ? window : undefined;\nvar browserGlobal = browserWindow || {};\nvar BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;\nvar isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';\n\n// test for web worker but not in IE10\nvar isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';\n\n// node\nfunction 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 return nextTick(flush);\n };\n}\n\n// vertx\nfunction useVertxTimer() {\n return function () {\n return vertxNext(flush);\n };\n}\n\nfunction useMutationObserver() {\n var iterations = 0;\n var observer = new BrowserMutationObserver(flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function () {\n return node.data = iterations = ++iterations % 2;\n };\n}\n\n// web worker\nfunction useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = flush;\n return function () {\n return channel.port2.postMessage(0);\n };\n}\n\nfunction useSetTimeout() {\n return function () {\n return setTimeout(flush, 1);\n };\n}\n\nvar queue$1 = new Array(1000);\n\nfunction flush() {\n for (var i = 0; i < len; i += 2) {\n var callback = queue$1[i];\n var arg = queue$1[i + 1];\n\n callback(arg);\n\n queue$1[i] = undefined;\n queue$1[i + 1] = undefined;\n }\n\n len = 0;\n}\n\nfunction attemptVertex() {\n try {\n var r = require;\n var vertx = r('vertx');\n vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return useVertxTimer();\n } catch (e) {\n return useSetTimeout();\n }\n}\n\nvar scheduleFlush$1 = undefined;\n// Decide what async method to use to triggering processing of queued callbacks:\nif (isNode) {\n scheduleFlush$1 = useNextTick();\n} else if (BrowserMutationObserver) {\n scheduleFlush$1 = useMutationObserver();\n} else if (isWorker) {\n scheduleFlush$1 = useMessageChannel();\n} else if (browserWindow === undefined && typeof require === 'function') {\n scheduleFlush$1 = attemptVertex();\n} else {\n scheduleFlush$1 = useSetTimeout();\n}\n\nvar platform = undefined;\n\n/* global self */\nif (typeof self === 'object') {\n platform = self;\n\n /* global global */\n} else if (typeof global === 'object') {\n platform = global;\n } else {\n throw new Error('no global: `self` or `global` found');\n }\n\nvar _async$filter;\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n// defaults\n\n// the default export here is for backwards compat:\n// https://github.com/tildeio/rsvp.js/issues/434\nconfig.async = asap;\nconfig.after = function (cb) {\n return setTimeout(cb, 0);\n};\nvar cast = resolve$2;\n\nvar async = function async(callback, arg) {\n return config.async(callback, arg);\n};\n\nfunction on() {\n config['on'].apply(config, arguments);\n}\n\nfunction off() {\n config['off'].apply(config, arguments);\n}\n\n// Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`\nif (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {\n var callbacks = window['__PROMISE_INSTRUMENTATION__'];\n configure('instrument', true);\n for (var eventName in callbacks) {\n if (callbacks.hasOwnProperty(eventName)) {\n on(eventName, callbacks[eventName]);\n }\n }\n}var rsvp = (_async$filter = {\n cast: cast,\n Promise: Promise,\n EventTarget: EventTarget,\n all: all$1,\n allSettled: allSettled,\n race: race$1,\n hash: hash,\n hashSettled: hashSettled,\n rethrow: rethrow,\n defer: defer,\n denodeify: denodeify,\n configure: configure,\n on: on,\n off: off,\n resolve: resolve$2,\n reject: reject$2,\n map: map\n}, _defineProperty(_async$filter, 'async', async), _defineProperty(_async$filter, 'filter', // babel seems to error if async isn't a computed prop here...\nfilter), _async$filter);\n\nexports['default'] = rsvp;\nexports.cast = cast;\nexports.Promise = Promise;\nexports.EventTarget = EventTarget;\nexports.all = all$1;\nexports.allSettled = allSettled;\nexports.race = race$1;\nexports.hash = hash;\nexports.hashSettled = hashSettled;\nexports.rethrow = rethrow;\nexports.defer = defer;\nexports.denodeify = denodeify;\nexports.configure = configure;\nexports.on = on;\nexports.off = off;\nexports.resolve = resolve$2;\nexports.reject = reject$2;\nexports.map = map;\nexports.async = async;\nexports.filter = filter;\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceMappingURL=rsvp.map\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/rsvp/dist/rsvp.js\n ** module id = 2\n ** module chunks = 0\n **/","// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 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 runTimeout(drainQueue);\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\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/process/browser.js\n ** module id = 3\n ** module chunks = 0\n **/","var nextTick = require('process/browser.js').nextTick;\nvar apply = Function.prototype.apply;\nvar slice = Array.prototype.slice;\nvar immediateIds = {};\nvar nextImmediateId = 0;\n\n// DOM APIs, for completeness\n\nexports.setTimeout = function() {\n return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);\n};\nexports.setInterval = function() {\n return new Timeout(apply.call(setInterval, window, arguments), clearInterval);\n};\nexports.clearTimeout =\nexports.clearInterval = function(timeout) { timeout.close(); };\n\nfunction Timeout(id, clearFn) {\n this._id = id;\n this._clearFn = clearFn;\n}\nTimeout.prototype.unref = Timeout.prototype.ref = function() {};\nTimeout.prototype.close = function() {\n this._clearFn.call(window, this._id);\n};\n\n// Does not start the time, just sets up the members needed.\nexports.enroll = function(item, msecs) {\n clearTimeout(item._idleTimeoutId);\n item._idleTimeout = msecs;\n};\n\nexports.unenroll = function(item) {\n clearTimeout(item._idleTimeoutId);\n item._idleTimeout = -1;\n};\n\nexports._unrefActive = exports.active = function(item) {\n clearTimeout(item._idleTimeoutId);\n\n var msecs = item._idleTimeout;\n if (msecs >= 0) {\n item._idleTimeoutId = setTimeout(function onTimeout() {\n if (item._onTimeout)\n item._onTimeout();\n }, msecs);\n }\n};\n\n// That's not how node.js implements it but the exposed api is the same.\nexports.setImmediate = typeof setImmediate === \"function\" ? setImmediate : function(fn) {\n var id = nextImmediateId++;\n var args = arguments.length < 2 ? false : slice.call(arguments, 1);\n\n immediateIds[id] = true;\n\n nextTick(function onNextTick() {\n if (immediateIds[id]) {\n // fn.call() is faster so we optimize for the common use-case\n // @see http://jsperf.com/call-apply-segu\n if (args) {\n fn.apply(null, args);\n } else {\n fn.call(null);\n }\n // Prevent ids from leaking\n exports.clearImmediate(id);\n }\n });\n\n return id;\n};\n\nexports.clearImmediate = typeof clearImmediate === \"function\" ? clearImmediate : function(id) {\n delete immediateIds[id];\n};\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/timers-browserify/main.js\n ** module id = 4\n ** module chunks = 0\n **/","/* (ignored) */\n\n\n/*****************\n ** WEBPACK FOOTER\n ** vertx (ignored)\n ** module id = 5\n ** module chunks = 0\n **/","/*!\n * URI.js - Mutating URLs\n *\n * Version: 1.18.1\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 *\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.18.1';\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\n if (parts.password) {\n t += ':' + URI.encode(parts.password);\n }\n\n if (t) {\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 switch (getType(name)) {\n case 'String':\n // Nothing to do here\n break;\n\n case 'RegExp':\n for (var key in data) {\n if (hasOwn.call(data, key)) {\n if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) {\n return true;\n }\n }\n }\n\n return false;\n\n case '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\n default:\n throw new TypeError('URI.hasQuery() accepts a string, regular expression or object 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.joinPaths = function() {\n var input = [];\n var segments = [];\n var nonEmptySegments = 0;\n\n for (var i = 0; i < arguments.length; i++) {\n var url = new URI(arguments[i]);\n input.push(url);\n var _segments = url.segment();\n for (var s = 0; s < _segments.length; s++) {\n if (typeof _segments[s] === 'string') {\n segments.push(_segments[s]);\n }\n\n if (_segments[s]) {\n nonEmptySegments++;\n }\n }\n }\n\n if (!segments.length || !nonEmptySegments) {\n return new URI('');\n }\n\n var uri = new URI('').segment(segments);\n\n if (input[0].path() === '' || input[0].path().slice(0, 1) === '/') {\n uri.path('/' + uri.path());\n }\n\n return uri.normalize();\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 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) {\n return '';\n }\n\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 var t = URI.buildUserinfo(this._parts);\n return t ? t.substring(0, t.length -1) : t;\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 _path = URI.recodePath(_path);\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.search(/\\/\\.\\.(\\/|$)/);\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 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\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/urijs/src/URI.js\n ** module id = 6\n ** module chunks = 0\n **/","/*! https://mths.be/punycode v1.4.0 by @mathias */\n;(function(root) {\n\n\t/** Detect free variables */\n\tvar freeExports = typeof exports == 'object' && exports &&\n\t\t!exports.nodeType && exports;\n\tvar freeModule = typeof module == 'object' && module &&\n\t\t!module.nodeType && module;\n\tvar freeGlobal = typeof global == 'object' && global;\n\tif (\n\t\tfreeGlobal.global === freeGlobal ||\n\t\tfreeGlobal.window === freeGlobal ||\n\t\tfreeGlobal.self === freeGlobal\n\t) {\n\t\troot = freeGlobal;\n\t}\n\n\t/**\n\t * The `punycode` object.\n\t * @name punycode\n\t * @type Object\n\t */\n\tvar punycode,\n\n\t/** Highest positive signed 32-bit float value */\n\tmaxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1\n\n\t/** Bootstring parameters */\n\tbase = 36,\n\ttMin = 1,\n\ttMax = 26,\n\tskew = 38,\n\tdamp = 700,\n\tinitialBias = 72,\n\tinitialN = 128, // 0x80\n\tdelimiter = '-', // '\\x2D'\n\n\t/** Regular expressions */\n\tregexPunycode = /^xn--/,\n\tregexNonASCII = /[^\\x20-\\x7E]/, // unprintable ASCII chars + non-ASCII chars\n\tregexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g, // RFC 3490 separators\n\n\t/** Error messages */\n\terrors = {\n\t\t'overflow': 'Overflow: input needs wider integers to process',\n\t\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t\t'invalid-input': 'Invalid input'\n\t},\n\n\t/** Convenience shortcuts */\n\tbaseMinusTMin = base - tMin,\n\tfloor = Math.floor,\n\tstringFromCharCode = String.fromCharCode,\n\n\t/** Temporary variable */\n\tkey;\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/**\n\t * A generic error utility function.\n\t * @private\n\t * @param {String} type The error type.\n\t * @returns {Error} Throws a `RangeError` with the applicable error message.\n\t */\n\tfunction error(type) {\n\t\tthrow new RangeError(errors[type]);\n\t}\n\n\t/**\n\t * A generic `Array#map` utility function.\n\t * @private\n\t * @param {Array} array The array to iterate over.\n\t * @param {Function} callback The function that gets called for every array\n\t * item.\n\t * @returns {Array} A new array of values returned by the callback function.\n\t */\n\tfunction map(array, fn) {\n\t\tvar length = array.length;\n\t\tvar result = [];\n\t\twhile (length--) {\n\t\t\tresult[length] = fn(array[length]);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * A simple `Array#map`-like wrapper to work with domain name strings or email\n\t * addresses.\n\t * @private\n\t * @param {String} domain The domain name or email address.\n\t * @param {Function} callback The function that gets called for every\n\t * character.\n\t * @returns {Array} A new string of characters returned by the callback\n\t * function.\n\t */\n\tfunction mapDomain(string, fn) {\n\t\tvar parts = string.split('@');\n\t\tvar result = '';\n\t\tif (parts.length > 1) {\n\t\t\t// In email addresses, only the domain name should be punycoded. Leave\n\t\t\t// the local part (i.e. everything up to `@`) intact.\n\t\t\tresult = parts[0] + '@';\n\t\t\tstring = parts[1];\n\t\t}\n\t\t// Avoid `split(regex)` for IE8 compatibility. See #17.\n\t\tstring = string.replace(regexSeparators, '\\x2E');\n\t\tvar labels = string.split('.');\n\t\tvar encoded = map(labels, fn).join('.');\n\t\treturn result + encoded;\n\t}\n\n\t/**\n\t * Creates an array containing the numeric code points of each Unicode\n\t * character in the string. While JavaScript uses UCS-2 internally,\n\t * this function will convert a pair of surrogate halves (each of which\n\t * UCS-2 exposes as separate characters) into a single code point,\n\t * matching UTF-16.\n\t * @see `punycode.ucs2.encode`\n\t * @see \n\t * @memberOf punycode.ucs2\n\t * @name decode\n\t * @param {String} string The Unicode input string (UCS-2).\n\t * @returns {Array} The new array of code points.\n\t */\n\tfunction ucs2decode(string) {\n\t\tvar output = [],\n\t\t counter = 0,\n\t\t length = string.length,\n\t\t value,\n\t\t extra;\n\t\twhile (counter < length) {\n\t\t\tvalue = string.charCodeAt(counter++);\n\t\t\tif (value >= 0xD800 && value <= 0xDBFF && counter < length) {\n\t\t\t\t// high surrogate, and there is a next character\n\t\t\t\textra = string.charCodeAt(counter++);\n\t\t\t\tif ((extra & 0xFC00) == 0xDC00) { // low surrogate\n\t\t\t\t\toutput.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n\t\t\t\t} else {\n\t\t\t\t\t// unmatched surrogate; only append this code unit, in case the next\n\t\t\t\t\t// code unit is the high surrogate of a surrogate pair\n\t\t\t\t\toutput.push(value);\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toutput.push(value);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Creates a string based on an array of numeric code points.\n\t * @see `punycode.ucs2.decode`\n\t * @memberOf punycode.ucs2\n\t * @name encode\n\t * @param {Array} codePoints The array of numeric code points.\n\t * @returns {String} The new Unicode string (UCS-2).\n\t */\n\tfunction ucs2encode(array) {\n\t\treturn map(array, function(value) {\n\t\t\tvar output = '';\n\t\t\tif (value > 0xFFFF) {\n\t\t\t\tvalue -= 0x10000;\n\t\t\t\toutput += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);\n\t\t\t\tvalue = 0xDC00 | value & 0x3FF;\n\t\t\t}\n\t\t\toutput += stringFromCharCode(value);\n\t\t\treturn output;\n\t\t}).join('');\n\t}\n\n\t/**\n\t * Converts a basic code point into a digit/integer.\n\t * @see `digitToBasic()`\n\t * @private\n\t * @param {Number} codePoint The basic numeric code point value.\n\t * @returns {Number} The numeric value of a basic code point (for use in\n\t * representing integers) in the range `0` to `base - 1`, or `base` if\n\t * the code point does not represent a value.\n\t */\n\tfunction basicToDigit(codePoint) {\n\t\tif (codePoint - 48 < 10) {\n\t\t\treturn codePoint - 22;\n\t\t}\n\t\tif (codePoint - 65 < 26) {\n\t\t\treturn codePoint - 65;\n\t\t}\n\t\tif (codePoint - 97 < 26) {\n\t\t\treturn codePoint - 97;\n\t\t}\n\t\treturn base;\n\t}\n\n\t/**\n\t * Converts a digit/integer into a basic code point.\n\t * @see `basicToDigit()`\n\t * @private\n\t * @param {Number} digit The numeric value of a basic code point.\n\t * @returns {Number} The basic code point whose value (when used for\n\t * representing integers) is `digit`, which needs to be in the range\n\t * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n\t * used; else, the lowercase form is used. The behavior is undefined\n\t * if `flag` is non-zero and `digit` has no uppercase form.\n\t */\n\tfunction digitToBasic(digit, flag) {\n\t\t// 0..25 map to ASCII a..z or A..Z\n\t\t// 26..35 map to ASCII 0..9\n\t\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n\t}\n\n\t/**\n\t * Bias adaptation function as per section 3.4 of RFC 3492.\n\t * https://tools.ietf.org/html/rfc3492#section-3.4\n\t * @private\n\t */\n\tfunction adapt(delta, numPoints, firstTime) {\n\t\tvar k = 0;\n\t\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\t\tdelta += floor(delta / numPoints);\n\t\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\t\tdelta = floor(delta / baseMinusTMin);\n\t\t}\n\t\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n\t}\n\n\t/**\n\t * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n\t * symbols.\n\t * @memberOf punycode\n\t * @param {String} input The Punycode string of ASCII-only symbols.\n\t * @returns {String} The resulting string of Unicode symbols.\n\t */\n\tfunction decode(input) {\n\t\t// Don't use UCS-2\n\t\tvar output = [],\n\t\t inputLength = input.length,\n\t\t out,\n\t\t i = 0,\n\t\t n = initialN,\n\t\t bias = initialBias,\n\t\t basic,\n\t\t j,\n\t\t index,\n\t\t oldi,\n\t\t w,\n\t\t k,\n\t\t digit,\n\t\t t,\n\t\t /** Cached calculation results */\n\t\t baseMinusT;\n\n\t\t// Handle the basic code points: let `basic` be the number of input code\n\t\t// points before the last delimiter, or `0` if there is none, then copy\n\t\t// the first basic code points to the output.\n\n\t\tbasic = input.lastIndexOf(delimiter);\n\t\tif (basic < 0) {\n\t\t\tbasic = 0;\n\t\t}\n\n\t\tfor (j = 0; j < basic; ++j) {\n\t\t\t// if it's not a basic code point\n\t\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\t\terror('not-basic');\n\t\t\t}\n\t\t\toutput.push(input.charCodeAt(j));\n\t\t}\n\n\t\t// Main decoding loop: start just after the last delimiter if any basic code\n\t\t// points were copied; start at the beginning otherwise.\n\n\t\tfor (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t\t// `index` is the index of the next character to be consumed.\n\t\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t\t// which gets added to `i`. The overflow checking is easier\n\t\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t\t// value at the end to obtain `delta`.\n\t\t\tfor (oldi = i, w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\t\tif (index >= inputLength) {\n\t\t\t\t\terror('invalid-input');\n\t\t\t\t}\n\n\t\t\t\tdigit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\t\tif (digit >= base || digit > floor((maxInt - i) / w)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\ti += digit * w;\n\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\t\tif (digit < t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tbaseMinusT = base - t;\n\t\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tw *= baseMinusT;\n\n\t\t\t}\n\n\t\t\tout = output.length + 1;\n\t\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t\t// incrementing `n` each time, so we'll fix that now:\n\t\t\tif (floor(i / out) > maxInt - n) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tn += floor(i / out);\n\t\t\ti %= out;\n\n\t\t\t// Insert `n` at position `i` of the output\n\t\t\toutput.splice(i++, 0, n);\n\n\t\t}\n\n\t\treturn ucs2encode(output);\n\t}\n\n\t/**\n\t * Converts a string of Unicode symbols (e.g. a domain name label) to a\n\t * Punycode string of ASCII-only symbols.\n\t * @memberOf punycode\n\t * @param {String} input The string of Unicode symbols.\n\t * @returns {String} The resulting Punycode string of ASCII-only symbols.\n\t */\n\tfunction encode(input) {\n\t\tvar n,\n\t\t delta,\n\t\t handledCPCount,\n\t\t basicLength,\n\t\t bias,\n\t\t j,\n\t\t m,\n\t\t q,\n\t\t k,\n\t\t t,\n\t\t currentValue,\n\t\t output = [],\n\t\t /** `inputLength` will hold the number of code points in `input`. */\n\t\t inputLength,\n\t\t /** Cached calculation results */\n\t\t handledCPCountPlusOne,\n\t\t baseMinusT,\n\t\t qMinusT;\n\n\t\t// Convert the input in UCS-2 to Unicode\n\t\tinput = ucs2decode(input);\n\n\t\t// Cache the length\n\t\tinputLength = input.length;\n\n\t\t// Initialize the state\n\t\tn = initialN;\n\t\tdelta = 0;\n\t\tbias = initialBias;\n\n\t\t// Handle the basic code points\n\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\tcurrentValue = input[j];\n\t\t\tif (currentValue < 0x80) {\n\t\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t\t}\n\t\t}\n\n\t\thandledCPCount = basicLength = output.length;\n\n\t\t// `handledCPCount` is the number of code points that have been handled;\n\t\t// `basicLength` is the number of basic code points.\n\n\t\t// Finish the basic string - if it is not empty - with a delimiter\n\t\tif (basicLength) {\n\t\t\toutput.push(delimiter);\n\t\t}\n\n\t\t// Main encoding loop:\n\t\twhile (handledCPCount < inputLength) {\n\n\t\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t\t// larger one:\n\t\t\tfor (m = maxInt, j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\t\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\t\tm = currentValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Increase `delta` enough to advance the decoder's state to ,\n\t\t\t// but guard against overflow\n\t\t\thandledCPCountPlusOne = handledCPCount + 1;\n\t\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\t\tn = m;\n\n\t\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\n\t\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tif (currentValue == n) {\n\t\t\t\t\t// Represent delta as a generalized variable-length integer\n\t\t\t\t\tfor (q = delta, k = base; /* no condition */; k += base) {\n\t\t\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqMinusT = q - t;\n\t\t\t\t\t\tbaseMinusT = base - t;\n\t\t\t\t\t\toutput.push(\n\t\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t\t);\n\t\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);\n\t\t\t\t\tdelta = 0;\n\t\t\t\t\t++handledCPCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t++delta;\n\t\t\t++n;\n\n\t\t}\n\t\treturn output.join('');\n\t}\n\n\t/**\n\t * Converts a Punycode string representing a domain name or an email address\n\t * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n\t * it doesn't matter if you call it on a string that has already been\n\t * converted to Unicode.\n\t * @memberOf punycode\n\t * @param {String} input The Punycoded domain name or email address to\n\t * convert to Unicode.\n\t * @returns {String} The Unicode representation of the given Punycode\n\t * string.\n\t */\n\tfunction toUnicode(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexPunycode.test(string)\n\t\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/**\n\t * Converts a Unicode string representing a domain name or an email address to\n\t * Punycode. Only the non-ASCII parts of the domain name will be converted,\n\t * i.e. it doesn't matter if you call it with a domain that's already in\n\t * ASCII.\n\t * @memberOf punycode\n\t * @param {String} input The domain name or email address to convert, as a\n\t * Unicode string.\n\t * @returns {String} The Punycode representation of the given domain name or\n\t * email address.\n\t */\n\tfunction toASCII(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexNonASCII.test(string)\n\t\t\t\t? 'xn--' + encode(string)\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/** Define the public API */\n\tpunycode = {\n\t\t/**\n\t\t * A string representing the current Punycode.js version number.\n\t\t * @memberOf punycode\n\t\t * @type String\n\t\t */\n\t\t'version': '1.3.2',\n\t\t/**\n\t\t * An object of methods to convert from JavaScript's internal character\n\t\t * representation (UCS-2) to Unicode code points, and back.\n\t\t * @see \n\t\t * @memberOf punycode\n\t\t * @type Object\n\t\t */\n\t\t'ucs2': {\n\t\t\t'decode': ucs2decode,\n\t\t\t'encode': ucs2encode\n\t\t},\n\t\t'decode': decode,\n\t\t'encode': encode,\n\t\t'toASCII': toASCII,\n\t\t'toUnicode': toUnicode\n\t};\n\n\t/** Expose `punycode` */\n\t// Some AMD build optimizers, like r.js, check for specific condition patterns\n\t// like the following:\n\tif (\n\t\ttypeof define == 'function' &&\n\t\ttypeof define.amd == 'object' &&\n\t\tdefine.amd\n\t) {\n\t\tdefine('punycode', function() {\n\t\t\treturn punycode;\n\t\t});\n\t} else if (freeExports && freeModule) {\n\t\tif (module.exports == freeExports) {\n\t\t\t// in Node.js, io.js, or RingoJS v0.8.0+\n\t\t\tfreeModule.exports = punycode;\n\t\t} else {\n\t\t\t// in Narwhal or RingoJS v0.7.0-\n\t\t\tfor (key in punycode) {\n\t\t\t\tpunycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// in Rhino or a web browser\n\t\troot.punycode = punycode;\n\t}\n\n}(this));\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/urijs/src/punycode.js\n ** module id = 7\n ** module chunks = 0\n **/","module.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tmodule.children = [];\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n}\r\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** (webpack)/buildin/module.js\n ** module id = 8\n ** module chunks = 0\n **/","/*!\n * URI.js - Mutating URLs\n * IPv6 Support\n *\n * Version: 1.18.1\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 *\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();\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory);\n } else {\n // Browser globals (root is window)\n root.IPv6 = factory(root);\n }\n}(this, function (root) {\n 'use strict';\n\n /*\n var _in = \"fe80:0000:0000:0000:0204:61ff:fe9d:f156\";\n var _out = IPv6.best(_in);\n var _expected = \"fe80::204:61ff:fe9d:f156\";\n\n console.log(_in, _out, _expected, _out === _expected);\n */\n\n // save current IPv6 variable, if any\n var _IPv6 = root && root.IPv6;\n\n function bestPresentation(address) {\n // based on:\n // Javascript to test an IPv6 address for proper format, and to\n // present the \"best text representation\" according to IETF Draft RFC at\n // http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04\n // 8 Feb 2010 Rich Brown, Dartware, LLC\n // Please feel free to use this code as long as you provide a link to\n // http://www.intermapper.com\n // http://intermapper.com/support/tools/IPV6-Validator.aspx\n // http://download.dartware.com/thirdparty/ipv6validator.js\n\n var _address = address.toLowerCase();\n var segments = _address.split(':');\n var length = segments.length;\n var total = 8;\n\n // trim colons (:: or ::a:b:c… or …a:b:c::)\n if (segments[0] === '' && segments[1] === '' && segments[2] === '') {\n // must have been ::\n // remove first two items\n segments.shift();\n segments.shift();\n } else if (segments[0] === '' && segments[1] === '') {\n // must have been ::xxxx\n // remove the first item\n segments.shift();\n } else if (segments[length - 1] === '' && segments[length - 2] === '') {\n // must have been xxxx::\n segments.pop();\n }\n\n length = segments.length;\n\n // adjust total segments for IPv4 trailer\n if (segments[length - 1].indexOf('.') !== -1) {\n // found a \".\" which means IPv4\n total = 7;\n }\n\n // fill empty segments them with \"0000\"\n var pos;\n for (pos = 0; pos < length; pos++) {\n if (segments[pos] === '') {\n break;\n }\n }\n\n if (pos < total) {\n segments.splice(pos, 1, '0000');\n while (segments.length < total) {\n segments.splice(pos, 0, '0000');\n }\n }\n\n // strip leading zeros\n var _segments;\n for (var i = 0; i < total; i++) {\n _segments = segments[i].split('');\n for (var j = 0; j < 3 ; j++) {\n if (_segments[0] === '0' && _segments.length > 1) {\n _segments.splice(0,1);\n } else {\n break;\n }\n }\n\n segments[i] = _segments.join('');\n }\n\n // find longest sequence of zeroes and coalesce them into one segment\n var best = -1;\n var _best = 0;\n var _current = 0;\n var current = -1;\n var inzeroes = false;\n // i; already declared\n\n for (i = 0; i < total; i++) {\n if (inzeroes) {\n if (segments[i] === '0') {\n _current += 1;\n } else {\n inzeroes = false;\n if (_current > _best) {\n best = current;\n _best = _current;\n }\n }\n } else {\n if (segments[i] === '0') {\n inzeroes = true;\n current = i;\n _current = 1;\n }\n }\n }\n\n if (_current > _best) {\n best = current;\n _best = _current;\n }\n\n if (_best > 1) {\n segments.splice(best, _best, '');\n }\n\n length = segments.length;\n\n // assemble remaining segments\n var result = '';\n if (segments[0] === '') {\n result = ':';\n }\n\n for (i = 0; i < length; i++) {\n result += segments[i];\n if (i === length - 1) {\n break;\n }\n\n result += ':';\n }\n\n if (segments[length - 1] === '') {\n result += ':';\n }\n\n return result;\n }\n\n function noConflict() {\n /*jshint validthis: true */\n if (root.IPv6 === this) {\n root.IPv6 = _IPv6;\n }\n \n return this;\n }\n\n return {\n best: bestPresentation,\n noConflict: noConflict\n };\n}));\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/urijs/src/IPv6.js\n ** module id = 9\n ** module chunks = 0\n **/","/*!\n * URI.js - Mutating URLs\n * Second Level Domain (SLD) Support\n *\n * Version: 1.18.1\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 *\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();\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory);\n } else {\n // Browser globals (root is window)\n root.SecondLevelDomains = factory(root);\n }\n}(this, function (root) {\n 'use strict';\n\n // save current SecondLevelDomains variable, if any\n var _SecondLevelDomains = root && root.SecondLevelDomains;\n\n var SLD = {\n // list of known Second Level Domains\n // converted list of SLDs from https://github.com/gavingmiller/second-level-domains\n // ----\n // publicsuffix.org is more current and actually used by a couple of browsers internally.\n // downside is it also contains domains like \"dyndns.org\" - which is fine for the security\n // issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js\n // ----\n list: {\n 'ac':' com gov mil net org ',\n 'ae':' ac co gov mil name net org pro sch ',\n 'af':' com edu gov net org ',\n 'al':' com edu gov mil net org ',\n 'ao':' co ed gv it og pb ',\n 'ar':' com edu gob gov int mil net org tur ',\n 'at':' ac co gv or ',\n 'au':' asn com csiro edu gov id net org ',\n 'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ',\n 'bb':' biz co com edu gov info net org store tv ',\n 'bh':' biz cc com edu gov info net org ',\n 'bn':' com edu gov net org ',\n 'bo':' com edu gob gov int mil net org tv ',\n 'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ',\n 'bs':' com edu gov net org ',\n 'bz':' du et om ov rg ',\n 'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ',\n 'ck':' biz co edu gen gov info net org ',\n 'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ',\n 'co':' com edu gov mil net nom org ',\n 'cr':' ac c co ed fi go or sa ',\n 'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ',\n 'do':' art com edu gob gov mil net org sld web ',\n 'dz':' art asso com edu gov net org pol ',\n 'ec':' com edu fin gov info med mil net org pro ',\n 'eg':' com edu eun gov mil name net org sci ',\n 'er':' com edu gov ind mil net org rochest w ',\n 'es':' com edu gob nom org ',\n 'et':' biz com edu gov info name net org ',\n 'fj':' ac biz com info mil name net org pro ',\n 'fk':' ac co gov net nom org ',\n 'fr':' asso com f gouv nom prd presse tm ',\n 'gg':' co net org ',\n 'gh':' com edu gov mil org ',\n 'gn':' ac com gov net org ',\n 'gr':' com edu gov mil net org ',\n 'gt':' com edu gob ind mil net org ',\n 'gu':' com edu gov net org ',\n 'hk':' com edu gov idv net org ',\n 'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ',\n 'id':' ac co go mil net or sch web ',\n 'il':' ac co gov idf k12 muni net org ',\n 'in':' ac co edu ernet firm gen gov i ind mil net nic org res ',\n 'iq':' com edu gov i mil net org ',\n 'ir':' ac co dnssec gov i id net org sch ',\n 'it':' edu gov ',\n 'je':' co net org ',\n 'jo':' com edu gov mil name net org sch ',\n 'jp':' ac ad co ed go gr lg ne or ',\n 'ke':' ac co go info me mobi ne or sc ',\n 'kh':' com edu gov mil net org per ',\n 'ki':' biz com de edu gov info mob net org tel ',\n 'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ',\n 'kn':' edu gov net org ',\n 'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ',\n 'kw':' com edu gov net org ',\n 'ky':' com edu gov net org ',\n 'kz':' com edu gov mil net org ',\n 'lb':' com edu gov net org ',\n 'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ',\n 'lr':' com edu gov net org ',\n 'lv':' asn com conf edu gov id mil net org ',\n 'ly':' com edu gov id med net org plc sch ',\n 'ma':' ac co gov m net org press ',\n 'mc':' asso tm ',\n 'me':' ac co edu gov its net org priv ',\n 'mg':' com edu gov mil nom org prd tm ',\n 'mk':' com edu gov inf name net org pro ',\n 'ml':' com edu gov net org presse ',\n 'mn':' edu gov org ',\n 'mo':' com edu gov net org ',\n 'mt':' com edu gov net org ',\n 'mv':' aero biz com coop edu gov info int mil museum name net org pro ',\n 'mw':' ac co com coop edu gov int museum net org ',\n 'mx':' com edu gob net org ',\n 'my':' com edu gov mil name net org sch ',\n 'nf':' arts com firm info net other per rec store web ',\n 'ng':' biz com edu gov mil mobi name net org sch ',\n 'ni':' ac co com edu gob mil net nom org ',\n 'np':' com edu gov mil net org ',\n 'nr':' biz com edu gov info net org ',\n 'om':' ac biz co com edu gov med mil museum net org pro sch ',\n 'pe':' com edu gob mil net nom org sld ',\n 'ph':' com edu gov i mil net ngo org ',\n 'pk':' biz com edu fam gob gok gon gop gos gov net org web ',\n 'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ',\n 'pr':' ac biz com edu est gov info isla name net org pro prof ',\n 'ps':' com edu gov net org plo sec ',\n 'pw':' belau co ed go ne or ',\n 'ro':' arts com firm info nom nt org rec store tm www ',\n 'rs':' ac co edu gov in org ',\n 'sb':' com edu gov net org ',\n 'sc':' com edu gov net org ',\n 'sh':' co com edu gov net nom org ',\n 'sl':' com edu gov net org ',\n 'st':' co com consulado edu embaixada gov mil net org principe saotome store ',\n 'sv':' com edu gob org red ',\n 'sz':' ac co org ',\n 'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ',\n 'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ',\n 'tw':' club com ebiz edu game gov idv mil net org ',\n 'mu':' ac co com gov net or org ',\n 'mz':' ac co edu gov org ',\n 'na':' co com ',\n 'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ',\n 'pa':' abo ac com edu gob ing med net nom org sld ',\n 'pt':' com edu gov int net nome org publ ',\n 'py':' com edu gov mil net org ',\n 'qa':' com edu gov mil net org ',\n 're':' asso com nom ',\n 'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ',\n 'rw':' ac co com edu gouv gov int mil net ',\n 'sa':' com edu gov med net org pub sch ',\n 'sd':' com edu gov info med net org tv ',\n 'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ',\n 'sg':' com edu gov idn net org per ',\n 'sn':' art com edu gouv org perso univ ',\n 'sy':' com edu gov mil net news org ',\n 'th':' ac co go in mi net or ',\n 'tj':' ac biz co com edu go gov info int mil name net nic org test web ',\n 'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ',\n 'tz':' ac co go ne or ',\n 'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ',\n 'ug':' ac co go ne or org sc ',\n 'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ',\n 'us':' dni fed isa kids nsn ',\n 'uy':' com edu gub mil net org ',\n 've':' co com edu gob info mil net org web ',\n 'vi':' co com k12 net org ',\n 'vn':' ac biz com edu gov health info int name net org pro ',\n 'ye':' co com gov ltd me net org plc ',\n 'yu':' ac co edu gov org ',\n 'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ',\n 'zm':' ac co com edu gov net org sch '\n },\n // gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost\n // in both performance and memory footprint. No initialization required.\n // http://jsperf.com/uri-js-sld-regex-vs-binary-search/4\n // Following methods use lastIndexOf() rather than array.split() in order\n // to avoid any memory allocations.\n has: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return false;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {\n return false;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return false;\n }\n return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0;\n },\n is: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return false;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset >= 0) {\n return false;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return false;\n }\n return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0;\n },\n get: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return null;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {\n return null;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return null;\n }\n if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) {\n return null;\n }\n return domain.slice(sldOffset+1);\n },\n noConflict: function(){\n if (root.SecondLevelDomains === this) {\n root.SecondLevelDomains = _SecondLevelDomains;\n }\n return this;\n }\n };\n\n return SLD;\n}));\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/urijs/src/SecondLevelDomains.js\n ** module id = 10\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar base64 = require('base64-js');\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\tvar uri = {\n\t\t\t\tprotocol : '',\n\t\t\t\thost : '',\n\t\t\t\tpath : '',\n\t\t\t\torigin : '',\n\t\t\t\tdirectory : '',\n\t\t\t\tbase : '',\n\t\t\t\tfilename : '',\n\t\t\t\textension : '',\n\t\t\t\tfragment : '',\n\t\t\t\thref : url\n\t\t\t},\n\t\t\tdoubleSlash = url.indexOf('://'),\n\t\t\tsearch = url.indexOf('?'),\n\t\t\tfragment = url.indexOf(\"#\"),\n\t\t\twithoutProtocol,\n\t\t\tdot,\n\t\t\tfirstSlash;\n\n\tif(fragment != -1) {\n\t\turi.fragment = url.slice(fragment + 1);\n\t\turl = url.slice(0, fragment);\n\t}\n\n\tif(search != -1) {\n\t\turi.search = url.slice(search + 1);\n\t\turl = url.slice(0, search);\n\t\thref = url;\n\t}\n\n\tif(doubleSlash != -1) {\n\t\turi.protocol = url.slice(0, doubleSlash);\n\t\twithoutProtocol = url.slice(doubleSlash+3);\n\t\tfirstSlash = withoutProtocol.indexOf('/');\n\n\t\tif(firstSlash === -1) {\n\t\t\turi.host = uri.path;\n\t\t\turi.path = \"\";\n\t\t} else {\n\t\t\turi.host = withoutProtocol.slice(0, firstSlash);\n\t\t\turi.path = withoutProtocol.slice(firstSlash);\n\t\t}\n\n\n\t\turi.origin = uri.protocol + \"://\" + uri.host;\n\n\t\turi.directory = folder(uri.path);\n\n\t\turi.base = uri.origin + uri.directory;\n\t\t// return origin;\n\t} else {\n\t\turi.path = url;\n\t\turi.directory = folder(url);\n\t\turi.base = uri.directory;\n\t}\n\n\t//-- Filename\n\turi.filename = url.replace(uri.base, '');\n\tdot = uri.filename.lastIndexOf('.');\n\tif(dot != -1) {\n\t\turi.extension = uri.filename.slice(dot+1);\n\t}\n\treturn uri;\n};\n\n//-- Parse out the folder, will return everything before the last slash\nfunction folder(url){\n\n\tvar lastSlash = url.lastIndexOf('/');\n\n\tif(lastSlash == -1) var folder = '';\n\n\tfolder = url.slice(0, lastSlash + 1);\n\n\treturn folder;\n\n};\n*/\nfunction isElement(obj) {\n\t\treturn !!(obj && obj.nodeType == 1);\n};\n\n// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\nfunction uuid() {\n\tvar d = new Date().getTime();\n\tvar uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n\t\t\tvar r = (d + Math.random()*16)%16 | 0;\n\t\t\td = Math.floor(d/16);\n\t\t\treturn (c=='x' ? r : (r&0x7|0x8)).toString(16);\n\t});\n\treturn uuid;\n};\n\n// From Lodash\nfunction values(object) {\n\tvar index = -1,\n\t\t\tprops = Object.keys(object),\n\t\t\tlength = props.length,\n\t\t\tresult = Array(length);\n\n\twhile (++index < length) {\n\t\tresult[index] = object[props[index]];\n\t}\n\treturn result;\n};\n\nfunction resolveUrl(base, path) {\n\tvar url = [],\n\t\tsegments = [],\n\t\tbaseUri = uri(base),\n\t\tpathUri = uri(path),\n\t\tbaseDirectory = baseUri.directory,\n\t\tpathDirectory = pathUri.directory,\n\t\tdirectories = [],\n\t\t// folders = base.split(\"/\"),\n\t\tpaths;\n\n\t// if(uri.host) {\n\t// return path;\n\t// }\n\n\tif(baseDirectory[0] === \"/\") {\n\t\tbaseDirectory = baseDirectory.substring(1);\n\t}\n\n\tif(pathDirectory[pathDirectory.length-1] === \"/\") {\n\t\tbaseDirectory = baseDirectory.substring(0, baseDirectory.length-1);\n\t}\n\n\tif(pathDirectory[0] === \"/\") {\n\t\tpathDirectory = pathDirectory.substring(1);\n\t}\n\n\tif(pathDirectory[pathDirectory.length-1] === \"/\") {\n\t\tpathDirectory = pathDirectory.substring(0, pathDirectory.length-1);\n\t}\n\n\tif(baseDirectory) {\n\t\tdirectories = baseDirectory.split(\"/\");\n\t}\n\n\tpaths = pathDirectory.split(\"/\");\n\n\tpaths.reverse().forEach(function(part, index){\n\t\tif(part === \"..\"){\n\t\t\tdirectories.pop();\n\t\t} else if(part === directories[directories.length-1]) {\n\t\t\tdirectories.pop();\n\t\t\tsegments.unshift(part);\n\t\t} else {\n\t\t\tsegments.unshift(part);\n\t\t}\n\t});\n\n\turl = [baseUri.origin];\n\n\tif(directories.length) {\n\t\turl = url.concat(directories);\n\t}\n\n\tif(segments) {\n\t\turl = url.concat(segments);\n\t}\n\n\turl = url.concat(pathUri.filename);\n\n\treturn url.join(\"/\");\n};\n\nfunction documentHeight() {\n\treturn Math.max(\n\t\t\tdocument.documentElement.clientHeight,\n\t\t\tdocument.body.scrollHeight,\n\t\t\tdocument.documentElement.scrollHeight,\n\t\t\tdocument.body.offsetHeight,\n\t\t\tdocument.documentElement.offsetHeight\n\t);\n};\n\nfunction isNumber(n) {\n\treturn !isNaN(parseFloat(n)) && isFinite(n);\n};\n\nfunction prefixed(unprefixed) {\n\tvar vendors = [\"Webkit\", \"Moz\", \"O\", \"ms\" ],\n\t\tprefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],\n\t\tupper = unprefixed[0].toUpperCase() + unprefixed.slice(1),\n\t\tlength = vendors.length;\n\n\tif (typeof(document) === 'undefined' || typeof(document.body.style[unprefixed]) != 'undefined') {\n\t\treturn unprefixed;\n\t}\n\n\tfor ( var i=0; i < length; i++ ) {\n\t\tif (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {\n\t\t\treturn vendors[i] + upper;\n\t\t}\n\t}\n\n\treturn unprefixed;\n};\n\nfunction defaults(obj) {\n\tfor (var i = 1, length = arguments.length; i < length; i++) {\n\t\tvar source = arguments[i];\n\t\tfor (var prop in source) {\n\t\t\tif (obj[prop] === void 0) obj[prop] = source[prop];\n\t\t}\n\t}\n\treturn obj;\n};\n\nfunction extend(target) {\n\t\tvar sources = [].slice.call(arguments, 1);\n\t\tsources.forEach(function (source) {\n\t\t\tif(!source) return;\n\t\t\tObject.getOwnPropertyNames(source).forEach(function(propName) {\n\t\t\t\tObject.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));\n\t\t\t});\n\t\t});\n\t\treturn 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\tvar location = locationOf(item, array, compareFunction);\n\tarray.splice(location, 0, item);\n\n\treturn location;\n};\n// Returns where something would fit in\nfunction locationOf(item, array, compareFunction, _start, _end) {\n\tvar start = _start || 0;\n\tvar end = _end || array.length;\n\tvar pivot = parseInt(start + (end - start) / 2);\n\tvar compared;\n\tif(!compareFunction){\n\t\tcompareFunction = function(a, b) {\n\t\t\tif(a > b) return 1;\n\t\t\tif(a < b) return -1;\n\t\t\tif(a = b) return 0;\n\t\t};\n\t}\n\tif(end-start <= 0) {\n\t\treturn pivot;\n\t}\n\n\tcompared = compareFunction(array[pivot], item);\n\tif(end-start === 1) {\n\t\treturn compared > 0 ? pivot : pivot + 1;\n\t}\n\n\tif(compared === 0) {\n\t\treturn pivot;\n\t}\n\tif(compared === -1) {\n\t\treturn locationOf(item, array, compareFunction, pivot, end);\n\t} else{\n\t\treturn locationOf(item, array, compareFunction, start, pivot);\n\t}\n};\n// Returns -1 of mpt found\nfunction indexOfSorted(item, array, compareFunction, _start, _end) {\n\tvar start = _start || 0;\n\tvar end = _end || array.length;\n\tvar pivot = parseInt(start + (end - start) / 2);\n\tvar compared;\n\tif(!compareFunction){\n\t\tcompareFunction = function(a, b) {\n\t\t\tif(a > b) return 1;\n\t\t\tif(a < b) return -1;\n\t\t\tif(a = b) return 0;\n\t\t};\n\t}\n\tif(end-start <= 0) {\n\t\treturn -1; // Not found\n\t}\n\n\tcompared = compareFunction(array[pivot], item);\n\tif(end-start === 1) {\n\t\treturn compared === 0 ? pivot : -1;\n\t}\n\tif(compared === 0) {\n\t\treturn pivot; // Found\n\t}\n\tif(compared === -1) {\n\t\treturn indexOfSorted(item, array, compareFunction, pivot, end);\n\t} else{\n\t\treturn indexOfSorted(item, array, compareFunction, start, pivot);\n\t}\n};\n\nfunction bounds(el) {\n\n\tvar style = window.getComputedStyle(el);\n\tvar widthProps = [\"width\", \"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n\tvar heightProps = [\"height\", \"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n\tvar width = 0;\n\tvar height = 0;\n\n\twidthProps.forEach(function(prop){\n\t\twidth += parseFloat(style[prop]) || 0;\n\t});\n\n\theightProps.forEach(function(prop){\n\t\theight += parseFloat(style[prop]) || 0;\n\t});\n\n\treturn {\n\t\theight: height,\n\t\twidth: width\n\t};\n\n};\n\nfunction borders(el) {\n\n\tvar style = window.getComputedStyle(el);\n\tvar widthProps = [\"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n\tvar heightProps = [\"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n\tvar width = 0;\n\tvar height = 0;\n\n\twidthProps.forEach(function(prop){\n\t\twidth += parseFloat(style[prop]) || 0;\n\t});\n\n\theightProps.forEach(function(prop){\n\t\theight += parseFloat(style[prop]) || 0;\n\t});\n\n\treturn {\n\t\theight: height,\n\t\twidth: width\n\t};\n\n};\n\nfunction windowBounds() {\n\n\tvar width = window.innerWidth;\n\tvar height = window.innerHeight;\n\n\treturn {\n\t\ttop: 0,\n\t\tleft: 0,\n\t\tright: width,\n\t\tbottom: height,\n\t\twidth: width,\n\t\theight: height\n\t};\n\n};\n\n//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496\nfunction cleanStringForXpath(str) {\n\t\tvar parts = str.match(/[^'\"]+|['\"]/g);\n\t\tparts = parts.map(function(part){\n\t\t\t\tif (part === \"'\") {\n\t\t\t\t\t\treturn '\\\"\\'\\\"'; // output \"'\"\n\t\t\t\t}\n\n\t\t\t\tif (part === '\"') {\n\t\t\t\t\t\treturn \"\\'\\\"\\'\"; // output '\"'\n\t\t\t\t}\n\t\t\t\treturn \"\\'\" + part + \"\\'\";\n\t\t});\n\t\treturn \"concat(\\'\\',\" + parts.join(\",\") + \")\";\n};\n\nfunction indexOfTextNode(textNode){\n\tvar parent = textNode.parentNode;\n\tvar children = parent.childNodes;\n\tvar sib;\n\tvar index = -1;\n\tfor (var i = 0; i < children.length; i++) {\n\t\tsib = children[i];\n\t\tif(sib.nodeType === Node.TEXT_NODE){\n\t\t\tindex++;\n\t\t}\n\t\tif(sib == textNode) break;\n\t}\n\n\treturn index;\n};\n\nfunction isXml(ext) {\n\treturn ['xml', 'opf', 'ncx'].indexOf(ext) > -1;\n}\n\nfunction createBlob(content, mime){\n\tvar blob = new Blob([content], {type : mime });\n\n\treturn blob;\n};\n\nfunction createBlobUrl(content, mime){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob = this.createBlob(content, mime);\n\n\ttempUrl = _URL.createObjectURL(blob);\n\n\treturn tempUrl;\n};\n\nfunction createBase64Url(content, mime){\n\tvar string;\n\tvar data;\n\tvar datauri;\n\n\tif (typeof(content) !== \"string\") {\n\t\t// Only handles strings\n\t\treturn;\n\t}\n\n\tdata = btoa(content);\n\n\tdatauri = \"data:\" + mime + \";base64,\" + data;\n\n\treturn datauri;\n};\n\nfunction type(obj){\n\treturn Object.prototype.toString.call(obj).slice(8, -1);\n}\n\nfunction parse(markup, mime) {\n\tvar doc;\n\t// console.log(\"parse\", markup);\n\n\tif (typeof DOMParser === \"undefined\") {\n\t\tDOMParser = require('xmldom').DOMParser;\n\t}\n\n\n\tdoc = new DOMParser().parseFromString(markup, mime);\n\n\treturn doc;\n}\n\nfunction qs(el, sel) {\n\tvar elements;\n\n\tif (typeof el.querySelector != \"undefined\") {\n\t\treturn el.querySelector(sel);\n\t} else {\n\t\telements = el.getElementsByTagName(sel);\n\t\tif (elements.length) {\n\t\t\treturn elements[0];\n\t\t}\n\t}\n}\n\nfunction qsa(el, sel) {\n\n\tif (typeof el.querySelector != \"undefined\") {\n\t\treturn el.querySelectorAll(sel);\n\t} else {\n\t\treturn el.getElementsByTagName(sel);\n\t}\n}\n\nfunction qsp(el, sel, props) {\n\tvar q, filtered;\n\tif (typeof el.querySelector != \"undefined\") {\n\t\tsel += '[';\n\t\tfor (var prop in props) {\n\t\t\tsel += prop + \"='\" + props[prop] + \"'\";\n\t\t}\n\t\tsel += ']';\n\t\treturn el.querySelector(sel);\n\t} else {\n\t\tq = el.getElementsByTagName(sel);\n\t\tfiltered = Array.prototype.slice.call(q, 0).filter(function(el) {\n\t\t\tfor (var prop in props) {\n\t\t\t\tif(el.getAttribute(prop) === props[prop]){\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\n\t\tif (filtered) {\n\t\t\treturn filtered[0];\n\t\t}\n\t}\n}\n\nfunction blob2base64(blob, cb) {\n\tvar reader = new FileReader();\n\treader.readAsDataURL(blob);\n\treader.onloadend = function() {\n\t\tcb(reader.result);\n\t}\n}\n\nmodule.exports = {\n\t// 'uri': uri,\n\t// 'folder': folder,\n\t'isElement': isElement,\n\t'uuid': uuid,\n\t'values': values,\n\t'resolveUrl': resolveUrl,\n\t'indexOfSorted': indexOfSorted,\n\t'documentHeight': documentHeight,\n\t'isNumber': isNumber,\n\t'prefixed': prefixed,\n\t'defaults': defaults,\n\t'extend': extend,\n\t'insert': insert,\n\t'locationOf': locationOf,\n\t'indexOfSorted': indexOfSorted,\n\t'requestAnimationFrame': requestAnimationFrame,\n\t'bounds': bounds,\n\t'borders': borders,\n\t'windowBounds': windowBounds,\n\t'cleanStringForXpath': cleanStringForXpath,\n\t'indexOfTextNode': indexOfTextNode,\n\t'isXml': isXml,\n\t'createBlob': createBlob,\n\t'createBlobUrl': createBlobUrl,\n\t'type': type,\n\t'parse' : parse,\n\t'qs' : qs,\n\t'qsa' : qsa,\n\t'qsp' : qsp,\n\t'blob2base64' : blob2base64,\n\t'createBase64Url': createBase64Url\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/core.js\n ** module id = 11\n ** module chunks = 0\n **/","'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction placeHoldersCount (b64) {\n var len = b64.length\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // the number of equal signs (place holders)\n // if there are two placeholders, than the two characters before it\n // represent one byte\n // if there is only one, then the three characters before it represent 2 bytes\n // this is just a cheap hack to not do indexOf twice\n return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0\n}\n\nfunction byteLength (b64) {\n // base64 is 4/3 + up to two characters of the original data\n return b64.length * 3 / 4 - placeHoldersCount(b64)\n}\n\nfunction toByteArray (b64) {\n var i, j, l, tmp, placeHolders, arr\n var len = b64.length\n placeHolders = placeHoldersCount(b64)\n\n arr = new Arr(len * 3 / 4 - placeHolders)\n\n // if there are placeholders, only get up to the last complete 4 chars\n l = placeHolders > 0 ? len - 4 : len\n\n var L = 0\n\n for (i = 0, j = 0; i < l; i += 4, j += 3) {\n tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]\n arr[L++] = (tmp >> 16) & 0xFF\n arr[L++] = (tmp >> 8) & 0xFF\n arr[L++] = tmp & 0xFF\n }\n\n if (placeHolders === 2) {\n tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[L++] = tmp & 0xFF\n } else if (placeHolders === 1) {\n tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[L++] = (tmp >> 8) & 0xFF\n arr[L++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var output = ''\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n output += lookup[tmp >> 2]\n output += lookup[(tmp << 4) & 0x3F]\n output += '=='\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + (uint8[len - 1])\n output += lookup[tmp >> 10]\n output += lookup[(tmp >> 4) & 0x3F]\n output += lookup[(tmp << 2) & 0x3F]\n output += '='\n }\n\n parts.push(output)\n\n return parts.join('')\n}\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/base64-js/index.js\n ** module id = 12\n ** module chunks = 0\n **/","module.exports = __WEBPACK_EXTERNAL_MODULE_13__;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** external \"xmldom\"\n ** module id = 13\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\nvar Section = require('./section');\nvar replacements = require('./replacements');\n\nfunction Spine(_request){\n\tthis.request = _request;\n\tthis.spineItems = [];\n\tthis.spineByHref = {};\n\tthis.spineById = {};\n\n\tthis.hooks = {};\n\tthis.hooks.serialize = new Hook();\n\tthis.hooks.content = new Hook();\n\n\t// Register replacements\n\tthis.hooks.content.register(replacements.base);\n\tthis.hooks.content.register(replacements.canonical);\n\n\tthis.epubcfi = new EpubCFI();\n\n\tthis.loaded = false;\n};\n\nSpine.prototype.load = function(_package) {\n\n\tthis.items = _package.spine;\n\tthis.manifest = _package.manifest;\n\tthis.spineNodeIndex = _package.spineNodeIndex;\n\tthis.baseUrl = _package.baseUrl || '';\n\tthis.length = this.items.length;\n\n\tthis.items.forEach(function(item, index){\n\t\tvar href, url;\n\t\tvar manifestItem = this.manifest[item.idref];\n\t\tvar spineItem;\n\n\t\titem.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);\n\n\t\tif(manifestItem) {\n\t\t\titem.href = manifestItem.href;\n\t\t\titem.url = this.baseUrl + item.href;\n\n\t\t\tif(manifestItem.properties.length){\n\t\t\t\titem.properties.push.apply(item.properties, manifestItem.properties);\n\t\t\t}\n\t\t}\n\n\t\t// if(index > 0) {\n\t\t\titem.prev = function(){ return this.get(index-1); }.bind(this);\n\t\t// }\n\n\t\t// if(index+1 < this.items.length) {\n\t\t\titem.next = function(){ return this.get(index+1); }.bind(this);\n\t\t// }\n\n\t\tspineItem = new Section(item, this.hooks);\n\n\t\tthis.append(spineItem);\n\n\n\t}.bind(this));\n\n\tthis.loaded = true;\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\tvar index = 0;\n\n\tif(this.epubcfi.isCfiString(target)) {\n\t\tcfi = new EpubCFI(target);\n\t\tindex = cfi.spinePos;\n\t} else if(target && (typeof target === \"number\" || isNaN(target) === false)){\n\t\tindex = target;\n\t} else if(target && target.indexOf(\"#\") === 0) {\n\t\tindex = this.spineById[target.substring(1)];\n\t} else if(target) {\n\t\t// Remove fragments\n\t\ttarget = target.split(\"#\")[0];\n\t\tindex = this.spineByHref[target];\n\t}\n\n\treturn this.spineItems[index] || null;\n};\n\nSpine.prototype.append = function(section) {\n\tvar index = this.spineItems.length;\n\tsection.index = index;\n\n\tthis.spineItems.push(section);\n\n\tthis.spineByHref[section.href] = index;\n\tthis.spineById[section.idref] = index;\n\n\treturn index;\n};\n\nSpine.prototype.prepend = function(section) {\n\tvar index = this.spineItems.unshift(section);\n\tthis.spineByHref[section.href] = 0;\n\tthis.spineById[section.idref] = 0;\n\n\t// Re-index\n\tthis.spineItems.forEach(function(item, index){\n\t\titem.index = index;\n\t});\n\n\treturn 0;\n};\n\nSpine.prototype.insert = function(section, index) {\n\n};\n\nSpine.prototype.remove = function(section) {\n\tvar index = this.spineItems.indexOf(section);\n\n\tif(index > -1) {\n\t\tdelete this.spineByHref[section.href];\n\t\tdelete this.spineById[section.idref];\n\n\t\treturn this.spineItems.splice(index, 1);\n\t}\n};\n\nSpine.prototype.each = function() {\n\treturn this.spineItems.forEach.apply(this.spineItems, arguments);\n};\n\nmodule.exports = Spine;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/spine.js\n ** module id = 14\n ** module chunks = 0\n **/","var URI = require('urijs');\nvar core = require('./core');\n\n/**\n\tEPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html\n\n\tImplements:\n\t- Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)\n\t- Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)\n\n\tDoes Not Implement:\n\t- Temporal Offset (~)\n\t- Spatial Offset (@)\n\t- Temporal-Spatial Offset (~ + @)\n\t- Text Location Assertion ([)\n*/\n\nfunction EpubCFI(cfiFrom, base, ignoreClass){\n\tvar type;\n\n\tthis.str = '';\n\n\tthis.base = {};\n\tthis.spinePos = 0; // For compatibility\n\n\tthis.range = false; // true || false;\n\n\tthis.path = {};\n\tthis.start = null;\n\tthis.end = null;\n\n\t// Allow instantiation without the 'new' keyword\n\tif (!(this instanceof EpubCFI)) {\n\t\treturn new EpubCFI(cfiFrom, base, ignoreClass);\n\t}\n\n\tif(typeof base === 'string') {\n\t\tthis.base = this.parseComponent(base);\n\t} else if(typeof base === 'object' && base.steps) {\n\t\tthis.base = base;\n\t}\n\n\ttype = this.checkType(cfiFrom);\n\n\n\tif(type === 'string') {\n\t\tthis.str = cfiFrom;\n\t\treturn core.extend(this, this.parse(cfiFrom));\n\t} else if (type === 'range') {\n\t\treturn core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));\n\t} else if (type === 'node') {\n\t\treturn core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));\n\t} else if (type === 'EpubCFI' && cfiFrom.path) {\n\t\treturn cfiFrom;\n\t} else if (!cfiFrom) {\n\t\treturn this;\n\t} else {\n\t\tthrow new TypeError('not a valid argument for EpubCFI');\n\t}\n\n};\n\nEpubCFI.prototype.checkType = function(cfi) {\n\n\tif (this.isCfiString(cfi)) {\n\t\treturn 'string';\n\t// Is a range object\n\t} else if (typeof cfi === 'object' && core.type(cfi) === \"Range\"){\n\t\treturn 'range';\n\t} else if (typeof cfi === 'object' && typeof(cfi.nodeType) != \"undefined\" ){ // || typeof cfi === 'function'\n\t\treturn 'node';\n\t} else if (typeof cfi === 'object' && cfi instanceof EpubCFI){\n\t\treturn 'EpubCFI';\n\t} else {\n\t\treturn false;\n\t}\n};\n\nEpubCFI.prototype.parse = function(cfiStr) {\n\tvar cfi = {\n\t\t\tspinePos: -1,\n\t\t\trange: false,\n\t\t\tbase: {},\n\t\t\tpath: {},\n\t\t\tstart: null,\n\t\t\tend: null\n\t\t};\n\tvar baseComponent, pathComponent, range;\n\n\tif(typeof cfiStr !== \"string\") {\n\t\treturn {spinePos: -1};\n\t}\n\n\tif(cfiStr.indexOf(\"epubcfi(\") === 0 && cfiStr[cfiStr.length-1] === \")\") {\n\t\t// Remove intial epubcfi( and ending )\n\t\tcfiStr = cfiStr.slice(8, cfiStr.length-1);\n\t}\n\n\tbaseComponent = this.getChapterComponent(cfiStr);\n\n\t// Make sure this is a valid cfi or return\n\tif(!baseComponent) {\n\t\treturn {spinePos: -1};\n\t}\n\n\tcfi.base = this.parseComponent(baseComponent);\n\n\tpathComponent = this.getPathComponent(cfiStr);\n\tcfi.path = this.parseComponent(pathComponent);\n\n\trange = this.getRange(cfiStr);\n\n\tif(range) {\n\t\tcfi.range = true;\n\t\tcfi.start = this.parseComponent(range[0]);\n\t\tcfi.end = this.parseComponent(range[1]);\n\t}\n\n\t// Get spine node position\n\t// cfi.spineSegment = cfi.base.steps[1];\n\n\t// Chapter segment is always the second step\n\tcfi.spinePos = cfi.base.steps[1].index;\n\n\treturn cfi;\n};\n\nEpubCFI.prototype.parseComponent = function(componentStr){\n\tvar component = {\n\t\tsteps: [],\n\t\tterminal: {\n\t\t\toffset: null,\n\t\t\tassertion: null\n\t\t}\n\t};\n\tvar parts = componentStr.split(':');\n\tvar steps = parts[0].split('/');\n\tvar terminal;\n\n\tif(parts.length > 1) {\n\t\tterminal = parts[1];\n\t\tcomponent.terminal = this.parseTerminal(terminal);\n\t}\n\n\tif (steps[0] === '') {\n\t\tsteps.shift(); // Ignore the first slash\n\t}\n\n\tcomponent.steps = steps.map(function(step){\n\t\treturn this.parseStep(step);\n\t}.bind(this));\n\n\treturn component;\n};\n\nEpubCFI.prototype.parseStep = function(stepStr){\n\tvar type, num, index, has_brackets, id;\n\n\thas_brackets = stepStr.match(/\\[(.*)\\]/);\n\tif(has_brackets && has_brackets[1]){\n\t\tid = has_brackets[1];\n\t}\n\n\t//-- Check if step is a text node or element\n\tnum = parseInt(stepStr);\n\n\tif(isNaN(num)) {\n\t\treturn;\n\t}\n\n\tif(num % 2 === 0) { // Even = is an element\n\t\ttype = \"element\";\n\t\tindex = num / 2 - 1;\n\t} else {\n\t\ttype = \"text\";\n\t\tindex = (num - 1 ) / 2;\n\t}\n\n\treturn {\n\t\t\"type\" : type,\n\t\t'index' : index,\n\t\t'id' : id || null\n\t};\n};\n\nEpubCFI.prototype.parseTerminal = function(termialStr){\n\tvar characterOffset, textLocationAssertion;\n\tvar assertion = termialStr.match(/\\[(.*)\\]/);\n\n\tif(assertion && assertion[1]){\n\t\tcharacterOffset = parseInt(termialStr.split('[')[0]) || null;\n\t\ttextLocationAssertion = assertion[1];\n\t} else {\n\t\tcharacterOffset = parseInt(termialStr) || null;\n\t}\n\n\treturn {\n\t\t'offset': characterOffset,\n\t\t'assertion': textLocationAssertion\n\t};\n\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n\tvar indirection = cfiStr.split(\"!\");\n\n\treturn indirection[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n\tvar indirection = cfiStr.split(\"!\");\n\n\tif(indirection[1]) {\n\t\tranges = indirection[1].split(',');\n\t\treturn ranges[0];\n\t}\n\n};\n\nEpubCFI.prototype.getRange = function(cfiStr) {\n\n\tvar ranges = cfiStr.split(\",\");\n\n\tif(ranges.length === 3){\n\t\treturn [\n\t\t\tranges[1],\n\t\t\tranges[2]\n\t\t];\n\t}\n\n\treturn false;\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n\tvar splitStr = cfiStr.split(\":\");\n\treturn splitStr[1] || '';\n};\n\nEpubCFI.prototype.joinSteps = function(steps) {\n\tif(!steps) {\n\t\treturn \"\";\n\t}\n\n\treturn steps.map(function(part){\n\t\tvar segment = '';\n\n\t\tif(part.type === 'element') {\n\t\t\tsegment += (part.index + 1) * 2;\n\t\t}\n\n\t\tif(part.type === 'text') {\n\t\t\tsegment += 1 + (2 * part.index); // TODO: double check that this is odd\n\t\t}\n\n\t\tif(part.id) {\n\t\t\tsegment += \"[\" + part.id + \"]\";\n\t\t}\n\n\t\treturn segment;\n\n\t}).join('/');\n\n};\n\nEpubCFI.prototype.segmentString = function(segment) {\n\tvar segmentString = '/';\n\n\tsegmentString += this.joinSteps(segment.steps);\n\n\tif(segment.terminal && segment.terminal.offset != null){\n\t\tsegmentString += ':' + segment.terminal.offset;\n\t}\n\n\tif(segment.terminal && segment.terminal.assertion != null){\n\t\tsegmentString += '[' + segment.terminal.assertion + ']';\n\t}\n\n\treturn segmentString;\n};\n\nEpubCFI.prototype.toString = function() {\n\tvar cfiString = 'epubcfi(';\n\n\tcfiString += this.segmentString(this.base);\n\n\tcfiString += '!';\n\tcfiString += this.segmentString(this.path);\n\n\t// Add Range, if present\n\tif(this.start) {\n\t\tcfiString += ',';\n\t\tcfiString += this.segmentString(this.start);\n\t}\n\n\tif(this.end) {\n\t\tcfiString += ',';\n\t\tcfiString += this.segmentString(this.end);\n\t}\n\n\tcfiString += \")\";\n\n\treturn cfiString;\n};\n\nEpubCFI.prototype.compare = function(cfiOne, cfiTwo) {\n\tif(typeof cfiOne === 'string') {\n\t\tcfiOne = new EpubCFI(cfiOne);\n\t}\n\tif(typeof cfiTwo === 'string') {\n\t\tcfiTwo = new EpubCFI(cfiTwo);\n\t}\n\t// Compare Spine Positions\n\tif(cfiOne.spinePos > cfiTwo.spinePos) {\n\t\treturn 1;\n\t}\n\tif(cfiOne.spinePos < cfiTwo.spinePos) {\n\t\treturn -1;\n\t}\n\n\n\t// Compare Each Step in the First item\n\tfor (var i = 0; i < cfiOne.path.steps.length; i++) {\n\t\tif(!cfiTwo.path.steps[i]) {\n\t\t\treturn 1;\n\t\t}\n\t\tif(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {\n\t\t\treturn 1;\n\t\t}\n\t\tif(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {\n\t\t\treturn -1;\n\t\t}\n\t\t// Otherwise continue checking\n\t}\n\n\t// All steps in First equal to Second and First is Less Specific\n\tif(cfiOne.path.steps.length < cfiTwo.path.steps.length) {\n\t\treturn 1;\n\t}\n\n\t// Compare the charecter offset of the text node\n\tif(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {\n\t\treturn 1;\n\t}\n\tif(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {\n\t\treturn -1;\n\t}\n\n\t// TODO: compare ranges\n\n\t// CFI's are equal\n\treturn 0;\n};\n\nEpubCFI.prototype.step = function(node) {\n\tvar nodeType = (node.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n\treturn {\n\t\t'id' : node.id,\n\t\t'tagName' : node.tagName,\n\t\t'type' : nodeType,\n\t\t'index' : this.position(node)\n\t};\n};\n\nEpubCFI.prototype.filteredStep = function(node, ignoreClass) {\n\tvar filteredNode = this.filter(node, ignoreClass);\n\tvar nodeType;\n\n\t// Node filtered, so ignore\n\tif (!filteredNode) {\n\t\treturn;\n\t}\n\n\t// Otherwise add the filter node in\n\tnodeType = (filteredNode.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n\treturn {\n\t\t'id' : filteredNode.id,\n\t\t'tagName' : filteredNode.tagName,\n\t\t'type' : nodeType,\n\t\t'index' : this.filteredPosition(filteredNode, ignoreClass)\n\t};\n};\n\nEpubCFI.prototype.pathTo = function(node, offset, ignoreClass) {\n\tvar segment = {\n\t\tsteps: [],\n\t\tterminal: {\n\t\t\toffset: null,\n\t\t\tassertion: null\n\t\t}\n\t};\n\tvar currentNode = node;\n\tvar step;\n\n\twhile(currentNode && currentNode.parentNode &&\n\t\t\t\tcurrentNode.parentNode.nodeType != Node.DOCUMENT_NODE) {\n\n\t\tif (ignoreClass) {\n\t\t\tstep = this.filteredStep(currentNode, ignoreClass);\n\t\t} else {\n\t\t\tstep = this.step(currentNode);\n\t\t}\n\n\t\tif (step) {\n\t\t\tsegment.steps.unshift(step);\n\t\t}\n\n\t\tcurrentNode = currentNode.parentNode;\n\n\t}\n\n\tif (offset != null && offset >= 0) {\n\n\t\tsegment.terminal.offset = offset;\n\n\t\t// Make sure we are getting to a textNode if there is an offset\n\t\tif(segment.steps[segment.steps.length-1].type != \"text\") {\n\t\t\tsegment.steps.push({\n\t\t\t\t'type' : \"text\",\n\t\t\t\t'index' : 0\n\t\t\t});\n\t\t}\n\n\t}\n\n\n\treturn segment;\n}\n\nEpubCFI.prototype.equalStep = function(stepA, stepB) {\n\tif (!stepA || !stepB) {\n\t\treturn false;\n\t}\n\n\tif(stepA.index === stepB.index &&\n\t\t stepA.id === stepB.id &&\n\t\t stepA.type === stepB.type) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\nEpubCFI.prototype.fromRange = function(range, base, ignoreClass) {\n\tvar cfi = {\n\t\t\trange: false,\n\t\t\tbase: {},\n\t\t\tpath: {},\n\t\t\tstart: null,\n\t\t\tend: null\n\t\t};\n\n\tvar start = range.startContainer;\n\tvar end = range.endContainer;\n\n\tvar startOffset = range.startOffset;\n\tvar endOffset = range.endOffset;\n\n\tvar needsIgnoring = false;\n\n\tif (ignoreClass) {\n\t\t// Tell pathTo if / what to ignore\n\t\tneedsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null);\n\t}\n\n\n\tif (typeof base === 'string') {\n\t\tcfi.base = this.parseComponent(base);\n\t\tcfi.spinePos = cfi.base.steps[1].index;\n\t} else if (typeof base === 'object') {\n\t\tcfi.base = base;\n\t}\n\n\tif (range.collapsed) {\n\t\tif (needsIgnoring) {\n\t\t\tstartOffset = this.patchOffset(start, startOffset, ignoreClass);\n\t\t}\n\t\tcfi.path = this.pathTo(start, startOffset, ignoreClass);\n\t} else {\n\t\tcfi.range = true;\n\n\t\tif (needsIgnoring) {\n\t\t\tstartOffset = this.patchOffset(start, startOffset, ignoreClass);\n\t\t}\n\n\t\tcfi.start = this.pathTo(start, startOffset, ignoreClass);\n\n\t\tif (needsIgnoring) {\n\t\t\tendOffset = this.patchOffset(end, endOffset, ignoreClass);\n\t\t}\n\n\t\tcfi.end = this.pathTo(end, endOffset, ignoreClass);\n\n\t\t// Create a new empty path\n\t\tcfi.path = {\n\t\t\tsteps: [],\n\t\t\tterminal: null\n\t\t};\n\n\t\t// Push steps that are shared between start and end to the common path\n\t\tvar len = cfi.start.steps.length;\n\t\tvar i;\n\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tif (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {\n\t\t\t\tif(i == len-1) {\n\t\t\t\t\t// Last step is equal, check terminals\n\t\t\t\t\tif(cfi.start.terminal === cfi.end.terminal) {\n\t\t\t\t\t\t// CFI's are equal\n\t\t\t\t\t\tcfi.path.steps.push(cfi.start.steps[i]);\n\t\t\t\t\t\t// Not a range\n\t\t\t\t\t\tcfi.range = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcfi.path.steps.push(cfi.start.steps[i]);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t};\n\n\t\tcfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);\n\t\tcfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length);\n\n\t\t// TODO: Add Sanity check to make sure that the end if greater than the start\n\t}\n\n\treturn cfi;\n}\n\nEpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) {\n\tvar cfi = {\n\t\t\trange: false,\n\t\t\tbase: {},\n\t\t\tpath: {},\n\t\t\tstart: null,\n\t\t\tend: null\n\t\t};\n\n\tvar needsIgnoring = false;\n\n\tif (ignoreClass) {\n\t\t// Tell pathTo if / what to ignore\n\t\tneedsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null);\n\t}\n\n\tif (typeof base === 'string') {\n\t\tcfi.base = this.parseComponent(base);\n\t\tcfi.spinePos = cfi.base.steps[1].index;\n\t} else if (typeof base === 'object') {\n\t\tcfi.base = base;\n\t}\n\n\tcfi.path = this.pathTo(anchor, null, ignoreClass);\n\n\treturn cfi;\n};\n\n\nEpubCFI.prototype.filter = function(anchor, ignoreClass) {\n\tvar needsIgnoring;\n\tvar sibling; // to join with\n\tvar parent, prevSibling, nextSibling;\n\tvar isText = false;\n\n\tif (anchor.nodeType === Node.TEXT_NODE) {\n\t\tisText = true;\n\t\tparent = anchor.parentNode;\n\t\tneedsIgnoring = anchor.parentNode.classList.contains(ignoreClass);\n\t} else {\n\t\tisText = false;\n\t\tneedsIgnoring = anchor.classList.contains(ignoreClass);\n\t}\n\n\tif (needsIgnoring && isText) {\n\t\tpreviousSibling = parent.previousSibling;\n\t\tnextSibling = parent.nextSibling;\n\n\t\t// If the sibling is a text node, join the nodes\n\t\tif (previousSibling && previousSibling.nodeType === Node.TEXT_NODE) {\n\t\t\tsibling = previousSibling;\n\t\t} else if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n\t\t\tsibling = nextSibling;\n\t\t}\n\n\t\tif (sibling) {\n\t\t\treturn sibling;\n\t\t} else {\n\t\t\t// Parent will be ignored on next step\n\t\t\treturn anchor;\n\t\t}\n\n\t} else if (needsIgnoring && !isText) {\n\t\t// Otherwise just skip the element node\n\t\treturn false;\n\t} else {\n\t\t// No need to filter\n\t\treturn anchor;\n\t}\n\n};\n\nEpubCFI.prototype.patchOffset = function(anchor, offset, ignoreClass) {\n\tvar needsIgnoring;\n\tvar sibling;\n\n\tif (anchor.nodeType != Node.TEXT_NODE) {\n\t\tconsole.error(\"Anchor must be a text node\");\n\t\treturn;\n\t}\n\n\tvar curr = anchor;\n\tvar totalOffset = offset;\n\n\t// If the parent is a ignored node, get offset from it's start\n\tif (anchor.parentNode.classList.contains(ignoreClass)) {\n\t\tcurr = anchor.parentNode;\n\t}\n\n\twhile (curr.previousSibling) {\n\t\tif(curr.previousSibling.nodeType === Node.ELEMENT_NODE) {\n\t\t\t// Originally a text node, so join\n\t\t\tif(curr.previousSibling.classList.contains(ignoreClass)){\n\t\t\t\ttotalOffset += curr.previousSibling.textContent.length;\n\t\t\t} else {\n\t\t\t\tbreak; // Normal node, dont join\n\t\t\t}\n\t\t} else {\n\t\t\t// If the previous sibling is a text node, join the nodes\n\t\t\ttotalOffset += curr.previousSibling.textContent.length;\n\t\t}\n\n\t\tcurr = curr.previousSibling;\n\t}\n\n\treturn totalOffset;\n\n};\n\nEpubCFI.prototype.normalizedMap = function(children, nodeType, ignoreClass) {\n\tvar output = {};\n\tvar prevIndex = -1;\n\tvar i, len = children.length;\n\tvar currNodeType;\n\tvar prevNodeType;\n\n\tfor (i = 0; i < len; i++) {\n\n\t\tcurrNodeType = children[i].nodeType;\n\n\t\t// Check if needs ignoring\n\t\tif (currNodeType === Node.ELEMENT_NODE &&\n\t\t\t\tchildren[i].classList.contains(ignoreClass)) {\n\t\t\tcurrNodeType = Node.TEXT_NODE;\n\t\t}\n\n\t\tif (i > 0 &&\n\t\t\t\tcurrNodeType === Node.TEXT_NODE &&\n\t\t\t\tprevNodeType === Node.TEXT_NODE) {\n\t\t\t// join text nodes\n\t\t\toutput[i] = prevIndex;\n\t\t} else if (nodeType === currNodeType){\n\t\t\tprevIndex = prevIndex + 1;\n\t\t\toutput[i] = prevIndex;\n\t\t}\n\n\t\tprevNodeType = currNodeType;\n\n\t}\n\n\treturn output;\n};\n\nEpubCFI.prototype.position = function(anchor) {\n\tvar children, index, map;\n\n\tif (anchor.nodeType === Node.ELEMENT_NODE) {\n\t\tchildren = anchor.parentNode.children;\n\t\tindex = Array.prototype.indexOf.call(children, anchor);\n\t} else {\n\t\tchildren = this.textNodes(anchor.parentNode);\n\t\tindex = children.indexOf(anchor);\n\t}\n\n\treturn index;\n};\n\nEpubCFI.prototype.filteredPosition = function(anchor, ignoreClass) {\n\tvar children, index, map;\n\n\tif (anchor.nodeType === Node.ELEMENT_NODE) {\n\t\tchildren = anchor.parentNode.children;\n\t\tmap = this.normalizedMap(children, Node.ELEMENT_NODE, ignoreClass);\n\t} else {\n\t\tchildren = anchor.parentNode.childNodes;\n\t\t// Inside an ignored node\n\t\tif(anchor.parentNode.classList.contains(ignoreClass)) {\n\t\t\tanchor = anchor.parentNode;\n\t\t\tchildren = anchor.parentNode.childNodes;\n\t\t}\n\t\tmap = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n\t}\n\n\n\tindex = Array.prototype.indexOf.call(children, anchor);\n\n\treturn map[index];\n};\n\nEpubCFI.prototype.stepsToXpath = function(steps) {\n\tvar xpath = [\".\", \"*\"];\n\n\tsteps.forEach(function(step){\n\t\tvar position = step.index + 1;\n\n\t\tif(step.id){\n\t\t\txpath.push(\"*[position()=\" + position + \" and @id='\" + step.id + \"']\");\n\t\t} else if(step.type === \"text\") {\n\t\t\txpath.push(\"text()[\" + position + \"]\");\n\t\t} else {\n\t\t\txpath.push(\"*[\" + position + \"]\");\n\t\t}\n\t});\n\n\treturn xpath.join(\"/\");\n};\n\n\n/*\n\nTo get the last step if needed:\n\n// Get the terminal step\nlastStep = steps[steps.length-1];\n// Get the query string\nquery = this.stepsToQuery(steps);\n// Find the containing element\nstartContainerParent = doc.querySelector(query);\n// Find the text node within that element\nif(startContainerParent && lastStep.type == \"text\") {\n\tcontainer = startContainerParent.childNodes[lastStep.index];\n}\n*/\nEpubCFI.prototype.stepsToQuerySelector = function(steps) {\n\tvar query = [\"html\"];\n\n\tsteps.forEach(function(step){\n\t\tvar position = step.index + 1;\n\n\t\tif(step.id){\n\t\t\tquery.push(\"#\" + step.id);\n\t\t} else if(step.type === \"text\") {\n\t\t\t// unsupported in querySelector\n\t\t\t// query.push(\"text()[\" + position + \"]\");\n\t\t} else {\n\t\t\tquery.push(\"*:nth-child(\" + position + \")\");\n\t\t}\n\t});\n\n\treturn query.join(\">\");\n\n};\n\nEpubCFI.prototype.textNodes = function(container, ignoreClass) {\n\treturn Array.prototype.slice.call(container.childNodes).\n\t\tfilter(function (node) {\n\t\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\treturn true;\n\t\t\t} else if (ignoreClass && node.classList.contains(ignoreClass)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n};\n\nEpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) {\n\tvar doc = _doc || document;\n\tvar container = doc.documentElement;\n\tvar step;\n\tvar len = steps.length;\n\tvar i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tstep = steps[i];\n\n\t\tif(step.type === \"element\") {\n\t\t\tcontainer = container.children[step.index];\n\t\t} else if(step.type === \"text\"){\n\t\t\tcontainer = this.textNodes(container, ignoreClass)[step.index];\n\t\t}\n\n\t};\n\n\treturn container;\n};\n\nEpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) {\n\tvar doc = _doc || document;\n\tvar container;\n\tvar xpath;\n\n\tif(!ignoreClass && typeof doc.evaluate != 'undefined') {\n\t\txpath = this.stepsToXpath(steps);\n\t\tcontainer = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n\t} else if(ignoreClass) {\n\t\tcontainer = this.walkToNode(steps, doc, ignoreClass);\n\t} else {\n\t\tcontainer = this.walkToNode(steps, doc);\n\t}\n\n\treturn container;\n};\n\nEpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {\n\tvar container = this.findNode(steps.slice(0,-1), _doc, ignoreClass);\n\tvar children = container.childNodes;\n\tvar map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n\tvar i;\n\tvar child;\n\tvar len;\n\tvar childIndex;\n\tvar lastStepIndex = steps[steps.length-1].index;\n\n\tfor (var childIndex in map) {\n\t\tif (!map.hasOwnProperty(childIndex)) return;\n\n\t\tif(map[childIndex] === lastStepIndex) {\n\t\t\tchild = children[childIndex];\n\t\t\tlen = child.textContent.length;\n\t\t\tif(offset > len) {\n\t\t\t\toffset = offset - len;\n\t\t\t} else {\n\t\t\t\tif (child.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\tcontainer = child.childNodes[0];\n\t\t\t\t} else {\n\t\t\t\t\tcontainer = child;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tcontainer: container,\n\t\toffset: offset\n\t};\n\n};\n\nEpubCFI.prototype.toRange = function(_doc, ignoreClass) {\n\tvar doc = _doc || document;\n\tvar range = doc.createRange();\n\tvar start, end, startContainer, endContainer;\n\tvar cfi = this;\n\tvar startSteps, endSteps;\n\tvar needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false;\n\tvar missed;\n\n\tif (cfi.range) {\n\t\tstart = cfi.start;\n\t\tstartSteps = cfi.path.steps.concat(start.steps);\n\t\tstartContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);\n\t\tend = cfi.end;\n\t\tendSteps = cfi.path.steps.concat(end.steps);\n\t\tendContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);\n\t} else {\n\t\tstart = cfi.path;\n\t\tstartSteps = cfi.path.steps;\n\t\tstartContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);\n\t}\n\n\tif(startContainer) {\n\t\ttry {\n\n\t\t\tif(start.terminal.offset != null) {\n\t\t\t\trange.setStart(startContainer, start.terminal.offset);\n\t\t\t} else {\n\t\t\t\trange.setStart(startContainer, 0);\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\tmissed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n\t\t\trange.setStart(missed.container, missed.offset);\n\t\t}\n\t} else {\n\t\t// No start found\n\t\treturn null;\n\t}\n\n\tif (endContainer) {\n\t\ttry {\n\n\t\t\tif(end.terminal.offset != null) {\n\t\t\t\trange.setEnd(endContainer, end.terminal.offset);\n\t\t\t} else {\n\t\t\t\trange.setEnd(endContainer, 0);\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\tmissed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n\t\t\trange.setEnd(missed.container, missed.offset);\n\t\t}\n\t}\n\n\n\t// doc.defaultView.getSelection().addRange(range);\n\treturn range;\n};\n\n// is a cfi string, should be wrapped with \"epubcfi()\"\nEpubCFI.prototype.isCfiString = function(str) {\n\tif(typeof str === 'string' &&\n\t\t\tstr.indexOf(\"epubcfi(\") === 0 &&\n\t\t\tstr[str.length-1] === \")\") {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nEpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {\n\tvar pos = parseInt(_pos),\n\t\tspineNodeIndex = _spineNodeIndex + 1,\n\t\tcfi = '/'+spineNodeIndex+'/';\n\n\tcfi += (pos + 1) * 2;\n\n\tif(id) {\n\t\tcfi += \"[\" + id + \"]\";\n\t}\n\n\treturn cfi;\n};\n\nmodule.exports = EpubCFI;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/epubcfi.js\n ** module id = 15\n ** module chunks = 0\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\tthis.context = context || this;\n\tthis.hooks = [];\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.register = function(){\n\tfor(var i = 0; i < arguments.length; ++i) {\n\t\tif (typeof arguments[i] === \"function\") {\n\t\t\tthis.hooks.push(arguments[i]);\n\t\t} else {\n\t\t\t// unpack array\n\t\t\tfor(var j = 0; j < arguments[i].length; ++j) {\n\t\t\t\tthis.hooks.push(arguments[i][j]);\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Triggers a hook to run all functions\nHook.prototype.trigger = function(){\n\tvar args = arguments;\n\tvar context = this.context;\n\tvar promises = [];\n\n\tthis.hooks.forEach(function(task, i) {\n\t\tvar executing = task.apply(context, args);\n\n\t\tif(executing && typeof executing[\"then\"] === \"function\") {\n\t\t\t// Task is a function that returns a promise\n\t\t\tpromises.push(executing);\n\t\t}\n\t\t// Otherwise Task resolves immediately, continue\n\t});\n\n\n\treturn RSVP.all(promises);\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.list = function(){\n\treturn this.hooks;\n};\n\nHook.prototype.clear = function(){\n\treturn this.hooks = [];\n};\n\nmodule.exports = Hook;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/hook.js\n ** module id = 16\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\n\nfunction Section(item, hooks){\n\t\tthis.idref = item.idref;\n\t\tthis.linear = item.linear;\n\t\tthis.properties = item.properties;\n\t\tthis.index = item.index;\n\t\tthis.href = item.href;\n\t\tthis.url = item.url;\n\t\tthis.next = item.next;\n\t\tthis.prev = item.prev;\n\n\t\tthis.cfiBase = item.cfiBase;\n\n\t\tif (hooks) {\n\t\t\tthis.hooks = hooks;\n\t\t} else {\n\t\t\tthis.hooks = {};\n\t\t\tthis.hooks.serialize = new Hook(this);\n\t\t\tthis.hooks.content = new Hook(this);\n\t\t}\n\n};\n\n\nSection.prototype.load = function(_request){\n\tvar request = _request || this.request || require('./request');\n\tvar loading = new RSVP.defer();\n\tvar loaded = loading.promise;\n\n\tif(this.contents) {\n\t\tloading.resolve(this.contents);\n\t} else {\n\t\trequest(this.url)\n\t\t\t.then(function(xml){\n\t\t\t\tvar base;\n\t\t\t\tvar directory = URI(this.url).directory();\n\n\t\t\t\tthis.document = xml;\n\t\t\t\tthis.contents = xml.documentElement;\n\n\t\t\t\treturn this.hooks.content.trigger(this.document, this);\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tloading.resolve(this.contents);\n\t\t\t}.bind(this))\n\t\t\t.catch(function(error){\n\t\t\t\tloading.reject(error);\n\t\t\t});\n\t}\n\n\treturn loaded;\n};\n\nSection.prototype.base = function(_document){\n\t\tvar task = new RSVP.defer();\n\t\tvar base = _document.createElement(\"base\"); // TODO: check if exists\n\t\tvar head;\n\t\tconsole.log(window.location.origin + \"/\" +this.url);\n\n\t\tbase.setAttribute(\"href\", window.location.origin + \"/\" +this.url);\n\n\t\tif(_document) {\n\t\t\thead = _document.querySelector(\"head\");\n\t\t}\n\t\tif(head) {\n\t\t\thead.insertBefore(base, head.firstChild);\n\t\t\ttask.resolve();\n\t\t} else {\n\t\t\ttask.reject(new Error(\"No head to insert into\"));\n\t\t}\n\n\n\t\treturn task.promise;\n};\n\nSection.prototype.beforeSectionLoad = function(){\n\t// Stub for a hook - replace me for now\n};\n\nSection.prototype.render = function(_request){\n\tvar rendering = new RSVP.defer();\n\tvar rendered = rendering.promise;\n\tthis.output; // TODO: better way to return this from hooks?\n\n\tthis.load(_request).\n\t\tthen(function(contents){\n\t\t\tvar serializer;\n\n\t\t\tif (typeof XMLSerializer === \"undefined\") {\n\t\t\t\tXMLSerializer = require('xmldom').XMLSerializer;\n\t\t\t}\n\t\t\tserializer = new XMLSerializer();\n\t\t\tthis.output = serializer.serializeToString(contents);\n\t\t\treturn this.output;\n\t\t}.bind(this)).\n\t\tthen(function(){\n\t\t\treturn this.hooks.serialize.trigger(this.output, this);\n\t\t}.bind(this)).\n\t\tthen(function(){\n\t\t\trendering.resolve(this.output);\n\t\t}.bind(this))\n\t\t.catch(function(error){\n\t\t\trendering.reject(error);\n\t\t});\n\n\treturn 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\t//-- Get the global defaults\n\tvar settings = {\n\t\tlayout : global.layout,\n\t\tspread : global.spread,\n\t\torientation : global.orientation\n\t};\n\n\t//-- Get the chapter's display type\n\tthis.properties.forEach(function(prop){\n\t\tvar rendition = prop.replace(\"rendition:\", '');\n\t\tvar split = rendition.indexOf(\"-\");\n\t\tvar property, value;\n\n\t\tif(split != -1){\n\t\t\tproperty = rendition.slice(0, split);\n\t\t\tvalue = rendition.slice(split+1);\n\n\t\t\tsettings[property] = value;\n\t\t}\n\t});\n return settings;\n};\n\nSection.prototype.cfiFromRange = function(_range) {\n\treturn new EpubCFI(_range, this.cfiBase).toString();\n};\n\nSection.prototype.cfiFromElement = function(el) {\n\treturn new EpubCFI(el, this.cfiBase).toString();\n};\n\nmodule.exports = Section;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/section.js\n ** module id = 17\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\n\nfunction request(url, type, withCredentials, headers) {\n\tvar supportsURL = (typeof window != \"undefined\") ? window.URL : false; // TODO: fallback for url if window isn't defined\n\tvar BLOB_RESPONSE = supportsURL ? \"blob\" : \"arraybuffer\";\n\tvar uri;\n\n\tvar deferred = new RSVP.defer();\n\n\tvar xhr = new XMLHttpRequest();\n\n\t//-- Check from PDF.js:\n\t// https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js\n\tvar xhrPrototype = XMLHttpRequest.prototype;\n\n\tvar header;\n\n\tif (!('overrideMimeType' in xhrPrototype)) {\n\t\t// IE10 might have response, but not overrideMimeType\n\t\tObject.defineProperty(xhrPrototype, 'overrideMimeType', {\n\t\t\tvalue: function xmlHttpRequestOverrideMimeType(mimeType) {}\n\t\t});\n\t}\n\tif(withCredentials) {\n\t\txhr.withCredentials = true;\n\t}\n\n\txhr.onreadystatechange = handler;\n\txhr.onerror = err;\n\n\txhr.open(\"GET\", url, true);\n\n\tfor(header in headers) {\n\t\txhr.setRequestHeader(header, headers[header]);\n\t}\n\n\tif(type == \"json\") {\n\t\txhr.setRequestHeader(\"Accept\", \"application/json\");\n\t}\n\n\t// 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\tif(type == 'blob'){\n\t\txhr.responseType = BLOB_RESPONSE;\n\t}\n\n\n\tif(core.isXml(type)) {\n\t\t// xhr.responseType = \"document\";\n\t\txhr.overrideMimeType('text/xml'); // for OPF parsing\n\t}\n\n\tif(type == 'xhtml') {\n\t\t// xhr.responseType = \"document\";\n\t}\n\n\tif(type == 'html' || type == 'htm') {\n\t\t// xhr.responseType = \"document\";\n\t }\n\n\tif(type == \"binary\") {\n\t\txhr.responseType = \"arraybuffer\";\n\t}\n\n\txhr.send();\n\n\tfunction err(e) {\n\t\tconsole.error(e);\n\t\tdeferred.reject(e);\n\t}\n\n\tfunction handler() {\n\t\tif (this.readyState === XMLHttpRequest.DONE) {\n\n\t\t\tif (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls\n\t\t\t\tvar r;\n\n\t\t\t\tif (!this.response && !this.responseXML) {\n\t\t\t\t\tdeferred.reject({\n\t\t\t\t\t\tstatus: this.status,\n\t\t\t\t\t\tmessage : \"Empty Response\",\n\t\t\t\t\t\tstack : new Error().stack\n\t\t\t\t\t});\n\t\t\t\t\treturn deferred.promise;\n\t\t\t\t}\n\n\t\t\t\tif (this.status === 403) {\n\t\t\t\t\tdeferred.reject({\n\t\t\t\t\t\tstatus: this.status,\n\t\t\t\t\t\tresponse: this.response,\n\t\t\t\t\t\tmessage : \"Forbidden\",\n\t\t\t\t\t\tstack : new Error().stack\n\t\t\t\t\t});\n\t\t\t\t\treturn deferred.promise;\n\t\t\t\t}\n\n\t\t\t\tif((this.responseType == '' || this.responseType == 'document')\n\t\t\t\t\t\t&& this.responseXML){\n\t\t\t\t\tr = this.responseXML;\n\t\t\t\t} else\n\t\t\t\tif(core.isXml(type)){\n\t\t\t\t\t// xhr.overrideMimeType('text/xml'); // for OPF parsing\n\t\t\t\t\t// If this.responseXML wasn't set, try to parse using a DOMParser from text\n\t\t\t\t\tr = core.parse(this.response, \"text/xml\");\n\t\t\t\t}else\n\t\t\t\tif(type == 'xhtml'){\n\t\t\t\t\tr = core.parse(this.response, \"application/xhtml+xml\");\n\t\t\t\t}else\n\t\t\t\tif(type == 'html' || type == 'htm'){\n\t\t\t\t\tr = core.parse(this.response, \"text/html\");\n\t\t\t\t}else\n\t\t\t\tif(type == 'json'){\n\t\t\t\t\tr = JSON.parse(this.response);\n\t\t\t\t}else\n\t\t\t\tif(type == 'blob'){\n\n\t\t\t\t\tif(supportsURL) {\n\t\t\t\t\t\tr = this.response;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//-- Safari doesn't support responseType blob, so create a blob from arraybuffer\n\t\t\t\t\t\tr = new Blob([this.response]);\n\t\t\t\t\t}\n\n\t\t\t\t}else{\n\t\t\t\t\tr = this.response;\n\t\t\t\t}\n\n\t\t\t\tdeferred.resolve(r);\n\t\t\t} else {\n\n\t\t\t\tdeferred.reject({\n\t\t\t\t\tstatus: this.status,\n\t\t\t\t\tmessage : this.response,\n\t\t\t\t\tstack : new Error().stack\n\t\t\t\t});\n\n\t\t\t}\n\t\t}\n\t}\n\n\treturn deferred.promise;\n};\n\nmodule.exports = request;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/request.js\n ** module id = 18\n ** module chunks = 0\n **/","var URI = require('urijs');\nvar core = require('./core');\n\nfunction base(doc, section){\n\tvar base;\n\tvar head;\n\n\tif(!doc){\n\t\treturn;\n\t}\n\n\t// head = doc.querySelector(\"head\");\n\t// base = head.querySelector(\"base\");\n\thead = core.qs(doc, \"head\");\n\tbase = core.qs(head, \"base\");\n\n\tif(!base) {\n\t\tbase = doc.createElement(\"base\");\n\t\thead.insertBefore(base, head.firstChild);\n\t}\n\n\tbase.setAttribute(\"href\", section.url);\n}\n\nfunction canonical(doc, section){\n\tvar head;\n\tvar link;\n\tvar url = section.url; // window.location.origin + window.location.pathname + \"?loc=\" + encodeURIComponent(section.url);\n\n\tif(!doc){\n\t\treturn;\n\t}\n\n\thead = core.qs(doc, \"head\");\n\tlink = core.qs(head, \"link[rel='canonical']\");\n\n\tif (link) {\n\t\tlink.setAttribute(\"href\", url);\n\t} else {\n\t\tlink = doc.createElement(\"link\");\n\t\tlink.setAttribute(\"rel\", \"canonical\");\n\t\tlink.setAttribute(\"href\", url);\n\t\thead.appendChild(link);\n\t}\n}\n\nfunction links(view, renderer) {\n\n\tvar links = view.document.querySelectorAll(\"a[href]\");\n\tvar replaceLinks = function(link){\n\t\tvar href = link.getAttribute(\"href\");\n\n\t\tif(href.indexOf(\"mailto:\") === 0){\n\t\t\treturn;\n\t\t}\n\n\t\tvar linkUri = URI(href);\n\t\tvar absolute = linkUri.absoluteTo(view.section.url);\n\t\tvar relative = absolute.relativeTo(this.book.baseUrl).toString();\n\n\t\tif(linkUri.protocol()){\n\n\t\t\tlink.setAttribute(\"target\", \"_blank\");\n\n\t\t}else{\n\t\t\t/*\n\t\t\tif(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\t\t\t*/\n\n\t\t\tif(linkUri.fragment()) {\n\t\t\t\t// do nothing with fragment yet\n\t\t\t} else {\n\t\t\t\tlink.onclick = function(){\n\t\t\t\t\trenderer.display(relative);\n\t\t\t\t\treturn false;\n\t\t\t\t};\n\t\t\t}\n\n\t\t}\n\t}.bind(this);\n\n\tfor (var i = 0; i < links.length; i++) {\n\t\treplaceLinks(links[i]);\n\t}\n\n\n};\n\nfunction substitute(content, urls, replacements) {\n\turls.forEach(function(url, i){\n\t\tif (url && replacements[i]) {\n\t\t\tcontent = content.replace(new RegExp(url, 'g'), replacements[i]);\n\t\t}\n\t});\n\treturn content;\n}\nmodule.exports = {\n\t'base': base,\n\t'canonical' : canonical,\n\t'links': links,\n\t'substitute': substitute\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/replacements.js\n ** module id = 19\n ** module chunks = 0\n **/","var core = require('./core');\nvar Queue = require('./queue');\nvar EpubCFI = require('./epubcfi');\nvar RSVP = require('rsvp');\n\nfunction Locations(spine, request) {\n\tthis.spine = spine;\n\tthis.request = request;\n\n\tthis.q = new Queue(this);\n\tthis.epubcfi = new EpubCFI();\n\n\tthis._locations = [];\n\tthis.total = 0;\n\n\tthis.break = 150;\n\n\tthis._current = 0;\n\n};\n\n// Load all of sections in the book\nLocations.prototype.generate = function(chars) {\n\n\tif (chars) {\n\t\tthis.break = chars;\n\t}\n\n\tthis.q.pause();\n\n\tthis.spine.each(function(section) {\n\n\t\tthis.q.enqueue(this.process, section);\n\n\t}.bind(this));\n\n\treturn this.q.run().then(function() {\n\t\tthis.total = this._locations.length-1;\n\n\t\tif (this._currentCfi) {\n\t\t\tthis.currentLocation = this._currentCfi;\n\t\t}\n\n\t\treturn this._locations;\n\t\t// console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));\n\t}.bind(this));\n\n};\n\nLocations.prototype.process = function(section) {\n\n\treturn section.load(this.request)\n\t\t.then(function(contents) {\n\n\t\t\tvar range;\n\t\t\tvar doc = contents.ownerDocument;\n\t\t\tvar counter = 0;\n\n\t\t\tthis.sprint(contents, function(node) {\n\t\t\t\tvar len = node.length;\n\t\t\t\tvar dist;\n\t\t\t\tvar pos = 0;\n\n\t\t\t\t// Start range\n\t\t\t\tif (counter == 0) {\n\t\t\t\t\trange = doc.createRange();\n\t\t\t\t\trange.setStart(node, 0);\n\t\t\t\t}\n\n\t\t\t\tdist = this.break - counter;\n\n\t\t\t\t// Node is smaller than a break\n\t\t\t\tif(dist > len){\n\t\t\t\t\tcounter += len;\n\t\t\t\t\tpos = len;\n\t\t\t\t}\n\n\t\t\t\twhile (pos < len) {\n\t\t\t\t\tcounter = this.break;\n\t\t\t\t\tpos += this.break;\n\n\t\t\t\t\t// Gone over\n\t\t\t\t\tif(pos >= len){\n\t\t\t\t\t\t// Continue counter for next node\n\t\t\t\t\t\tcounter = len - (pos - this.break);\n\n\t\t\t\t\t// At End\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// End the previous range\n\t\t\t\t\t\trange.setEnd(node, pos);\n\t\t\t\t\t\tcfi = section.cfiFromRange(range);\n\t\t\t\t\t\tthis._locations.push(cfi);\n\t\t\t\t\t\tcounter = 0;\n\n\t\t\t\t\t\t// Start new range\n\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\trange = doc.createRange();\n\t\t\t\t\t\trange.setStart(node, pos);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\n\t\t\t}.bind(this));\n\n\t\t\t// Close remaining\n\t\t\tif (range) {\n\t\t\t\trange.setEnd(prev, prev.length);\n\t\t\t\tcfi = section.cfiFromRange(range);\n\t\t\t\tthis._locations.push(cfi)\n\t\t\t\tcounter = 0;\n\t\t\t}\n\n\t\t}.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\t// Check if the location has not been set yet\n\tif(this._locations.length === 0) {\n\t\treturn -1;\n\t}\n\n\treturn core.locationOf(cfi, this._locations, this.epubcfi.compare);\n};\n\nLocations.prototype.precentageFromCfi = function(cfi) {\n\t// Find closest cfi\n\tvar loc = this.locationFromCfi(cfi);\n\t// Get percentage in total\n\treturn this.precentageFromLocation(loc);\n};\n\nLocations.prototype.percentageFromLocation = function(loc) {\n\tif (!loc || !this.total) {\n\t\treturn 0;\n\t}\n\treturn (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\tvar 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\tthis.total = this._locations.length-1;\n\treturn 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\tvar loc;\n\n\tif(typeof curr == \"string\"){\n\t\tthis._currentCfi = curr;\n\t} else if (typeof curr == \"number\") {\n\t\tthis._current = curr;\n\t} else {\n\t\treturn;\n\t}\n\n\tif(this._locations.length === 0) {\n\t\treturn;\n\t}\n\n\tif(typeof curr == \"string\"){\n\t\tloc = this.locationFromCfi(curr);\n\t\tthis._current = loc;\n\t} else {\n\t\tloc = curr;\n\t}\n\n\tthis.trigger(\"changed\", {\n\t\tpercentage: this.precentageFromLocation(loc)\n\t});\n};\n\nObject.defineProperty(Locations.prototype, 'currentLocation', {\n\tget: function () {\n\t\treturn this._current;\n\t},\n\tset: function (curr) {\n\t\tthis.setCurrent(curr);\n\t}\n});\n\nRSVP.EventTarget.mixin(Locations.prototype);\n\nmodule.exports = Locations;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/locations.js\n ** module id = 20\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar core = require('./core');\n\nfunction Queue(_context){\n\tthis._q = [];\n\tthis.context = _context;\n\tthis.tick = core.requestAnimationFrame;\n\tthis.running = false;\n\tthis.paused = false;\n};\n\n// Add an item to the queue\nQueue.prototype.enqueue = function() {\n\tvar deferred, promise;\n\tvar queued;\n\tvar task = [].shift.call(arguments);\n\tvar args = arguments;\n\n\t// Handle single args without context\n\t// if(args && !Array.isArray(args)) {\n\t// args = [args];\n\t// }\n\tif(!task) {\n\t\treturn console.error(\"No Task Provided\");\n\t}\n\n\tif(typeof task === \"function\"){\n\n\t\tdeferred = new RSVP.defer();\n\t\tpromise = deferred.promise;\n\n\t\tqueued = {\n\t\t\t\"task\" : task,\n\t\t\t\"args\" : args,\n\t\t\t//\"context\" : context,\n\t\t\t\"deferred\" : deferred,\n\t\t\t\"promise\" : promise\n\t\t};\n\n\t} else {\n\t\t// Task is a promise\n\t\tqueued = {\n\t\t\t\"promise\" : task\n\t\t};\n\n\t}\n\n\tthis._q.push(queued);\n\n\t// Wait to start queue flush\n\tif (this.paused == false && !this.running) {\n\t\t// setTimeout(this.flush.bind(this), 0);\n\t\t// this.tick.call(window, this.run.bind(this));\n\t\tthis.run();\n\t}\n\n\treturn queued.promise;\n};\n\n// Run one item\nQueue.prototype.dequeue = function(){\n\tvar inwait, task, result;\n\n\tif(this._q.length) {\n\t\tinwait = this._q.shift();\n\t\ttask = inwait.task;\n\t\tif(task){\n\t\t\t// console.log(task)\n\n\t\t\tresult = task.apply(this.context, inwait.args);\n\n\t\t\tif(result && typeof result[\"then\"] === \"function\") {\n\t\t\t\t// Task is a function that returns a promise\n\t\t\t\treturn result.then(function(){\n\t\t\t\t\tinwait.deferred.resolve.apply(this.context, arguments);\n\t\t\t\t}.bind(this));\n\t\t\t} else {\n\t\t\t\t// Task resolves immediately\n\t\t\t\tinwait.deferred.resolve.apply(this.context, result);\n\t\t\t\treturn inwait.promise;\n\t\t\t}\n\n\n\n\t\t} else if(inwait.promise) {\n\t\t\t// Task is a promise\n\t\t\treturn inwait.promise;\n\t\t}\n\n\t} else {\n\t\tinwait = new RSVP.defer();\n\t\tinwait.deferred.resolve();\n\t\treturn inwait.promise;\n\t}\n\n};\n\n// Run All Immediately\nQueue.prototype.dump = function(){\n\twhile(this._q.length) {\n\t\tthis.dequeue();\n\t}\n};\n\n// Run all sequentially, at convince\n\nQueue.prototype.run = function(){\n\n\tif(!this.running){\n\t\tthis.running = true;\n\t\tthis.defered = new RSVP.defer();\n\t}\n\n\tthis.tick.call(window, function() {\n\n\t\tif(this._q.length) {\n\n\t\t\tthis.dequeue()\n\t\t\t\t.then(function(){\n\t\t\t\t\tthis.run();\n\t\t\t\t}.bind(this));\n\n\t\t} else {\n\t\t\tthis.defered.resolve();\n\t\t\tthis.running = undefined;\n\t\t}\n\n\t}.bind(this));\n\n\t// Unpause\n\tif(this.paused == true) {\n\t\tthis.paused = false;\n\t}\n\n\treturn this.defered.promise;\n};\n\n// Flush all, as quickly as possible\nQueue.prototype.flush = function(){\n\n\tif(this.running){\n\t\treturn this.running;\n\t}\n\n\tif(this._q.length) {\n\t\tthis.running = this.dequeue()\n\t\t\t.then(function(){\n\t\t\t\tthis.running = undefined;\n\t\t\t\treturn this.flush();\n\t\t\t}.bind(this));\n\n\t\treturn this.running;\n\t}\n\n};\n\n// Clear all items in wait\nQueue.prototype.clear = function(){\n\tthis._q = [];\n\tthis.running = false;\n};\n\nQueue.prototype.length = function(){\n\treturn this._q.length;\n};\n\nQueue.prototype.pause = function(){\n\tthis.paused = true;\n};\n\n// Create a new task from a callback\nfunction Task(task, args, context){\n\n\treturn function(){\n\t\tvar toApply = arguments || [];\n\n\t\treturn new RSVP.Promise(function(resolve, reject) {\n\t\t\tvar callback = function(value){\n\t\t\t\tresolve(value);\n\t\t\t};\n\t\t\t// Add the callback to the arguments list\n\t\t\ttoApply.push(callback);\n\n\t\t\t// Apply all arguments to the functions\n\t\t\ttask.apply(this, toApply);\n\n\t}.bind(this));\n\n\t};\n\n};\n\nmodule.exports = Queue;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/queue.js\n ** module id = 21\n ** module chunks = 0\n **/","var URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\n\nfunction Parser(){};\n\nParser.prototype.container = function(containerXml){\n\t\t//-- \n\t\tvar rootfile, fullpath, folder, encoding;\n\n\t\tif(!containerXml) {\n\t\t\tconsole.error(\"Container File Not Found\");\n\t\t\treturn;\n\t\t}\n\n\t\trootfile = core.qs(containerXml, \"rootfile\");\n\n\t\tif(!rootfile) {\n\t\t\tconsole.error(\"No RootFile Found\");\n\t\t\treturn;\n\t\t}\n\n\t\tfullpath = rootfile.getAttribute('full-path');\n\t\tfolder = URI(fullpath).directory();\n\t\tencoding = containerXml.xmlEncoding;\n\n\t\t//-- Now that we have the path we can parse the contents\n\t\treturn {\n\t\t\t'packagePath' : fullpath,\n\t\t\t'basePath' : folder,\n\t\t\t'encoding' : encoding\n\t\t};\n};\n\nParser.prototype.identifier = function(packageXml){\n\tvar metadataNode;\n\n\tif(!packageXml) {\n\t\tconsole.error(\"Package File Not Found\");\n\t\treturn;\n\t}\n\n\tmetadataNode = core.qs(packageXml, \"metadata\");\n\n\tif(!metadataNode) {\n\t\tconsole.error(\"No Metadata Found\");\n\t\treturn;\n\t}\n\n\treturn this.getElementText(metadataNode, \"identifier\");\n};\n\nParser.prototype.packageContents = function(packageXml){\n\tvar parse = this;\n\tvar metadataNode, manifestNode, spineNode;\n\tvar manifest, navPath, ncxPath, coverPath;\n\tvar spineNodeIndex;\n\tvar spine;\n\tvar spineIndexByURL;\n\tvar metadata;\n\n\tif(!packageXml) {\n\t\tconsole.error(\"Package File Not Found\");\n\t\treturn;\n\t}\n\n\tmetadataNode = core.qs(packageXml, \"metadata\");\n\tif(!metadataNode) {\n\t\tconsole.error(\"No Metadata Found\");\n\t\treturn;\n\t}\n\n\tmanifestNode = core.qs(packageXml, \"manifest\");\n\tif(!manifestNode) {\n\t\tconsole.error(\"No Manifest Found\");\n\t\treturn;\n\t}\n\n\tspineNode = core.qs(packageXml, \"spine\");\n\tif(!spineNode) {\n\t\tconsole.error(\"No Spine Found\");\n\t\treturn;\n\t}\n\n\tmanifest = parse.manifest(manifestNode);\n\tnavPath = parse.findNavPath(manifestNode);\n\tncxPath = parse.findNcxPath(manifestNode, spineNode);\n\tcoverPath = parse.findCoverPath(packageXml);\n\n\tspineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);\n\n\tspine = parse.spine(spineNode, manifest);\n\n\tmetadata = parse.metadata(metadataNode);\n\n\tmetadata.direction = spineNode.getAttribute(\"page-progression-direction\");\n\n\treturn {\n\t\t'metadata' : metadata,\n\t\t'spine' : spine,\n\t\t'manifest' : manifest,\n\t\t'navPath' : navPath,\n\t\t'ncxPath' : ncxPath,\n\t\t'coverPath': coverPath,\n\t\t'spineNodeIndex' : spineNodeIndex\n\t};\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\t// var node = manifestNode.querySelector(\"item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']\");\n\tvar node = core.qsp(manifestNode, \"item\", {\"properties\":\"nav\"});\n\treturn 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\t// var node = manifestNode.querySelector(\"item[media-type='application/x-dtbncx+xml']\");\n\tvar node = core.qsp(manifestNode, \"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\t// node = manifestNode.querySelector(\"item[id='\" + tocId + \"']\");\n\t\t\tnode = manifestNode.getElementById(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\tvar metadata = {},\n\t\t\tp = this;\n\n\tmetadata.title = p.getElementText(xml, 'title');\n\tmetadata.creator = p.getElementText(xml, 'creator');\n\tmetadata.description = p.getElementText(xml, 'description');\n\n\tmetadata.pubdate = p.getElementText(xml, 'date');\n\n\tmetadata.publisher = p.getElementText(xml, 'publisher');\n\n\tmetadata.identifier = p.getElementText(xml, \"identifier\");\n\tmetadata.language = p.getElementText(xml, \"language\");\n\tmetadata.rights = p.getElementText(xml, \"rights\");\n\n\tmetadata.modified_date = p.getPropertyText(xml, 'dcterms:modified');\n\n\tmetadata.layout = p.getPropertyText(xml, \"rendition:layout\");\n\tmetadata.orientation = p.getPropertyText(xml, 'rendition:orientation');\n\tmetadata.flow = p.getPropertyText(xml, 'rendition:flow');\n\tmetadata.viewport = p.getPropertyText(xml, 'rendition:viewport');\n\t// metadata.page_prog_dir = packageXml.querySelector(\"spine\").getAttribute(\"page-progression-direction\");\n\n\treturn metadata;\n};\n\n//-- Find Cover: \n//-- Fallback for Epub 2.0\nParser.prototype.findCoverPath = function(packageXml){\n\tvar pkg = core.qs(packageXml, \"package\");\n\tvar epubVersion = pkg.getAttribute('version');\n\n\tif (epubVersion === '2.0') {\n\t\tvar metaCover = core.qsp(packageXml, 'meta', {'name':'cover'});\n\t\tif (metaCover) {\n\t\t\tvar coverId = metaCover.getAttribute('content');\n\t\t\t// var cover = packageXml.querySelector(\"item[id='\" + coverId + \"']\");\n\t\t\tvar cover = packageXml.getElementById(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\t// var node = packageXml.querySelector(\"item[properties='cover-image']\");\n\t\tvar node = core.qsp(packageXml, 'item', {'properties':'cover-image'});\n\t\treturn node ? node.getAttribute('href') : false;\n\t}\n};\n\nParser.prototype.getElementText = function(xml, tag){\n\tvar found = xml.getElementsByTagNameNS(\"http://purl.org/dc/elements/1.1/\", tag),\n\t\tel;\n\n\tif(!found || found.length === 0) return '';\n\n\tel = found[0];\n\n\tif(el.childNodes.length){\n\t\treturn el.childNodes[0].nodeValue;\n\t}\n\n\treturn '';\n\n};\n\nParser.prototype.getPropertyText = function(xml, property){\n\tvar el = core.qsp(xml, \"meta\", {\"property\":property});\n\n\tif(el && el.childNodes.length){\n\t\treturn el.childNodes[0].nodeValue;\n\t}\n\n\treturn '';\n};\n\nParser.prototype.querySelectorText = function(xml, q){\n\tvar el = xml.querySelector(q);\n\n\tif(el && el.childNodes.length){\n\t\treturn el.childNodes[0].nodeValue;\n\t}\n\n\treturn '';\n};\n\nParser.prototype.manifest = function(manifestXml){\n\tvar manifest = {};\n\n\t//-- Turn items into an array\n\t// var selected = manifestXml.querySelectorAll(\"item\");\n\tvar selected = core.qsa(manifestXml, \"item\");\n\tvar items = Array.prototype.slice.call(selected);\n\n\t//-- Create an object with the id as key\n\titems.forEach(function(item){\n\t\tvar id = item.getAttribute('id'),\n\t\t\t\thref = item.getAttribute('href') || '',\n\t\t\t\ttype = item.getAttribute('media-type') || '',\n\t\t\t\tproperties = item.getAttribute('properties') || '';\n\n\t\tmanifest[id] = {\n\t\t\t'href' : href,\n\t\t\t// 'url' : href,\n\t\t\t'type' : type,\n\t\t\t'properties' : properties.length ? properties.split(' ') : []\n\t\t};\n\n\t});\n\n\treturn manifest;\n\n};\n\nParser.prototype.spine = function(spineXml, manifest){\n\tvar spine = [];\n\n\tvar selected = spineXml.getElementsByTagName(\"itemref\"),\n\t\t\titems = Array.prototype.slice.call(selected);\n\n\tvar epubcfi = new EpubCFI();\n\n\t//-- Add to array to mantain ordering and cross reference with manifest\n\titems.forEach(function(item, index){\n\t\tvar idref = item.getAttribute('idref');\n\t\t// var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);\n\t\tvar props = item.getAttribute('properties') || '';\n\t\tvar propArray = props.length ? props.split(' ') : [];\n\t\t// var manifestProps = manifest[Id].properties;\n\t\t// var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];\n\n\t\tvar itemref = {\n\t\t\t'idref' : idref,\n\t\t\t'linear' : item.getAttribute('linear') || '',\n\t\t\t'properties' : propArray,\n\t\t\t// 'href' : manifest[Id].href,\n\t\t\t// 'url' : manifest[Id].url,\n\t\t\t'index' : index\n\t\t\t// 'cfiBase' : cfiBase\n\t\t};\n\t\tspine.push(itemref);\n\t});\n\n\treturn spine;\n};\n\nParser.prototype.querySelectorByType = function(html, element, type){\n\tvar query;\n\tif (typeof html.querySelector != \"undefined\") {\n\t\tquery = html.querySelector(element+'[*|type=\"'+type+'\"]');\n\t}\n\t// Handle IE not supporting namespaced epub:type in querySelector\n\tif(!query || query.length === 0) {\n\t\tquery = core.qsa(html, 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\t// var navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar navItems = navElement ? core.qsa(navElement, \"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\t// content = item.querySelector(\"a, span\"),\n\t\t\tcontent = core.qs(item, \"a\"),\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\t/*\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\t*/\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.ncx = function(tocXml, spineIndexByURL, bookSpine){\n\t// var navPoints = tocXml.querySelectorAll(\"navMap navPoint\");\n\tvar navPoints = core.qsa(tocXml, \"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.ncxItem(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.ncxItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\t// content = item.querySelector(\"content\"),\n\t\t\tcontent = core.qs(item, \"content\"),\n\t\t\tsrc = content.getAttribute('src'),\n\t\t\t// navLabel = item.querySelector(\"navLabel\"),\n\t\t\tnavLabel = core.qs(item, \"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\t/*\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\t*/\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\t// var navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar navItems = navElement ? core.qsa(navElement, \"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\t// content = item.querySelector(\"a\"),\n\t\tcontent = core.qs(item, \"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\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/parser.js\n ** module id = 22\n ** module chunks = 0\n **/","var core = require('./core');\nvar Parser = require('./parser');\nvar RSVP = require('rsvp');\nvar URI = require('urijs');\n\nfunction Navigation(_package, _request){\n\tvar navigation = this;\n\tvar parse = new Parser();\n\tvar request = _request || require('./request');\n\n\tthis.package = _package;\n\tthis.toc = [];\n\tthis.tocByHref = {};\n\tthis.tocById = {};\n\n\tif(_package.navPath) {\n\t\tthis.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();\n\t\tthis.nav = {};\n\n\t\tthis.nav.load = function(_request){\n\t\t\tvar loading = new RSVP.defer();\n\t\t\tvar loaded = loading.promise;\n\n\t\t\trequest(navigation.navUrl, 'xml').then(function(xml){\n\t\t\t\tnavigation.toc = parse.nav(xml);\n\t\t\t\tnavigation.loaded(navigation.toc);\n\t\t\t\tloading.resolve(navigation.toc);\n\t\t\t});\n\n\t\t\treturn loaded;\n\t\t};\n\n\t}\n\n\tif(_package.ncxPath) {\n\t\tthis.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();\n\t\tthis.ncx = {};\n\n\t\tthis.ncx.load = function(_request){\n\t\t\tvar loading = new RSVP.defer();\n\t\t\tvar loaded = loading.promise;\n\n\t\t\trequest(navigation.ncxUrl, 'xml').then(function(xml){\n\t\t\t\tnavigation.toc = parse.toc(xml);\n\t\t\t\tnavigation.loaded(navigation.toc);\n\t\t\t\tloading.resolve(navigation.toc);\n\t\t\t});\n\n\t\t\treturn loaded;\n\t\t};\n\n\t}\n};\n\n// Load the navigation\nNavigation.prototype.load = function(_request) {\n\tvar request = _request || require('./request');\n\tvar loading, loaded;\n\n\tif(this.nav) {\n\t\tloading = this.nav.load();\n\t} else if(this.ncx) {\n\t\tloading = this.ncx.load();\n\t} else {\n\t\tloaded = new RSVP.defer();\n\t\tloaded.resolve([]);\n\t\tloading = loaded.promise;\n\t}\n\n\treturn loading;\n\n};\n\nNavigation.prototype.loaded = function(toc) {\n\tvar item;\n\n\tfor (var i = 0; i < toc.length; i++) {\n\t\titem = toc[i];\n\t\tthis.tocByHref[item.href] = i;\n\t\tthis.tocById[item.id] = i;\n\t}\n\n};\n\n// Get an item from the navigation\nNavigation.prototype.get = function(target) {\n\tvar index;\n\n\tif(!target) {\n\t\treturn this.toc;\n\t}\n\n\tif(target.indexOf(\"#\") === 0) {\n\t\tindex = this.tocById[target.substring(1)];\n\t} else if(target in this.tocByHref){\n\t\tindex = this.tocByHref[target];\n\t}\n\n\treturn this.toc[index];\n};\n\nmodule.exports = Navigation;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/navigation.js\n ** module id = 23\n ** module chunks = 0\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 Layout = require('./layout');\nvar Mapping = require('./mapping');\n\nfunction Rendition(book, options) {\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\twidth: null,\n\t\theight: null,\n\t\tignoreClass: '',\n\t\tmanager: \"single\",\n\t\tview: \"iframe\",\n\t\tflow: null,\n\t\tlayout: null,\n\t\tspread: null,\n\t\tminSpreadWidth: 800, //-- overridden by spread: none (never) / both (always),\n\t\tuseBase64: true\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass\n\t};\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\tthis.epubcfi = new EpubCFI();\n\n\tthis.q = new Queue(this);\n\n\tthis.q.enqueue(this.book.opened);\n\n\t// Block the queue until rendering is started\n\t// this.starting = new RSVP.defer();\n\t// this.started = this.starting.promise;\n\tthis.q.enqueue(this.start);\n\n\tif(this.book.unarchived) {\n\t\tthis.q.enqueue(this.replacements.bind(this));\n\t}\n\n};\n\nRendition.prototype.setManager = function(manager) {\n\tthis.manager = manager;\n};\n\nRendition.prototype.requireManager = function(manager) {\n\tvar viewManager;\n\n\t// If manager is a string, try to load from register managers,\n\t// or require included managers directly\n\tif (typeof manager === \"string\") {\n\t\t// Use global or require\n\t\tviewManager = typeof ePub != \"undefined\" ? ePub.ViewManagers[manager] : undefined; //require('./managers/'+manager);\n\t} else {\n\t\t// otherwise, assume we were passed a function\n\t\tviewManager = manager\n\t}\n\n\treturn viewManager;\n};\n\nRendition.prototype.requireView = function(view) {\n\tvar View;\n\n\tif (typeof view == \"string\") {\n\t\tView = typeof ePub != \"undefined\" ? ePub.Views[view] : undefined; //require('./views/'+view);\n\t} else {\n\t\t// otherwise, assume we were passed a function\n\t\tView = view\n\t}\n\n\treturn View;\n};\n\nRendition.prototype.start = function(){\n\n\tif(!this.manager) {\n\t\tthis.ViewManager = this.requireManager(this.settings.manager);\n\t\tthis.View = this.requireView(this.settings.view);\n\n\t\tthis.manager = new this.ViewManager({\n\t\t\tview: this.View,\n\t\t\tqueue: this.q,\n\t\t\trequest: this.book.request,\n\t\t\tsettings: this.settings\n\t\t});\n\t}\n\n\t// Parse metadata to get layout props\n\tthis.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata);\n\n\tthis.flow(this.settings.globalLayoutProperties.flow);\n\n\tthis.layout(this.settings.globalLayoutProperties);\n\n\t// Listen for displayed views\n\tthis.manager.on(\"added\", this.afterDisplayed.bind(this));\n\n\t// Listen for resizing\n\tthis.manager.on(\"resized\", this.onResized.bind(this));\n\n\t// Listen for scroll changes\n\tthis.manager.on(\"scroll\", this.reportLocation.bind(this));\n\n\n\tthis.on('displayed', this.reportLocation.bind(this));\n\n\t// Trigger that rendering has started\n\tthis.trigger(\"started\");\n\n\t// Start processing queue\n\t// this.starting.resolve();\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\n\treturn this.q.enqueue(function () {\n\n\t\t// Start rendering\n\t\tthis.manager.render(element, {\n\t\t\t\"width\" : this.settings.width,\n\t\t\t\"height\" : this.settings.height\n\t\t});\n\n\t\t// Trigger Attached\n\t\tthis.trigger(\"attached\");\n\n\t}.bind(this));\n\n};\n\nRendition.prototype.display = function(target){\n\n\t// if (!this.book.spine.spineItems.length > 0) {\n\t\t// Book isn't open yet\n\t\t// return this.q.enqueue(this.display, target);\n\t// }\n\n\treturn this.q.enqueue(this._display, target);\n\n};\n\nRendition.prototype._display = function(target){\n\tvar isCfiString = this.epubcfi.isCfiString(target);\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\tvar section;\n\tvar moveTo;\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// Trim the target fragment\n\t// removing the chapter\n\tif(!isCfiString && typeof target === \"string\" &&\n\t\ttarget.indexOf(\"#\") > -1) {\n\t\t\tmoveTo = target.substring(target.indexOf(\"#\")+1);\n\t}\n\n\tif (isCfiString) {\n\t\tmoveTo = target;\n\t}\n\n\treturn this.manager.display(section, moveTo)\n\t\t.then(function(){\n\t\t\tthis.trigger(\"displayed\", section);\n\t\t}.bind(this));\n\n};\n\n/*\nRendition.prototype.render = function(view, show) {\n\n\t// view.onLayout = this.layout.format.bind(this.layout);\n\tview.create();\n\n\t// Fit to size of the container, apply padding\n\tthis.manager.resizeView(view);\n\n\t// Render Chain\n\treturn view.section.render(this.book.request)\n\t\t.then(function(contents){\n\t\t\treturn view.load(contents);\n\t\t}.bind(this))\n\t\t.then(function(doc){\n\t\t\treturn this.hooks.content.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\tthis.layout.format(view.contents);\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) {\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\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.hooks.content.trigger(view, this);\n\tthis.trigger(\"rendered\", view.section);\n\tthis.reportLocation();\n};\n\nRendition.prototype.onResized = function(size){\n\n\tif(this.location) {\n\t\tthis.display(this.location.start);\n\t}\n\n\tthis.trigger(\"resized\", {\n\t\twidth: size.width,\n\t\theight: size.height\n\t});\n\n};\n\nRendition.prototype.moveTo = function(offset){\n\tthis.manager.moveTo(offset);\n};\n\nRendition.prototype.next = function(){\n\treturn this.q.enqueue(this.manager.next.bind(this.manager))\n\t\t.then(this.reportLocation.bind(this));\n};\n\nRendition.prototype.prev = function(){\n\treturn this.q.enqueue(this.manager.prev.bind(this.manager))\n\t\t.then(this.reportLocation.bind(this));\n};\n\n//-- http://www.idpf.org/epub/301/spec/epub-publications.html#meta-properties-rendering\nRendition.prototype.determineLayoutProperties = function(metadata){\n\tvar settings;\n\tvar layout = this.settings.layout || metadata.layout || \"reflowable\";\n\tvar spread = this.settings.spread || metadata.spread || \"auto\";\n\tvar orientation = this.settings.orientation || metadata.orientation || \"auto\";\n\tvar flow = this.settings.flow || metadata.flow || \"auto\";\n\tvar viewport = metadata.viewport || \"\";\n\tvar minSpreadWidth = this.settings.minSpreadWidth || metadata.minSpreadWidth || 800;\n\n\tif (this.settings.width >= 0 && this.settings.height >= 0) {\n\t\tviewport = \"width=\"+this.settings.width+\", height=\"+this.settings.height+\"\";\n\t}\n\n\tsettings = {\n\t\tlayout : layout,\n\t\tspread : spread,\n\t\torientation : orientation,\n\t\tflow : flow,\n\t\tviewport : viewport,\n\t\tminSpreadWidth : minSpreadWidth\n\t};\n\n\treturn settings;\n};\n\n// Rendition.prototype.applyLayoutProperties = function(){\n// \tvar settings = this.determineLayoutProperties(this.book.package.metadata);\n//\n// \tthis.flow(settings.flow);\n//\n// \tthis.layout(settings);\n// };\n\n// paginated | scrolled\n// (scrolled-continuous vs scrolled-doc are handled by different view managers)\nRendition.prototype.flow = function(_flow){\n\tvar flow;\n\tif (_flow === \"scrolled-doc\" || _flow === \"scrolled-continuous\") {\n\t\tflow = \"scrolled\";\n\t}\n\n\tif (_flow === \"auto\" || _flow === \"paginated\") {\n\t\tflow = \"paginated\";\n\t}\n\n\tif (this._layout) {\n\t\tthis._layout.flow(flow);\n\t}\n\n\tif (this.manager) {\n\t\tthis.manager.updateFlow(flow);\n\t}\n};\n\n// reflowable | pre-paginated\nRendition.prototype.layout = function(settings){\n\tif (settings) {\n\t\tthis._layout = new Layout(settings);\n\t\tthis._layout.spread(settings.spread, this.settings.minSpreadWidth);\n\n\t\tthis.mapping = new Mapping(this._layout);\n\t}\n\n\tif (this.manager && this._layout) {\n\t\tthis.manager.applyLayout(this._layout);\n\t}\n\n\treturn this._layout;\n};\n\n// none | auto (TODO: implement landscape, portrait, both)\nRendition.prototype.spread = function(spread, min){\n\n\tthis._layout.spread(spread, min);\n\n\tif (this.manager.isRendered()) {\n\t\tthis.manager.updateLayout();\n\t}\n};\n\n\nRendition.prototype.reportLocation = function(){\n\treturn this.q.enqueue(function(){\n\t\tvar location = this.manager.currentLocation();\n\t\tif (location && location.then && typeof location.then === 'function') {\n\t\t\tlocation.then(function(result) {\n\t\t\t\tthis.location = result;\n\t\t\t\tthis.trigger(\"locationChanged\", this.location);\n\t\t\t}.bind(this));\n\t\t} else if (location) {\n\t\t\tthis.location = location;\n\t\t\tthis.trigger(\"locationChanged\", this.location);\n\t\t}\n\n\t}.bind(this));\n};\n\n\nRendition.prototype.destroy = function(){\n\t// Clear the queue\n\tthis.q.clear();\n\n\tthis.manager.destroy();\n};\n\nRendition.prototype.passViewEvents = function(view){\n\tview.contents.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\tthis.trigger(e.type, e);\n};\n\nRendition.prototype.triggerSelectedEvent = function(cfirange){\n\tthis.trigger(\"selected\", cfirange);\n};\n\nRendition.prototype.replacements = function(){\n\t// Wait for loading\n\t// return this.q.enqueue(function () {\n\t\t// Get thes books manifest\n\t\tvar manifest = this.book.package.manifest;\n\t\tvar manifestArray = Object.keys(manifest).\n\t\t\tmap(function (key){\n\t\t\t\treturn manifest[key];\n\t\t\t});\n\n\t\t// Exclude HTML\n\t\tvar items = manifestArray.\n\t\t\tfilter(function (item){\n\t\t\t\tif (item.type != \"application/xhtml+xml\" &&\n\t\t\t\t\t\titem.type != \"text/html\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t});\n\n\t\t// Only CSS\n\t\tvar css = items.\n\t\t\tfilter(function (item){\n\t\t\t\tif (item.type === \"text/css\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\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\tvar urls = items.\n\t\t\tmap(function(item) {\n\t\t\t\treturn item.href;\n\t\t\t}.bind(this));\n\n\t\t// Create blob urls for all the assets\n\t\tvar processing = urls.\n\t\t\tmap(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\t\t\treturn this.book.unarchived.createUrl(absolute, {\"base64\": this.settings.useBase64});\n\t\t\t}.bind(this));\n\n\t\tvar replacementUrls;\n\n\t\t// After all the urls are created\n\t\treturn RSVP.all(processing)\n\t\t\t.then(function(_replacementUrls) {\n\t\t\t\tvar replaced = [];\n\n\t\t\t\treplacementUrls = _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\treplaced.push(this.replaceCss(href, urls, replacementUrls));\n\t\t\t\t}.bind(this));\n\n\t\t\t\treturn RSVP.all(replaced);\n\n\t\t\t}.bind(this))\n\t\t\t.then(function () {\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\t\t\tthis.book.spine.hooks.serialize.register(function(output, section) {\n\n\t\t\t\t\tthis.replaceAssets(section, urls, replacementUrls);\n\n\t\t\t\t}.bind(this));\n\n\t\t\t}.bind(this))\n\t\t\t.catch(function(reason){\n\t\t\t\tconsole.error(reason);\n\t\t\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 textResponse = this.book.unarchived.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\treturn textResponse.then(function (text) {\n\t\t\t// Replacements in the css text\n\t\t\ttext = replace.substitute(text, relUrls, replacementUrls);\n\n\t\t\t// Get the new url\n\t\t\tif (this.settings.useBase64) {\n\t\t\t\tnewUrl = core.createBase64Url(text, 'text/css');\n\t\t\t} else {\n\t\t\t\tnewUrl = core.createBlobUrl(text, 'text/css');\n\t\t\t}\n\n\t\t\t// switch the url in the replacementUrls\n\t\t\tindexInUrls = urls.indexOf(href);\n\t\t\tif (indexInUrls > -1) {\n\t\t\t\treplacementUrls[indexInUrls] = newUrl;\n\t\t\t}\n\n\t\t\treturn new RSVP.Promise(function(resolve, reject){\n\t\t\t\tresolve(urls, replacementUrls);\n\t\t\t});\n\n\t\t}.bind(this));\n\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\nRendition.prototype.range = function(_cfi, ignoreClass){\n\tvar cfi = new EpubCFI(_cfi);\n\tvar found = this.visible().filter(function (view) {\n\t\tif(cfi.spinePos === view.index) return true;\n\t});\n\n\t// Should only every return 1 item\n\tif (found.length) {\n\t\treturn found[0].range(cfi, ignoreClass);\n\t}\n};\n\nRendition.prototype.adjustImages = function(view) {\n\n\tview.addStylesheetRules([\n\t\t\t[\"img\",\n\t\t\t\t[\"max-width\", (view.layout.spreadWidth) + \"px\"],\n\t\t\t\t[\"max-height\", (view.layout.height) + \"px\"]\n\t\t\t]\n\t]);\n\treturn new RSVP.Promise(function(resolve, reject){\n\t\t// Wait to apply\n\t\tsetTimeout(function() {\n\t\t\tresolve();\n\t\t}, 1);\n\t});\n};\n\n//-- Enable binding events to Renderer\nRSVP.EventTarget.mixin(Rendition.prototype);\n\nmodule.exports = Rendition;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/rendition.js\n ** module id = 24\n ** module chunks = 0\n **/","var core = require('./core');\nvar RSVP = require('rsvp');\n\nfunction Layout(settings){\n\tthis.name = settings.layout || \"reflowable\";\n\tthis._spread = (settings.spread === \"none\") ? false : true;\n\tthis._minSpreadWidth = settings.spread || 800;\n\tthis._evenSpreads = settings.evenSpreads || false;\n\n\tif (settings.flow === \"scrolled-continuous\" ||\n\t\t\tsettings.flow === \"scrolled-doc\") {\n\t\tthis._flow = \"scrolled\";\n\t} else {\n\t\tthis._flow = \"paginated\";\n\t}\n\n\n\tthis.width = 0;\n\tthis.height = 0;\n\tthis.spreadWidth = 0;\n\tthis.delta = 0;\n\n\tthis.columnWidth = 0;\n\tthis.gap = 0;\n\tthis.divisor = 1;\n};\n\n// paginated | scrolled\nLayout.prototype.flow = function(flow) {\n\tthis._flow = (flow === \"paginated\") ? \"paginated\" : \"scrolled\";\n}\n\n// true | false\nLayout.prototype.spread = function(spread, min) {\n\n\tthis._spread = (spread === \"none\") ? false : true;\n\n\tif (min >= 0) {\n\t\tthis._minSpreadWidth = min;\n\t}\n}\n\nLayout.prototype.calculate = function(_width, _height, _gap){\n\n\tvar divisor = 1;\n\tvar gap = _gap || 0;\n\n\t//-- Check the width and create even width columns\n\tvar fullWidth = Math.floor(_width);\n\tvar width = _width;\n\n\tvar section = Math.floor(width / 8);\n\n\tvar colWidth;\n\tvar spreadWidth;\n\tvar delta;\n\n\tif (this._spread && width >= this._minSpreadWidth) {\n\t\tdivisor = 2;\n\t} else {\n\t\tdivisor = 1;\n\t}\n\n\tif (this.name === \"reflowable\" && this._flow === \"paginated\" && !(_gap >= 0)) {\n\t\tgap = ((section % 2 === 0) ? section : section - 1);\n\t}\n\n\tif (this.name === \"pre-paginated\" ) {\n\t\tgap = 0;\n\t}\n\n\t//-- Double Page\n\tif(divisor > 1) {\n\t\tcolWidth = Math.floor((width - gap) / divisor);\n\t} else {\n\t\tcolWidth = width;\n\t}\n\n\tif (this.name === \"pre-paginated\" && divisor > 1) {\n\t\twidth = colWidth;\n\t}\n\n\tspreadWidth = colWidth * divisor;\n\n\tdelta = (colWidth + gap) * divisor;\n\n\tthis.width = width;\n\tthis.height = _height;\n\tthis.spreadWidth = spreadWidth;\n\tthis.delta = delta;\n\n\tthis.columnWidth = colWidth;\n\tthis.gap = gap;\n\tthis.divisor = divisor;\n};\n\nLayout.prototype.format = function(contents){\n\tvar formating;\n\n\tif (this.name === \"pre-paginated\") {\n\t\tformating = contents.fit(this.columnWidth, this.height);\n\t} else if (this._flow === \"paginated\") {\n\t\tformating = contents.columns(this.width, this.height, this.columnWidth, this.gap);\n\t} else { // scrolled\n\t\tformating = contents.size(this.width, null);\n\t}\n\n\treturn formating; // might be a promise in some View Managers\n};\n\nLayout.prototype.count = function(totalWidth) {\n\t// var totalWidth = contents.scrollWidth();\n\tvar spreads = Math.ceil( totalWidth / this.spreadWidth);\n\n\treturn {\n\t\tspreads : spreads,\n\t\tpages : spreads * this.divisor\n\t};\n};\n\nmodule.exports = Layout;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/layout.js\n ** module id = 25\n ** module chunks = 0\n **/","var EpubCFI = require('./epubcfi');\n\nfunction Mapping(layout){\n\tthis.layout = layout;\n};\n\nMapping.prototype.section = function(view) {\n\tvar ranges = this.findRanges(view);\n\tvar map = this.rangeListToCfiList(view.section.cfiBase, ranges);\n\n\treturn map;\n};\n\nMapping.prototype.page = function(contents, cfiBase, start, end) {\n\tvar root = contents && contents.document ? contents.document.body : false;\n\n\tif (!root) {\n\t\treturn;\n\t}\n\n\treturn this.rangePairToCfiPair(cfiBase, {\n\t\tstart: this.findStart(root, start, end),\n\t\tend: this.findEnd(root, start, end)\n\t});\n};\n\nMapping.prototype.walk = function(root, func) {\n\t//var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);\n\tvar treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n\t\t\tacceptNode: function (node) {\n\t\t\t\t\tif ( node.data.trim().length > 0 ) {\n\t\t\t\t\t\treturn NodeFilter.FILTER_ACCEPT;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn NodeFilter.FILTER_REJECT;\n\t\t\t\t\t}\n\t\t\t}\n\t}, false);\n\tvar node;\n\tvar result;\n\twhile ((node = treeWalker.nextNode())) {\n\t\tresult = func(node);\n\t\tif(result) break;\n\t}\n\n\treturn result;\n};\n\nMapping.prototype.findRanges = function(view){\n\tvar columns = [];\n\tvar scrollWidth = view.contents.scrollWidth();\n\tvar count = this.layout.count(scrollWidth);\n\tvar column = this.layout.column;\n\tvar gap = this.layout.gap;\n\tvar start, end;\n\n\tfor (var i = 0; i < count.pages; i++) {\n\t\tstart = (column + gap) * i;\n\t\tend = (column * (i+1)) + (gap * i);\n\t\tcolumns.push({\n\t\t\tstart: this.findStart(view.document.body, start, end),\n\t\t\tend: this.findEnd(view.document.body, start, end)\n\t\t});\n\t}\n\n\treturn columns;\n};\n\nMapping.prototype.findStart = function(root, start, end){\n\tvar stack = [root];\n\tvar $el;\n\tvar found;\n\tvar $prev = root;\n\twhile (stack.length) {\n\n\t\t$el = stack.shift();\n\n\t\tfound = this.walk($el, function(node){\n\t\t\tvar left, right;\n\t\t\tvar elPos;\n\t\t\tvar elRange;\n\n\n\t\t\tif(node.nodeType == Node.TEXT_NODE){\n\t\t\t\telRange = document.createRange();\n\t\t\t\telRange.selectNodeContents(node);\n\t\t\t\telPos = elRange.getBoundingClientRect();\n\t\t\t} else {\n\t\t\t\telPos = node.getBoundingClientRect();\n\t\t\t}\n\n\t\t\tleft = elPos.left;\n\t\t\tright = elPos.right;\n\n\t\t\tif( left >= start && left <= end ) {\n\t\t\t\treturn node;\n\t\t\t} else if (right > start) {\n\t\t\t\treturn node;\n\t\t\t} else {\n\t\t\t\t$prev = node;\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t});\n\n\t\tif(found) {\n\t\t\treturn this.findTextStartRange(found, start, end);\n\t\t}\n\n\t}\n\n\t// Return last element\n\treturn this.findTextStartRange($prev, start, end);\n};\n\nMapping.prototype.findEnd = function(root, start, end){\n\tvar stack = [root];\n\tvar $el;\n\tvar $prev = root;\n\tvar found;\n\n\twhile (stack.length) {\n\n\t\t$el = stack.shift();\n\n\t\tfound = this.walk($el, function(node){\n\n\t\t\tvar left, right;\n\t\t\tvar elPos;\n\t\t\tvar elRange;\n\n\n\t\t\tif(node.nodeType == Node.TEXT_NODE){\n\t\t\t\telRange = document.createRange();\n\t\t\t\telRange.selectNodeContents(node);\n\t\t\t\telPos = elRange.getBoundingClientRect();\n\t\t\t} else {\n\t\t\t\telPos = node.getBoundingClientRect();\n\t\t\t}\n\n\t\t\tleft = elPos.left;\n\t\t\tright = elPos.right;\n\n\t\t\tif(left > end && $prev) {\n\t\t\t\treturn $prev;\n\t\t\t} else if(right > end) {\n\t\t\t\treturn node;\n\t\t\t} else {\n\t\t\t\t$prev = node;\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t});\n\n\n\t\tif(found){\n\t\t\treturn this.findTextEndRange(found, start, end);\n\t\t}\n\n\t}\n\n\t// end of chapter\n\treturn this.findTextEndRange($prev, start, end);\n};\n\n\nMapping.prototype.findTextStartRange = function(node, start, end){\n\tvar ranges = this.splitTextNodeIntoRanges(node);\n\tvar prev;\n\tvar range;\n\tvar pos;\n\n\tfor (var i = 0; i < ranges.length; i++) {\n\t\trange = ranges[i];\n\n\t\tpos = range.getBoundingClientRect();\n\n\t\tif( pos.left >= start ) {\n\t\t\treturn range;\n\t\t}\n\n\t\tprev = range;\n\n\t}\n\n\treturn ranges[0];\n};\n\nMapping.prototype.findTextEndRange = function(node, start, end){\n\tvar ranges = this.splitTextNodeIntoRanges(node);\n\tvar prev;\n\tvar range;\n\tvar pos;\n\n\tfor (var i = 0; i < ranges.length; i++) {\n\t\trange = ranges[i];\n\n\t\tpos = range.getBoundingClientRect();\n\n\t\tif(pos.left > end && prev) {\n\t\t\treturn prev;\n\t\t} else if(pos.right > end) {\n\t\t\treturn range;\n\t\t}\n\n\t\tprev = range;\n\n\t}\n\n\t// Ends before limit\n\treturn ranges[ranges.length-1];\n\n};\n\nMapping.prototype.splitTextNodeIntoRanges = function(node, _splitter){\n\tvar ranges = [];\n\tvar textContent = node.textContent || \"\";\n\tvar text = textContent.trim();\n\tvar range;\n\tvar rect;\n\tvar list;\n\tvar doc = node.ownerDocument;\n\tvar splitter = _splitter || \" \";\n\n\tpos = text.indexOf(splitter);\n\n\tif(pos === -1 || node.nodeType != Node.TEXT_NODE) {\n\t\trange = doc.createRange();\n\t\trange.selectNodeContents(node);\n\t\treturn [range];\n\t}\n\n\trange = doc.createRange();\n\trange.setStart(node, 0);\n\trange.setEnd(node, pos);\n\tranges.push(range);\n\trange = false;\n\n\twhile ( pos != -1 ) {\n\n\t\tpos = text.indexOf(splitter, pos + 1);\n\t\tif(pos > 0) {\n\n\t\t\tif(range) {\n\t\t\t\trange.setEnd(node, pos);\n\t\t\t\tranges.push(range);\n\t\t\t}\n\n\t\t\trange = doc.createRange();\n\t\t\trange.setStart(node, pos+1);\n\t\t}\n\t}\n\n\tif(range) {\n\t\trange.setEnd(node, text.length);\n\t\tranges.push(range);\n\t}\n\n\treturn ranges;\n};\n\n\n\nMapping.prototype.rangePairToCfiPair = function(cfiBase, rangePair){\n\n\tvar startRange = rangePair.start;\n\tvar endRange = rangePair.end;\n\n\tstartRange.collapse(true);\n\tendRange.collapse(true);\n\n\t// startCfi = section.cfiFromRange(startRange);\n\t// endCfi = section.cfiFromRange(endRange);\n\tstartCfi = new EpubCFI(startRange, cfiBase).toString();\n\tendCfi = new EpubCFI(endRange, cfiBase).toString();\n\n\treturn {\n\t\tstart: startCfi,\n\t\tend: endCfi\n\t};\n\n};\n\nMapping.prototype.rangeListToCfiList = function(cfiBase, columns){\n\tvar map = [];\n\tvar rangePair, cifPair;\n\n\tfor (var i = 0; i < columns.length; i++) {\n\t\tcifPair = this.rangePairToCfiPair(cfiBase, columns[i]);\n\n\t\tmap.push(cifPair);\n\n\t}\n\n\treturn map;\n};\n\nmodule.exports = Mapping;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/mapping.js\n ** module id = 26\n ** module chunks = 0\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\tthis.checkRequirements();\n\tthis.urlCache = {};\n\n}\n\nUnarchive.prototype.checkRequirements = function(callback){\n\ttry {\n\t\tif (typeof JSZip !== 'undefined') {\n\t\t\tthis.zip = new JSZip();\n\t\t} else {\n\t\t\tJSZip = require('jszip');\n\t\t\tthis.zip = new JSZip();\n\t\t}\n\t} catch (e) {\n\t\tconsole.error(\"JSZip lib not loaded\");\n\t}\n};\n\nUnarchive.prototype.open = function(zipUrl, isBase64){\n\tif (zipUrl instanceof ArrayBuffer || isBase64) {\n\t\treturn this.zip.loadAsync(zipUrl, {\"base64\": isBase64});\n\t} else {\n\t\treturn request(zipUrl, \"binary\")\n\t\t\t.then(function(data){\n\t\t\t\treturn this.zip.loadAsync(data);\n\t\t\t}.bind(this));\n\t}\n};\n\nUnarchive.prototype.request = function(url, type){\n\tvar deferred = new RSVP.defer();\n\tvar response;\n\tvar r;\n\n\t// 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\tif(type == 'blob'){\n\t\tresponse = this.getBlob(url);\n\t} else {\n\t\tresponse = this.getText(url);\n\t}\n\n\tif (response) {\n\t\tresponse.then(function (r) {\n\t\t\tresult = this.handleResponse(r, type);\n\t\t\tdeferred.resolve(result);\n\t\t}.bind(this));\n\t} else {\n\t\tdeferred.reject({\n\t\t\tmessage : \"File not found in the epub: \" + url,\n\t\t\tstack : new Error().stack\n\t\t});\n\t}\n\treturn deferred.promise;\n};\n\nUnarchive.prototype.handleResponse = function(response, type){\n\tvar r;\n\n\tif(type == \"json\") {\n\t\tr = JSON.parse(response);\n\t}\n\telse\n\tif(core.isXml(type)) {\n\t\tr = core.parse(response, \"text/xml\");\n\t}\n\telse\n\tif(type == 'xhtml') {\n\t\tr = core.parse(response, \"application/xhtml+xml\");\n\t}\n\telse\n\tif(type == 'html' || type == 'htm') {\n\t\tr = core.parse(response, \"text/html\");\n\t } else {\n\t\t r = response;\n\t }\n\n\treturn 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\tvar mimeType;\n\n\tif(entry) {\n\t\tmimeType = _mimeType || mime.lookup(entry.name);\n\t\treturn entry.async(\"uint8array\").then(function(uint8array) {\n\t\t\treturn new Blob([uint8array], {type : mimeType});\n\t\t});\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\t\treturn entry.async(\"string\").then(function(text) {\n\t\t\treturn text;\n\t\t});\n\t}\n};\n\nUnarchive.prototype.getBase64 = function(url, _mimeType){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n\tvar mimeType;\n\n\tif(entry) {\n\t\tmimeType = _mimeType || mime.lookup(entry.name);\n\t\treturn entry.async(\"base64\").then(function(data) {\n\t\t\treturn \"data:\" + mimeType + \";base64,\" + data;\n\t\t});\n\t}\n};\n\nUnarchive.prototype.createUrl = function(url, options){\n\tvar deferred = new RSVP.defer();\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob;\n\tvar response;\n\tvar useBase64 = options && options.base64;\n\n\tif(url in this.urlCache) {\n\t\tdeferred.resolve(this.urlCache[url]);\n\t\treturn deferred.promise;\n\t}\n\n\tif (useBase64) {\n\t\tresponse = this.getBase64(url);\n\n\t\tif (response) {\n\t\t\tresponse.then(function(tempUrl) {\n\n\t\t\t\tthis.urlCache[url] = tempUrl;\n\t\t\t\tdeferred.resolve(tempUrl);\n\n\t\t\t}.bind(this));\n\n\t\t}\n\n\t} else {\n\n\t\tresponse = this.getBlob(url);\n\n\t\tif (response) {\n\t\t\tresponse.then(function(blob) {\n\n\t\t\t\ttempUrl = _URL.createObjectURL(blob);\n\t\t\t\tthis.urlCache[url] = tempUrl;\n\t\t\t\tdeferred.resolve(tempUrl);\n\n\t\t\t}.bind(this));\n\n\t\t}\n\t}\n\n\n\tif (!response) {\n\t\tdeferred.reject({\n\t\t\tmessage : \"File not found in the epub: \" + url,\n\t\t\tstack : new Error().stack\n\t\t});\n\t}\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\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/unarchive.js\n ** module id = 27\n ** module chunks = 0\n **/","/*\n From Zip.js, by Gildas Lormeau\nedited down\n */\n\nvar table = {\n\t\"application\" : {\n\t\t\"ecmascript\" : [ \"es\", \"ecma\" ],\n\t\t\"javascript\" : \"js\",\n\t\t\"ogg\" : \"ogx\",\n\t\t\"pdf\" : \"pdf\",\n\t\t\"postscript\" : [ \"ps\", \"ai\", \"eps\", \"epsi\", \"epsf\", \"eps2\", \"eps3\" ],\n\t\t\"rdf+xml\" : \"rdf\",\n\t\t\"smil\" : [ \"smi\", \"smil\" ],\n\t\t\"xhtml+xml\" : [ \"xhtml\", \"xht\" ],\n\t\t\"xml\" : [ \"xml\", \"xsl\", \"xsd\", \"opf\", \"ncx\" ],\n\t\t\"zip\" : \"zip\",\n\t\t\"x-httpd-eruby\" : \"rhtml\",\n\t\t\"x-latex\" : \"latex\",\n\t\t\"x-maker\" : [ \"frm\", \"maker\", \"frame\", \"fm\", \"fb\", \"book\", \"fbdoc\" ],\n\t\t\"x-object\" : \"o\",\n\t\t\"x-shockwave-flash\" : [ \"swf\", \"swfl\" ],\n\t\t\"x-silverlight\" : \"scr\",\n\t\t\"epub+zip\" : \"epub\",\n\t\t\"font-tdpfr\" : \"pfr\",\n\t\t\"inkml+xml\" : [ \"ink\", \"inkml\" ],\n\t\t\"json\" : \"json\",\n\t\t\"jsonml+json\" : \"jsonml\",\n\t\t\"mathml+xml\" : \"mathml\",\n\t\t\"metalink+xml\" : \"metalink\",\n\t\t\"mp4\" : \"mp4s\",\n\t\t// \"oebps-package+xml\" : \"opf\",\n\t\t\"omdoc+xml\" : \"omdoc\",\n\t\t\"oxps\" : \"oxps\",\n\t\t\"vnd.amazon.ebook\" : \"azw\",\n\t\t\"widget\" : \"wgt\",\n\t\t// \"x-dtbncx+xml\" : \"ncx\",\n\t\t\"x-dtbook+xml\" : \"dtb\",\n\t\t\"x-dtbresource+xml\" : \"res\",\n\t\t\"x-font-bdf\" : \"bdf\",\n\t\t\"x-font-ghostscript\" : \"gsf\",\n\t\t\"x-font-linux-psf\" : \"psf\",\n\t\t\"x-font-otf\" : \"otf\",\n\t\t\"x-font-pcf\" : \"pcf\",\n\t\t\"x-font-snf\" : \"snf\",\n\t\t\"x-font-ttf\" : [ \"ttf\", \"ttc\" ],\n\t\t\"x-font-type1\" : [ \"pfa\", \"pfb\", \"pfm\", \"afm\" ],\n\t\t\"x-font-woff\" : \"woff\",\n\t\t\"x-mobipocket-ebook\" : [ \"prc\", \"mobi\" ],\n\t\t\"x-mspublisher\" : \"pub\",\n\t\t\"x-nzb\" : \"nzb\",\n\t\t\"x-tgif\" : \"obj\",\n\t\t\"xaml+xml\" : \"xaml\",\n\t\t\"xml-dtd\" : \"dtd\",\n\t\t\"xproc+xml\" : \"xpl\",\n\t\t\"xslt+xml\" : \"xslt\",\n\t\t\"internet-property-stream\" : \"acx\",\n\t\t\"x-compress\" : \"z\",\n\t\t\"x-compressed\" : \"tgz\",\n\t\t\"x-gzip\" : \"gz\",\n\t},\n\t\"audio\" : {\n\t\t\"flac\" : \"flac\",\n\t\t\"midi\" : [ \"mid\", \"midi\", \"kar\", \"rmi\" ],\n\t\t\"mpeg\" : [ \"mpga\", \"mpega\", \"mp2\", \"mp3\", \"m4a\", \"mp2a\", \"m2a\", \"m3a\" ],\n\t\t\"mpegurl\" : \"m3u\",\n\t\t\"ogg\" : [ \"oga\", \"ogg\", \"spx\" ],\n\t\t\"x-aiff\" : [ \"aif\", \"aiff\", \"aifc\" ],\n\t\t\"x-ms-wma\" : \"wma\",\n\t\t\"x-wav\" : \"wav\",\n\t\t\"adpcm\" : \"adp\",\n\t\t\"mp4\" : \"mp4a\",\n\t\t\"webm\" : \"weba\",\n\t\t\"x-aac\" : \"aac\",\n\t\t\"x-caf\" : \"caf\",\n\t\t\"x-matroska\" : \"mka\",\n\t\t\"x-pn-realaudio-plugin\" : \"rmp\",\n\t\t\"xm\" : \"xm\",\n\t\t\"mid\" : [ \"mid\", \"rmi\" ]\n\t},\n\t\"image\" : {\n\t\t\"gif\" : \"gif\",\n\t\t\"ief\" : \"ief\",\n\t\t\"jpeg\" : [ \"jpeg\", \"jpg\", \"jpe\" ],\n\t\t\"pcx\" : \"pcx\",\n\t\t\"png\" : \"png\",\n\t\t\"svg+xml\" : [ \"svg\", \"svgz\" ],\n\t\t\"tiff\" : [ \"tiff\", \"tif\" ],\n\t\t\"x-icon\" : \"ico\",\n\t\t\"bmp\" : \"bmp\",\n\t\t\"webp\" : \"webp\",\n\t\t\"x-pict\" : [ \"pic\", \"pct\" ],\n\t\t\"x-tga\" : \"tga\",\n\t\t\"cis-cod\" : \"cod\"\n\t},\n\t\"text\" : {\n\t\t\"cache-manifest\" : [ \"manifest\", \"appcache\" ],\n\t\t\"css\" : \"css\",\n\t\t\"csv\" : \"csv\",\n\t\t\"html\" : [ \"html\", \"htm\", \"shtml\", \"stm\" ],\n\t\t\"mathml\" : \"mml\",\n\t\t\"plain\" : [ \"txt\", \"text\", \"brf\", \"conf\", \"def\", \"list\", \"log\", \"in\", \"bas\" ],\n\t\t\"richtext\" : \"rtx\",\n\t\t\"tab-separated-values\" : \"tsv\",\n\t\t\"x-bibtex\" : \"bib\"\n\t},\n\t\"video\" : {\n\t\t\"mpeg\" : [ \"mpeg\", \"mpg\", \"mpe\", \"m1v\", \"m2v\", \"mp2\", \"mpa\", \"mpv2\" ],\n\t\t\"mp4\" : [ \"mp4\", \"mp4v\", \"mpg4\" ],\n\t\t\"quicktime\" : [ \"qt\", \"mov\" ],\n\t\t\"ogg\" : \"ogv\",\n\t\t\"vnd.mpegurl\" : [ \"mxu\", \"m4u\" ],\n\t\t\"x-flv\" : \"flv\",\n\t\t\"x-la-asf\" : [ \"lsf\", \"lsx\" ],\n\t\t\"x-mng\" : \"mng\",\n\t\t\"x-ms-asf\" : [ \"asf\", \"asx\", \"asr\" ],\n\t\t\"x-ms-wm\" : \"wm\",\n\t\t\"x-ms-wmv\" : \"wmv\",\n\t\t\"x-ms-wmx\" : \"wmx\",\n\t\t\"x-ms-wvx\" : \"wvx\",\n\t\t\"x-msvideo\" : \"avi\",\n\t\t\"x-sgi-movie\" : \"movie\",\n\t\t\"x-matroska\" : [ \"mpv\", \"mkv\", \"mk3d\", \"mks\" ],\n\t\t\"3gpp2\" : \"3g2\",\n\t\t\"h261\" : \"h261\",\n\t\t\"h263\" : \"h263\",\n\t\t\"h264\" : \"h264\",\n\t\t\"jpeg\" : \"jpgv\",\n\t\t\"jpm\" : [ \"jpm\", \"jpgm\" ],\n\t\t\"mj2\" : [ \"mj2\", \"mjp2\" ],\n\t\t\"vnd.ms-playready.media.pyv\" : \"pyv\",\n\t\t\"vnd.uvvu.mp4\" : [ \"uvu\", \"uvvu\" ],\n\t\t\"vnd.vivo\" : \"viv\",\n\t\t\"webm\" : \"webm\",\n\t\t\"x-f4v\" : \"f4v\",\n\t\t\"x-m4v\" : \"m4v\",\n\t\t\"x-ms-vob\" : \"vob\",\n\t\t\"x-smv\" : \"smv\"\n\t}\n};\n\nvar mimeTypes = (function() {\n\tvar type, subtype, val, index, mimeTypes = {};\n\tfor (type in table) {\n\t\tif (table.hasOwnProperty(type)) {\n\t\t\tfor (subtype in table[type]) {\n\t\t\t\tif (table[type].hasOwnProperty(subtype)) {\n\t\t\t\t\tval = table[type][subtype];\n\t\t\t\t\tif (typeof val == \"string\") {\n\t\t\t\t\t\tmimeTypes[val] = type + \"/\" + subtype;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (index = 0; index < val.length; index++) {\n\t\t\t\t\t\t\tmimeTypes[val[index]] = type + \"/\" + subtype;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn mimeTypes;\n})();\n\nvar defaultValue = \"text/plain\";//\"application/octet-stream\";\n\nfunction lookup(filename) {\n\treturn filename && mimeTypes[filename.split(\".\").pop().toLowerCase()] || defaultValue;\n};\n\nmodule.exports = {\n\t'lookup': lookup\n}\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./libs/mime/mime.js\n ** module id = 28\n ** module chunks = 0\n **/","if(typeof __WEBPACK_EXTERNAL_MODULE_29__ === 'undefined') {var e = new Error(\"Cannot find module \\\"JSZip\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e;}\nmodule.exports = __WEBPACK_EXTERNAL_MODULE_29__;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** external \"JSZip\"\n ** module id = 29\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Mapping = require('./mapping');\n\n\nfunction Contents(doc, content, cfiBase) {\n\t// Blank Cfi for Parsing\n\tthis.epubcfi = new EpubCFI();\n\n\tthis.document = doc;\n\tthis.documentElement = this.document.documentElement;\n\tthis.content = content || this.document.body;\n\tthis.window = this.document.defaultView;\n\t// Dom events to listen for\n\tthis.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n\n\tthis._size = {\n\t\twidth: 0,\n\t\theight: 0\n\t}\n\n\tthis.cfiBase = cfiBase || \"\";\n\n\tthis.listeners();\n};\n\nContents.prototype.width = function(w) {\n\t// var frame = this.documentElement;\n\tvar frame = this.content;\n\n\tif (w && core.isNumber(w)) {\n\t\tw = w + \"px\";\n\t}\n\n\tif (w) {\n\t\tframe.style.width = w;\n\t\t// this.content.style.width = w;\n\t}\n\n\treturn this.window.getComputedStyle(frame)['width'];\n\n\n};\n\nContents.prototype.height = function(h) {\n\t// var frame = this.documentElement;\n\tvar frame = this.content;\n\n\tif (h && core.isNumber(h)) {\n\t\th = h + \"px\";\n\t}\n\n\tif (h) {\n\t\tframe.style.height = h;\n\t\t// this.content.style.height = h;\n\t}\n\n\treturn this.window.getComputedStyle(frame)['height'];\n\n};\n\nContents.prototype.contentWidth = function(w) {\n\n\tvar content = this.content || this.document.body;\n\n\tif (w && core.isNumber(w)) {\n\t\tw = w + \"px\";\n\t}\n\n\tif (w) {\n\t\tcontent.style.width = w;\n\t}\n\n\treturn this.window.getComputedStyle(content)['width'];\n\n\n};\n\nContents.prototype.contentHeight = function(h) {\n\n\tvar content = this.content || this.document.body;\n\n\tif (h && core.isNumber(h)) {\n\t\th = h + \"px\";\n\t}\n\n\tif (h) {\n\t\tcontent.style.height = h;\n\t}\n\n\treturn this.window.getComputedStyle(content)['height'];\n\n};\n\nContents.prototype.textWidth = function() {\n\tvar width;\n\tvar range = this.document.createRange();\n\tvar content = this.content || this.document.body;\n\n\t// Select the contents of frame\n\trange.selectNodeContents(content);\n\n\t// get the width of the text content\n\twidth = range.getBoundingClientRect().width;\n\n\treturn width;\n\n};\n\nContents.prototype.textHeight = function() {\n\tvar height;\n\tvar range = this.document.createRange();\n\tvar content = this.content || this.document.body;\n\n\trange.selectNodeContents(content);\n\n\theight = range.getBoundingClientRect().height;\n\n\treturn height;\n};\n\nContents.prototype.scrollWidth = function() {\n\tvar width = this.documentElement.scrollWidth;\n\n\treturn width;\n};\n\nContents.prototype.scrollHeight = function() {\n\tvar height = this.documentElement.scrollHeight;\n\n\treturn height;\n};\n\nContents.prototype.overflow = function(overflow) {\n\n\tif (overflow) {\n\t\tthis.documentElement.style.overflow = overflow;\n\t}\n\n\treturn this.window.getComputedStyle(this.documentElement)['overflow'];\n};\n\nContents.prototype.overflowX = function(overflow) {\n\n\tif (overflow) {\n\t\tthis.documentElement.style.overflowX = overflow;\n\t}\n\n\treturn this.window.getComputedStyle(this.documentElement)['overflowX'];\n};\n\nContents.prototype.overflowY = function(overflow) {\n\n\tif (overflow) {\n\t\tthis.documentElement.style.overflowY = overflow;\n\t}\n\n\treturn this.window.getComputedStyle(this.documentElement)['overflowY'];\n};\n\nContents.prototype.css = function(property, value) {\n\tvar content = this.content || this.document.body;\n\n\tif (value) {\n\t\tcontent.style[property] = value;\n\t}\n\n\treturn this.window.getComputedStyle(content)[property];\n};\n\nContents.prototype.viewport = function(options) {\n\tvar width, height, scale, scalable;\n\tvar $viewport = this.document.querySelector(\"meta[name='viewport']\");\n\tvar newContent = '';\n\n\t/**\n\t* check for the viewport size\n\t* \n\t*/\n\tif($viewport && $viewport.hasAttribute(\"content\")) {\n\t\tcontent = $viewport.getAttribute(\"content\");\n\t\tcontents = content.split(/\\s*,\\s*/);\n\t\tif(contents[0]){\n\t\t\twidth = contents[0].replace(\"width=\", '').trim();\n\t\t}\n\t\tif(contents[1]){\n\t\t\theight = contents[1].replace(\"height=\", '').trim();\n\t\t}\n\t\tif(contents[2]){\n\t\t\tscale = contents[2].replace(\"initial-scale=\", '').trim();\n\t\t}\n\t\tif(contents[3]){\n\t\t\tscalable = contents[3].replace(\"user-scalable=\", '').trim();\n\t\t}\n\t}\n\n\tif (options) {\n\n\t\tnewContent += \"width=\" + (options.width || width);\n\t\tnewContent += \", height=\" + (options.height || height);\n\t\tif (options.scale || scale) {\n\t\t\tnewContent += \", initial-scale=\" + (options.scale || scale);\n\t\t}\n\t\tif (options.scalable || scalable) {\n\t\t\tnewContent += \", user-scalable=\" + (options.scalable || scalable);\n\t\t}\n\n\t\tif (!$viewport) {\n\t\t\t$viewport = this.document.createElement(\"meta\");\n\t\t\t$viewport.setAttribute(\"name\", \"viewport\");\n\t\t\tthis.document.querySelector('head').appendChild($viewport);\n\t\t}\n\n\t\t$viewport.setAttribute(\"content\", newContent);\n\t}\n\n\n\treturn {\n\t\twidth: parseInt(width),\n\t\theight: parseInt(height)\n\t};\n};\n\n\n// Contents.prototype.layout = function(layoutFunc) {\n//\n// this.iframe.style.display = \"inline-block\";\n//\n// // Reset Body Styles\n// this.content.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//\n// Contents.prototype.onLayout = function(view) {\n// // stub\n// };\n\nContents.prototype.expand = function() {\n\tthis.trigger(\"expand\");\n};\n\nContents.prototype.listeners = function() {\n\n\tthis.imageLoadListeners();\n\n\tthis.mediaQueryListeners();\n\n\t// this.fontLoadListeners();\n\n\tthis.addEventListeners();\n\n\tthis.addSelectionListeners();\n\n\tthis.resizeListeners();\n\n};\n\nContents.prototype.removeListeners = function() {\n\n\tthis.removeEventListeners();\n\n\tthis.removeSelectionListeners();\n};\n\nContents.prototype.resizeListeners = function() {\n\tvar width, height;\n\t// Test size again\n\tclearTimeout(this.expanding);\n\n\twidth = this.scrollWidth();\n\theight = this.scrollHeight();\n\n\tif (width != this._size.width || height != this._size.height) {\n\n\t\tthis._size = {\n\t\t\twidth: width,\n\t\t\theight: height\n\t\t}\n\n\t\tthis.trigger(\"resize\", this._size);\n\t}\n\n\tthis.expanding = setTimeout(this.resizeListeners.bind(this), 350);\n};\n\n//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js\nContents.prototype.mediaQueryListeners = function() {\n\t\tvar sheets = this.document.styleSheets;\n\t\tvar mediaChangeHandler = function(m){\n\t\t\tif(m.matches && !this._expanding) {\n\t\t\t\tsetTimeout(this.expand.bind(this), 1);\n\t\t\t\t// this.expand();\n\t\t\t}\n\t\t}.bind(this);\n\n\t\tfor (var i = 0; i < sheets.length; i += 1) {\n\t\t\t\tvar rules = sheets[i].cssRules;\n\t\t\t\tif(!rules) return; // Stylesheets changed\n\t\t\t\tfor (var j = 0; j < rules.length; j += 1) {\n\t\t\t\t\t\t//if (rules[j].constructor === CSSMediaRule) {\n\t\t\t\t\t\tif(rules[j].media){\n\t\t\t\t\t\t\t\tvar mql = this.window.matchMedia(rules[j].media.mediaText);\n\t\t\t\t\t\t\t\tmql.addListener(mediaChangeHandler);\n\t\t\t\t\t\t\t\t//mql.onchange = mediaChangeHandler;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n};\n\nContents.prototype.observe = function(target) {\n\tvar renderer = this;\n\n\t// create an observer instance\n\tvar observer = new MutationObserver(function(mutations) {\n\t\tif(renderer._expanding) {\n\t\t\trenderer.expand();\n\t\t}\n\t\t// mutations.forEach(function(mutation) {\n\t\t// console.log(mutation);\n\t\t// });\n\t});\n\n\t// configuration of the observer:\n\tvar config = { attributes: true, childList: true, characterData: true, subtree: true };\n\n\t// pass in the target node, as well as the observer options\n\tobserver.observe(target, config);\n\n\treturn observer;\n};\n\nContents.prototype.imageLoadListeners = function(target) {\n\tvar images = this.document.querySelectorAll(\"img\");\n\tvar img;\n\tfor (var i = 0; i < images.length; i++) {\n\t\timg = images[i];\n\n\t\tif (typeof img.naturalWidth !== \"undefined\" &&\n\t\t\t\timg.naturalWidth === 0) {\n\t\t\timg.onload = this.expand.bind(this);\n\t\t}\n\t}\n};\n\nContents.prototype.fontLoadListeners = function(target) {\n\tif (!this.document || !this.document.fonts) {\n\t\treturn;\n\t}\n\n\tthis.document.fonts.ready.then(function () {\n\t\tthis.expand();\n\t}.bind(this));\n\n};\n\nContents.prototype.root = function() {\n\tif(!this.document) return null;\n\treturn this.document.documentElement;\n};\n\nContents.prototype.locationOf = function(target, ignoreClass) {\n\tvar position;\n\tvar targetPos = {\"left\": 0, \"top\": 0};\n\n\tif(!this.document) return;\n\n\tif(this.epubcfi.isCfiString(target)) {\n\t\trange = new EpubCFI(target).toRange(this.document, ignoreClass);\n\n\t\tif(range) {\n\t\t\tif (range.startContainer.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\tposition = range.startContainer.getBoundingClientRect();\n\t\t\t\ttargetPos.left = position.left;\n\t\t\t\ttargetPos.top = position.top;\n\t\t\t} else {\n\t\t\t\tposition = range.getBoundingClientRect();\n\t\t\t\ttargetPos.left = position.left;\n\t\t\t\ttargetPos.top = position.top;\n\t\t\t}\n\t\t}\n\n\t} else if(typeof target === \"string\" &&\n\t\ttarget.indexOf(\"#\") > -1) {\n\n\t\tid = target.substring(target.indexOf(\"#\")+1);\n\t\tel = this.document.getElementById(id);\n\n\t\tif(el) {\n\t\t\tposition = el.getBoundingClientRect();\n\t\t\ttargetPos.left = position.left;\n\t\t\ttargetPos.top = position.top;\n\t\t}\n\t}\n\n\treturn targetPos;\n};\n\nContents.prototype.addStylesheet = function(src) {\n\treturn new RSVP.Promise(function(resolve, reject){\n\t\tvar $stylesheet;\n\t\tvar ready = false;\n\n\t\tif(!this.document) {\n\t\t\tresolve(false);\n\t\t\treturn;\n\t\t}\n\n\t\t$stylesheet = this.document.createElement('link');\n\t\t$stylesheet.type = 'text/css';\n\t\t$stylesheet.rel = \"stylesheet\";\n\t\t$stylesheet.href = src;\n\t\t$stylesheet.onload = $stylesheet.onreadystatechange = function() {\n\t\t\tif ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n\t\t\t\tready = true;\n\t\t\t\t// Let apply\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tresolve(true);\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t};\n\n\t\tthis.document.head.appendChild($stylesheet);\n\n\t}.bind(this));\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule\nContents.prototype.addStylesheetRules = function(rules) {\n\tvar styleEl;\n\tvar styleSheet;\n\n\tif(!this.document) return;\n\n\tstyleEl = this.document.createElement('style');\n\n\t// Append style element to head\n\tthis.document.head.appendChild(styleEl);\n\n\t// Grab style sheet\n\tstyleSheet = styleEl.sheet;\n\n\tfor (var i = 0, rl = rules.length; i < rl; i++) {\n\t\tvar j = 1, rule = rules[i], selector = rules[i][0], propStr = '';\n\t\t// If the second argument of a rule is an array of arrays, correct our variables.\n\t\tif (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {\n\t\t\trule = rule[1];\n\t\t\tj = 0;\n\t\t}\n\n\t\tfor (var pl = rule.length; j < pl; j++) {\n\t\t\tvar prop = rule[j];\n\t\t\tpropStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\\n';\n\t\t}\n\n\t\t// Insert CSS Rule\n\t\tstyleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);\n\t}\n};\n\nContents.prototype.addScript = function(src) {\n\n\treturn new RSVP.Promise(function(resolve, reject){\n\t\tvar $script;\n\t\tvar ready = false;\n\n\t\tif(!this.document) {\n\t\t\tresolve(false);\n\t\t\treturn;\n\t\t}\n\n\t\t$script = this.document.createElement('script');\n\t\t$script.type = 'text/javascript';\n\t\t$script.async = true;\n\t\t$script.src = src;\n\t\t$script.onload = $script.onreadystatechange = function() {\n\t\t\tif ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n\t\t\t\tready = true;\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tresolve(true);\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t};\n\n\t\tthis.document.head.appendChild($script);\n\n\t}.bind(this));\n};\n\nContents.prototype.addEventListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.listenedEvents.forEach(function(eventName){\n\t\tthis.document.addEventListener(eventName, this.triggerEvent.bind(this), false);\n\t}, this);\n\n};\n\nContents.prototype.removeEventListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.listenedEvents.forEach(function(eventName){\n\t\tthis.document.removeEventListener(eventName, this.triggerEvent, false);\n\t}, this);\n\n};\n\n// Pass browser events\nContents.prototype.triggerEvent = function(e){\n\tthis.trigger(e.type, e);\n};\n\nContents.prototype.addSelectionListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.document.addEventListener(\"selectionchange\", this.onSelectionChange.bind(this), false);\n};\n\nContents.prototype.removeSelectionListeners = function(){\n\tif(!this.document) {\n\t\treturn;\n\t}\n\tthis.document.removeEventListener(\"selectionchange\", this.onSelectionChange, false);\n};\n\nContents.prototype.onSelectionChange = function(e){\n\tif (this.selectionEndTimeout) {\n\t\tclearTimeout(this.selectionEndTimeout);\n\t}\n\tthis.selectionEndTimeout = setTimeout(function() {\n\t\tvar selection = this.window.getSelection();\n\t\tthis.triggerSelectedEvent(selection);\n\t}.bind(this), 500);\n};\n\nContents.prototype.triggerSelectedEvent = function(selection){\n\tvar range, cfirange;\n\n\tif (selection && selection.rangeCount > 0) {\n\t\trange = selection.getRangeAt(0);\n\t\tif(!range.collapsed) {\n\t\t\t// cfirange = this.section.cfiFromRange(range);\n\t\t\tcfirange = new EpubCFI(range, this.cfiBase).toString();\n\t\t\tthis.trigger(\"selected\", cfirange);\n\t\t\tthis.trigger(\"selectedRange\", range);\n\t\t}\n\t}\n};\n\nContents.prototype.range = function(_cfi, ignoreClass){\n\tvar cfi = new EpubCFI(_cfi);\n\treturn cfi.toRange(this.document, ignoreClass);\n};\n\nContents.prototype.map = function(layout){\n\tvar map = new Mapping(layout);\n\treturn map.section();\n};\n\nContents.prototype.size = function(width, height){\n\n\tif (width >= 0) {\n\t\tthis.width(width);\n\t}\n\n\tif (height >= 0) {\n\t\tthis.height(height);\n\t}\n\n\tthis.css(\"margin\", \"0\");\n\tthis.css(\"boxSizing\", \"border-box\");\n\n};\n\nContents.prototype.columns = function(width, height, columnWidth, gap){\n\tvar COLUMN_AXIS = core.prefixed('columnAxis');\n\tvar COLUMN_GAP = core.prefixed('columnGap');\n\tvar COLUMN_WIDTH = core.prefixed('columnWidth');\n\tvar COLUMN_FILL = core.prefixed('columnFill');\n\tvar textWidth;\n\n\tthis.width(width);\n\tthis.height(height);\n\n\t// Deal with Mobile trying to scale to viewport\n\tthis.viewport({ width: width, height: height, scale: 1.0 });\n\n\t// this.overflowY(\"hidden\");\n\tthis.css(\"overflowY\", \"hidden\");\n\tthis.css(\"margin\", \"0\");\n\tthis.css(\"boxSizing\", \"border-box\");\n\tthis.css(\"maxWidth\", \"inherit\");\n\n\tthis.css(COLUMN_AXIS, \"horizontal\");\n\tthis.css(COLUMN_FILL, \"auto\");\n\n\tthis.css(COLUMN_GAP, gap+\"px\");\n\tthis.css(COLUMN_WIDTH, columnWidth+\"px\");\n};\n\nContents.prototype.scale = function(scale, offsetX, offsetY){\n\tvar scale = \"scale(\" + scale + \")\";\n\tvar translate = '';\n\t// this.css(\"position\", \"absolute\"));\n\tthis.css(\"transformOrigin\", \"top left\");\n\n\tif (offsetX >= 0 || offsetY >= 0) {\n\t\ttranslate = \" translate(\" + (offsetX || 0 )+ \"px, \" + (offsetY || 0 )+ \"px )\";\n\t}\n\n\tthis.css(\"transform\", scale + translate);\n};\n\nContents.prototype.fit = function(width, height){\n\tvar viewport = this.viewport();\n\tvar widthScale = width / viewport.width;\n\tvar heightScale = height / viewport.height;\n\tvar scale = widthScale < heightScale ? widthScale : heightScale;\n\n\tvar offsetY = (height - (viewport.height * scale)) / 2;\n\n\tthis.width(width);\n\tthis.height(height);\n\tthis.overflow(\"hidden\");\n\n\t// Deal with Mobile trying to scale to viewport\n\tthis.viewport({ scale: 1.0 });\n\n\t// Scale to the correct size\n\tthis.scale(scale, 0, offsetY);\n\n\tthis.css(\"backgroundColor\", \"transparent\");\n};\n\nContents.prototype.mapPage = function(cfiBase, start, end) {\n\tvar mapping = new Mapping();\n\n\treturn mapping.page(this, cfiBase, start, end);\n};\n\nContents.prototype.destroy = function() {\n\t// Stop observing\n\tif(this.observer) {\n\t\tthis.observer.disconnect();\n\t}\n\n\tthis.removeListeners();\n\n};\n\nRSVP.EventTarget.mixin(Contents.prototype);\n\nmodule.exports = Contents;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/contents.js\n ** module id = 30\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar core = require('../../core');\nvar EpubCFI = require('../../epubcfi');\nvar Contents = require('../../contents');\n\nfunction IframeView(section, options) {\n\tthis.settings = core.extend({\n\t\tignoreClass : '',\n\t\taxis: 'vertical',\n\t\twidth: 0,\n\t\theight: 0,\n\t\tlayout: undefined,\n\t\tglobalLayoutProperties: {},\n\t}, options || {});\n\n\tthis.id = \"epubjs-view-\" + core.uuid();\n\tthis.section = section;\n\tthis.index = section.index;\n\n\tthis.element = this.container(this.settings.axis);\n\n\tthis.added = false;\n\tthis.displayed = false;\n\tthis.rendered = false;\n\n\tthis.width = this.settings.width;\n\tthis.height = this.settings.height;\n\n\tthis.fixedWidth = 0;\n\tthis.fixedHeight = 0;\n\n\t// Blank Cfi for Parsing\n\tthis.epubcfi = new EpubCFI();\n\n\tthis.layout = this.settings.layout;\n\t// Dom events to listen for\n\t// this.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n};\n\nIframeView.prototype.container = function(axis) {\n\tvar element = document.createElement('div');\n\n\telement.classList.add(\"epub-view\");\n\n\t// this.element.style.minHeight = \"100px\";\n\telement.style.height = \"0px\";\n\telement.style.width = \"0px\";\n\telement.style.overflow = \"hidden\";\n\n\tif(axis && axis == \"horizontal\"){\n\t\telement.style.display = \"inline-block\";\n\t} else {\n\t\telement.style.display = \"block\";\n\t}\n\n\treturn element;\n};\n\nIframeView.prototype.create = function() {\n\n\tif(this.iframe) {\n\t\treturn this.iframe;\n\t}\n\n\tif(!this.element) {\n\t\tthis.element = this.createContainer();\n\t}\n\n\tthis.iframe = document.createElement('iframe');\n\tthis.iframe.id = this.id;\n\tthis.iframe.scrolling = \"no\"; // Might need to be removed: breaks ios width calculations\n\tthis.iframe.style.overflow = \"hidden\";\n\tthis.iframe.seamless = \"seamless\";\n\t// Back up if seamless isn't supported\n\tthis.iframe.style.border = \"none\";\n\n\tthis.resizing = true;\n\n\t// this.iframe.style.display = \"none\";\n\tthis.element.style.visibility = \"hidden\";\n\tthis.iframe.style.visibility = \"hidden\";\n\n\tthis.iframe.style.width = \"0\";\n\tthis.iframe.style.height = \"0\";\n\tthis._width = 0;\n\tthis._height = 0;\n\n\tthis.element.appendChild(this.iframe);\n\tthis.added = true;\n\n\tthis.elementBounds = core.bounds(this.element);\n\n\t// if(width || height){\n\t// this.resize(width, height);\n\t// } else if(this.width && this.height){\n\t// this.resize(this.width, this.height);\n\t// } else {\n\t// this.iframeBounds = core.bounds(this.iframe);\n\t// }\n\n\t// Firefox has trouble with baseURI and srcdoc\n\t// TODO: Disable for now in firefox\n\n\tif(!!(\"srcdoc\" in this.iframe)) {\n\t\tthis.supportsSrcdoc = true;\n\t} else {\n\t\tthis.supportsSrcdoc = false;\n\t}\n\n\treturn this.iframe;\n};\n\nIframeView.prototype.render = function(request, show) {\n\n\t// view.onLayout = this.layout.format.bind(this.layout);\n\tthis.create();\n\n\t// Fit to size of the container, apply padding\n\tthis.size();\n\n\tif(!this.sectionRender) {\n\t\tthis.sectionRender = this.section.render(request);\n\t}\n\n\t// Render Chain\n\treturn this.sectionRender\n\t\t.then(function(contents){\n\t\t\treturn this.load(contents);\n\t\t}.bind(this))\n\t\t// .then(function(doc){\n\t\t// \treturn this.hooks.content.trigger(view, this);\n\t\t// }.bind(this))\n\t\t.then(function(){\n\t\t\t// this.settings.layout.format(view.contents);\n\t\t\t// return this.hooks.layout.trigger(view, this);\n\t\t}.bind(this))\n\t\t// .then(function(){\n\t\t// \treturn this.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\n\t\t\t// apply the layout function to the contents\n\t\t\tthis.settings.layout.format(this.contents);\n\n\t\t\t// Expand the iframe to the full size of the content\n\t\t\tthis.expand();\n\n\t\t\t// Listen for events that require an expansion of the iframe\n\t\t\tthis.addListeners();\n\n\t\t\tif(show !== false) {\n\t\t\t\t//this.q.enqueue(function(view){\n\t\t\t\t\t// this.show();\n\t\t\t\t//}, view);\n\t\t\t}\n\t\t\t// this.map = new Map(view, this.layout);\n\t\t\t//this.hooks.show.trigger(view, this);\n\t\t\tthis.trigger(\"rendered\", this.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// Determine locks base on settings\nIframeView.prototype.size = function(_width, _height) {\n\tvar width = _width || this.settings.width;\n\tvar height = _height || this.settings.height;\n\n\tif(this.layout.name === \"pre-paginated\") {\n\t\tthis.lock(\"both\", width, height);\n\t} else if(this.settings.axis === \"horizontal\") {\n\t\tthis.lock(\"height\", width, height);\n\t} else {\n\t\tthis.lock(\"width\", width, height);\n\t}\n\n};\n\n// Lock an axis to element dimensions, taking borders into account\nIframeView.prototype.lock = function(what, width, height) {\n\tvar elBorders = core.borders(this.element);\n\tvar iframeBorders;\n\n\tif(this.iframe) {\n\t\tiframeBorders = core.borders(this.iframe);\n\t} else {\n\t\tiframeBorders = {width: 0, height: 0};\n\t}\n\n\tif(what == \"width\" && core.isNumber(width)){\n\t\tthis.lockedWidth = width - elBorders.width - iframeBorders.width;\n\t\tthis.resize(this.lockedWidth, width); // width keeps ratio correct\n\t}\n\n\tif(what == \"height\" && core.isNumber(height)){\n\t\tthis.lockedHeight = height - elBorders.height - iframeBorders.height;\n\t\tthis.resize(width, this.lockedHeight);\n\t}\n\n\tif(what === \"both\" &&\n\t\t core.isNumber(width) &&\n\t\t core.isNumber(height)){\n\n\t\tthis.lockedWidth = width - elBorders.width - iframeBorders.width;\n\t\tthis.lockedHeight = height - elBorders.height - iframeBorders.height;\n\n\t\tthis.resize(this.lockedWidth, this.lockedHeight);\n\t}\n\n\tif(this.displayed && this.iframe) {\n\n\t\t\t// this.contents.layout();\n\t\t\tthis.expand();\n\n\t}\n\n\n\n};\n\n// Resize a single axis based on content dimensions\nIframeView.prototype.expand = function(force) {\n\tvar width = this.lockedWidth;\n\tvar height = this.lockedHeight;\n\tvar columns;\n\n\tvar textWidth, textHeight;\n\n\tif(!this.iframe || this._expanding) return;\n\n\tthis._expanding = true;\n\n\t// Expand Horizontally\n\t// if(height && !width) {\n\tif(this.settings.axis === \"horizontal\") {\n\t\t// Get the width of the text\n\t\ttextWidth = this.contents.textWidth();\n\t\t// Check if the textWidth has changed\n\t\tif(textWidth != this._textWidth){\n\t\t\t// Get the contentWidth by resizing the iframe\n\t\t\t// Check with a min reset of the textWidth\n\t\t\twidth = this.contentWidth(textWidth);\n\n\t\t\tcolumns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap));\n\n\t\t\tif ( this.settings.layout.divisor > 1 &&\n\t\t\t\t\t this.settings.layout.name === \"reflowable\" &&\n\t\t\t\t\t(columns % 2 > 0)) {\n\t\t\t\t\t// add a blank page\n\t\t\t\t\twidth += this.settings.layout.gap + this.settings.layout.columnWidth;\n\t\t\t}\n\n\t\t\t// Save the textWdith\n\t\t\tthis._textWidth = textWidth;\n\t\t\t// Save the contentWidth\n\t\t\tthis._contentWidth = width;\n\t\t} else {\n\t\t\t// Otherwise assume content height hasn't changed\n\t\t\twidth = this._contentWidth;\n\t\t}\n\t} // Expand Vertically\n\telse if(this.settings.axis === \"vertical\") {\n\t\ttextHeight = this.contents.textHeight();\n\t\tif(textHeight != this._textHeight){\n\t\t\theight = this.contentHeight(textHeight);\n\t\t\tthis._textHeight = textHeight;\n\t\t\tthis._contentHeight = height;\n\t\t} else {\n\t\t\theight = this._contentHeight;\n\t\t}\n\n\t}\n\n\t// Only Resize if dimensions have changed or\n\t// if Frame is still hidden, so needs reframing\n\tif(this._needsReframe || width != this._width || height != this._height){\n\t\tthis.resize(width, height);\n\t}\n\n\tthis._expanding = false;\n};\n\nIframeView.prototype.contentWidth = function(min) {\n\tvar prev;\n\tvar width;\n\n\t// Save previous width\n\tprev = this.iframe.style.width;\n\t// Set the iframe size to min, width will only ever be greater\n\t// Will preserve the aspect ratio\n\tthis.iframe.style.width = (min || 0) + \"px\";\n\t// Get the scroll overflow width\n\twidth = this.contents.scrollWidth();\n\t// Reset iframe size back\n\tthis.iframe.style.width = prev;\n\treturn width;\n};\n\nIframeView.prototype.contentHeight = function(min) {\n\tvar prev;\n\tvar height;\n\n\tprev = this.iframe.style.height;\n\tthis.iframe.style.height = (min || 0) + \"px\";\n\theight = this.contents.scrollHeight();\n\n\tthis.iframe.style.height = prev;\n\treturn height;\n};\n\n\nIframeView.prototype.resize = function(width, height) {\n\n\tif(!this.iframe) return;\n\n\tif(core.isNumber(width)){\n\t\tthis.iframe.style.width = width + \"px\";\n\t\tthis._width = width;\n\t}\n\n\tif(core.isNumber(height)){\n\t\tthis.iframe.style.height = height + \"px\";\n\t\tthis._height = height;\n\t}\n\n\tthis.iframeBounds = core.bounds(this.iframe);\n\n\tthis.reframe(this.iframeBounds.width, this.iframeBounds.height);\n\n};\n\nIframeView.prototype.reframe = function(width, height) {\n\tvar size;\n\n\t// if(!this.displayed) {\n\t// this._needsReframe = true;\n\t// return;\n\t// }\n\tif(core.isNumber(width)){\n\t\tthis.element.style.width = width + \"px\";\n\t}\n\n\tif(core.isNumber(height)){\n\t\tthis.element.style.height = height + \"px\";\n\t}\n\n\tthis.prevBounds = this.elementBounds;\n\n\tthis.elementBounds = core.bounds(this.element);\n\n\tsize = {\n\t\twidth: this.elementBounds.width,\n\t\theight: this.elementBounds.height,\n\t\twidthDelta: this.elementBounds.width - this.prevBounds.width,\n\t\theightDelta: this.elementBounds.height - this.prevBounds.height,\n\t};\n\n\tthis.onResize(this, size);\n\n\tthis.trigger(\"resized\", size);\n\n};\n\n\nIframeView.prototype.load = function(contents) {\n\tvar loading = new RSVP.defer();\n\tvar loaded = loading.promise;\n\n\tif(!this.iframe) {\n\t\tloading.reject(new Error(\"No Iframe Available\"));\n\t\treturn loaded;\n\t}\n\n\tthis.iframe.onload = function(event) {\n\n\t\tthis.onLoad(event, loading);\n\n\t}.bind(this);\n\n\tif(this.supportsSrcdoc){\n\t\tthis.iframe.srcdoc = contents;\n\t} else {\n\n\t\tthis.document = this.iframe.contentDocument;\n\n\t\tif(!this.document) {\n\t\t\tloading.reject(new Error(\"No Document Available\"));\n\t\t\treturn loaded;\n\t\t}\n\n\t\tthis.iframe.contentDocument.open();\n\t\tthis.iframe.contentDocument.write(contents);\n\t\tthis.iframe.contentDocument.close();\n\n\t}\n\n\treturn loaded;\n};\n\nIframeView.prototype.onLoad = function(event, promise) {\n\n\t\tthis.window = this.iframe.contentWindow;\n\t\tthis.document = this.iframe.contentDocument;\n\n\t\tthis.contents = new Contents(this.document, this.document.body, this.section.cfiBase);\n\n\t\tthis.rendering = false;\n\n\t\tvar link = this.document.querySelector(\"link[rel='canonical']\");\n\t\tif (link) {\n\t\t\tlink.setAttribute(\"href\", this.section.url);\n\t\t} else {\n\t\t\tlink = this.document.createElement(\"link\");\n\t\t\tlink.setAttribute(\"rel\", \"canonical\");\n\t\t\tlink.setAttribute(\"href\", this.section.url);\n\t\t\tthis.document.querySelector(\"head\").appendChild(link);\n\t\t}\n\n\t\tthis.contents.on(\"expand\", function () {\n\t\t\tif(this.displayed && this.iframe) {\n\t\t\t\t\tthis.expand();\n\t\t\t}\n\t\t});\n\n\t\tpromise.resolve(this.contents);\n};\n\n\n\n// IframeView.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// this.layoutFunc = layoutFunc;\n// }\n//\n// this.contents.layout(this.layoutFunc);\n//\n// };\n//\n// IframeView.prototype.onLayout = function(view) {\n// // stub\n// };\n\nIframeView.prototype.setLayout = function(layout) {\n\tthis.layout = layout;\n};\n\nIframeView.prototype.setAxis = function(axis) {\n\tthis.settings.axis = axis;\n};\n\nIframeView.prototype.resizeListenters = function() {\n\t// Test size again\n\tclearTimeout(this.expanding);\n\tthis.expanding = setTimeout(this.expand.bind(this), 350);\n};\n\nIframeView.prototype.addListeners = function() {\n\t//TODO: Add content listeners for expanding\n};\n\nIframeView.prototype.removeListeners = function(layoutFunc) {\n\t//TODO: remove content listeners for expanding\n};\n\nIframeView.prototype.display = function(request) {\n\tvar displayed = new RSVP.defer();\n\n\tif (!this.displayed) {\n\n\t\tthis.render(request).then(function () {\n\n\t\t\tthis.trigger(\"displayed\", this);\n\t\t\tthis.onDisplayed(this);\n\n\t\t\tthis.displayed = true;\n\t\t\tdisplayed.resolve(this);\n\n\t\t}.bind(this));\n\n\t} else {\n\t\tdisplayed.resolve(this);\n\t}\n\n\n\treturn displayed.promise;\n};\n\nIframeView.prototype.show = function() {\n\n\tthis.element.style.visibility = \"visible\";\n\n\tif(this.iframe){\n\t\tthis.iframe.style.visibility = \"visible\";\n\t}\n\n\tthis.trigger(\"shown\", this);\n};\n\nIframeView.prototype.hide = function() {\n\t// this.iframe.style.display = \"none\";\n\tthis.element.style.visibility = \"hidden\";\n\tthis.iframe.style.visibility = \"hidden\";\n\n\tthis.stopExpanding = true;\n\tthis.trigger(\"hidden\", this);\n};\n\nIframeView.prototype.position = function() {\n\treturn this.element.getBoundingClientRect();\n};\n\nIframeView.prototype.locationOf = function(target) {\n\tvar parentPos = this.iframe.getBoundingClientRect();\n\tvar targetPos = this.contents.locationOf(target, this.settings.ignoreClass);\n\n\treturn {\n\t\t\"left\": window.scrollX + parentPos.left + targetPos.left,\n\t\t\"top\": window.scrollY + parentPos.top + targetPos.top\n\t};\n};\n\nIframeView.prototype.onDisplayed = function(view) {\n\t// Stub, override with a custom functions\n};\n\nIframeView.prototype.onResize = function(view, e) {\n\t// Stub, override with a custom functions\n};\n\nIframeView.prototype.bounds = function() {\n\tif(!this.elementBounds) {\n\t\tthis.elementBounds = core.bounds(this.element);\n\t}\n\treturn this.elementBounds;\n};\n\nIframeView.prototype.destroy = function() {\n\n\tif(this.displayed){\n\t\tthis.displayed = false;\n\n\t\tthis.removeListeners();\n\n\t\tthis.stopExpanding = true;\n\t\tthis.element.removeChild(this.iframe);\n\t\tthis.displayed = false;\n\t\tthis.iframe = null;\n\n\t\tthis._textWidth = null;\n\t\tthis._textHeight = null;\n\t\tthis._width = null;\n\t\tthis._height = null;\n\t}\n\t// this.element.style.height = \"0px\";\n\t// this.element.style.width = \"0px\";\n};\n\nRSVP.EventTarget.mixin(IframeView.prototype);\n\nmodule.exports = IframeView;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/managers/views/iframe.js\n ** module id = 31\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar core = require('../../core');\nvar EpubCFI = require('../../epubcfi');\nvar Mapping = require('../../mapping');\nvar Queue = require('../../queue');\nvar Stage = require('../helpers/stage');\nvar Views = require('../helpers/views');\n\nfunction DefaultViewManager(options) {\n\n\tthis.name = \"default\";\n\tthis.View = options.view;\n\tthis.request = options.request;\n\tthis.renditionQueue = options.queue;\n\tthis.q = new Queue(this);\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\thidden: false,\n\t\twidth: undefined,\n\t\theight: undefined,\n\t\t// globalLayoutProperties : { layout: 'reflowable', spread: 'auto', orientation: 'auto'},\n\t\t// layout: null,\n\t\taxis: \"vertical\",\n\t\tignoreClass: ''\n\t});\n\n\tcore.extend(this.settings, options.settings || {});\n\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass,\n\t\taxis: this.settings.axis,\n\t\tlayout: this.layout,\n\t\twidth: 0,\n\t\theight: 0\n\t};\n\n}\n\nDefaultViewManager.prototype.render = function(element, size){\n\n\t// Save the stage\n\tthis.stage = new Stage({\n\t\twidth: size.width,\n\t\theight: size.height,\n\t\toverflow: this.settings.overflow,\n\t\thidden: this.settings.hidden,\n\t\taxis: this.settings.axis\n\t});\n\n\tthis.stage.attachTo(element);\n\n\t// Get this stage container div\n\tthis.container = this.stage.getContainer();\n\n\t// Views array methods\n\tthis.views = new Views(this.container);\n\n\t// Calculate Stage Size\n\tthis._bounds = this.bounds();\n\tthis._stageSize = this.stage.size();\n\n\t// Set the dimensions for views\n\tthis.viewSettings.width = this._stageSize.width;\n\tthis.viewSettings.height = this._stageSize.height;\n\n\t// Function to handle a resize event.\n\t// Will only attach if width and height are both fixed.\n\tthis.stage.onResize(this.onResized.bind(this));\n\n\t// Add Event Listeners\n\tthis.addEventListeners();\n\n\t// Add Layout method\n\t// this.applyLayoutMethod();\n\tif (this.layout) {\n\t\tthis.updateLayout();\n\t}\n};\n\nDefaultViewManager.prototype.addEventListeners = function(){\n\twindow.addEventListener('unload', function(e){\n\t\tthis.destroy();\n\t}.bind(this));\n};\n\nDefaultViewManager.prototype.destroy = function(){\n\t// this.views.each(function(view){\n\t// \tview.destroy();\n\t// });\n\n\t/*\n\n\t\tclearTimeout(this.trimTimeout);\n\t\tif(this.settings.hidden) {\n\t\t\tthis.element.removeChild(this.wrapper);\n\t\t} else {\n\t\t\tthis.element.removeChild(this.container);\n\t\t}\n\t*/\n};\n\nDefaultViewManager.prototype.onResized = function(e) {\n\tclearTimeout(this.resizeTimeout);\n\tthis.resizeTimeout = setTimeout(function(){\n\t\tthis.resize();\n\t}.bind(this), 150);\n};\n\nDefaultViewManager.prototype.resize = function(width, height){\n\n\t// Clear the queue\n\tthis.q.clear();\n\n\tthis._stageSize = this.stage.size(width, height);\n\tthis._bounds = this.bounds();\n\n\t// Update for new views\n\tthis.viewSettings.width = this._stageSize.width;\n\tthis.viewSettings.height = this._stageSize.height;\n\n\t// Update for existing views\n\tthis.views.each(function(view) {\n\t\tview.size(this._stageSize.width, this._stageSize.height);\n\t}.bind(this));\n\n\tthis.updateLayout();\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nDefaultViewManager.prototype.createView = function(section) {\n\treturn new this.View(section, this.viewSettings);\n};\n\nDefaultViewManager.prototype.display = function(section, target){\n\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\n\t// Check to make sure the section we want isn't already shown\n\tvar visible = this.views.find(section);\n\n\t// View is already shown, just move to correct location\n\tif(visible && target) {\n\t\toffset = visible.locationOf(target);\n\t\tthis.moveTo(offset);\n\t\tdisplaying.resolve();\n\t\treturn displayed;\n\t}\n\n\t// Hide all current views\n\tthis.views.hide();\n\n\tthis.views.clear();\n\n\tthis.add(section)\n\t\t.then(function(){\n\t\t\tvar next;\n\t\t\tif (this.layout.name === \"pre-paginated\" &&\n\t\t\t\t\tthis.layout.divisor > 1) {\n\t\t\t\tnext = section.next();\n\t\t\t\tif (next) {\n\t\t\t\t\treturn this.add(next);\n\t\t\t\t}\n\t\t\t}\n\t\t}.bind(this))\n\t\t.then(function(view){\n\n\t\t\t// Move to correct place within the section, if needed\n\t\t\tif(target) {\n\t\t\t\toffset = view.locationOf(target);\n\t\t\t\tthis.moveTo(offset);\n\t\t\t}\n\n\t\t\tthis.views.show();\n\n\t\t\tdisplaying.resolve();\n\n\t\t}.bind(this))\n\t\t// .then(function(){\n\t\t// \treturn this.hooks.display.trigger(view);\n\t\t// }.bind(this))\n\t\t// .then(function(){\n\t\t// \tthis.views.show();\n\t\t// }.bind(this));\n\t\treturn displayed;\n};\n\nDefaultViewManager.prototype.afterDisplayed = function(view){\n\tthis.trigger(\"added\", view);\n};\n\nDefaultViewManager.prototype.afterResized = function(view){\n\tthis.trigger(\"resize\", view.section);\n};\n\n// DefaultViewManager.prototype.moveTo = function(offset){\n// \tthis.scrollTo(offset.left, offset.top);\n// };\n\nDefaultViewManager.prototype.moveTo = function(offset){\n\tvar distX = 0,\n\t\t\tdistY = 0;\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tdistY = offset.top;\n\t} else {\n\t\tdistX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n\n\t\tif (distX + this.layout.delta > this.container.scrollWidth) {\n\t\t\tdistX = this.container.scrollWidth - this.layout.delta;\n\t\t}\n\t}\n\n\tthis.scrollTo(distX, distY);\n};\n\nDefaultViewManager.prototype.add = function(section){\n\tvar view = this.createView(section);\n\n\tthis.views.append(view);\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\tview.onResize = this.afterResized.bind(this);\n\n\treturn view.display(this.request);\n\n};\n\nDefaultViewManager.prototype.append = function(section){\n\tvar view = this.createView(section);\n\tthis.views.append(view);\n\treturn view.display(this.request);\n};\n\nDefaultViewManager.prototype.prepend = function(section){\n\tvar view = this.createView(section);\n\n\tthis.views.prepend(view);\n\treturn view.display(this.request);\n};\n// DefaultViewManager.prototype.resizeView = function(view) {\n//\n// \tif(this.settings.globalLayoutProperties.layout === \"pre-paginated\") {\n// \t\tview.lock(\"both\", this.bounds.width, this.bounds.height);\n// \t} else {\n// \t\tview.lock(\"width\", this.bounds.width, this.bounds.height);\n// \t}\n//\n// };\n\nDefaultViewManager.prototype.next = function(){\n\tvar next;\n\tvar view;\n\tvar left;\n\n\tif(!this.views.length) return;\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\n\t\tleft = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;\n\n\t\tif(left < this.container.scrollWidth) {\n\t\t\tthis.scrollBy(this.layout.delta, 0);\n\t\t} else if (left - this.layout.columnWidth === this.container.scrollWidth) {\n\t\t\tthis.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n\t\t} else {\n\t\t\tnext = this.views.last().section.next();\n\t\t}\n\n\n\t} else {\n\n\t\tnext = this.views.last().section.next();\n\n\t}\n\n\tif(next) {\n\t\tthis.views.clear();\n\n\t\treturn this.append(next)\n\t\t\t.then(function(){\n\t\t\t\tvar right;\n\t\t\t\tif (this.layout.name && this.layout.divisor > 1) {\n\t\t\t\t\tright = next.next();\n\t\t\t\t\tif (right) {\n\t\t\t\t\t\treturn this.append(right);\n\t\t\t\t\t}\n\t\t\t\t}\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\n};\n\nDefaultViewManager.prototype.prev = function(){\n\tvar prev;\n\tvar view;\n\tvar left;\n\n\tif(!this.views.length) return;\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\n\t\tleft = this.container.scrollLeft;\n\n\t\tif(left > 0) {\n\t\t\tthis.scrollBy(-this.layout.delta, 0);\n\t\t} else {\n\t\t\tprev = this.views.first().section.prev();\n\t\t}\n\n\n\t} else {\n\n\t\tprev = this.views.first().section.prev();\n\n\t}\n\n\tif(prev) {\n\t\tthis.views.clear();\n\n\t\treturn this.prepend(prev)\n\t\t\t.then(function(){\n\t\t\t\tvar left;\n\t\t\t\tif (this.layout.name && this.layout.divisor > 1) {\n\t\t\t\t\tleft = prev.prev();\n\t\t\t\t\tif (left) {\n\t\t\t\t\t\treturn this.prepend(left);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tif(this.settings.axis === \"horizontal\") {\n\t\t\t\t\tthis.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n\t\t\t\t}\n\t\t\t\tthis.views.show();\n\t\t\t}.bind(this));\n\t}\n};\n\nDefaultViewManager.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\treturn null;\n};\n\nDefaultViewManager.prototype.currentLocation = function(){\n\tvar view;\n\tvar start, end;\n\n\tif(this.views.length) {\n\t\tview = this.views.first();\n\t\tstart = container.left - view.position().left;\n\t\tend = start + this.layout.spread;\n\n\t\treturn this.mapping.page(view, view.section.cfiBase);\n\t}\n\n};\n\nDefaultViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){\n\tvar position = view.position();\n\tvar container = _container || this.bounds();\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\t} else if(this.settings.axis === \"vertical\" &&\n\t\tposition.bottom > container.top - offsetPrev &&\n\t\tposition.top < container.bottom + offsetNext) {\n\n\t\treturn true;\n\t}\n\n\treturn false;\n\n};\n\nDefaultViewManager.prototype.visible = function(){\n\t// return this.views.displayed();\n\tvar container = this.bounds();\n\tvar views = this.views.displayed();\n\tvar viewsLength = views.length;\n\tvar visible = [];\n\tvar isVisible;\n\tvar view;\n\n\tfor (var i = 0; i < viewsLength; i++) {\n\t\tview = views[i];\n\t\tisVisible = this.isVisible(view, 0, 0, container);\n\n\t\tif(isVisible === true) {\n\t\t\tvisible.push(view);\n\t\t}\n\n\t}\n\treturn visible;\n};\n\nDefaultViewManager.prototype.scrollBy = function(x, y, silent){\n\tif(silent) {\n\t\tthis.ignore = true;\n\t}\n\n\tif(this.settings.height) {\n\n\t\tif(x) this.container.scrollLeft += x;\n\t\tif(y) this.container.scrollTop += y;\n\n\t} else {\n\t\twindow.scrollBy(x,y);\n\t}\n\t// console.log(\"scrollBy\", x, y);\n\tthis.scrolled = true;\n\tthis.onScroll();\n};\n\nDefaultViewManager.prototype.scrollTo = function(x, y, silent){\n\tif(silent) {\n\t\tthis.ignore = true;\n\t}\n\n\tif(this.settings.height) {\n\t\tthis.container.scrollLeft = x;\n\t\tthis.container.scrollTop = y;\n\t} else {\n\t\twindow.scrollTo(x,y);\n\t}\n\t// console.log(\"scrollTo\", x, y);\n\tthis.scrolled = true;\n\tthis.onScroll();\n\t// if(this.container.scrollLeft != x){\n\t// setTimeout(function() {\n\t// this.scrollTo(x, y, silent);\n\t// }.bind(this), 10);\n\t// return;\n\t// };\n };\n\nDefaultViewManager.prototype.onScroll = function(){\n\n};\n\nDefaultViewManager.prototype.bounds = function() {\n\tvar bounds;\n\n\tbounds = this.stage.bounds();\n\n\treturn bounds;\n};\n\nDefaultViewManager.prototype.applyLayout = function(layout) {\n\n\tthis.layout = layout;\n\tthis.updateLayout();\n\n\tthis.mapping = new Mapping(this.layout);\n\t // this.manager.layout(this.layout.format);\n};\n\nDefaultViewManager.prototype.updateLayout = function() {\n\tif (!this.stage) {\n\t\treturn;\n\t}\n\n\tthis._stageSize = this.stage.size();\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.layout.calculate(this._stageSize.width, this._stageSize.height);\n\t} else {\n\t\tthis.layout.calculate(\n\t\t\tthis._stageSize.width,\n\t\t\tthis._stageSize.height,\n\t\t\tthis.settings.gap\n\t\t);\n\n\t\t// Set the look ahead offset for what is visible\n\t\tthis.settings.offset = this.layout.delta;\n\n\t\tthis.stage.addStyleRules(\"iframe\", [{\"margin-right\" : this.layout.gap + \"px\"}]);\n\n\t}\n\n\t// Set the dimensions for views\n\tthis.viewSettings.width = this.layout.width;\n\tthis.viewSettings.height = this.layout.height;\n\n\tthis.setLayout(this.layout);\n\n};\n\nDefaultViewManager.prototype.setLayout = function(layout){\n\n\tthis.viewSettings.layout = layout;\n\n\tif(this.views) {\n\n\t\tthis.views.each(function(view){\n\t\t\tview.setLayout(layout);\n\t\t});\n\n\t}\n\n};\n\nDefaultViewManager.prototype.updateFlow = function(flow){\n\tvar axis = (flow === \"paginated\") ? \"horizontal\" : \"vertical\";\n\n\tthis.settings.axis = axis;\n\n\tthis.viewSettings.axis = axis;\n\n\tthis.settings.overflow = (flow === \"paginated\") ? \"hidden\" : \"auto\";\n\t// this.views.each(function(view){\n\t// \tview.setAxis(axis);\n\t// });\n\n};\n\n //-- Enable binding events to Manager\n RSVP.EventTarget.mixin(DefaultViewManager.prototype);\n\n module.exports = DefaultViewManager;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/managers/default/index.js\n ** module id = 32\n ** module chunks = 0\n **/","var core = require('../../core');\n\nfunction Stage(_options) {\n\tthis.settings = _options || {};\n\tthis.id = \"epubjs-container-\" + core.uuid();\n\n\tthis.container = this.create(this.settings);\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t}\n\n}\n\n/**\n* Creates an element to render to.\n* Resizes to passed width and height or to the elements size\n*/\nStage.prototype.create = function(options){\n\tvar height = options.height;// !== false ? options.height : \"100%\";\n\tvar width = options.width;// !== false ? options.width : \"100%\";\n\tvar overflow = options.overflow || false;\n\tvar axis = options.axis || \"vertical\";\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 = this.id;\n\tcontainer.classList.add(\"epub-container\");\n\n\t// Style Element\n\t// container.style.fontSize = \"0\";\n\tcontainer.style.wordSpacing = \"0\";\n\tcontainer.style.lineHeight = \"0\";\n\tcontainer.style.verticalAlign = \"top\";\n\n\tif(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\tif (overflow) {\n\t\tcontainer.style.overflow = overflow;\n\t}\n\n\treturn container;\n};\n\nStage.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\nStage.prototype.getElement = function(_element){\n\tvar element;\n\n\tif(core.isElement(_element)) {\n\t\telement = _element;\n\t} else if (typeof _element === \"string\") {\n\t\telement = document.getElementById(_element);\n\t}\n\n\tif(!element){\n\t\tconsole.error(\"Not an Element\");\n\t\treturn;\n\t}\n\n\treturn element;\n};\n\nStage.prototype.attachTo = function(what){\n\n\tvar element = this.getElement(what);\n\tvar base;\n\n\tif(!element){\n\t\treturn;\n\t}\n\n\tif(this.settings.hidden) {\n\t\tbase = this.wrapper;\n\t} else {\n\t\tbase = this.container;\n\t}\n\n\telement.appendChild(base);\n\n\tthis.element = element;\n\n\treturn element;\n\n};\n\nStage.prototype.getContainer = function() {\n\treturn this.container;\n};\n\nStage.prototype.onResize = function(func){\n\t// Only listen to window for resize event if width and height are not fixed.\n\t// This applies if it is set to a percent or auto.\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", func, false);\n\t}\n\n};\n\nStage.prototype.size = function(width, height){\n\tvar bounds;\n\t// var width = _width || this.settings.width;\n\t// var height = _height || this.settings.height;\n\n\t// If width or height are set to false, inherit them from containing element\n\tif(width === null) {\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 === null) {\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(!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(!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\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\treturn {\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};\n\nStage.prototype.bounds = function(){\n\n\tif(!this.container) {\n\t\treturn core.windowBounds();\n\t} else {\n\t\treturn this.container.getBoundingClientRect();\n\t}\n\n}\n\nStage.prototype.getSheet = function(){\n\tvar style = document.createElement(\"style\");\n\n\t// WebKit hack --> https://davidwalsh.name/add-rules-stylesheets\n\tstyle.appendChild(document.createTextNode(\"\"));\n\n\tdocument.head.appendChild(style);\n\n\treturn style.sheet;\n}\n\nStage.prototype.addStyleRules = function(selector, rulesArray){\n\tvar scope = \"#\" + this.id + \" \";\n\tvar rules = \"\";\n\n\tif(!this.sheet){\n\t\tthis.sheet = this.getSheet();\n\t}\n\n\trulesArray.forEach(function(set) {\n\t\tfor (var prop in set) {\n\t\t\tif(set.hasOwnProperty(prop)) {\n\t\t\t\trules += prop + \":\" + set[prop] + \";\";\n\t\t\t}\n\t\t}\n\t})\n\n\tthis.sheet.insertRule(scope + selector + \" {\" + rules + \"}\", 0);\n}\n\n\n\nmodule.exports = Stage;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/managers/helpers/stage.js\n ** module id = 33\n ** module chunks = 0\n **/","function Views(container) {\n\tthis.container = container;\n\tthis._views = [];\n\tthis.length = 0;\n\tthis.hidden = false;\n};\n\nViews.prototype.all = function() {\n\treturn this._views;\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.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\tif(this.container){\n\t\tthis.container.appendChild(view.element);\n\t}\n\tthis.length++;\n\treturn view;\n};\n\nViews.prototype.prepend = function(view){\n\tthis._views.unshift(view);\n\tif(this.container){\n\t\tthis.container.insertBefore(view.element, this.container.firstChild);\n\t}\n\tthis.length++;\n\treturn view;\n};\n\nViews.prototype.insert = function(view, index) {\n\tthis._views.splice(index, 0, view);\n\n\tif(this.container){\n\t\tif(index < this.container.children.length){\n\t\t\tthis.container.insertBefore(view.element, this.container.children[index]);\n\t\t} else {\n\t\t\tthis.container.appendChild(view.element);\n\t\t}\n\t}\n\n\tthis.length++;\n\treturn 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\tthis.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\tif(this.container){\n\t\t this.container.removeChild(view.element);\n\t}\n\tview = null;\n};\n\n// Iterators\n\nViews.prototype.each = function() {\n\treturn this._views.forEach.apply(this._views, arguments);\n};\n\nViews.prototype.clear = function(){\n\t// Remove all views\n\tvar view;\n\tvar len = this.length;\n\n\tif(!this.length) return;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tthis.destroy(view);\n\t}\n\n\tthis._views = [];\n\tthis.length = 0;\n};\n\nViews.prototype.find = function(section){\n\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed && view.section.index == section.index) {\n\t\t\treturn view;\n\t\t}\n\t}\n\n};\n\nViews.prototype.displayed = function(){\n\tvar displayed = [];\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed){\n\t\t\tdisplayed.push(view);\n\t\t}\n\t}\n\treturn displayed;\n};\n\nViews.prototype.show = function(){\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed){\n\t\t\tview.show();\n\t\t}\n\t}\n\tthis.hidden = false;\n};\n\nViews.prototype.hide = function(){\n\tvar view;\n\tvar len = this.length;\n\n\tfor (var i = 0; i < len; i++) {\n\t\tview = this._views[i];\n\t\tif(view.displayed){\n\t\t\tview.hide();\n\t\t}\n\t}\n\tthis.hidden = true;\n};\n\nmodule.exports = Views;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/managers/helpers/views.js\n ** module id = 34\n ** module chunks = 0\n **/","var RSVP = require('rsvp');\nvar core = require('../../core');\nvar DefaultViewManager = require('../default');\n\nfunction ContinuousViewManager(options) {\n\n\tDefaultViewManager.apply(this, arguments); // call super constructor.\n\n\tthis.name = \"continuous\";\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\twidth: undefined,\n\t\theight: undefined\n\t});\n\n\tcore.extend(this.settings, options.settings || {});\n\n\t// Gap can be 0, byt defaults doesn't handle that\n\tif (options.settings.gap != \"undefined\" && options.settings.gap === 0) {\n\t\tthis.settings.gap = options.settings.gap;\n\t}\n\n\t// this.viewSettings.axis = this.settings.axis;\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass,\n\t\taxis: this.settings.axis,\n\t\tlayout: this.layout,\n\t\twidth: 0,\n\t\theight: 0\n\t};\n\n\tthis.scrollTop = 0;\n\tthis.scrollLeft = 0;\n};\n\n// subclass extends superclass\nContinuousViewManager.prototype = Object.create(DefaultViewManager.prototype);\nContinuousViewManager.prototype.constructor = ContinuousViewManager;\n\nContinuousViewManager.prototype.display = function(section, target){\n\treturn DefaultViewManager.prototype.display.call(this, section, target)\n\t\t.then(function () {\n\t\t\treturn this.fill();\n\t\t}.bind(this));\n};\n\nContinuousViewManager.prototype.fill = function(_full){\n\tvar full = _full || new RSVP.defer();\n\n\tthis.check().then(function(result) {\n\t\tif (result) {\n\t\t\tthis.fill(full);\n\t\t} else {\n\t\t\tfull.resolve();\n\t\t}\n\t}.bind(this));\n\n\treturn full.promise;\n}\n\nContinuousViewManager.prototype.moveTo = function(offset){\n\t// var bounds = this.stage.bounds();\n\t// var dist = Math.floor(offset.top / bounds.height) * bounds.height;\n\tvar distX = 0,\n\t\t\tdistY = 0;\n\n\tvar offsetX = 0,\n\t\t\toffsetY = 0;\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tdistY = offset.top;\n\t\toffsetY = offset.top+this.settings.offset;\n\t} else {\n\t\tdistX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n\t\toffsetX = distX+this.settings.offset;\n\t}\n\n\treturn this.check(offsetX, offsetY)\n\t\t.then(function(){\n\t\t\tthis.scrollBy(distX, distY);\n\t\t}.bind(this));\n};\n\n/*\nContinuousViewManager.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.bind(this), nextView);\n\t}\n\n\tif(index === 0 && prev) {\n\t\tprevView = this.createView(prev, this.viewSettings);\n\t\tthis.q.enqueue(this.prepend.bind(this), 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\nContinuousViewManager.prototype.resize = function(width, height){\n\n\t// Clear the queue\n\tthis.q.clear();\n\n\tthis._stageSize = this.stage.size(width, height);\n\tthis._bounds = this.bounds();\n\n\t// Update for new views\n\tthis.viewSettings.width = this._stageSize.width;\n\tthis.viewSettings.height = this._stageSize.height;\n\n\t// Update for existing views\n\tthis.views.each(function(view) {\n\t\tview.size(this._stageSize.width, this._stageSize.height);\n\t}.bind(this));\n\n\tthis.updateLayout();\n\n\t// if(this.location) {\n\t// this.rendition.display(this.location.start);\n\t// }\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nContinuousViewManager.prototype.onResized = function(e) {\n\n\t// this.views.clear();\n\n\tclearTimeout(this.resizeTimeout);\n\tthis.resizeTimeout = setTimeout(function(){\n\t\tthis.resize();\n\t}.bind(this), 150);\n};\n\nContinuousViewManager.prototype.afterResized = function(view){\n\tthis.trigger(\"resize\", view.section);\n};\n\n// Remove Previous Listeners if present\nContinuousViewManager.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\n\n// ContinuousViewManager.prototype.append = function(section){\n// \treturn this.q.enqueue(function() {\n//\n// \t\tthis._append(section);\n//\n//\n// \t}.bind(this));\n// };\n//\n// ContinuousViewManager.prototype.prepend = function(section){\n// \treturn this.q.enqueue(function() {\n//\n// \t\tthis._prepend(section);\n//\n// \t}.bind(this));\n//\n// };\n\nContinuousViewManager.prototype.append = function(section){\n\tvar view = this.createView(section);\n\tthis.views.append(view);\n\treturn view;\n};\n\nContinuousViewManager.prototype.prepend = function(section){\n\tvar view = this.createView(section);\n\n\tview.on(\"resized\", this.counter.bind(this));\n\n\tthis.views.prepend(view);\n\treturn view;\n};\n\nContinuousViewManager.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\nContinuousViewManager.prototype.update = function(_offset){\n\tvar container = this.bounds();\n\tvar views = this.views.all();\n\tvar viewsLength = views.length;\n\tvar visible = [];\n\tvar offset = typeof _offset != \"undefined\" ? _offset : (this.settings.offset || 0);\n\tvar isVisible;\n\tvar view;\n\n\tvar updating = new RSVP.defer();\n\tvar promises = [];\n\n\tfor (var i = 0; i < viewsLength; i++) {\n\t\tview = views[i];\n\n\t\tisVisible = this.isVisible(view, offset, offset, container);\n\n\t\tif(isVisible === true) {\n\t\t\tif (!view.displayed) {\n\t\t\t\tpromises.push(view.display(this.request).then(function (view) {\n\t\t\t\t\tview.show();\n\t\t\t\t}));\n\t\t\t}\n\t\t\tvisible.push(view);\n\t\t} else {\n\t\t\tthis.q.enqueue(view.destroy.bind(view));\n\n\t\t\tclearTimeout(this.trimTimeout);\n\t\t\tthis.trimTimeout = setTimeout(function(){\n\t\t\t\tthis.q.enqueue(this.trim.bind(this));\n\t\t\t}.bind(this), 250);\n\t\t}\n\n\t}\n\n\tif(promises.length){\n\t\treturn RSVP.all(promises);\n\t} else {\n\t\tupdating.resolve();\n\t\treturn updating.promise;\n\t}\n\n};\n\nContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){\n\tvar last, first, next, prev;\n\n\tvar checking = new RSVP.defer();\n\tvar newViews = [];\n\n\tvar horizontal = (this.settings.axis === \"horizontal\");\n\tvar delta = this.settings.offset || 0;\n\n\tif (_offsetLeft && horizontal) {\n\t\tdelta = _offsetLeft;\n\t}\n\n\tif (_offsetTop && !horizontal) {\n\t\tdelta = _offsetTop;\n\t}\n\n\tvar bounds = this._bounds; // bounds saved this until resize\n\n\tvar offset = horizontal ? this.scrollLeft : this.scrollTop;\n\tvar visibleLength = horizontal ? bounds.width : bounds.height;\n\tvar contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;\n\n\tif (offset + visibleLength + delta >= contentLength) {\n\t\tlast = this.views.last();\n\t\tnext = last && last.section.next();\n\t\tif(next) {\n\t\t\tnewViews.push(this.append(next));\n\t\t}\n\t}\n\n\tif (offset - delta < 0 ) {\n\t\tfirst = this.views.first();\n\t\tprev = first && first.section.prev();\n\t\tif(prev) {\n\t\t\tnewViews.push(this.prepend(prev));\n\t\t}\n\t}\n\n\tif(newViews.length){\n\t\t// RSVP.all(promises)\n\t\t\t// .then(function() {\n\t\t\t\t// Check to see if anything new is on screen after rendering\n\t\t\t\treturn this.q.enqueue(function(){\n\t\t\t\t\treturn this.update(delta);\n\t\t\t\t}.bind(this));\n\n\n\t\t\t// }.bind(this));\n\n\t} else {\n\t\tchecking.resolve(false);\n\t\treturn checking.promise;\n\t}\n\n\n};\n\nContinuousViewManager.prototype.trim = function(){\n\tvar task = new RSVP.defer();\n\tvar displayed = this.views.displayed();\n\tvar first = displayed[0];\n\tvar last = displayed[displayed.length-1];\n\tvar firstIndex = this.views.indexOf(first);\n\tvar lastIndex = this.views.indexOf(last);\n\tvar above = this.views.slice(0, firstIndex);\n\tvar below = this.views.slice(lastIndex+1);\n\n\t// Erase all but last above\n\tfor (var i = 0; i < above.length-1; i++) {\n\t\tthis.erase(above[i], above);\n\t}\n\n\t// Erase all except first below\n\tfor (var j = 1; j < below.length; j++) {\n\t\tthis.erase(below[j]);\n\t}\n\n\ttask.resolve();\n\treturn task.promise;\n};\n\nContinuousViewManager.prototype.erase = function(view, above){ //Trim\n\n\tvar prevTop;\n\tvar prevLeft;\n\n\tif(this.settings.height) {\n\t\tprevTop = this.container.scrollTop;\n\t\tprevLeft = this.container.scrollLeft;\n\t} else {\n\t\tprevTop = window.scrollY;\n\t\tprevLeft = window.scrollX;\n\t}\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\nContinuousViewManager.prototype.addEventListeners = function(stage){\n\n\twindow.addEventListener('unload', function(e){\n\t\tthis.ignore = true;\n\t\t// this.scrollTo(0,0);\n\t\tthis.destroy();\n\t}.bind(this));\n\n\tthis.addScrollListeners();\n};\n\nContinuousViewManager.prototype.addScrollListeners = function() {\n\tvar scroller;\n\n\tthis.tick = core.requestAnimationFrame;\n\n\tif(this.settings.height) {\n\t\tthis.prevScrollTop = this.container.scrollTop;\n\t\tthis.prevScrollLeft = this.container.scrollLeft;\n\t} else {\n\t\tthis.prevScrollTop = window.scrollY;\n\t\tthis.prevScrollLeft = window.scrollX;\n\t}\n\n\tthis.scrollDeltaVert = 0;\n\tthis.scrollDeltaHorz = 0;\n\n\tif(this.settings.height) {\n\t\tscroller = this.container;\n\t\tthis.scrollTop = this.container.scrollTop;\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\t} else {\n\t\tscroller = window;\n\t\tthis.scrollTop = window.scrollY;\n\t\tthis.scrollLeft = window.scrollX;\n\t}\n\n\tscroller.addEventListener(\"scroll\", this.onScroll.bind(this));\n\n\t// this.tick.call(window, this.onScroll.bind(this));\n\n\tthis.scrolled = false;\n\n};\n\nContinuousViewManager.prototype.onScroll = function(){\n\n\t// if(!this.ignore) {\n\n\t\tif(this.settings.height) {\n\t\t\tscrollTop = this.container.scrollTop;\n\t\t\tscrollLeft = this.container.scrollLeft;\n\t\t} else {\n\t\t\tscrollTop = window.scrollY;\n\t\t\tscrollLeft = window.scrollX;\n\t\t}\n\n\t\tthis.scrollTop = scrollTop;\n\t\tthis.scrollLeft = scrollLeft;\n\n\t\tif(!this.ignore) {\n\n\t\t\tif((this.scrollDeltaVert === 0 &&\n\t\t\t\t this.scrollDeltaHorz === 0) ||\n\t\t\t\t this.scrollDeltaVert > this.settings.offsetDelta ||\n\t\t\t\t this.scrollDeltaHorz > this.settings.offsetDelta) {\n\n\t\t\t\tthis.q.enqueue(function() {\n\t\t\t\t\tthis.check();\n\t\t\t\t}.bind(this));\n\t\t\t\t// this.check();\n\n\t\t\t\tthis.scrollDeltaVert = 0;\n\t\t\t\tthis.scrollDeltaHorz = 0;\n\n\t\t\t\tthis.trigger(\"scroll\", {\n\t\t\t\t\ttop: scrollTop,\n\t\t\t\t\tleft: scrollLeft\n\t\t\t\t});\n\n\t\t\t\tclearTimeout(this.afterScrolled);\n\t\t\t\tthis.afterScrolled = setTimeout(function () {\n\t\t\t\t\tthis.trigger(\"scrolled\", {\n\t\t\t\t\t\ttop: this.scrollTop,\n\t\t\t\t\t\tleft: this.scrollLeft\n\t\t\t\t\t});\n\t\t\t\t}.bind(this));\n\n\t\t\t}\n\n\t\t} else {\n\t\t\tthis.ignore = false;\n\t\t}\n\n\t\tthis.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);\n\t\tthis.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);\n\n\t\tthis.prevScrollTop = scrollTop;\n\t\tthis.prevScrollLeft = scrollLeft;\n\n\t\tclearTimeout(this.scrollTimeout);\n\t\tthis.scrollTimeout = setTimeout(function(){\n\t\t\tthis.scrollDeltaVert = 0;\n\t\t\tthis.scrollDeltaHorz = 0;\n\t\t}.bind(this), 150);\n\n\n\t\tthis.scrolled = false;\n\t// }\n\n\t// this.tick.call(window, this.onScroll.bind(this));\n\n};\n\n\n// ContinuousViewManager.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\nContinuousViewManager.prototype.currentLocation = function(){\n\n\tif (this.settings.axis === \"vertical\") {\n\t\tthis.location = this.scrolledLocation();\n\t} else {\n\t\tthis.location = this.paginatedLocation();\n\t}\n\n\treturn this.location;\n};\n\nContinuousViewManager.prototype.scrolledLocation = function(){\n\n\tvar visible = this.visible();\n\tvar startPage, endPage;\n\n\tvar container = this.container.getBoundingClientRect();\n\n\tif(visible.length === 1) {\n\t\treturn this.mapping.page(visible[0].contents, visible[0].section.cfiBase);\n\t}\n\n\tif(visible.length > 1) {\n\n\t\tstartPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase);\n\t\tendPage = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase);\n\n\t\treturn {\n\t\t\tstart: startPage.start,\n\t\t\tend: endPage.end\n\t\t};\n\t}\n\n};\n\nContinuousViewManager.prototype.paginatedLocation = function(){\n\tvar visible = this.visible();\n\tvar startA, startB, endA, endB;\n\tvar pageLeft, pageRight;\n\tvar container = this.container.getBoundingClientRect();\n\n\tif(visible.length === 1) {\n\t\tstartA = container.left - visible[0].position().left;\n\t\tendA = startA + this.layout.spreadWidth;\n\n\t\treturn this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);\n\t}\n\n\tif(visible.length > 1) {\n\n\t\t// Left Col\n\t\tstartA = container.left - visible[0].position().left;\n\t\tendA = startA + this.layout.columnWidth;\n\n\t\t// Right Col\n\t\tstartB = container.left + this.layout.spreadWidth - visible[visible.length-1].position().left;\n\t\tendB = startB + this.layout.columnWidth;\n\n\t\tpageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);\n\t\tpageRight = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase, startB, endB);\n\n\t\treturn {\n\t\t\tstart: pageLeft.start,\n\t\t\tend: pageRight.end\n\t\t};\n\t}\n};\n\n/*\nContinuous.prototype.current = function(what){\n\tvar view, top;\n\tvar container = this.container.getBoundingClientRect();\n\tvar length = this.views.length - 1;\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tfor (var i = length; i >= 0; i--) {\n\t\t\tview = this.views[i];\n\t\t\tleft = view.position().left;\n\n\t\t\tif(left < container.right) {\n\n\t\t\t\tif(this._current == view) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._current = view;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t} else {\n\n\t\tfor (var i = length; i >= 0; i--) {\n\t\t\tview = this.views[i];\n\t\t\ttop = view.bounds().top;\n\t\t\tif(top < container.bottom) {\n\n\t\t\t\tif(this._current == view) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._current = view;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t}\n\n\treturn this._current;\n};\n*/\n\nContinuousViewManager.prototype.updateLayout = function() {\n\n\tif (!this.stage) {\n\t\treturn;\n\t}\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.layout.calculate(this._stageSize.width, this._stageSize.height);\n\t} else {\n\t\tthis.layout.calculate(\n\t\t\tthis._stageSize.width,\n\t\t\tthis._stageSize.height,\n\t\t\tthis.settings.gap\n\t\t);\n\n\t\t// Set the look ahead offset for what is visible\n\t\tthis.settings.offset = this.layout.delta;\n\n\t\tthis.stage.addStyleRules(\"iframe\", [{\"margin-right\" : this.layout.gap + \"px\"}]);\n\n\t}\n\n\t// Set the dimensions for views\n\tthis.viewSettings.width = this.layout.width;\n\tthis.viewSettings.height = this.layout.height;\n\n\tthis.setLayout(this.layout);\n\n};\n\nContinuousViewManager.prototype.next = function(){\n\n\tif(this.settings.axis === \"horizontal\") {\n\n\t\tthis.scrollLeft = this.container.scrollLeft;\n\n\t\tif(this.container.scrollLeft +\n\t\t\t this.container.offsetWidth +\n\t\t\t this.layout.delta < this.container.scrollWidth) {\n\t\t\tthis.scrollBy(this.layout.delta, 0);\n\t\t} else {\n\t\t\tthis.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n\t\t}\n\n\t} else {\n\t\tthis.scrollBy(0, this.layout.height);\n\t}\n};\n\nContinuousViewManager.prototype.prev = function(){\n\tif(this.settings.axis === \"horizontal\") {\n\t\tthis.scrollBy(-this.layout.delta, 0);\n\t} else {\n\t\tthis.scrollBy(0, -this.layout.height);\n\t}\n};\n\nContinuousViewManager.prototype.updateFlow = function(flow){\n\tvar axis = (flow === \"paginated\") ? \"horizontal\" : \"vertical\";\n\n\tthis.settings.axis = axis;\n\n\tthis.viewSettings.axis = axis;\n\n\tthis.settings.overflow = (flow === \"paginated\") ? \"hidden\" : \"auto\";\n\n\t// this.views.each(function(view){\n\t// \tview.setAxis(axis);\n\t// });\n\n\tif (this.settings.axis === \"vertical\") {\n\t\tthis.settings.infinite = true;\n\t} else {\n\t\tthis.settings.infinite = false;\n\t}\n\n};\nmodule.exports = ContinuousViewManager;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/managers/continuous/index.js\n ** module id = 35\n ** module chunks = 0\n **/"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/epub.min.js b/dist/epub.min.js index 2a68969..5dc9a01 100644 --- a/dist/epub.min.js +++ b/dist/epub.min.js @@ -1,5 +1,48 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.ePub=t()}}(function(){var t;return function e(t,i,r){function n(s,a){if(!i[s]){if(!t[s]){var h="function"==typeof require&&require;if(!a&&h)return h(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var c=i[s]={exports:{}};t[s][0].call(c.exports,function(e){var i=t[s][1][e];return n(i?i:e)},c,c.exports,e,t,i,r)}return i[s].exports}for(var o="function"==typeof require&&require,s=0;s1)for(var i=1;ii;i++)if(t[i]===e)return i;return-1}function n(t){var e=t._promiseCallbacks;return e||(e=t._promiseCallbacks={}),e}function o(t,e){return"onerror"===t?(K.on("error",e),void 0):2!==arguments.length?K[t]:(K[t]=e,void 0)}function s(t){return"function"==typeof t||"object"==typeof t&&null!==t}function a(t){return"function"==typeof t}function h(t){return"object"==typeof t&&null!==t}function u(){}function c(){}function p(t){try{return t.then}catch(e){return he.error=e,he}}function l(t,e,i,r){try{t.call(e,i,r)}catch(n){return n}}function d(t,e,i){K.async(function(t){var r=!1,n=l(i,e,function(i){r||(r=!0,e!==i?g(t,i):v(t,i))},function(e){r||(r=!0,b(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&n&&(r=!0,b(t,n))},t)}function f(t,e){e._state===se?v(t,e._result):t._state===ae?b(t,e._result):w(e,void 0,function(i){e!==i?g(t,i):v(t,i)},function(e){b(t,e)})}function m(t,e){if(e.constructor===t.constructor)f(t,e);else{var i=p(e);i===he?b(t,he.error):void 0===i?v(t,e):a(i)?d(t,e,i):v(t,e)}}function g(t,e){t===e?v(t,e):s(e)?m(t,e):v(t,e)}function y(t){t._onerror&&t._onerror(t._result),x(t)}function v(t,e){t._state===oe&&(t._result=e,t._state=se,0===t._subscribers.length?K.instrument&&ne("fulfilled",t):K.async(x,t))}function b(t,e){t._state===oe&&(t._state=ae,t._result=e,K.async(y,t))}function w(t,e,i,r){var n=t._subscribers,o=n.length;t._onerror=null,n[o]=e,n[o+se]=i,n[o+ae]=r,0===o&&t._state&&K.async(x,t)}function x(t){var e=t._subscribers,i=t._state;if(K.instrument&&ne(i===se?"fulfilled":"rejected",t),0!==e.length){for(var r,n,o=t._result,s=0;sa;a++)s[a]=t[a];for(r=0;rr;r++)i[r-1]=t[r];return i}function z(t,e){return{then:function(i,r){return t.call(e,i,r)}}}function F(t,e,i,r){var n=N(i,r,e);return n===ve&&b(t,n.value),t}function I(t,e,i,r){return ye.all(e).then(function(e){var n=N(i,r,e);return n===ve&&b(t,n.value),t})}function j(t){return t&&"object"==typeof t?t.constructor===ye?!0:L(t):!1}function U(t,e,i){this._superConstructor(t,e,!1,i)}function Q(t,e,i){this._superConstructor(t,e,!0,i)}function D(t,e,i){this._superConstructor(t,e,!1,i)}function H(){return function(){e.nextTick(X)}}function M(){var t=0,e=new Fe(X),i=document.createTextNode("");return e.observe(i,{characterData:!0}),function(){i.data=t=++t%2}}function W(){var t=new MessageChannel;return t.port1.onmessage=X,function(){t.port2.postMessage(0)}}function V(){return function(){setTimeout(X,1)}}function X(){for(var t=0;Oe>t;t+=2){var e=je[t],i=je[t+1];e(i),je[t]=void 0,je[t+1]=void 0}Oe=0}function $(t,e){K.async(t,e)}function J(){K.on.apply(K,arguments)}function Z(){K.off.apply(K,arguments)}var Y={mixin:function(t){return t.on=this.on,t.off=this.off,t.trigger=this.trigger,t._promiseCallbacks=void 0,t},on:function(t,e){var i,o=n(this);i=o[t],i||(i=o[t]=[]),-1===r(i,e)&&i.push(e)},off:function(t,e){var i,o,s=n(this);return e?(i=s[t],o=r(i,e),-1!==o&&i.splice(o,1),void 0):(s[t]=[],void 0)},trigger:function(t,e){var i,r,o=n(this);if(i=o[t])for(var s=0;s1)throw new Error("Second argument not supported");if("object"!=typeof t)throw new TypeError("Argument must be an object");return u.prototype=t,new u},re=[],ne=function(t,e,i){1===re.push({name:t,payload:{guid:e._guidKey+e._id,eventName:t,detail:e._result,childGuid:i&&e._guidKey+i._id,label:e._label,timeStamp:ee(),stack:new Error(e._label).stack}})&&setTimeout(function(){for(var t,e=0;er;r++)this._eachEntry(i[r],r)},C.prototype._eachEntry=function(t,e){var i=this._instanceConstructor;h(t)?t.constructor===i&&t._state!==oe?(t._onerror=null,this._settledAt(t._state,e,t._result)):this._willSettleAt(i.resolve(t),e):(this._remaining--,this._result[e]=this._makeResult(se,e,t))},C.prototype._settledAt=function(t,e,i){var r=this.promise;r._state===oe&&(this._remaining--,this._abortOnReject&&t===ae?b(r,i):this._result[e]=this._makeResult(t,e,i)),0===this._remaining&&v(r,this._result)},C.prototype._makeResult=function(t,e,i){return i},C.prototype._willSettleAt=function(t,e){var i=this;w(t,void 0,function(t){i._settledAt(se,e,t)},function(t){i._settledAt(ae,e,t)})};var pe=function(t,e){return new ce(this,t,!0,e).promise},le=function(t,e){function i(t){g(o,t)}function r(t){b(o,t)}var n=this,o=new n(c,e);if(!te(t))return b(o,new TypeError("You must pass an array to race.")),o;for(var s=t.length,a=0;o._state===oe&&s>a;a++)w(n.resolve(t[a]),void 0,i,r);return o},de=function(t,e){var i=this;if(t&&"object"==typeof t&&t.constructor===i)return t;var r=new i(c,e);return g(r,t),r},fe=function(t,e){var i=this,r=new i(c,e);return b(r,t),r},me="rsvp_"+ee()+"-",ge=0,ye=P;P.cast=de,P.all=pe,P.race=le,P.resolve=de,P.reject=fe,P.prototype={constructor:P,_guidKey:me,_onerror:function(t){K.trigger("error",t)},then:function(t,e,i){var r=this,n=r._state;if(n===se&&!t||n===ae&&!e)return K.instrument&&ne("chained",this,this),this;r._onerror=null;var o=new this.constructor(c,i),s=r._result;if(K.instrument&&ne("chained",r,o),n){var a=arguments[n-1];K.async(function(){T(n,o,a,s)})}else w(r,o,t,e);return o},"catch":function(t,e){return this.then(null,t,e)},"finally":function(t,e){var i=this.constructor;return this.then(function(e){return i.resolve(t()).then(function(){return e})},function(e){return i.resolve(t()).then(function(){throw e})},e)}};var ve=new R,be=new R,we=function(t,e){var i=function(){for(var i,r=this,n=arguments.length,o=new Array(n+1),s=!1,a=0;n>a;++a){if(i=arguments[a],!s){if(s=j(i),s===be){var h=new ye(c);return b(h,be.value),h}s&&s!==!0&&(i=z(s,i))}o[a]=i}var u=new ye(c);return o[n]=function(t,i){t?b(u,t):void 0===e?g(u,i):e===!0?g(u,B(arguments)):te(e)?g(u,O(arguments,e)):g(u,i)},s?I(u,o,t,r):F(u,o,t,r)};return i.__proto__=t,i},xe=function(t,e){return ye.all(t,e)};U.prototype=ie(ce.prototype),U.prototype._superConstructor=ce,U.prototype._makeResult=k,U.prototype._validationError=function(){return new Error("allSettled must be called with an array")};var _e=function(t,e){return new U(ye,t,e).promise},Se=function(t,e){return ye.race(t,e)},Te=Q;Q.prototype=ie(ce.prototype),Q.prototype._superConstructor=ce,Q.prototype._init=function(){this._result={}},Q.prototype._validateInput=function(t){return t&&"object"==typeof t},Q.prototype._validationError=function(){return new Error("Promise.hash must be called with an object")},Q.prototype._enumerate=function(){var t=this.promise,e=this._input,i=[];for(var r in e)t._state===oe&&e.hasOwnProperty(r)&&i.push({position:r,entry:e[r]});var n=i.length;this._remaining=n;for(var o,s=0;t._state===oe&&n>s;s++)o=i[s],this._eachEntry(o.entry,o.position)};var Ee=function(t,e){return new Te(ye,t,e).promise};D.prototype=ie(Te.prototype),D.prototype._superConstructor=ce,D.prototype._makeResult=k,D.prototype._validationError=function(){return new Error("hashSettled must be called with an object")};var ke,Ce=function(t,e){return new D(ye,t,e).promise},qe=function(t){throw setTimeout(function(){throw t}),t},Ae=function(t){var e={};return e.promise=new ye(function(t,i){e.resolve=t,e.reject=i},t),e},Pe=function(t,e,i){return ye.all(t,i).then(function(t){if(!a(e))throw new TypeError("You must pass a function as map's second argument.");for(var r=t.length,n=new Array(r),o=0;r>o;o++)n[o]=e(t[o]);return ye.all(n,i)})},Re=function(t,e){return ye.resolve(t,e)},Le=function(t,e){return ye.reject(t,e)},Ne=function(t,e,i){return ye.all(t,i).then(function(t){if(!a(e))throw new TypeError("You must pass a function as filter's second argument.");for(var r=t.length,n=new Array(r),o=0;r>o;o++)n[o]=e(t[o]);return ye.all(n,i).then(function(e){for(var i=new Array(r),n=0,o=0;r>o;o++)e[o]&&(i[n]=t[o],n++);return i.length=n,i})})},Oe=0,Be=function(t,e){je[Oe]=t,je[Oe+1]=e,Oe+=2,2===Oe&&ke()},ze="undefined"!=typeof window?window:{},Fe=ze.MutationObserver||ze.WebKitMutationObserver,Ie="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,je=new Array(1e3);ke="undefined"!=typeof e&&"[object process]"==={}.toString.call(e)?H():Fe?M():Ie?W():V(),K.async=Be;if("undefined"!=typeof window&&"object"==typeof window.__PROMISE_INSTRUMENTATION__){var Ue=window.__PROMISE_INSTRUMENTATION__;o("instrument",!0);for(var Qe in Ue)Ue.hasOwnProperty(Qe)&&J(Qe,Ue[Qe])}var De={race:Se,Promise:ye,allSettled:_e,hash:Ee,hashSettled:Ce,denodeify:we,on:J,off:Z,map:Pe,filter:Ne,resolve:Re,reject:Le,all:xe,rethrow:qe,defer:Ae,EventTarget:Y,configure:o,async:$};"function"==typeof t&&t.amd?t(function(){return De}):"undefined"!=typeof i&&i.exports?i.exports=De:"undefined"!=typeof this&&(this.RSVP=De)}).call(this)}).call(this,e("_process"))},{_process:3}],5:[function(e,i,r){!function(n,o){"use strict";"object"==typeof r?i.exports=o(e("./punycode"),e("./IPv6"),e("./SecondLevelDomains")):"function"==typeof t&&t.amd?t(["./punycode","./IPv6","./SecondLevelDomains"],o):n.URI=o(n.punycode,n.IPv6,n.SecondLevelDomains,n)}(this,function(t,e,i,r){"use strict";function n(t,e){var i=arguments.length>=1,r=arguments.length>=2;if(!(this instanceof n))return i?r?new n(t,e):new n(t):new n;if(void 0===t){if(i)throw new TypeError("undefined is not a valid argument for URI");t="undefined"!=typeof location?location.href+"":""}return this.href(t),void 0!==e?this.absoluteTo(e):this}function o(t){return t.replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}function s(t){return void 0===t?"Undefined":String(Object.prototype.toString.call(t)).slice(8,-1)}function a(t){return"Array"===s(t)}function h(t,e){var i,r,n={};if("RegExp"===s(e))n=null;else if(a(e))for(i=0,r=e.length;r>i;i++)n[e[i]]=!0;else n[e]=!0;for(i=0,r=t.length;r>i;i++){var o=n&&void 0!==n[t[i]]||!n&&e.test(t[i]);o&&(t.splice(i,1),r--,i--)}return t}function u(t,e){var i,r;if(a(e)){for(i=0,r=e.length;r>i;i++)if(!u(t,e[i]))return!1;return!0}var n=s(e);for(i=0,r=t.length;r>i;i++)if("RegExp"===n){if("string"==typeof t[i]&&t[i].match(e))return!0}else if(t[i]===e)return!0;return!1}function c(t,e){if(!a(t)||!a(e))return!1;if(t.length!==e.length)return!1;t.sort(),e.sort();for(var i=0,r=t.length;r>i;i++)if(t[i]!==e[i])return!1;return!0}function p(t){var e=/^\/+|\/+$/g;return t.replace(e,"")}function l(t){return escape(t)}function d(t){return encodeURIComponent(t).replace(/[!'()*]/g,l).replace(/\*/g,"%2A")}function f(t){return function(e,i){return void 0===e?this._parts[t]||"":(this._parts[t]=e||null,this.build(!i),this)}}function m(t,e){return function(i,r){return void 0===i?this._parts[t]||"":(null!==i&&(i+="",i.charAt(0)===e&&(i=i.substring(1))),this._parts[t]=i,this.build(!r),this)}}var g=r&&r.URI;n.version="1.17.0";var y=n.prototype,v=Object.prototype.hasOwnProperty;n._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:n.duplicateQueryParameters,escapeQuerySpace:n.escapeQuerySpace}},n.duplicateQueryParameters=!1,n.escapeQuerySpace=!0,n.protocol_expression=/^[a-z][a-z0-9.+-]*$/i,n.idn_expression=/[^a-z0-9\.-]/i,n.punycode_expression=/(xn--)/i,n.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,n.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.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`!()\[\]{};:'".,<>?«»“”‘’]))/gi,n.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?«»“”„‘’]+$/},n.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"},n.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/,n.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src",audio:"src",video:"src"},n.getDomAttribute=function(t){if(!t||!t.nodeName)return void 0;var e=t.nodeName.toLowerCase();return"input"===e&&"image"!==t.type?void 0:n.domAttributes[e]},n.encode=d,n.decode=decodeURIComponent,n.iso8859=function(){n.encode=escape,n.decode=unescape},n.unicode=function(){n.encode=d,n.decode=decodeURIComponent},n.characters={pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/gi,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/gi,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}},urnpath:{encode:{expression:/%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/gi,map:{"%21":"!","%24":"$","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"=","%40":"@"}},decode:{expression:/[\/\?#:]/g,map:{"/":"%2F","?":"%3F","#":"%23",":":"%3A"}}}},n.encodeQuery=function(t,e){var i=n.encode(t+"");return void 0===e&&(e=n.escapeQuerySpace),e?i.replace(/%20/g,"+"):i},n.decodeQuery=function(t,e){t+="",void 0===e&&(e=n.escapeQuerySpace);try{return n.decode(e?t.replace(/\+/g,"%20"):t)}catch(i){return t}};var b,w={encode:"encode",decode:"decode"},x=function(t,e){return function(i){try{return n[e](i+"").replace(n.characters[t][e].expression,function(i){return n.characters[t][e].map[i]})}catch(r){return i}}};for(b in w)n[b+"PathSegment"]=x("pathname",w[b]),n[b+"UrnPathSegment"]=x("urnpath",w[b]);var _=function(t,e,i){return function(r){var o;o=i?function(t){return n[e](n[i](t))}:n[e];for(var s=(r+"").split(t),a=0,h=s.length;h>a;a++)s[a]=o(s[a]);return s.join(t)}};n.decodePath=_("/","decodePathSegment"),n.decodeUrnPath=_(":","decodeUrnPathSegment"),n.recodePath=_("/","encodePathSegment","decode"),n.recodeUrnPath=_(":","encodeUrnPathSegment","decode"),n.encodeReserved=x("reserved","encode"),n.parse=function(t,e){var i;return e||(e={}),i=t.indexOf("#"),i>-1&&(e.fragment=t.substring(i+1)||null,t=t.substring(0,i)),i=t.indexOf("?"),i>-1&&(e.query=t.substring(i+1)||null,t=t.substring(0,i)),"//"===t.substring(0,2)?(e.protocol=null,t=t.substring(2),t=n.parseAuthority(t,e)):(i=t.indexOf(":"),i>-1&&(e.protocol=t.substring(0,i)||null,e.protocol&&!e.protocol.match(n.protocol_expression)?e.protocol=void 0:"//"===t.substring(i+1,i+3)?(t=t.substring(i+3),t=n.parseAuthority(t,e)):(t=t.substring(i+1),e.urn=!0))),e.path=t,e},n.parseHost=function(t,e){t=t.replace(/\\/g,"/");var i,r,n=t.indexOf("/");if(-1===n&&(n=t.length),"["===t.charAt(0))i=t.indexOf("]"),e.hostname=t.substring(1,i)||null,e.port=t.substring(i+2,n)||null,"/"===e.port&&(e.port=null);else{var o=t.indexOf(":"),s=t.indexOf("/"),a=t.indexOf(":",o+1);-1!==a&&(-1===s||s>a)?(e.hostname=t.substring(0,n)||null,e.port=null):(r=t.substring(0,n).split(":"),e.hostname=r[0]||null,e.port=r[1]||null)}return e.hostname&&"/"!==t.substring(n).charAt(0)&&(n++,t="/"+t),t.substring(n)||"/"},n.parseAuthority=function(t,e){return t=n.parseUserinfo(t,e),n.parseHost(t,e)},n.parseUserinfo=function(t,e){var i,r=t.indexOf("/"),o=t.lastIndexOf("@",r>-1?r:t.length-1);return o>-1&&(-1===r||r>o)?(i=t.substring(0,o).split(":"),e.username=i[0]?n.decode(i[0]):null,i.shift(),e.password=i[0]?n.decode(i.join(":")):null,t=t.substring(o+1)):(e.username=null,e.password=null),t},n.parseQuery=function(t,e){if(!t)return{};if(t=t.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,""),!t)return{};for(var i,r,o,s={},a=t.split("&"),h=a.length,u=0;h>u;u++)i=a[u].split("="),r=n.decodeQuery(i.shift(),e),o=i.length?n.decodeQuery(i.join("="),e):null,v.call(s,r)?(("string"==typeof s[r]||null===s[r])&&(s[r]=[s[r]]),s[r].push(o)):s[r]=o;return s},n.build=function(t){var e="";return t.protocol&&(e+=t.protocol+":"),t.urn||!e&&!t.hostname||(e+="//"),e+=n.buildAuthority(t)||"","string"==typeof t.path&&("/"!==t.path.charAt(0)&&"string"==typeof t.hostname&&(e+="/"),e+=t.path),"string"==typeof t.query&&t.query&&(e+="?"+t.query),"string"==typeof t.fragment&&t.fragment&&(e+="#"+t.fragment),e},n.buildHost=function(t){var e="";return t.hostname?(e+=n.ip6_expression.test(t.hostname)?"["+t.hostname+"]":t.hostname,t.port&&(e+=":"+t.port),e):""},n.buildAuthority=function(t){return n.buildUserinfo(t)+n.buildHost(t)},n.buildUserinfo=function(t){var e="";return t.username&&(e+=n.encode(t.username),t.password&&(e+=":"+n.encode(t.password)),e+="@"),e},n.buildQuery=function(t,e,i){var r,o,s,h,u="";for(o in t)if(v.call(t,o)&&o)if(a(t[o]))for(r={},s=0,h=t[o].length;h>s;s++)void 0!==t[o][s]&&void 0===r[t[o][s]+""]&&(u+="&"+n.buildQueryParameter(o,t[o][s],i),e!==!0&&(r[t[o][s]+""]=!0));else void 0!==t[o]&&(u+="&"+n.buildQueryParameter(o,t[o],i));return u.substring(1)},n.buildQueryParameter=function(t,e,i){return n.encodeQuery(t,i)+(null!==e?"="+n.encodeQuery(e,i):"")},n.addQuery=function(t,e,i){if("object"==typeof e)for(var r in e)v.call(e,r)&&n.addQuery(t,r,e[r]);else{if("string"!=typeof e)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");if(void 0===t[e])return t[e]=i,void 0;"string"==typeof t[e]&&(t[e]=[t[e]]),a(i)||(i=[i]),t[e]=(t[e]||[]).concat(i)}},n.removeQuery=function(t,e,i){var r,o,u;if(a(e))for(r=0,o=e.length;o>r;r++)t[e[r]]=void 0;else if("RegExp"===s(e))for(u in t)e.test(u)&&(t[u]=void 0);else if("object"==typeof e)for(u in e)v.call(e,u)&&n.removeQuery(t,u,e[u]);else{if("string"!=typeof e)throw new TypeError("URI.removeQuery() accepts an object, string, RegExp as the first parameter");void 0!==i?"RegExp"===s(i)?t[e]=!a(t[e])&&i.test(t[e])?void 0:h(t[e],i):t[e]!==String(i)||a(i)&&1!==i.length?a(t[e])&&(t[e]=h(t[e],i)):t[e]=void 0:t[e]=void 0}},n.hasQuery=function(t,e,i,r){if("object"==typeof e){for(var o in e)if(v.call(e,o)&&!n.hasQuery(t,o,e[o]))return!1;return!0}if("string"!=typeof e)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");switch(s(i)){case"Undefined":return e in t;case"Boolean":var h=Boolean(a(t[e])?t[e].length:t[e]);return i===h;case"Function":return!!i(t[e],e,t);case"Array":if(!a(t[e]))return!1;var p=r?u:c;return p(t[e],i);case"RegExp":return a(t[e])?r?u(t[e],i):!1:Boolean(t[e]&&t[e].match(i));case"Number":i=String(i);case"String":return a(t[e])?r?u(t[e],i):!1:t[e]===i;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter")}},n.commonPath=function(t,e){var i,r=Math.min(t.length,e.length);for(i=0;r>i;i++)if(t.charAt(i)!==e.charAt(i)){i--;break}return 1>i?t.charAt(0)===e.charAt(0)&&"/"===t.charAt(0)?"/":"":(("/"!==t.charAt(i)||"/"!==e.charAt(i))&&(i=t.substring(0,i).lastIndexOf("/")),t.substring(0,i+1))},n.withinString=function(t,e,i){i||(i={});var r=i.start||n.findUri.start,o=i.end||n.findUri.end,s=i.trim||n.findUri.trim,a=/[a-z0-9-]=["']?$/i;for(r.lastIndex=0;;){var h=r.exec(t);if(!h)break;var u=h.index;if(i.ignoreHtml){var c=t.slice(Math.max(u-3,0),u);if(c&&a.test(c))continue}var p=u+t.slice(u).search(o),l=t.slice(u,p).replace(s,"");if(!i.ignore||!i.ignore.test(l)){p=u+l.length;var d=e(l,u,p,t);t=t.slice(0,u)+d+t.slice(p),r.lastIndex=u+d.length}}return r.lastIndex=0,t},n.ensureValidHostname=function(e){if(e.match(n.invalid_hostname_characters)){if(!t)throw new TypeError('Hostname "'+e+'" contains characters other than [A-Z0-9.-] and Punycode.js is not available');if(t.toASCII(e).match(n.invalid_hostname_characters))throw new TypeError('Hostname "'+e+'" contains characters other than [A-Z0-9.-]')}},n.noConflict=function(t){if(t){var e={URI:this.noConflict()};return r.URITemplate&&"function"==typeof r.URITemplate.noConflict&&(e.URITemplate=r.URITemplate.noConflict()),r.IPv6&&"function"==typeof r.IPv6.noConflict&&(e.IPv6=r.IPv6.noConflict()),r.SecondLevelDomains&&"function"==typeof r.SecondLevelDomains.noConflict&&(e.SecondLevelDomains=r.SecondLevelDomains.noConflict()),e}return r.URI===this&&(r.URI=g),this},y.build=function(t){return t===!0?this._deferred_build=!0:(void 0===t||this._deferred_build)&&(this._string=n.build(this._parts),this._deferred_build=!1),this},y.clone=function(){return new n(this)},y.valueOf=y.toString=function(){return this.build(!1)._string},y.protocol=f("protocol"),y.username=f("username"),y.password=f("password"),y.hostname=f("hostname"),y.port=f("port"),y.query=m("query","?"),y.fragment=m("fragment","#"),y.search=function(t,e){var i=this.query(t,e);return"string"==typeof i&&i.length?"?"+i:i},y.hash=function(t,e){var i=this.fragment(t,e);return"string"==typeof i&&i.length?"#"+i:i},y.pathname=function(t,e){if(void 0===t||t===!0){var i=this._parts.path||(this._parts.hostname?"/":"");return t?(this._parts.urn?n.decodeUrnPath:n.decodePath)(i):i}return this._parts.path=this._parts.urn?t?n.recodeUrnPath(t):"":t?n.recodePath(t):"/",this.build(!e),this},y.path=y.pathname,y.href=function(t,e){var i;if(void 0===t)return this.toString();this._string="",this._parts=n._parts();var r=t instanceof n,o="object"==typeof t&&(t.hostname||t.path||t.pathname);if(t.nodeName){var s=n.getDomAttribute(t);t=t[s]||"",o=!1}if(!r&&o&&void 0!==t.pathname&&(t=t.toString()),"string"==typeof t||t instanceof String)this._parts=n.parse(String(t),this._parts);else{if(!r&&!o)throw new TypeError("invalid input");var a=r?t._parts:t;for(i in a)v.call(this._parts,i)&&(this._parts[i]=a[i])}return this.build(!e),this},y.is=function(t){var e=!1,r=!1,o=!1,s=!1,a=!1,h=!1,u=!1,c=!this._parts.urn;switch(this._parts.hostname&&(c=!1,r=n.ip4_expression.test(this._parts.hostname),o=n.ip6_expression.test(this._parts.hostname),e=r||o,s=!e,a=s&&i&&i.has(this._parts.hostname),h=s&&n.idn_expression.test(this._parts.hostname),u=s&&n.punycode_expression.test(this._parts.hostname)),t.toLowerCase()){case"relative":return c;case"absolute":return!c;case"domain":case"name":return s;case"sld":return a;case"ip":return e;case"ip4":case"ipv4":case"inet4":return r;case"ip6":case"ipv6":case"inet6":return o;case"idn":return h;case"url":return!this._parts.urn;case"urn":return!!this._parts.urn;case"punycode":return u}return null};var S=y.protocol,T=y.port,E=y.hostname;y.protocol=function(t,e){if(void 0!==t&&t&&(t=t.replace(/:(\/\/)?$/,""),!t.match(n.protocol_expression)))throw new TypeError('Protocol "'+t+"\" contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return S.call(this,t,e)},y.scheme=y.protocol,y.port=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0!==t&&(0===t&&(t=null),t&&(t+="",":"===t.charAt(0)&&(t=t.substring(1)),t.match(/[^0-9]/))))throw new TypeError('Port "'+t+'" contains characters other than [0-9]');return T.call(this,t,e)},y.hostname=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0!==t){var i={},r=n.parseHost(t,i);if("/"!==r)throw new TypeError('Hostname "'+t+'" contains characters other than [A-Z0-9.-]');t=i.hostname}return E.call(this,t,e)},y.origin=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t){var i=this.protocol(),r=this.authority();return r?(i?i+"://":"")+this.authority():""}var o=n(t);return this.protocol(o.protocol()).authority(o.authority()).build(!e),this},y.host=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t)return this._parts.hostname?n.buildHost(this._parts):"";var i=n.parseHost(t,this._parts);if("/"!==i)throw new TypeError('Hostname "'+t+'" contains characters other than [A-Z0-9.-]');return this.build(!e),this},y.authority=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t)return this._parts.hostname?n.buildAuthority(this._parts):"";var i=n.parseAuthority(t,this._parts);if("/"!==i)throw new TypeError('Hostname "'+t+'" contains characters other than [A-Z0-9.-]');return this.build(!e),this},y.userinfo=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t){if(!this._parts.username)return"";var i=n.buildUserinfo(this._parts);return i.substring(0,i.length-1)}return"@"!==t[t.length-1]&&(t+="@"),n.parseUserinfo(t,this._parts),this.build(!e),this},y.resource=function(t,e){var i;return void 0===t?this.path()+this.search()+this.hash():(i=n.parse(t),this._parts.path=i.path,this._parts.query=i.query,this._parts.fragment=i.fragment,this.build(!e),this) -},y.subdomain=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t){if(!this._parts.hostname||this.is("IP"))return"";var i=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,i)||""}var r=this._parts.hostname.length-this.domain().length,s=this._parts.hostname.substring(0,r),a=new RegExp("^"+o(s));return t&&"."!==t.charAt(t.length-1)&&(t+="."),t&&n.ensureValidHostname(t),this._parts.hostname=this._parts.hostname.replace(a,t),this.build(!e),this},y.domain=function(t,e){if(this._parts.urn)return void 0===t?"":this;if("boolean"==typeof t&&(e=t,t=void 0),void 0===t){if(!this._parts.hostname||this.is("IP"))return"";var i=this._parts.hostname.match(/\./g);if(i&&i.length<2)return this._parts.hostname;var r=this._parts.hostname.length-this.tld(e).length-1;return r=this._parts.hostname.lastIndexOf(".",r-1)+1,this._parts.hostname.substring(r)||""}if(!t)throw new TypeError("cannot set domain empty");if(n.ensureValidHostname(t),!this._parts.hostname||this.is("IP"))this._parts.hostname=t;else{var s=new RegExp(o(this.domain())+"$");this._parts.hostname=this._parts.hostname.replace(s,t)}return this.build(!e),this},y.tld=function(t,e){if(this._parts.urn)return void 0===t?"":this;if("boolean"==typeof t&&(e=t,t=void 0),void 0===t){if(!this._parts.hostname||this.is("IP"))return"";var r=this._parts.hostname.lastIndexOf("."),n=this._parts.hostname.substring(r+1);return e!==!0&&i&&i.list[n.toLowerCase()]?i.get(this._parts.hostname)||n:n}var s;if(!t)throw new TypeError("cannot set TLD empty");if(t.match(/[^a-zA-Z0-9-]/)){if(!i||!i.is(t))throw new TypeError('TLD "'+t+'" contains characters other than [A-Z0-9]');s=new RegExp(o(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(s,t)}else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");s=new RegExp(o(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(s,t)}return this.build(!e),this},y.directory=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t||t===!0){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var i=this._parts.path.length-this.filename().length-1,r=this._parts.path.substring(0,i)||(this._parts.hostname?"/":"");return t?n.decodePath(r):r}var s=this._parts.path.length-this.filename().length,a=this._parts.path.substring(0,s),h=new RegExp("^"+o(a));return this.is("relative")||(t||(t="/"),"/"!==t.charAt(0)&&(t="/"+t)),t&&"/"!==t.charAt(t.length-1)&&(t+="/"),t=n.recodePath(t),this._parts.path=this._parts.path.replace(h,t),this.build(!e),this},y.filename=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t||t===!0){if(!this._parts.path||"/"===this._parts.path)return"";var i=this._parts.path.lastIndexOf("/"),r=this._parts.path.substring(i+1);return t?n.decodePathSegment(r):r}var s=!1;"/"===t.charAt(0)&&(t=t.substring(1)),t.match(/\.?\//)&&(s=!0);var a=new RegExp(o(this.filename())+"$");return t=n.recodePath(t),this._parts.path=this._parts.path.replace(a,t),s?this.normalizePath(e):this.build(!e),this},y.suffix=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t||t===!0){if(!this._parts.path||"/"===this._parts.path)return"";var i,r,s=this.filename(),a=s.lastIndexOf(".");return-1===a?"":(i=s.substring(a+1),r=/^[a-z0-9%]+$/i.test(i)?i:"",t?n.decodePathSegment(r):r)}"."===t.charAt(0)&&(t=t.substring(1));var h,u=this.suffix();if(u)h=t?new RegExp(o(u)+"$"):new RegExp(o("."+u)+"$");else{if(!t)return this;this._parts.path+="."+n.recodePath(t)}return h&&(t=n.recodePath(t),this._parts.path=this._parts.path.replace(h,t)),this.build(!e),this},y.segment=function(t,e,i){var r=this._parts.urn?":":"/",n=this.path(),o="/"===n.substring(0,1),s=n.split(r);if(void 0!==t&&"number"!=typeof t&&(i=e,e=t,t=void 0),void 0!==t&&"number"!=typeof t)throw new Error('Bad segment "'+t+'", must be 0-based integer');if(o&&s.shift(),0>t&&(t=Math.max(s.length+t,0)),void 0===e)return void 0===t?s:s[t];if(null===t||void 0===s[t])if(a(e)){s=[];for(var h=0,u=e.length;u>h;h++)(e[h].length||s.length&&s[s.length-1].length)&&(s.length&&!s[s.length-1].length&&s.pop(),s.push(p(e[h])))}else(e||"string"==typeof e)&&(e=p(e),""===s[s.length-1]?s[s.length-1]=e:s.push(e));else e?s[t]=p(e):s.splice(t,1);return o&&s.unshift(""),this.path(s.join(r),i)},y.segmentCoded=function(t,e,i){var r,o,s;if("number"!=typeof t&&(i=e,e=t,t=void 0),void 0===e){if(r=this.segment(t,e,i),a(r))for(o=0,s=r.length;s>o;o++)r[o]=n.decode(r[o]);else r=void 0!==r?n.decode(r):void 0;return r}if(a(e))for(o=0,s=e.length;s>o;o++)e[o]=n.encode(e[o]);else e="string"==typeof e||e instanceof String?n.encode(e):e;return this.segment(t,e,i)};var k=y.query;return y.query=function(t,e){if(t===!0)return n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("function"==typeof t){var i=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace),r=t.call(this,i);return this._parts.query=n.buildQuery(r||i,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!e),this}return void 0!==t&&"string"!=typeof t?(this._parts.query=n.buildQuery(t,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!e),this):k.call(this,t,e)},y.setQuery=function(t,e,i){var r=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("string"==typeof t||t instanceof String)r[t]=void 0!==e?e:null;else{if("object"!=typeof t)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");for(var o in t)v.call(t,o)&&(r[o]=t[o])}return this._parts.query=n.buildQuery(r,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof t&&(i=e),this.build(!i),this},y.addQuery=function(t,e,i){var r=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return n.addQuery(r,t,void 0===e?null:e),this._parts.query=n.buildQuery(r,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof t&&(i=e),this.build(!i),this},y.removeQuery=function(t,e,i){var r=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return n.removeQuery(r,t,e),this._parts.query=n.buildQuery(r,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof t&&(i=e),this.build(!i),this},y.hasQuery=function(t,e,i){var r=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return n.hasQuery(r,t,e,i)},y.setSearch=y.setQuery,y.addSearch=y.addQuery,y.removeSearch=y.removeQuery,y.hasSearch=y.hasQuery,y.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()},y.normalizeProtocol=function(t){return"string"==typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!t)),this},y.normalizeHostname=function(i){return this._parts.hostname&&(this.is("IDN")&&t?this._parts.hostname=t.toASCII(this._parts.hostname):this.is("IPv6")&&e&&(this._parts.hostname=e.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!i)),this},y.normalizePort=function(t){return"string"==typeof this._parts.protocol&&this._parts.port===n.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!t)),this},y.normalizePath=function(t){var e=this._parts.path;if(!e)return this;if(this._parts.urn)return this._parts.path=n.recodeUrnPath(this._parts.path),this.build(!t),this;if("/"===this._parts.path)return this;var i,r,o,s="";for("/"!==e.charAt(0)&&(i=!0,e="/"+e),("/.."===e.slice(-3)||"/."===e.slice(-2))&&(e+="/"),e=e.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/"),i&&(s=e.substring(1).match(/^(\.\.\/)+/)||"",s&&(s=s[0]));;){if(r=e.indexOf("/.."),-1===r)break;0!==r?(o=e.substring(0,r).lastIndexOf("/"),-1===o&&(o=r),e=e.substring(0,o)+e.substring(r+3)):e=e.substring(3)}return i&&this.is("relative")&&(e=s+e.substring(1)),e=n.recodePath(e),this._parts.path=e,this.build(!t),this},y.normalizePathname=y.normalizePath,y.normalizeQuery=function(t){return"string"==typeof this._parts.query&&(this._parts.query.length?this.query(n.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!t)),this},y.normalizeFragment=function(t){return this._parts.fragment||(this._parts.fragment=null,this.build(!t)),this},y.normalizeSearch=y.normalizeQuery,y.normalizeHash=y.normalizeFragment,y.iso8859=function(){var t=n.encode,e=n.decode;n.encode=escape,n.decode=decodeURIComponent;try{this.normalize()}finally{n.encode=t,n.decode=e}return this},y.unicode=function(){var t=n.encode,e=n.decode;n.encode=d,n.decode=unescape;try{this.normalize()}finally{n.encode=t,n.decode=e}return this},y.readable=function(){var e=this.clone();e.username("").password("").normalize();var i="";if(e._parts.protocol&&(i+=e._parts.protocol+"://"),e._parts.hostname&&(e.is("punycode")&&t?(i+=t.toUnicode(e._parts.hostname),e._parts.port&&(i+=":"+e._parts.port)):i+=e.host()),e._parts.hostname&&e._parts.path&&"/"!==e._parts.path.charAt(0)&&(i+="/"),i+=e.path(!0),e._parts.query){for(var r="",o=0,s=e._parts.query.split("&"),a=s.length;a>o;o++){var h=(s[o]||"").split("=");r+="&"+n.decodeQuery(h[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"),void 0!==h[1]&&(r+="="+n.decodeQuery(h[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}i+="?"+r.substring(1)}return i+=n.decodeQuery(e.hash(),!0)},y.absoluteTo=function(t){var e,i,r,o=this.clone(),s=["protocol","username","password","hostname","port"];if(this._parts.urn)throw new Error("URNs do not have any generally defined hierarchical components");if(t instanceof n||(t=new n(t)),o._parts.protocol||(o._parts.protocol=t._parts.protocol),this._parts.hostname)return o;for(i=0;r=s[i];i++)o._parts[r]=t._parts[r];return o._parts.path?".."===o._parts.path.substring(-2)&&(o._parts.path+="/"):(o._parts.path=t._parts.path,o._parts.query||(o._parts.query=t._parts.query)),"/"!==o.path().charAt(0)&&(e=t.directory(),e=e?e:0===t.path().indexOf("/")?"/":"",o._parts.path=(e?e+"/":"")+o._parts.path,o.normalizePath()),o.build(),o},y.relativeTo=function(t){var e,i,r,o,s,a=this.clone().normalize();if(a._parts.urn)throw new Error("URNs do not have any generally defined hierarchical components");if(t=new n(t).normalize(),e=a._parts,i=t._parts,o=a.path(),s=t.path(),"/"!==o.charAt(0))throw new Error("URI is already relative");if("/"!==s.charAt(0))throw new Error("Cannot calculate a URI relative to another relative URI");if(e.protocol===i.protocol&&(e.protocol=null),e.username!==i.username||e.password!==i.password)return a.build();if(null!==e.protocol||null!==e.username||null!==e.password)return a.build();if(e.hostname!==i.hostname||e.port!==i.port)return a.build();if(e.hostname=null,e.port=null,o===s)return e.path="",a.build();if(r=n.commonPath(o,s),!r)return a.build();var h=i.path.substring(r.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../");return e.path=h+e.path.substring(r.length)||"./",a.build()},y.equals=function(t){var e,i,r,o=this.clone(),s=new n(t),h={},u={},p={};if(o.normalize(),s.normalize(),o.toString()===s.toString())return!0;if(e=o.query(),i=s.query(),o.query(""),s.query(""),o.toString()!==s.toString())return!1;if(e.length!==i.length)return!1;h=n.parseQuery(e,this._parts.escapeQuerySpace),u=n.parseQuery(i,this._parts.escapeQuerySpace);for(r in h)if(v.call(h,r)){if(a(h[r])){if(!c(h[r],u[r]))return!1}else if(h[r]!==u[r])return!1;p[r]=!0}for(r in u)if(v.call(u,r)&&!p[r])return!1;return!0},y.duplicateQueryParameters=function(t){return this._parts.duplicateQueryParameters=!!t,this},y.escapeQuerySpace=function(t){return this._parts.escapeQuerySpace=!!t,this},n})},{"./IPv6":2,"./SecondLevelDomains":2,"./punycode":2}],6:[function(t,e){function i(t){this.opening=new r.defer,this.opened=this.opening.promise,this.isOpen=!1,this.url=void 0,this.loading={manifest:new r.defer,spine:new r.defer,metadata:new r.defer,cover:new r.defer,navigation:new r.defer,pageList:new r.defer},this.loaded={manifest:this.loading.manifest.promise,spine:this.loading.spine.promise,metadata:this.loading.metadata.promise,cover:this.loading.cover.promise,navigation:this.loading.navigation.promise,pageList:this.loading.pageList.promise},this.ready=r.hash(this.loaded),this.isRendered=!1,this.request=this.requestMethod.bind(this),this.spine=new o(this.request),this.locations=new s(this.spine,this.request),t&&this.open(t)}var r=t("rsvp"),n=t("urijs"),o=(t("./core"),t("./spine")),s=t("./locations"),a=t("./parser"),h=t("./navigation"),u=(t("./rendition"),t("./continuous"),t("./paginate"),t("./unarchive")),c=t("./request");i.prototype.open=function(t){var e,i,r,o=new a,s=this,h="META-INF/container.xml";return t?(e=n(t),this.url=t,"opf"===e.suffix()?(this.packageUrl=t,this.containerUrl="",this.baseUrl=e.origin()?e.origin()+"/"+e.directory()+"/":window?e.absoluteTo(window.location.href).directory()+"/":e.directory()+"/",i=this.request(this.packageUrl)):this.isArchivedUrl(e)?(this.url="/",this.containerUrl=n(h).absoluteTo(this.url).toString(),r=this.unarchive(t).then(function(){return this.request(this.containerUrl)}.bind(this))):e.suffix()||(this.containerUrl=this.url+h,r=this.request(this.containerUrl)),r&&(i=r.then(function(t){return o.container(t)}).then(function(t){var i=n(t.packagePath);return s.packageUrl=i.absoluteTo(s.url).toString(),s.encoding=t.encoding,s.baseUrl=i.origin()?i.origin()+"/"+i.directory()+"/":window&&!s.isArchivedUrl(e)?i.absoluteTo(window.location.href).directory()+"/":"/"+i.directory()+"/",s.request(s.packageUrl)}).catch(function(t){console.error("Could not load book at: "+(this.packageUrl||this.containerPath)),s.trigger("book:loadFailed",this.packageUrl||this.containerPath),s.opening.reject(t)})),i.then(function(t){s.unpack(t),s.loading.manifest.resolve(s.package.manifest),s.loading.metadata.resolve(s.package.metadata),s.loading.spine.resolve(s.spine),s.loading.cover.resolve(s.cover),s.isOpen=!0,s.opening.resolve(s)}).catch(function(t){console.error(t.message,t.stack),s.opening.reject(t)}),this.opened):(this.opening.resolve(this),this.opened)},i.prototype.unpack=function(t){var e=this,i=new a;e.package=i.packageContents(t),e.package.baseUrl=e.baseUrl,this.spine.load(e.package),e.navigation=new h(e.package,this.request),e.navigation.load().then(function(t){e.toc=t,e.loading.navigation.resolve(e.toc)}),e.cover=n(e.package.coverPath).absoluteTo(e.baseUrl).toString()},i.prototype.section=function(t){return this.spine.get(t)},i.prototype.renderTo=function(e,i){var r=i&&i.method?i.method:"rendition",n=t("./"+r);return this.rendition=new n(this,i),this.rendition.attachTo(e),this.rendition},i.prototype.requestMethod=function(t){return this.archive?this.archive.request(t):c(t,null,this.requestCredentials,this.requestHeaders)},i.prototype.setRequestCredentials=function(t){this.requestCredentials=t},i.prototype.setRequestHeaders=function(t){this.requestHeaders=t},i.prototype.unarchive=function(t){return this.archive=new u,this.archive.open(t)},i.prototype.isArchivedUrl=function(t){var e,i;return t instanceof ArrayBuffer?!0:(e=n(t),i=e.suffix(),!i||"epub"!=i&&"zip"!=i?!1:!0)},i.prototype.coverUrl=function(){var t=this.loaded.cover.then(function(){return this.archive?this.archive.createUrl(this.cover):this.cover}.bind(this));return t},e.exports=i,r.EventTarget.mixin(i.prototype),r.on("error",function(t){console.error(t)}),r.configure("instrument",!0),r.on("rejected",function(t){console.error(t.detail.message,t.detail.stack)})},{"./continuous":7,"./core":8,"./locations":12,"./navigation":14,"./paginate":15,"./parser":16,"./rendition":18,"./request":20,"./spine":22,"./unarchive":23,rsvp:4,urijs:5}],7:[function(t,e){function i(t,e){o.apply(this,arguments),this.settings=n.extend(this.settings||{},{infinite:!0,overflow:"auto",axis:"vertical",offset:500,offsetDelta:250}),n.extend(this.settings,e),this.settings.hidden&&(this.wrapper=this.wrap(this.container))}{var r=t("rsvp"),n=t("./core"),o=t("./rendition");t("./view")}i.prototype=Object.create(o.prototype),i.prototype.constructor=i,i.prototype.attachListeners=function(){n.isNumber(this.settings.width)&&n.isNumber(this.settings.height)||window.addEventListener("resize",this.onResized.bind(this),!1),this.settings.infinite&&this.start()},i.prototype.parseTarget=function(t){this.epubcfi.isCfiString(t)?(cfi=this.epubcfi.parse(t),spinePos=cfi.spinePos,section=this.book.spine.get(spinePos)):section=this.book.spine.get(t)},i.prototype.moveTo=function(t){return this.check(t.left+this.settings.offset,t.top+this.settings.offset).then(function(){"vertical"===this.settings.axis?this.scrollBy(0,t.top):this.scrollBy(t.left,0)}.bind(this))},i.prototype.afterDisplayed=function(t){var e,i,r=t.section.next(),n=t.section.prev(),o=this.views.indexOf(t);o+1===this.views.length&&r&&(i=this.createView(r),this.q.enqueue(this.append,i)),0===o&&n&&(e=this.createView(n,this.viewSettings),this.q.enqueue(this.prepend,e)),this.trigger("added",t.section)},i.prototype.removeShownListeners=function(t){t.onDisplayed=function(){}},i.prototype.append=function(t){return t.onDisplayed=this.afterDisplayed.bind(this),this.views.append(t),this.check()},i.prototype.prepend=function(t){return t.onDisplayed=this.afterDisplayed.bind(this),t.on("resized",this.counter.bind(this)),this.views.prepend(t),this.check()},i.prototype.counter=function(t){"vertical"===this.settings.axis?this.scrollBy(0,t.heightDelta,!0):this.scrollBy(t.widthDelta,0,!0)},i.prototype.check=function(t){var e=new r.defer,i=this.bounds(),n=[],o=t||this.settings.offset;return this.views.each(function(t){var e=this.isVisible(t,o,o,i);e?t.displayed||t.rendering||n.push(this.render(t)):t.displayed&&(this.q.enqueue(t.destroy.bind(t)),clearTimeout(this.trimTimeout),this.trimTimeout=setTimeout(function(){this.q.enqueue(this.trim)}.bind(this),250))}.bind(this)),n.length?r.all(n).then(function(){this.q.enqueue(this.check)}.bind(this)):(e.resolve(),e.promise)},i.prototype.trim=function(){for(var t=new r.defer,e=this.views.displayed(),i=e[0],n=e[e.length-1],o=this.views.indexOf(i),s=this.views.indexOf(n),a=this.views.slice(0,o),h=this.views.slice(s+1),u=0;uthis.settings.offsetDelta||this.scrollDeltaHorz>this.settings.offsetDelta)&&(this.q.enqueue(this.check),this.scrollDeltaVert=0,this.scrollDeltaHorz=0,this.trigger("scroll",{top:scrollTop,left:scrollLeft})),this.scrollDeltaVert+=Math.abs(scrollTop-this.prevScrollTop),this.scrollDeltaHorz+=Math.abs(scrollLeft-this.prevScrollLeft),this.prevScrollTop=scrollTop,this.prevScrollLeft=scrollLeft,clearTimeout(this.scrollTimeout),this.scrollTimeout=setTimeout(function(){this.scrollDeltaVert=0,this.scrollDeltaHorz=0}.bind(this),150),this.scrolled=!1),this.tick.call(window,this.onScroll.bind(this))},i.prototype.resizeView=function(t){"horizontal"===this.settings.axis?t.lock("height",this.stage.width,this.stage.height):t.lock("width",this.stage.width,this.stage.height)},i.prototype.currentLocation=function(){{var t,e,i=this.visible();this.container.getBoundingClientRect()}return 1===i.length?this.map.page(i[0]):i.length>1?(t=this.map.page(i[0]),e=this.map.page(i[i.length-1]),{start:t.start,end:e.end}):void 0},e.exports=i},{"./core":8,"./rendition":18,"./view":24,rsvp:4}],8:[function(t,e){function i(t){return!(!t||1!=t.nodeType)}function r(){var t=(new Date).getTime(),e="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?i:7&i|8).toString(16)});return e}function n(t){for(var e=-1,i=Object.keys(t),r=i.length,n=Array(r);++en;n++)if("undefined"!=typeof document.body.style[e[n]+i])return e[n]+i;return t}function u(t){for(var e=1,i=arguments.length;i>e;e++){var r=arguments[e];for(var n in r)void 0===t[n]&&(t[n]=r[n])}return t}function c(t){var e=[].slice.call(arguments,1);return e.forEach(function(e){e&&Object.getOwnPropertyNames(e).forEach(function(i){Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))})}),t}function p(t,e,i){var r=l(t,e,i);return e.splice(r,0,t),r}function l(t,e,i,r,n){var o,s=r||0,a=n||e.length,h=parseInt(s+(a-s)/2);return i||(i=function(t,e){return t>e?1:e>t?-1:(t=e)?0:void 0}),0>=a-s?h:(o=i(e[h],t),a-s===1?o>0?h:h+1:0===o?h:-1===o?l(t,e,i,h,a):l(t,e,i,s,h))}function d(t,e,i,r,n){var o,s=r||0,a=n||e.length,h=parseInt(s+(a-s)/2);return i||(i=function(t,e){return t>e?1:e>t?-1:(t=e)?0:void 0}),0>=a-s?-1:(o=i(e[h],t),a-s===1?0===o?h:-1:0===o?h:-1===o?d(t,e,i,h,a):d(t,e,i,s,h))}function f(t){var e=window.getComputedStyle(t),i=["width","paddingRight","paddingLeft","marginRight","marginLeft","borderRightWidth","borderLeftWidth"],r=["height","paddingTop","paddingBottom","marginTop","marginBottom","borderTopWidth","borderBottomWidth"],n=0,o=0;return i.forEach(function(t){n+=parseFloat(e[t])||0}),r.forEach(function(t){o+=parseFloat(e[t])||0}),{height:o,width:n}}function m(t){var e=window.getComputedStyle(t),i=["paddingRight","paddingLeft","marginRight","marginLeft","borderRightWidth","borderLeftWidth"],r=["paddingTop","paddingBottom","marginTop","marginBottom","borderTopWidth","borderBottomWidth"],n=0,o=0;return i.forEach(function(t){n+=parseFloat(e[t])||0}),r.forEach(function(t){o+=parseFloat(e[t])||0}),{height:o,width:n}}function g(){var t=window.innerWidth,e=window.innerHeight;return{top:0,left:0,right:t,bottom:e,width:t,height:e}}function y(t){var e=t.match(/[^'"]+|['"]/g);return e=e.map(function(t){return"'"===t?'"\'"':'"'===t?"'\"'":"'"+t+"'"}),"concat('',"+e.join(",")+")"}function v(t){for(var e,i=t.parentNode,r=i.childNodes,n=-1,o=0;o-1}function w(t,e){var i,r=window.URL||window.webkitURL||window.mozURL,n=new Blob([t],{type:e});return i=r.createObjectURL(n)}var x=(t("rsvp"),window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame);e.exports={isElement:i,uuid:r,values:n,resolveUrl:o,indexOfSorted:d,documentHeight:s,isNumber:a,prefixed:h,defaults:u,extend:c,insert:p,locationOf:l,indexOfSorted:d,requestAnimationFrame:x,bounds:f,borders:m,windowBounds:g,cleanStringForXpath:y,indexOfTextNode:v,isXml:b,createBlobUrl:w}},{rsvp:4}],9:[function(t,e){function i(t){return t?this.parse(t):void 0}var r=t("urijs"),n=t("./core");i.prototype.generateChapterComponent=function(t,e,i){var r=parseInt(e),n=t+1,o="/"+n+"/";return o+=2*(r+1),i&&(o+="["+i+"]"),o},i.prototype.generatePathComponent=function(t){var e=[];return t.forEach(function(t){var i="";i+=2*(t.index+1),t.id&&(i+="["+t.id+"]"),e.push(i)}),e.join("/")},i.prototype.generateCfiFromElement=function(t,e){var i=this.pathTo(t),r=this.generatePathComponent(i);return r.length?"epubcfi("+e+"!"+r+"/1:0)":"epubcfi("+e+"!/4/)"},i.prototype.pathTo=function(t){for(var e,i=[];t&&null!==t.parentNode&&9!=t.parentNode.nodeType;)e=t.parentNode.children,i.unshift({id:t.id,tagName:t.tagName,index:e?Array.prototype.indexOf.call(e,t):0}),t=t.parentNode;return i},i.prototype.getChapterComponent=function(t){var e=t.split("!");return e[0]},i.prototype.getPathComponent=function(t){var e=t.split("!"),i=e[1]?e[1].split(":"):"";return i[0]},i.prototype.getCharecterOffsetComponent=function(t){var e=t.split(":");return e[1]||""},i.prototype.parse=function(t){var e,i,r,n,o,s,a,h,u,c={},p=function(t){var e,i,r,n;return e="element",i=parseInt(t)/2-1,r=t.match(/\[(.*)\]/),r&&r[1]&&(n=r[1]),{type:e,index:i,id:n||!1}};return"string"!=typeof t?{spinePos:-1}:(c.str=t,0===t.indexOf("epubcfi(")&&")"===t[t.length-1]&&(t=t.slice(8,t.length-1)),i=this.getChapterComponent(t),r=this.getPathComponent(t)||"",n=this.getCharecterOffsetComponent(t),i?(e=i.split("/")[2]||"")?(c.spinePos=parseInt(e)/2-1||0,s=e.match(/\[(.*)\]/),c.spineId=s?s[1]:!1,-1!=r.indexOf(",")&&console.warn("CFI Ranges are not supported"),a=r.split("/"),h=a.pop(),c.steps=[],a.forEach(function(t){var e;t&&(e=p(t),c.steps.push(e))}),u=parseInt(h),isNaN(u)||(u%2===0?c.steps.push(p(h)):c.steps.push({type:"text",index:(u-1)/2})),o=n.match(/\[(.*)\]/),o&&o[1]?(c.characterOffset=parseInt(n.split("[")[0]),c.textLocationAssertion=o[1]):c.characterOffset=parseInt(n),c):{spinePos:-1}:{spinePos:-1})},i.prototype.addMarker=function(t,e,i){var r,n,o,s,a=e||document,h=i||this.createMarker(a);return"string"==typeof t&&(t=this.parse(t)),n=t.steps[t.steps.length-1],-1===t.spinePos?!1:(r=this.findParent(t,a))?(n&&"text"===n.type?(o=r.childNodes[n.index],t.characterOffset?(s=o.splitText(t.characterOffset),h.classList.add("EPUBJS-CFI-SPLIT"),r.insertBefore(h,s)):r.insertBefore(h,o)):r.insertBefore(h,r.firstChild),h):!1},i.prototype.createMarker=function(t){var e=t||document,i=e.createElement("span");return i.id="EPUBJS-CFI-MARKER:"+n.uuid(),i.classList.add("EPUBJS-CFI-MARKER"),i},i.prototype.removeMarker=function(t,e){t.classList.contains("EPUBJS-CFI-SPLIT")?(nextSib=t.nextSibling,prevSib=t.previousSibling,nextSib&&prevSib&&3===nextSib.nodeType&&3===prevSib.nodeType&&(prevSib.textContent+=nextSib.textContent,t.parentNode.removeChild(nextSib)),t.parentNode.removeChild(t)):t.classList.contains("EPUBJS-CFI-MARKER")&&t.parentNode.removeChild(t)},i.prototype.findParent=function(t,e){var i,r,n,o=e||document,s=o.getElementsByTagName("html")[0],a=Array.prototype.slice.call(s.children);if("string"==typeof t&&(t=this.parse(t)),r=t.steps.slice(0),!r.length)return o.getElementsByTagName("body")[0];for(;r&&r.length>0;){if(i=r.shift(),"text"===i.type?(n=s.childNodes[i.index],s=n.parentNode||s):s=i.id?o.getElementById(i.id):a[i.index],"undefined"==typeof s)return console.error("No Element For",i,t.str),!1;a=Array.prototype.slice.call(s.children)}return s},i.prototype.compare=function(t,e){if("string"==typeof t&&(t=new i(t)),"string"==typeof e&&(e=new i(e)),t.spinePos>e.spinePos)return 1;if(t.spinePose.steps[r].index)return 1;if(t.steps[r].indexe.characterOffset?1:t.characterOffset")},i.prototype.generateRangeFromCfi=function(t,e){var i,r,n,o,s,a,h=e||document,u=h.createRange();return"string"==typeof t&&(t=this.parse(t)),-1===t.spinePos?!1:(i=t.steps[t.steps.length-1],"undefined"!=typeof document.evaluate?(r=this.generateXpathFromSteps(t.steps),n=h.evaluate(r,h,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue):(s=this.generateQueryFromSteps(t.steps),a=h.querySelector(s),a&&"text"==i.type&&(n=a.childNodes[i.index])),n?(n&&t.characterOffset>=0?(o=n.length,t.characterOffset=0?i:p%2===0?p:p-1;n=h>1?Math.floor((c-l)/h):c,s=n*h,a=(n+l)*h,this.columnAxis=o.prefixed("columnAxis"),this.columnGap=o.prefixed("columnGap"),this.columnWidth=o.prefixed("columnWidth"),this.columnFill=o.prefixed("columnFill"),this.width=c,this.height=e,this.spread=s,this.delta=a,this.column=n,this.gap=l,this.divisor=h},i.prototype.format=function(t){var e=t.document.documentElement,i=t.document.body;e.style.overflow="hidden",e.style.width=this.width+"px",i.style.height=this.height+"px",i.style[this.columnAxis]="horizontal",i.style[this.columnFill]="auto",i.style[this.columnGap]=this.gap+"px",i.style[this.columnWidth]=this.column+"px",t.iframe.style.marginRight=this.gap+"px" -},i.prototype.count=function(t){var e=t.root().scrollWidth,i=Math.ceil(e/this.spread);return{spreads:i,pages:i*this.divisor}},r.prototype.calculate=function(){},r.prototype.format=function(t){var e,i,r=t.document.documentElement,n=documentElement.querySelector("[name=viewport");n&&n.hasAttribute("content")&&(content=n.getAttribute("content"),contents=content.split(","),contents[0]&&(e=contents[0].replace("width=","")),contents[1]&&(i=contents[1].replace("height=",""))),t.resize(e,i),r.style.overflow="auto"},r.prototype.count=function(){return{spreads:1,pages:1}},n.prototype.calculate=function(t){this.spread=t,this.column=t,this.gap=0},n.prototype.format=function(t){var e=t.document.documentElement;e.style.width="auto",e.style.height="auto"},n.prototype.count=function(){return{spreads:1,pages:1}},e.exports={Reflowable:i,Fixed:r,Scroll:n}},{"./core":8}],12:[function(t,e){function i(t,e){this.spine=t,this.request=e,this.q=new n(this),this.epubcfi=new o,this._locations=[],this.total=0,this.break=150,this._current=0}var r=t("./core"),n=t("./queue"),o=t("./epubcfi"),s=t("rsvp");i.prototype.generate=function(t){return t&&(this.break=t),this.q.pause(),this.spine.each(function(t){this.q.enqueue(this.process,t)}.bind(this)),this.q.run().then(function(){return this.total=this._locations.length-1,this._currentCfi&&(this.currentLocation=this._currentCfi),this._locations}.bind(this))},i.prototype.process=function(t){return t.load(this.request).then(function(e){var i,r=e.ownerDocument,n=0;this.sprint(e,function(e){var o,s=e.length,a=0;for(0==n&&(i=r.createRange(),i.setStart(e,0)),o=this.break-n,o>s&&(n+=s,a=s);s>a;)n=this.break,a+=this.break,a>=s?n=s-(a-this.break):(i.setEnd(e,a),cfi=t.cfiFromRange(i),this._locations.push(cfi),n=0,a+=1,i=r.createRange(),i.setStart(e,a))}.bind(this)),i&&(i.setEnd(prev,prev.length),cfi=t.cfiFromRange(i),this._locations.push(cfi),n=0)}.bind(this))},i.prototype.sprint=function(t,e){for(var i=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,null,!1);node=i.nextNode();)e(node)},i.prototype.locationFromCfi=function(t){return 0===this._locations.length?-1:r.locationOf(t,this._locations,this.epubcfi.compare)},i.prototype.precentageFromCfi=function(t){var e=this.locationFromCfi(t);return this.precentageFromLocation(e)},i.prototype.percentageFromLocation=function(t){return t&&this.total?t/this.total:0},i.prototype.cfiFromLocation=function(t){var e=-1;return"number"!=typeof t&&(t=parseInt(pg)),t>=0&&t1?t/100:t,i=Math.ceil(this.total*e);return this.cfiFromLocation(i)},i.prototype.load=function(t){return this._locations=JSON.parse(t),this.total=this._locations.length-1,this._locations},i.prototype.save=function(){return JSON.stringify(this._locations)},i.prototype.getCurrent=function(){return this._current},i.prototype.setCurrent=function(t){var e;if("string"==typeof t)this._currentCfi=t;else{if("number"!=typeof t)return;this._current=t}0!==this._locations.length&&("string"==typeof t?(e=this.locationFromCfi(t),this._current=e):e=t,this.trigger("changed",{percentage:this.precentageFromLocation(e)}))},Object.defineProperty(i.prototype,"currentLocation",{get:function(){return this._current},set:function(t){this.setCurrent(t)}}),s.EventTarget.mixin(i.prototype),e.exports=i},{"./core":8,"./epubcfi":9,"./queue":17,rsvp:4}],13:[function(t,e){function i(t){this.layout=t}i.prototype.section=function(t){var e=this.findRanges(t),i=this.rangeListToCfiList(t,e);return i},i.prototype.page=function(t,e,i){var r=t.document.body;return this.rangePairToCfiPair(t.section,{start:this.findStart(r,e,i),end:this.findEnd(r,e,i)})},i.prototype.walk=function(t,e){for(var i,r,n=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,{acceptNode:function(t){return t.data.trim().length>0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}},!1);(i=n.nextNode())&&!(r=e(i)););return r},i.prototype.findRanges=function(t){for(var e,i,r=[],n=this.layout.count(t),o=this.layout.column,s=this.layout.gap,a=0;a=e&&i>=r?t:n>e?t:(s=t,o.push(t),void 0)}))return this.findTextStartRange(n,e,i);return this.findTextStartRange(s,e,i)},i.prototype.findEnd=function(t,e,i){for(var r,n,o=[t],s=t;o.length;)if(r=o.shift(),n=this.walk(r,function(t){var e,r,n,a;return t.nodeType==Node.TEXT_NODE?(a=document.createRange(),a.selectNodeContents(t),n=a.getBoundingClientRect()):n=t.getBoundingClientRect(),e=n.left,r=n.right,e>i&&s?s:r>i?t:(s=t,o.push(t),void 0)}))return this.findTextEndRange(n,e,i);return this.findTextEndRange(s,e,i)},i.prototype.findTextStartRange=function(t,e){for(var i,r,n,o=this.splitTextNodeIntoRanges(t),s=0;s=e)return r;i=r}return o[0]},i.prototype.findTextEndRange=function(t,e,i){for(var r,n,o,s=this.splitTextNodeIntoRanges(t),a=0;ai&&r)return r;if(o.right>i)return n;r=n}return s[s.length-1]},i.prototype.splitTextNodeIntoRanges=function(t,e){var i,r=[],n=t.textContent||"",o=n.trim(),s=t.ownerDocument,a=e||" ";if(pos=o.indexOf(a),-1===pos||t.nodeType!=Node.TEXT_NODE)return i=s.createRange(),i.selectNodeContents(t),[i];for(i=s.createRange(),i.setStart(t,0),i.setEnd(t,pos),r.push(i),i=!1;-1!=pos;)pos=o.indexOf(a,pos+1),pos>0&&(i&&(i.setEnd(t,pos),r.push(i)),i=s.createRange(),i.setStart(t,pos+1));return i&&(i.setEnd(t,o.length),r.push(i)),r},i.prototype.rangePairToCfiPair=function(t,e){var i=e.start,r=e.end;return i.collapse(!0),r.collapse(!0),startCfi=t.cfiFromRange(i),endCfi=t.cfiFromRange(r),{start:startCfi,end:endCfi}},i.prototype.rangeListToCfiList=function(t,e){for(var i,r=[],n=0;n1?(t=a.left-s[0].position().left,i=t+this.layout.column,e=a.left+this.layout.spread-s[s.length-1].position().left,r=e+this.layout.column,n=this.map.page(s[0],t,i),o=this.map.page(s[s.length-1],e,r),{start:n.start,end:o.end}):void 0},i.prototype.resize=function(t,e){this.q.clear(),this.stageSize(t,e),this.updateLayout(),this.location&&this.display(this.location.start),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},i.prototype.onResized=function(){this.views.clear(),clearTimeout(this.resizeTimeout),this.resizeTimeout=setTimeout(function(){this.resize()}.bind(this),150)},i.prototype.adjustImages=function(t){return t.addStylesheetRules([["img",["max-width",this.layout.spread+"px"],["max-height",this.layout.height+"px"]]]),new r.Promise(function(t){setTimeout(function(){t()},1)})},e.exports=i},{"./continuous":7,"./core":8,"./layout":11,"./map":13,rsvp:4}],16:[function(t,e){function i(){}var r=t("urijs"),n=(t("./core"),t("./epubcfi"));i.prototype.container=function(t){var e,i,n,o;return t?(e=t.querySelector("rootfile"))?(i=e.getAttribute("full-path"),n=r(i).directory(),o=t.xmlEncoding,{packagePath:i,basePath:n,encoding:o}):(console.error("No RootFile Found"),void 0):(console.error("Container File Not Found"),void 0)},i.prototype.identifier=function(t){var e;return t?(e=t.querySelector("metadata"),e?this.getElementText(e,"identifier"):(console.error("No Metadata Found"),void 0)):(console.error("Package File Not Found"),void 0)},i.prototype.packageContents=function(t){var e,i,r,n,o,s,a,h,u,c,p=this;return t?(e=t.querySelector("metadata"))?(i=t.querySelector("manifest"))?(r=t.querySelector("spine"))?(n=p.manifest(i),o=p.findNavPath(i),s=p.findNcxPath(i,r),a=p.findCoverPath(t),h=Array.prototype.indexOf.call(r.parentNode.childNodes,r),u=p.spine(r,n),c=p.metadata(e),c.direction=r.getAttribute("page-progression-direction"),{metadata:c,spine:u,manifest:n,navPath:o,ncxPath:s,coverPath:a,spineNodeIndex:h}):(console.error("No Spine Found"),void 0):(console.error("No Manifest Found"),void 0):(console.error("No Metadata Found"),void 0):(console.error("Package File Not Found"),void 0)},i.prototype.findNavPath=function(t){var e=t.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']");return e?e.getAttribute("href"):!1},i.prototype.findNcxPath=function(t,e){var i,r=t.querySelector("item[media-type='application/x-dtbncx+xml']");return r||(i=e.getAttribute("toc"),i&&(r=t.querySelector("item[id='"+i+"']"))),r?r.getAttribute("href"):!1},i.prototype.metadata=function(t){var e={},i=this;return e.title=i.getElementText(t,"title"),e.creator=i.getElementText(t,"creator"),e.description=i.getElementText(t,"description"),e.pubdate=i.getElementText(t,"date"),e.publisher=i.getElementText(t,"publisher"),e.identifier=i.getElementText(t,"identifier"),e.language=i.getElementText(t,"language"),e.rights=i.getElementText(t,"rights"),e.modified_date=i.querySelectorText(t,"meta[property='dcterms:modified']"),e.layout=i.querySelectorText(t,"meta[property='rendition:layout']"),e.orientation=i.querySelectorText(t,"meta[property='rendition:orientation']"),e.spread=i.querySelectorText(t,"meta[property='rendition:spread']"),e},i.prototype.findCoverPath=function(t){var e=t.querySelector("package").getAttribute("version");if("2.0"===e){var i=t.querySelector('meta[name="cover"]');if(i){var r=i.getAttribute("content"),n=t.querySelector("item[id='"+r+"']");return n?n.getAttribute("href"):!1}return!1}var o=t.querySelector("item[properties='cover-image']");return o?o.getAttribute("href"):!1},i.prototype.getElementText=function(t,e){var i,r=t.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/",e);return r&&0!==r.length?(i=r[0],i.childNodes.length?i.childNodes[0].nodeValue:""):""},i.prototype.querySelectorText=function(t,e){var i=t.querySelector(e);return i&&i.childNodes.length?i.childNodes[0].nodeValue:""},i.prototype.manifest=function(t){var e={},i=t.querySelectorAll("item"),r=Array.prototype.slice.call(i);return r.forEach(function(t){var i=t.getAttribute("id"),r=t.getAttribute("href")||"",n=t.getAttribute("media-type")||"",o=t.getAttribute("properties")||"";e[i]={href:r,type:n,properties:o.length?o.split(" "):[]}}),e},i.prototype.spine=function(t){{var e=[],i=t.getElementsByTagName("itemref"),r=Array.prototype.slice.call(i);new n}return r.forEach(function(t,i){var r=t.getAttribute("idref"),n=t.getAttribute("properties")||"",o=n.length?n.split(" "):[],s={idref:r,linear:t.getAttribute("linear")||"",properties:o,index:i};e.push(s)}),e},i.prototype.querySelectorByType=function(t,e,i){var r=t.querySelector(e+'[*|type="'+i+'"]');if(null!==r&&0!==r.length)return r;r=t.querySelectorAll(e);for(var n=0;nr;++r)n=this.navItem(a[r],e,i),u[n.id]=n,n.parent?(o=u[n.parent],o.subitems.push(n)):c.push(n);return c},i.prototype.navItem=function(t){var e,i=t.getAttribute("id")||!1,r=t.querySelector("a, span"),n=r.getAttribute("href")||"",o=r.textContent||"",s=[],a=t.parentNode;return a&&"navPoint"===a.nodeName&&(e=a.getAttribute("id")),{id:i,href:n,label:o,subitems:s,parent:e}},i.prototype.toc=function(t,e,i){var r,n,o,s=t.querySelectorAll("navMap navPoint"),a=s.length,h={},u=[];if(!s||0===a)return u;for(r=0;a>r;++r)n=this.tocItem(s[r],e,i),h[n.id]=n,n.parent?(o=h[n.parent],o.subitems.push(n)):u.push(n);return u},i.prototype.tocItem=function(t){var e,i=t.getAttribute("id")||!1,r=t.querySelector("content"),n=r.getAttribute("src"),o=t.querySelector("navLabel"),s=o.textContent?o.textContent:"",a=[],h=t.parentNode;return h&&"navPoint"===h.nodeName&&(e=h.getAttribute("id")),{id:i,href:n,label:s,subitems:a,parent:e}},i.prototype.pageList=function(t,e,i){var r,n,o=this.querySelectorByType(t,"nav","page-list"),s=o?o.querySelectorAll("ol li"):[],a=s.length,h=[];if(!s||0===a)return h;for(r=0;a>r;++r)n=this.pageListItem(s[r],e,i),h.push(n);return h},i.prototype.pageListItem=function(t){var e,i,r,n=(t.getAttribute("id")||!1,t.querySelector("a")),o=n.getAttribute("href")||"",s=n.textContent||"",a=parseInt(s),h=o.indexOf("epubcfi");return-1!=h?(e=o.split("#"),i=e[0],r=e.length>1?e[1]:!1,{cfi:r,href:o,packageUrl:i,page:a}):{href:o,page:a}},e.exports=i},{"./core":8,"./epubcfi":9,urijs:5}],17:[function(t,e){function i(t){this._q=[],this.context=t,this.tick=n.requestAnimationFrame,this.running=!1,this.paused=!1}var r=t("rsvp"),n=t("./core");i.prototype.enqueue=function(){var t,e,i,n=[].shift.call(arguments),o=arguments;return n?("function"==typeof n?(t=new r.defer,e=t.promise,i={task:n,args:o,deferred:t,promise:e}):i={promise:n},this._q.push(i),0!=this.paused||this.running||this.run(),i.promise):console.error("No Task Provided")},i.prototype.dequeue=function(){var t,e,i;return this._q.length?(t=this._q.shift(),(e=t.task)?(i=e.apply(this.context,t.args),i&&"function"==typeof i.then?i.then(function(){t.deferred.resolve.apply(this.context,arguments)}.bind(this)):(t.deferred.resolve.apply(this.context,i),t.promise)):t.promise?t.promise:void 0):(t=new r.defer,t.deferred.resolve(),t.promise)},i.prototype.dump=function(){for(;this._q.length;)this.dequeue()},i.prototype.run=function(){return this.running||(this.running=!0,this.defered=new r.defer),this.tick.call(window,function(){this._q.length?this.dequeue().then(function(){this.run()}.bind(this)):(this.defered.resolve(),this.running=void 0)}.bind(this)),1==this.paused&&(this.paused=!1),this.defered.promise},i.prototype.flush=function(){return this.running?this.running:this._q.length?(this.running=this.dequeue().then(function(){return this.running=void 0,this.flush()}.bind(this)),this.running):void 0},i.prototype.clear=function(){this._q=[],this.running=!1},i.prototype.length=function(){return this._q.length},i.prototype.pause=function(){this.paused=!0},e.exports=i},{"./core":8,rsvp:4}],18:[function(t,e){function i(t,e){this.settings=o.extend(this.settings||{},{infinite:!0,hidden:!1,width:!1,height:null,layoutOveride:null,axis:"vertical"}),o.extend(this.settings,e),this.viewSettings={},this.book=t,this.views=null,this.hooks={},this.hooks.display=new a(this),this.hooks.serialize=new a(this),this.hooks.content=new a(this),this.hooks.layout=new a(this),this.hooks.render=new a(this),this.hooks.show=new a(this),this.hooks.content.register(s.links.bind(this)),this.hooks.content.register(this.passViewEvents.bind(this)),this.epubcfi=new h,this.q=new u(this),this.q.enqueue(this.book.opened),this.q.enqueue(this.parseLayoutProperties),this.book.archive&&this.replacements()}var r=t("rsvp"),n=t("urijs"),o=t("./core"),s=t("./replacements"),a=t("./hook"),h=t("./epubcfi"),u=t("./queue"),c=t("./view"),p=t("./views"),l=t("./layout"),d=t("./map");i.prototype.initialize=function(t){{var e,i=t||{},r=i.height,n=i.width;i.hidden||!1}return i.height&&o.isNumber(i.height)&&(r=i.height+"px"),i.width&&o.isNumber(i.width)&&(n=i.width+"px"),e=document.createElement("div"),e.id="epubjs-container:"+o.uuid(),e.classList.add("epub-container"),e.style.fontSize="0",e.style.wordSpacing="0",e.style.lineHeight="0",e.style.verticalAlign="top","horizontal"===this.settings.axis&&(e.style.whiteSpace="nowrap"),n&&(e.style.width=n),r&&(e.style.height=r),e.style.overflow=this.settings.overflow,e},i.wrap=function(t){var e=document.createElement("div");return e.style.visibility="hidden",e.style.overflow="hidden",e.style.width="0",e.style.height="0",e.appendChild(t),e},i.prototype.attachTo=function(t){return this.container=this.initialize({width:this.settings.width,height:this.settings.height}),o.isElement(t)?this.element=t:"string"==typeof t&&(this.element=document.getElementById(t)),this.element?(this.settings.hidden?(this.wrapper=this.wrap(this.container),this.element.appendChild(this.wrapper)):this.element.appendChild(this.container),this.views=new p(this.container),this.attachListeners(),this.stageSize(),this.applyLayoutMethod(),this.trigger("attached"),void 0):(console.error("Not an Element"),void 0)},i.prototype.attachListeners=function(){o.isNumber(this.settings.width)&&o.isNumber(this.settings.height)||window.addEventListener("resize",this.onResized.bind(this),!1)},i.prototype.bounds=function(){return this.container.getBoundingClientRect()},i.prototype.display=function(t){return this.q.enqueue(this._display,t)},i.prototype._display=function(t){var e,i,n,o,s,a=new r.defer,h=a.promise,u=this.epubcfi.isCfiString(t);return(e=this.book.spine.get(t))?(s=this.views.find(e),s?(n=i.locationOf(t),h=this.moveTo(n).then(function(){return this.check()})):(this.views.hide(),i=this.createView(e),h=this.fill(i).then(function(){return"string"==typeof t&&t.indexOf("#")>-1&&(o=t.substring(t.indexOf("#")+1)),u||o?(n=i.locationOf(t),this.moveTo(n)):"function"==typeof this.check?this.check():void 0}.bind(this)).then(function(){return this.hooks.display.trigger(i)}.bind(this)).then(function(){this.views.show()}.bind(this))),h.then(function(){this.trigger("displayed",e)}.bind(this)),h):(a.reject(new Error("No Section Found")),h)},i.prototype.moveTo=function(t){this.scrollBy(t.left,t.top)},i.prototype.render=function(t,e){return t.create(),t.onLayout=this.layout.format.bind(this.layout),this.resizeView(t),t.render(this.book.request).then(function(){return this.hooks.content.trigger(t,this)}.bind(this)).then(function(){return this.hooks.layout.trigger(t,this)}.bind(this)).then(function(){return t.display()}.bind(this)).then(function(){return this.hooks.render.trigger(t,this)}.bind(this)).then(function(){e!==!1&&this.views.hidden===!1&&this.q.enqueue(function(t){t.show()},t),this.hooks.show.trigger(t,this),this.trigger("rendered",t.section)}.bind(this)).catch(function(t){this.trigger("loaderror",t)}.bind(this))},i.prototype.afterDisplayed=function(t){this.trigger("added",t.section)},i.prototype.fill=function(t){return this.views.clear(),this.views.append(t),t.onDisplayed=this.afterDisplayed.bind(this),this.render(t)},i.prototype.resizeView=function(t){"pre-paginated"===this.globalLayoutProperties.layout?t.lock("both",this.stage.width,this.stage.height):t.lock("width",this.stage.width,this.stage.height)},i.prototype.stageSize=function(t,e){var i,r=t||this.settings.width,n=e||this.settings.height;return r===!1&&(i=this.element.getBoundingClientRect(),i.width&&(r=i.width,this.container.style.width=i.width+"px")),n===!1&&(i=i||this.element.getBoundingClientRect(),i.height&&(n=i.height,this.container.style.height=i.height+"px")),r&&!o.isNumber(r)&&(i=this.container.getBoundingClientRect(),r=i.width),n&&!o.isNumber(n)&&(i=i||this.container.getBoundingClientRect(),n=i.height),this.containerStyles=window.getComputedStyle(this.container),this.containerPadding={left:parseFloat(this.containerStyles["padding-left"])||0,right:parseFloat(this.containerStyles["padding-right"])||0,top:parseFloat(this.containerStyles["padding-top"])||0,bottom:parseFloat(this.containerStyles["padding-bottom"])||0},this.stage={width:r-this.containerPadding.left-this.containerPadding.right,height:n-this.containerPadding.top-this.containerPadding.bottom},this.stage},i.prototype.applyLayoutMethod=function(){this.layout=new l.Scroll,this.updateLayout(),this.map=new d(this.layout)},i.prototype.updateLayout=function(){this.layout.calculate(this.stage.width,this.stage.height)},i.prototype.resize=function(t,e){this.stageSize(t,e),this.updateLayout(),this.views.each(this.resizeView.bind(this)),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},i.prototype.onResized=function(){this.resize()},i.prototype.createView=function(t){return t.hooks.serialize.register(this.hooks.serialize.list()),new c(t,this.viewSettings)},i.prototype.next=function(){return this.q.enqueue(function(){var t,e;return this.views.length?(t=this.views.last().section.next(),t?(e=this.createView(t),this.fill(e)):void 0):void 0})},i.prototype.prev=function(){return this.q.enqueue(function(){var t,e;return this.views.length?(t=this.views.first().section.prev(),t?(e=this.createView(t),this.fill(e)):void 0):void 0})},i.prototype.parseLayoutProperties=function(t){var e=t||this.book.package.metadata,i=this.layoutOveride&&this.layoutOveride.layout||e.layout||"reflowable",r=this.layoutOveride&&this.layoutOveride.spread||e.spread||"auto",n=this.layoutOveride&&this.layoutOveride.orientation||e.orientation||"auto";return this.globalLayoutProperties={layout:i,spread:r,orientation:n},this.globalLayoutProperties},i.prototype.current=function(){var t=this.visible();return t.length?t[t.length-1]:null},i.prototype.isVisible=function(t,e,i,r){var n=t.position(),o=r||this.container.getBoundingClientRect();return"horizontal"===this.settings.axis&&n.right>o.left-e&&n.lefto.top-e&&n.top-1&&(i[a]=r)},i.prototype.replaceAssets=function(t,e,i){var r=n(t.url),o=e.map(function(t){var e=n(t).absoluteTo(this.book.baseUrl),i=e.relativeTo(r).toString();return i}.bind(this));t.output=s.substitute(t.output,o,i)},r.EventTarget.mixin(i.prototype),e.exports=i},{"./core":8,"./epubcfi":9,"./hook":10,"./layout":11,"./map":13,"./queue":17,"./replacements":19,"./view":24,"./views":25,rsvp:4,urijs:5}],19:[function(t,e){function i(t,e){var i,r;t&&(r=t.querySelector("head"),i=r.querySelector("base"),i||(i=t.createElement("base")),i.setAttribute("href",e.url),r.insertBefore(i,r.firstChild))}function r(t,e){for(var i=t.document.querySelectorAll("a[href]"),r=function(i){var r=i.getAttribute("href"),n=o(r),s=n.absoluteTo(t.section.url),a=s.relativeTo(this.book.baseUrl).toString();n.protocol()?i.setAttribute("target","_blank"):n.fragment()||(i.onclick=function(){return e.display(a),!1})},n=0;n-1?(delete this.spineByHref[t.href],delete this.spineById[t.idref],this.spineItems.splice(e,1)):void 0},i.prototype.each=function(){return this.spineItems.forEach.apply(this.spineItems,arguments)},e.exports=i},{"./core":8,"./epubcfi":9,"./section":21,rsvp:4}],23:[function(t,e){function i(){this.checkRequirements(),this.urlCache={}}var r=t("rsvp"),n=t("urijs"),o=t("./core"),s=t("./request"),a=t("../libs/mime/mime");i.prototype.checkRequirements=function(){try{"undefined"!=typeof JSZip?this.zip=new JSZip:(JSZip=t("jszip"),this.zip=new JSZip)}catch(e){console.error("JSZip lib not loaded")}},i.prototype.open=function(t){return t instanceof ArrayBuffer?new r.Promise(function(e){this.zip=new JSZip(t),e(this.zip)}):s(t,"binary").then(function(t){return this.zip=new JSZip(t),this.zip}.bind(this))},i.prototype.request=function(t,e){var i,o,s=new r.defer;return e||(uri=n(t),e=uri.suffix()),i="blob"==e?this.getBlob(t):this.getText(t),i?(o=this.handleResponse(i,e),s.resolve(o)):s.reject({message:"File not found in the epub: "+t,stack:(new Error).stack}),s.promise},i.prototype.handleResponse=function(t,e){var i;return i="json"==e?JSON.parse(t):o.isXml(e)?(new DOMParser).parseFromString(t,"text/xml"):"xhtml"==e?(new DOMParser).parseFromString(t,"application/xhtml+xml"):"html"==e||"htm"==e?(new DOMParser).parseFromString(t,"text/html"):t},i.prototype.getBlob=function(t,e){var i,r=window.decodeURIComponent(t.substr(1)),n=this.zip.file(r);return n?(i=e||a.lookup(n.name),new Blob([n.asUint8Array()],{type:i})):void 0},i.prototype.getText=function(t){var e=window.decodeURIComponent(t.substr(1)),i=this.zip.file(e);return i?i.asText():void 0},i.prototype.createUrl=function(t){var e,i,n=new r.defer,o=window.URL||window.webkitURL||window.mozURL;return t in this.urlCache?(n.resolve(this.urlCache[t]),n.promise):(i=this.getBlob(t),i?(e=o.createObjectURL(i),n.resolve(e),this.urlCache[t]=e):n.reject({message:"File not found in the epub: "+t,stack:(new Error).stack}),n.promise)},i.prototype.revokeUrl=function(t){var e=window.URL||window.webkitURL||window.mozURL,i=this.urlCache[t];i&&e.revokeObjectURL(i)},e.exports=i},{"../libs/mime/mime":1,"./core":8,"./request":20,jszip:"jszip",rsvp:4,urijs:5}],24:[function(t,e){function i(t,e){this.settings=e||{},this.id="epubjs-view:"+n.uuid(),this.section=t,this.index=t.index,this.element=document.createElement("div"),this.element.classList.add("epub-view"),this.element.style.height="0px",this.element.style.width="0px",this.element.style.overflow="hidden",this.added=!1,this.displayed=!1,this.rendered=!1,this.epubcfi=new o,this.element.style.display=this.settings.axis&&"horizontal"==this.settings.axis?"inline-block":"block",this.listenedEvents=["keydown","keyup","keypressed","mouseup","mousedown","click","touchend","touchstart"]}var r=t("rsvp"),n=t("./core"),o=t("./epubcfi");i.prototype.create=function(){return this.iframe?this.iframe:(this.iframe=document.createElement("iframe"),this.iframe.id=this.id,this.iframe.scrolling="no",this.iframe.style.overflow="hidden",this.iframe.seamless="seamless",this.iframe.style.border="none",this.resizing=!0,this.element.style.visibility="hidden",this.iframe.style.visibility="hidden",this.iframe.style.width="0",this.iframe.style.height="0",this._width=0,this._height=0,this.element.appendChild(this.iframe),this.added=!0,this.elementBounds=n.bounds(this.element),this.supportsSrcdoc=!1,this.iframe)},i.prototype.lock=function(t,e,i){var r,o=n.borders(this.element);r=this.iframe?n.borders(this.iframe):{width:0,height:0},"width"==t&&n.isNumber(e)&&(this.lockedWidth=e-o.width-r.width,this.resize(this.lockedWidth,e)),"height"==t&&n.isNumber(i)&&(this.lockedHeight=i-o.height-r.height,this.resize(e,this.lockedHeight)),"both"===t&&n.isNumber(e)&&n.isNumber(i)&&(this.lockedWidth=e-o.width-r.width,this.lockedHeight=i-o.height-r.height,this.resize(this.lockedWidth,this.lockedHeight)),this.displayed&&this.iframe&&(this.layout(),this.expand())},i.prototype.expand=function(){var t,e,i=this.lockedWidth,r=this.lockedHeight;this.iframe&&!this._expanding&&(this._expanding=!0,r&&!i&&(t=this.textWidth(),t!=this._textWidth?(i=this.contentWidth(t),this._textWidth=t,this._contentWidth=i):i=this._contentWidth),i&&!r&&(e=this.textHeight(),e!=this._textHeight?(r=this.contentHeight(e),this._textHeight=e,this._contentHeight=r):r=this._contentHeight),(this._needsReframe||i!=this._width||r!=this._height)&&this.resize(i,r),this._expanding=!1)},i.prototype.contentWidth=function(t){var e,i;return e=this.iframe.style.width,this.iframe.style.width=(t||0)+"px",i=this.document.body.scrollWidth,this.iframe.style.width=e,i},i.prototype.contentHeight=function(t){var e,i;return e=this.iframe.style.height,this.iframe.style.height=(t||0)+"px",i=this.document.body.scrollHeight,this.iframe.style.height=e,i},i.prototype.textWidth=function(){var t,e=this.document.createRange();return e.selectNodeContents(this.document.body),t=e.getBoundingClientRect().width},i.prototype.textHeight=function(){var t,e=this.document.createRange();return e.selectNodeContents(this.document.body),t=e.getBoundingClientRect().height},i.prototype.resize=function(t,e){this.iframe&&(n.isNumber(t)&&(this.iframe.style.width=t+"px",this._width=t),n.isNumber(e)&&(this.iframe.style.height=e+"px",this._height=e),this.iframeBounds=n.bounds(this.iframe),this.reframe(this.iframeBounds.width,this.iframeBounds.height))},i.prototype.reframe=function(t,e){return this.displayed?(n.isNumber(t)&&(this.element.style.width=t+"px"),n.isNumber(e)&&(this.element.style.height=e+"px"),this.prevBounds=this.elementBounds,this.elementBounds=n.bounds(this.element),this.trigger("resized",{width:this.elementBounds.width,height:this.elementBounds.height,widthDelta:this.elementBounds.width-this.prevBounds.width,heightDelta:this.elementBounds.height-this.prevBounds.height}),void 0):(this._needsReframe=!0,void 0)},i.prototype.resized=function(){},i.prototype.render=function(t){return this.rendering=!0,this.section.render(t).then(function(t){return this.load(t)}.bind(this))},i.prototype.load=function(t){var e=new r.defer,i=e.promise;if(!this.iframe)return e.reject(new Error("No Iframe Available")),i;if(this.iframe.onload=function(){this.window=this.iframe.contentWindow,this.document=this.iframe.contentDocument,this.rendering=!1,e.resolve(this)}.bind(this),this.supportsSrcdoc)this.iframe.srcdoc=t;else{if(this.document=this.iframe.contentDocument,!this.document)return e.reject(new Error("No Document Available")),i;this.document.open(),this.document.write(t),this.document.close()}return i},i.prototype.layout=function(t){this.iframe.style.display="inline-block",this.document.body.style.margin="0",t&&t(this),this.onLayout(this)},i.prototype.onLayout=function(){},i.prototype.listeners=function(){this.document.fonts&&"loading"===this.document.fonts.status&&(this.document.fonts.onloadingdone=function(){this.expand()}.bind(this)),this.section.properties.indexOf("scripted")>-1&&(this.observer=this.observe(this.document.body)),this.imageLoadListeners(),this.mediaQueryListeners(),this.addEventListeners(),this.addSelectionListeners()},i.prototype.removeListeners=function(){this.removeEventListeners(),this.removeSelectionListeners()},i.prototype.resizeListenters=function(){clearTimeout(this.expanding),this.expanding=setTimeout(this.expand.bind(this),350)},i.prototype.mediaQueryListeners=function(){for(var t=this.document.styleSheets,e=function(t){t.matches&&!this._expanding&&setTimeout(this.expand.bind(this),1)}.bind(this),i=0;i-1&&(id=t.substring(t.indexOf("#")+1),el=this.document.getElementById(id),el&&(i=el.getBoundingClientRect())),{left:window.scrollX+e.left+i.left,top:window.scrollY+e.top+i.top}):void 0},i.prototype.addCss=function(t){return new r.Promise(function(e){var i,r=!1;return this.document?(i=this.document.createElement("link"),i.type="text/css",i.rel="stylesheet",i.href=t,i.onload=i.onreadystatechange=function(){r||this.readyState&&"complete"!=this.readyState||(r=!0,setTimeout(function(){e(!0)},1))},this.document.head.appendChild(i),void 0):(e(!1),void 0)}.bind(this))},i.prototype.addStylesheetRules=function(t){var e,i;if(this.document){e=this.document.createElement("style"),this.document.head.appendChild(e),i=e.sheet;for(var r=0,n=t.length;n>r;r++){var o=1,s=t[r],a=t[r][0],h="";"[object Array]"===Object.prototype.toString.call(s[1][0])&&(s=s[1],o=0);for(var u=s.length;u>o;o++){var c=s[o];h+=c[0]+":"+c[1]+(c[2]?" !important":"")+";\n"}i.insertRule(a+"{"+h+"}",i.cssRules.length)}}},i.prototype.addScript=function(t){return new r.Promise(function(e){var i,r=!1;return this.document?(i=this.document.createElement("script"),i.type="text/javascript",i.async=!0,i.src=t,i.onload=i.onreadystatechange=function(){r||this.readyState&&"complete"!=this.readyState||(r=!0,setTimeout(function(){e(!0)},1))},this.document.head.appendChild(i),void 0):(e(!1),void 0)}.bind(this))},i.prototype.addEventListeners=function(){this.document&&this.listenedEvents.forEach(function(t){this.document.addEventListener(t,this.triggerEvent.bind(this),!1)},this)},i.prototype.removeEventListeners=function(){this.document&&this.listenedEvents.forEach(function(t){this.document.removeEventListener(t,this.triggerEvent,!1)},this)},i.prototype.triggerEvent=function(t){this.trigger(t.type,t)},i.prototype.addSelectionListeners=function(){this.document&&this.document.addEventListener("selectionchange",this.onSelectionChange.bind(this),!1)},i.prototype.removeSelectionListeners=function(){this.document&&this.document.removeEventListener("selectionchange",this.onSelectionChange,!1)},i.prototype.onSelectionChange=function(){this.selectionEndTimeout&&clearTimeout(this.selectionEndTimeout),this.selectionEndTimeout=setTimeout(function(){this.selectedRange=this.window.getSelection(),this.trigger("selected",this.selectedRange)}.bind(this),500)},r.EventTarget.mixin(i.prototype),e.exports=i},{"./core":8,"./epubcfi":9,rsvp:4}],25:[function(t,e){function i(t){this.container=t,this._views=[],this.length=0,this.hidden=!1}i.prototype.first=function(){return this._views[0]},i.prototype.last=function(){return this._views[this._views.length-1]},i.prototype.each=function(){return this._views.forEach.apply(this._views,arguments)},i.prototype.indexOf=function(t){return this._views.indexOf(t)},i.prototype.slice=function(){return this._views.slice.apply(this._views,arguments)},i.prototype.get=function(t){return this._views[t]},i.prototype.append=function(t){return this._views.push(t),this.container.appendChild(t.element),this.length++,t},i.prototype.prepend=function(t){return this._views.unshift(t),this.container.insertBefore(t.element,this.container.firstChild),this.length++,t},i.prototype.insert=function(t,e){return this._views.splice(e,0,t),e-1&&this._views.splice(e,1),this.destroy(t),this.length--},i.prototype.destroy=function(t){t.off("resized"),t.displayed&&t.destroy(),this.container.removeChild(t.element),t=null},i.prototype.clear=function(){var t,e=this.length;if(this.length){for(var i=0;e>i;i++)t=this._views[i],this.destroy(t);this._views=[],this.length=0}},i.prototype.find=function(t){for(var e,i=this.length,r=0;i>r;r++)if(e=this._views[r],e.displayed&&e.section.index==t.index)return e},i.prototype.displayed=function(){for(var t,e=[],i=this.length,r=0;i>r;r++)t=this._views[r],t.displayed&&e.push(t);return e},i.prototype.show=function(){for(var t,e=this.length,i=0;e>i;i++)t=this._views[i],t.displayed&&t.show();this.hidden=!1},i.prototype.hide=function(){for(var t,e=this.length,i=0;e>i;i++)t=this._views[i],t.displayed&&t.hide();this.hidden=!0},e.exports=i},{}],epub:[function(t,e){(function(i){function r(t){return new n(t)}"undefined"==typeof EPUBJS&&(("undefined"!=typeof window?window:i).EPUBJS={}),EPUBJS.VERSION="0.3.0";var n=t("./book");e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./book":6}]},{},["epub"])("epub")}); -//# sourceMappingURL=epub.min.js.map +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("xmldom"),function(){try{return require("JSZip")}catch(t){}}()):"function"==typeof define&&define.amd?define(["xmldom","JSZip"],e):"object"==typeof exports?exports.ePub=e(require("xmldom"),function(){try{return require("JSZip")}catch(t){}}()):t.ePub=e(t.xmldom,t.JSZip)}(this,function(t,e){return function(t){function e(n){if(i[n])return i[n].exports;var r=i[n]={exports:{},id:n,loaded:!1};return t[n].call(r.exports,r,r.exports,e),r.loaded=!0,r.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){function n(t){return new r(t)}var r=i(1),o=i(15),s=i(24),a=i(30),h=i(2);n.VERSION="0.3.0",n.CFI=o,n.Rendition=s,n.Contents=a,n.RSVP=h,n.ViewManagers={},n.Views={},n.register={manager:function(t,e){return n.ViewManagers[t]=e},view:function(t,e){return n.Views[t]=e}},n.register.view("iframe",i(31)),n.register.manager("single",i(32)),n.register.manager("continuous",i(35)),t.exports=n},function(t,e,i){function n(t,e){this.settings=s.extend(this.settings||{},{requestMethod:this.requestMethod}),s.extend(this.settings,e),this.opening=new r.defer,this.opened=this.opening.promise,this.isOpen=!1,this.url=void 0,this.loading={manifest:new r.defer,spine:new r.defer,metadata:new r.defer,cover:new r.defer,navigation:new r.defer,pageList:new r.defer},this.loaded={manifest:this.loading.manifest.promise,spine:this.loading.spine.promise,metadata:this.loading.metadata.promise,cover:this.loading.cover.promise,navigation:this.loading.navigation.promise,pageList:this.loading.pageList.promise},this.ready=r.hash(this.loaded),this.isRendered=!1,this.request=this.settings.requestMethod.bind(this),this.spine=new a(this.request),this.locations=new h(this.spine,this.request),t&&this.open(t)["catch"](function(e){var i=new Error("Cannot load book at "+t);console.error(i),this.trigger("loadFailed",e)}.bind(this))}var r=i(2),o=i(6),s=i(11),a=i(14),h=i(20),u=i(22),c=i(23),l=i(24),p=i(27),d=i(18),f=i(15);n.prototype.open=function(t,e){var i,n,r,s,a=new u,h=this,c="META-INF/container.xml",l=!1,p=e&&e.base64;return t?(t instanceof ArrayBuffer||p?(l=!0,this.url="/"):i=o(t),window&&window.location&&i?(s=i.absoluteTo(window.location.href),this.url=s.toString()):window&&window.location?this.url=window.location.href:this.url=t,i&&"opf"===i.suffix()?(this.packageUrl=t,this.containerUrl="",i.origin()?this.baseUrl=i.origin()+"/"+i.directory()+"/":s?(this.baseUrl=s.origin(),this.baseUrl+=s.directory()+"/"):this.baseUrl=i.directory()+"/",n=this.request(this.packageUrl)["catch"](function(t){h.opening.reject(t)})):l||p||this.isArchivedUrl(i)?(this.url="/",this.containerUrl=o(c).absoluteTo(this.url).toString(),r=this.unarchive(t,p).then(function(){return this.request(this.containerUrl)}.bind(this))["catch"](function(t){h.opening.reject(t)})):i.suffix()||(this.containerUrl=this.url+c,r=this.request(this.containerUrl)["catch"](function(t){h.opening.reject(t)})),r&&(n=r.then(function(t){return a.container(t)}).then(function(t){var e=o(t.packagePath),i=e.absoluteTo(h.url);return h.packageUrl=i.toString(),h.encoding=t.encoding,i.origin()?h.baseUrl=i.origin()+i.directory()+"/":e.directory()?h.baseUrl="/"+e.directory()+"/":h.baseUrl="/",h.request(h.packageUrl)})["catch"](function(t){h.opening.reject(t)})),n.then(function(t){t&&(h.unpack(t),h.loading.manifest.resolve(h["package"].manifest),h.loading.metadata.resolve(h["package"].metadata),h.loading.spine.resolve(h.spine),h.loading.cover.resolve(h.cover),h.isOpen=!0,h.opening.resolve(h))})["catch"](function(t){h.opening.reject(t)}),this.opened):(this.opening.resolve(this),this.opened)},n.prototype.unpack=function(t){var e=this,i=new u;e["package"]=i.packageContents(t),e["package"]&&(e["package"].baseUrl=e.baseUrl,this.spine.load(e["package"]),e.navigation=new c(e["package"],this.request),e.navigation.load().then(function(t){e.toc=t,e.loading.navigation.resolve(e.toc)}),e.cover=o(e["package"].coverPath).absoluteTo(e.baseUrl).toString())},n.prototype.section=function(t){return this.spine.get(t)},n.prototype.renderTo=function(t,e){return this.rendition=new l(this,e),this.rendition.attachTo(t),this.rendition},n.prototype.requestMethod=function(t){return this.unarchived?this.unarchived.request(t):d(t,null,this.requestCredentials,this.requestHeaders)},n.prototype.setRequestCredentials=function(t){this.requestCredentials=t},n.prototype.setRequestHeaders=function(t){this.requestHeaders=t},n.prototype.unarchive=function(t,e){return this.unarchived=new p,this.unarchived.open(t,e)},n.prototype.isArchivedUrl=function(t){var e,i;return t instanceof ArrayBuffer||(e=o(t),i=e.suffix(),!(!i||"epub"!=i&&"zip"!=i))},n.prototype.coverUrl=function(){var t=this.loaded.cover.then(function(t){return this.unarchived?this.unarchived.createUrl(this.cover):this.cover}.bind(this));return t},n.prototype.range=function(t){var e=new f(t),i=this.spine.get(e.spinePos);return i.load().then(function(t){var n=e.toRange(i.document);return n})},t.exports=n,r.EventTarget.mixin(n.prototype),r.on("error",function(t){console.error(t)}),r.configure("instrument",!1),r.on("rejected",function(t){console.error(t.detail.message,t.detail.stack)})},function(t,e,i){(function(t,n,r){/*! + * @overview RSVP - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2016 Yehuda Katz, Tom Dale, Stefan Penner and contributors + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE + * @version 3.3.2 + */ +!function(t,i){i(e)}(this,function(e){"use strict";function o(t,e){for(var i=0,n=t.length;i1)throw new Error("Second argument not supported");if("object"!=typeof t)throw new TypeError("Argument must be an object");return l.prototype=t,new l},qt=[],Nt=void 0,Lt=1,Rt=2,Pt=new C,jt=new C;P.prototype._validateInput=function(t){return zt(t)},P.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},P.prototype._init=function(){this._result=new Array(this.length)},P.prototype._enumerate=function(){for(var t=this.length,e=this.promise,i=this._input,n=0;e._state===Nt&&n1)for(var i=1;i=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},e.setImmediate="function"==typeof t?t:function(t){var i=u++,n=!(arguments.length<2)&&a.call(arguments,1);return h[i]=!0,o(function(){h[i]&&(n?t.apply(null,n):t.call(null),e.clearImmediate(i))}),i},e.clearImmediate="function"==typeof n?n:function(t){delete h[t]}}).call(e,i(4).setImmediate,i(4).clearImmediate)},function(t,e){},function(t,e,i){/*! + * URI.js - Mutating URLs + * + * Version: 1.18.1 + * + * Author: Rodney Rehm + * Web: http://medialize.github.io/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * + */ +!function(e,n){"use strict";t.exports=n(i(7),i(9),i(10))}(this,function(t,e,i,n){"use strict";function r(t,e){var i=arguments.length>=1,n=arguments.length>=2;if(!(this instanceof r))return i?n?new r(t,e):new r(t):new r;if(void 0===t){if(i)throw new TypeError("undefined is not a valid argument for URI");t="undefined"!=typeof location?location.href+"":""}return this.href(t),void 0!==e?this.absoluteTo(e):this}function o(t){return t.replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}function s(t){return void 0===t?"Undefined":String(Object.prototype.toString.call(t)).slice(8,-1)}function a(t){return"Array"===s(t)}function h(t,e){var i,n,r={};if("RegExp"===s(e))r=null;else if(a(e))for(i=0,n=e.length;i]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/gi,r.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?«»“”„‘’]+$/},r.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"},r.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/,r.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src",audio:"src",video:"src"},r.getDomAttribute=function(t){if(t&&t.nodeName){var e=t.nodeName.toLowerCase();if("input"!==e||"image"===t.type)return r.domAttributes[e]}},r.encode=d,r.decode=decodeURIComponent,r.iso8859=function(){r.encode=escape,r.decode=unescape},r.unicode=function(){r.encode=d,r.decode=decodeURIComponent},r.characters={pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/gi,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/gi,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}},urnpath:{encode:{expression:/%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/gi,map:{"%21":"!","%24":"$","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"=","%40":"@"}},decode:{expression:/[\/\?#:]/g,map:{"/":"%2F","?":"%3F","#":"%23",":":"%3A"}}}},r.encodeQuery=function(t,e){var i=r.encode(t+"");return void 0===e&&(e=r.escapeQuerySpace),e?i.replace(/%20/g,"+"):i},r.decodeQuery=function(t,e){t+="",void 0===e&&(e=r.escapeQuerySpace);try{return r.decode(e?t.replace(/\+/g,"%20"):t)}catch(i){return t}};var b,w={encode:"encode",decode:"decode"},x=function(t,e){return function(i){try{return r[e](i+"").replace(r.characters[t][e].expression,function(i){return r.characters[t][e].map[i]})}catch(n){return i}}};for(b in w)r[b+"PathSegment"]=x("pathname",w[b]),r[b+"UrnPathSegment"]=x("urnpath",w[b]);var _=function(t,e,i){return function(n){var o;o=i?function(t){return r[e](r[i](t))}:r[e];for(var s=(n+"").split(t),a=0,h=s.length;a-1&&(e.fragment=t.substring(i+1)||null,t=t.substring(0,i)),i=t.indexOf("?"),i>-1&&(e.query=t.substring(i+1)||null,t=t.substring(0,i)),"//"===t.substring(0,2)?(e.protocol=null,t=t.substring(2),t=r.parseAuthority(t,e)):(i=t.indexOf(":"),i>-1&&(e.protocol=t.substring(0,i)||null,e.protocol&&!e.protocol.match(r.protocol_expression)?e.protocol=void 0:"//"===t.substring(i+1,i+3)?(t=t.substring(i+3),t=r.parseAuthority(t,e)):(t=t.substring(i+1),e.urn=!0))),e.path=t,e},r.parseHost=function(t,e){t=t.replace(/\\/g,"/");var i,n,r=t.indexOf("/");if(r===-1&&(r=t.length),"["===t.charAt(0))i=t.indexOf("]"),e.hostname=t.substring(1,i)||null,e.port=t.substring(i+2,r)||null,"/"===e.port&&(e.port=null);else{var o=t.indexOf(":"),s=t.indexOf("/"),a=t.indexOf(":",o+1);a!==-1&&(s===-1||a-1?n:t.length-1);return o>-1&&(n===-1||o1&&(n=i[0]+"@",t=i[1]),t=t.replace(N,".");var r=t.split("."),o=a(r,e).join(".");return n+o}function u(t){for(var e,i,n=[],r=0,o=t.length;r=55296&&e<=56319&&r65535&&(t-=65536,e+=j(t>>>10&1023|55296),t=56320|1023&t),e+=j(t)}).join("")}function l(t){return t-48<10?t-22:t-65<26?t-65:t-97<26?t-97:x}function p(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function d(t,e,i){var n=0;for(t=i?P(t/S):t>>1,t+=P(t/e);t>R*T>>1;n+=x)t=P(t/R);return P(n+(R+1)*t/(t+k))}function f(t){var e,i,n,r,o,a,h,u,p,f,g=[],m=t.length,v=0,y=z,b=E;for(i=t.lastIndexOf(C),i<0&&(i=0),n=0;n=128&&s("not-basic"),g.push(t.charCodeAt(n));for(r=i>0?i+1:0;r=m&&s("invalid-input"),u=l(t.charCodeAt(r++)),(u>=x||u>P((w-v)/a))&&s("overflow"),v+=u*a,p=h<=b?_:h>=b+T?T:h-b,!(uP(w/f)&&s("overflow"),a*=f;e=g.length+1,b=d(v-o,e,0==o),P(v/e)>w-y&&s("overflow"),y+=P(v/e),v%=e,g.splice(v++,0,y)}return c(g)}function g(t){var e,i,n,r,o,a,h,c,l,f,g,m,v,y,b,k=[];for(t=u(t),m=t.length,e=z,i=0,o=E,a=0;a=e&&gP((w-i)/v)&&s("overflow"),i+=(h-e)*v,e=h,a=0;aw&&s("overflow"),g==e){for(c=i,l=x;f=l<=o?_:l>=o+T?T:l-o,!(c= 0x80 (not a basic code point)","invalid-input":"Invalid input"},R=x-_,P=Math.floor,j=String.fromCharCode;b={version:"1.3.2",ucs2:{decode:u,encode:c},decode:f,encode:g,toASCII:v,toUnicode:m},n=function(){return b}.call(e,i,e,t),!(void 0!==n&&(t.exports=n))}(this)}).call(e,i(8)(t),function(){return this}())},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}},function(t,e,i){/*! + * URI.js - Mutating URLs + * IPv6 Support + * + * Version: 1.18.1 + * + * Author: Rodney Rehm + * Web: http://medialize.github.io/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * + */ +!function(e,i){"use strict";t.exports=i()}(this,function(t){"use strict";function e(t){var e=t.toLowerCase(),i=e.split(":"),n=i.length,r=8;""===i[0]&&""===i[1]&&""===i[2]?(i.shift(),i.shift()):""===i[0]&&""===i[1]?i.shift():""===i[n-1]&&""===i[n-2]&&i.pop(),n=i.length,i[n-1].indexOf(".")!==-1&&(r=7);var o;for(o=0;o1);h++)s.splice(0,1);i[a]=s.join("")}var u=-1,c=0,l=0,p=-1,d=!1;for(a=0;ac&&(u=p,c=l)):"0"===i[a]&&(d=!0,p=a,l=1);l>c&&(u=p,c=l),c>1&&i.splice(u,c,""),n=i.length;var f="";for(""===i[0]&&(f=":"),a=0;a=t.length-1)return!1;var n=t.lastIndexOf(".",e-1);if(n<=0||n>=e-1)return!1;var r=i.list[t.slice(e+1)];return!!r&&r.indexOf(" "+t.slice(n+1,e)+" ")>=0},is:function(t){var e=t.lastIndexOf(".");if(e<=0||e>=t.length-1)return!1;var n=t.lastIndexOf(".",e-1);if(n>=0)return!1;var r=i.list[t.slice(e+1)];return!!r&&r.indexOf(" "+t.slice(0,e)+" ")>=0},get:function(t){var e=t.lastIndexOf(".");if(e<=0||e>=t.length-1)return null;var n=t.lastIndexOf(".",e-1);if(n<=0||n>=e-1)return null;var r=i.list[t.slice(e+1)];return r?r.indexOf(" "+t.slice(n+1,e)+" ")<0?null:t.slice(n+1):null},noConflict:function(){return t.SecondLevelDomains===this&&(t.SecondLevelDomains=e),this}};return i})},function(t,e,i){function n(t){return!(!t||1!=t.nodeType)}function r(){var t=(new Date).getTime(),e="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?i:7&i|8).toString(16)});return e}function o(t){for(var e=-1,i=Object.keys(t),n=i.length,r=Array(n);++ee?1:t0?h:h+1:0===o?h:o===-1?d(t,e,i,h,a):d(t,e,i,s,h))}function f(t,e,i,n,r){var o,s=n||0,a=r||e.length,h=parseInt(s+(a-s)/2);return i||(i=function(t,e){return t>e?1:t-1}function x(t,e){var i=new Blob([t],{type:e});return i}function _(t,e){var i,n=window.URL||window.webkitURL||window.mozURL,r=this.createBlob(t,e);return i=n.createObjectURL(r)}function T(t,e){var i,n;if("string"==typeof t)return i=btoa(t),n="data:"+e+";base64,"+i}function k(t){return Object.prototype.toString.call(t).slice(8,-1)}function S(t,e){var n;return"undefined"==typeof DOMParser&&(DOMParser=i(13).DOMParser),n=(new DOMParser).parseFromString(t,e)}function E(t,e){var i;return"undefined"!=typeof t.querySelector?t.querySelector(e):(i=t.getElementsByTagName(e),i.length?i[0]:void 0)}function z(t,e){return"undefined"!=typeof t.querySelector?t.querySelectorAll(e):t.getElementsByTagName(e)}function C(t,e,i){var n,r;if("undefined"!=typeof t.querySelector){e+="[";for(var o in i)e+=o+"='"+i[o]+"'";return e+="]",t.querySelector(e)}if(n=t.getElementsByTagName(e),r=Array.prototype.slice.call(n,0).filter(function(t){for(var e in i)if(t.getAttribute(e)===i[e])return!0;return!1}))return r[0]}function A(t,e){var i=new FileReader;i.readAsDataURL(t),i.onloadend=function(){e(i.result)}}var q=(i(2),i(12),"undefined"!=typeof window&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame));t.exports={isElement:n,uuid:r,values:o,resolveUrl:s,indexOfSorted:f,documentHeight:a,isNumber:h,prefixed:u,defaults:c,extend:l,insert:p,locationOf:d,indexOfSorted:f,requestAnimationFrame:q,bounds:g,borders:m,windowBounds:v,cleanStringForXpath:y,indexOfTextNode:b,isXml:w,createBlob:x,createBlobUrl:_,type:k,parse:S,qs:E,qsa:z,qsp:C,blob2base64:A,createBase64Url:T}},function(t,e){"use strict";function i(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===t[e-2]?2:"="===t[e-1]?1:0}function n(t){return 3*t.length/4-i(t)}function r(t){var e,n,r,o,s,a,h=t.length;s=i(t),a=new c(3*h/4-s),r=s>0?h-4:h;var l=0;for(e=0,n=0;e>16&255,a[l++]=o>>8&255,a[l++]=255&o;return 2===s?(o=u[t.charCodeAt(e)]<<2|u[t.charCodeAt(e+1)]>>4,a[l++]=255&o):1===s&&(o=u[t.charCodeAt(e)]<<10|u[t.charCodeAt(e+1)]<<4|u[t.charCodeAt(e+2)]>>2,a[l++]=o>>8&255,a[l++]=255&o),a}function o(t){return h[t>>18&63]+h[t>>12&63]+h[t>>6&63]+h[63&t]}function s(t,e,i){for(var n,r=[],s=e;sc?c:u+a));return 1===n?(e=t[i-1],r+=h[e>>2],r+=h[e<<4&63],r+="=="):2===n&&(e=(t[i-2]<<8)+t[i-1],r+=h[e>>10],r+=h[e>>4&63],r+=h[e<<2&63],r+="="),o.push(r),o.join("")}e.byteLength=n,e.toByteArray=r,e.fromByteArray=a;for(var h=[],u=[],c="undefined"!=typeof Uint8Array?Uint8Array:Array,l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",p=0,d=l.length;p-1)return delete this.spineByHref[t.href],delete this.spineById[t.idref],this.spineItems.splice(e,1)},n.prototype.each=function(){return this.spineItems.forEach.apply(this.spineItems,arguments)},t.exports=n},function(t,e,i){function n(t,e,i){var o;if(this.str="",this.base={},this.spinePos=0,this.range=!1,this.path={},this.start=null,this.end=null,!(this instanceof n))return new n(t,e,i);if("string"==typeof e?this.base=this.parseComponent(e):"object"==typeof e&&e.steps&&(this.base=e),o=this.checkType(t),"string"===o)return this.str=t,r.extend(this,this.parse(t));if("range"===o)return r.extend(this,this.fromRange(t,this.base,i));if("node"===o)return r.extend(this,this.fromNode(t,this.base,i));if("EpubCFI"===o&&t.path)return t;if(t)throw new TypeError("not a valid argument for EpubCFI");return this}var r=(i(6),i(11));n.prototype.checkType=function(t){return this.isCfiString(t)?"string":"object"==typeof t&&"Range"===r.type(t)?"range":"object"==typeof t&&"undefined"!=typeof t.nodeType?"node":"object"==typeof t&&t instanceof n&&"EpubCFI"},n.prototype.parse=function(t){var e,i,n,r={spinePos:-1,range:!1,base:{},path:{},start:null,end:null};return"string"!=typeof t?{spinePos:-1}:(0===t.indexOf("epubcfi(")&&")"===t[t.length-1]&&(t=t.slice(8,t.length-1)),(e=this.getChapterComponent(t))?(r.base=this.parseComponent(e),i=this.getPathComponent(t),r.path=this.parseComponent(i),n=this.getRange(t),n&&(r.range=!0,r.start=this.parseComponent(n[0]),r.end=this.parseComponent(n[1])),r.spinePos=r.base.steps[1].index,r):{spinePos:-1})},n.prototype.parseComponent=function(t){var e,i={steps:[],terminal:{offset:null,assertion:null}},n=t.split(":"),r=n[0].split("/");return n.length>1&&(e=n[1],i.terminal=this.parseTerminal(e)),""===r[0]&&r.shift(),i.steps=r.map(function(t){return this.parseStep(t)}.bind(this)),i},n.prototype.parseStep=function(t){var e,i,n,r,o;if(r=t.match(/\[(.*)\]/),r&&r[1]&&(o=r[1]),i=parseInt(t),!isNaN(i))return i%2===0?(e="element",n=i/2-1):(e="text",n=(i-1)/2),{type:e,index:n,id:o||null}},n.prototype.parseTerminal=function(t){var e,i,n=t.match(/\[(.*)\]/);return n&&n[1]?(e=parseInt(t.split("[")[0])||null,i=n[1]):e=parseInt(t)||null,{offset:e,assertion:i}},n.prototype.getChapterComponent=function(t){var e=t.split("!");return e[0]},n.prototype.getPathComponent=function(t){var e=t.split("!");if(e[1])return ranges=e[1].split(","),ranges[0]},n.prototype.getRange=function(t){var e=t.split(",");return 3===e.length&&[e[1],e[2]]},n.prototype.getCharecterOffsetComponent=function(t){var e=t.split(":");return e[1]||""},n.prototype.joinSteps=function(t){return t?t.map(function(t){var e="";return"element"===t.type&&(e+=2*(t.index+1)),"text"===t.type&&(e+=1+2*t.index),t.id&&(e+="["+t.id+"]"),e}).join("/"):""},n.prototype.segmentString=function(t){var e="/";return e+=this.joinSteps(t.steps),t.terminal&&null!=t.terminal.offset&&(e+=":"+t.terminal.offset),t.terminal&&null!=t.terminal.assertion&&(e+="["+t.terminal.assertion+"]"),e},n.prototype.toString=function(){var t="epubcfi(";return t+=this.segmentString(this.base),t+="!",t+=this.segmentString(this.path),this.start&&(t+=",",t+=this.segmentString(this.start)),this.end&&(t+=",",t+=this.segmentString(this.end)),t+=")"},n.prototype.compare=function(t,e){if("string"==typeof t&&(t=new n(t)),"string"==typeof e&&(e=new n(e)),t.spinePos>e.spinePos)return 1;if(t.spinePose.path.steps[i].index)return 1;if(t.path.steps[i].indexe.path.terminal.offset?1:t.path.terminal.offset=0&&(r.terminal.offset=e,"text"!=r.steps[r.steps.length-1].type&&r.steps.push({type:"text",index:0})),r},n.prototype.equalStep=function(t,e){return!(!t||!e)&&(t.index===e.index&&t.id===e.id&&t.type===e.type)},n.prototype.fromRange=function(t,e,i){var n={range:!1,base:{},path:{},start:null,end:null},r=t.startContainer,o=t.endContainer,s=t.startOffset,a=t.endOffset,h=!1;if(i&&(h=null!=r.ownerDocument.querySelector("."+i)),"string"==typeof e?(n.base=this.parseComponent(e),n.spinePos=n.base.steps[1].index):"object"==typeof e&&(n.base=e),t.collapsed)h&&(s=this.patchOffset(r,s,i)),n.path=this.pathTo(r,s,i);else{n.range=!0,h&&(s=this.patchOffset(r,s,i)),n.start=this.pathTo(r,s,i),h&&(a=this.patchOffset(o,a,i)),n.end=this.pathTo(o,a,i),n.path={steps:[],terminal:null};var u,c=n.start.steps.length;for(u=0;u0&&r===Node.TEXT_NODE&&o===Node.TEXT_NODE?s[n]=a:e===r&&(a+=1,s[n]=a),o=r;return s},n.prototype.position=function(t){var e,i;return t.nodeType===Node.ELEMENT_NODE?(e=t.parentNode.children,i=Array.prototype.indexOf.call(e,t)):(e=this.textNodes(t.parentNode),i=e.indexOf(t)),i},n.prototype.filteredPosition=function(t,e){var i,n,r;return t.nodeType===Node.ELEMENT_NODE?(i=t.parentNode.children,r=this.normalizedMap(i,Node.ELEMENT_NODE,e)):(i=t.parentNode.childNodes,t.parentNode.classList.contains(e)&&(t=t.parentNode,i=t.parentNode.childNodes),r=this.normalizedMap(i,Node.TEXT_NODE,e)),n=Array.prototype.indexOf.call(i,t),r[n]},n.prototype.stepsToXpath=function(t){var e=[".","*"];return t.forEach(function(t){var i=t.index+1;t.id?e.push("*[position()="+i+" and @id='"+t.id+"']"):"text"===t.type?e.push("text()["+i+"]"):e.push("*["+i+"]")}),e.join("/")},n.prototype.stepsToQuerySelector=function(t){var e=["html"];return t.forEach(function(t){var i=t.index+1;t.id?e.push("#"+t.id):"text"===t.type||e.push("*:nth-child("+i+")")}),e.join(">")},n.prototype.textNodes=function(t,e){return Array.prototype.slice.call(t.childNodes).filter(function(t){return t.nodeType===Node.TEXT_NODE||!(!e||!t.classList.contains(e))})},n.prototype.walkToNode=function(t,e,i){var n,r,o=e||document,s=o.documentElement,a=t.length;for(r=0;ro)){a=r.nodeType===Node.ELEMENT_NODE?r.childNodes[0]:r;break}e-=o}}return{container:a,offset:e}},n.prototype.toRange=function(t,e){var i,n,r,o,s,a,h,u=t||document,c=u.createRange(),l=this,p=!!e&&null!=u.querySelector("."+e);if(l.range?(i=l.start,s=l.path.steps.concat(i.steps),r=this.findNode(s,u,p?e:null),n=l.end,a=l.path.steps.concat(n.steps),o=this.findNode(a,u,p?e:null)):(i=l.path,s=l.path.steps,r=this.findNode(l.path.steps,u,p?e:null)),!r)return null;try{null!=i.terminal.offset?c.setStart(r,i.terminal.offset):c.setStart(r,0)}catch(d){h=this.fixMiss(s,i.terminal.offset,u,p?e:null),c.setStart(h.container,h.offset)}if(o)try{null!=n.terminal.offset?c.setEnd(o,n.terminal.offset):c.setEnd(o,0)}catch(d){h=this.fixMiss(a,l.end.terminal.offset,u,p?e:null),c.setEnd(h.container,h.offset)}return c},n.prototype.isCfiString=function(t){return"string"==typeof t&&0===t.indexOf("epubcfi(")&&")"===t[t.length-1]},n.prototype.generateChapterComponent=function(t,e,i){var n=parseInt(e),r=t+1,o="/"+r+"/";return o+=2*(n+1),i&&(o+="["+i+"]"),o},t.exports=n},function(t,e,i){function n(t){this.context=t||this,this.hooks=[]}var r=i(2);n.prototype.register=function(){for(var t=0;ts&&(r+=s,a=s);a=s?r=s-(a-this["break"]):(i.setEnd(e,a),cfi=t.cfiFromRange(i),this._locations.push(cfi),r=0,a+=1,i=n.createRange(),i.setStart(e,a))}.bind(this)),i&&(i.setEnd(prev,prev.length),cfi=t.cfiFromRange(i),this._locations.push(cfi),r=0)}.bind(this))},n.prototype.sprint=function(t,e){for(var i=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,null,!1);node=i.nextNode();)e(node); +},n.prototype.locationFromCfi=function(t){return 0===this._locations.length?-1:r.locationOf(t,this._locations,this.epubcfi.compare)},n.prototype.precentageFromCfi=function(t){var e=this.locationFromCfi(t);return this.precentageFromLocation(e)},n.prototype.percentageFromLocation=function(t){return t&&this.total?t/this.total:0},n.prototype.cfiFromLocation=function(t){var e=-1;return"number"!=typeof t&&(t=parseInt(pg)),t>=0&&t1?t/100:t,i=Math.ceil(this.total*e);return this.cfiFromLocation(i)},n.prototype.load=function(t){return this._locations=JSON.parse(t),this.total=this._locations.length-1,this._locations},n.prototype.save=function(t){return JSON.stringify(this._locations)},n.prototype.getCurrent=function(t){return this._current},n.prototype.setCurrent=function(t){var e;if("string"==typeof t)this._currentCfi=t;else{if("number"!=typeof t)return;this._current=t}0!==this._locations.length&&("string"==typeof t?(e=this.locationFromCfi(t),this._current=e):e=t,this.trigger("changed",{percentage:this.precentageFromLocation(e)}))},Object.defineProperty(n.prototype,"currentLocation",{get:function(){return this._current},set:function(t){this.setCurrent(t)}}),a.EventTarget.mixin(n.prototype),t.exports=n},function(t,e,i){function n(t){this._q=[],this.context=t,this.tick=o.requestAnimationFrame,this.running=!1,this.paused=!1}var r=i(2),o=i(11);n.prototype.enqueue=function(){var t,e,i,n=[].shift.call(arguments),o=arguments;return n?("function"==typeof n?(t=new r.defer,e=t.promise,i={task:n,args:o,deferred:t,promise:e}):i={promise:n},this._q.push(i),0!=this.paused||this.running||this.run(),i.promise):console.error("No Task Provided")},n.prototype.dequeue=function(){var t,e,i;return this._q.length?(t=this._q.shift(),(e=t.task)?(i=e.apply(this.context,t.args),i&&"function"==typeof i.then?i.then(function(){t.deferred.resolve.apply(this.context,arguments)}.bind(this)):(t.deferred.resolve.apply(this.context,i),t.promise)):t.promise?t.promise:void 0):(t=new r.defer,t.deferred.resolve(),t.promise)},n.prototype.dump=function(){for(;this._q.length;)this.dequeue()},n.prototype.run=function(){return this.running||(this.running=!0,this.defered=new r.defer),this.tick.call(window,function(){this._q.length?this.dequeue().then(function(){this.run()}.bind(this)):(this.defered.resolve(),this.running=void 0)}.bind(this)),1==this.paused&&(this.paused=!1),this.defered.promise},n.prototype.flush=function(){return this.running?this.running:this._q.length?(this.running=this.dequeue().then(function(){return this.running=void 0,this.flush()}.bind(this)),this.running):void 0},n.prototype.clear=function(){this._q=[],this.running=!1},n.prototype.length=function(){return this._q.length},n.prototype.pause=function(){this.paused=!0},t.exports=n},function(t,e,i){function n(){}var r=i(6),o=i(11),s=i(15);n.prototype.container=function(t){var e,i,n,s;return t?(e=o.qs(t,"rootfile"))?(i=e.getAttribute("full-path"),n=r(i).directory(),s=t.xmlEncoding,{packagePath:i,basePath:n,encoding:s}):void console.error("No RootFile Found"):void console.error("Container File Not Found")},n.prototype.identifier=function(t){var e;return t?(e=o.qs(t,"metadata"),e?this.getElementText(e,"identifier"):void console.error("No Metadata Found")):void console.error("Package File Not Found")},n.prototype.packageContents=function(t){var e,i,n,r,s,a,h,u,c,l,p=this;return t?(e=o.qs(t,"metadata"))?(i=o.qs(t,"manifest"))?(n=o.qs(t,"spine"))?(r=p.manifest(i),s=p.findNavPath(i),a=p.findNcxPath(i,n),h=p.findCoverPath(t),u=Array.prototype.indexOf.call(n.parentNode.childNodes,n),c=p.spine(n,r),l=p.metadata(e),l.direction=n.getAttribute("page-progression-direction"),{metadata:l,spine:c,manifest:r,navPath:s,ncxPath:a,coverPath:h,spineNodeIndex:u}):void console.error("No Spine Found"):void console.error("No Manifest Found"):void console.error("No Metadata Found"):void console.error("Package File Not Found")},n.prototype.findNavPath=function(t){var e=o.qsp(t,"item",{properties:"nav"});return!!e&&e.getAttribute("href")},n.prototype.findNcxPath=function(t,e){var i,n=o.qsp(t,"item",{"media-type":"application/x-dtbncx+xml"});return n||(i=e.getAttribute("toc"),i&&(n=t.getElementById(i))),!!n&&n.getAttribute("href")},n.prototype.metadata=function(t){var e={},i=this;return e.title=i.getElementText(t,"title"),e.creator=i.getElementText(t,"creator"),e.description=i.getElementText(t,"description"),e.pubdate=i.getElementText(t,"date"),e.publisher=i.getElementText(t,"publisher"),e.identifier=i.getElementText(t,"identifier"),e.language=i.getElementText(t,"language"),e.rights=i.getElementText(t,"rights"),e.modified_date=i.getPropertyText(t,"dcterms:modified"),e.layout=i.getPropertyText(t,"rendition:layout"),e.orientation=i.getPropertyText(t,"rendition:orientation"),e.flow=i.getPropertyText(t,"rendition:flow"),e.viewport=i.getPropertyText(t,"rendition:viewport"),e},n.prototype.findCoverPath=function(t){var e=o.qs(t,"package"),i=e.getAttribute("version");if("2.0"===i){var n=o.qsp(t,"meta",{name:"cover"});if(n){var r=n.getAttribute("content"),s=t.getElementById(r);return!!s&&s.getAttribute("href")}return!1}var a=o.qsp(t,"item",{properties:"cover-image"});return!!a&&a.getAttribute("href")},n.prototype.getElementText=function(t,e){var i,n=t.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/",e);return n&&0!==n.length?(i=n[0],i.childNodes.length?i.childNodes[0].nodeValue:""):""},n.prototype.getPropertyText=function(t,e){var i=o.qsp(t,"meta",{property:e});return i&&i.childNodes.length?i.childNodes[0].nodeValue:""},n.prototype.querySelectorText=function(t,e){var i=t.querySelector(e);return i&&i.childNodes.length?i.childNodes[0].nodeValue:""},n.prototype.manifest=function(t){var e={},i=o.qsa(t,"item"),n=Array.prototype.slice.call(i);return n.forEach(function(t){var i=t.getAttribute("id"),n=t.getAttribute("href")||"",r=t.getAttribute("media-type")||"",o=t.getAttribute("properties")||"";e[i]={href:n,type:r,properties:o.length?o.split(" "):[]}}),e},n.prototype.spine=function(t,e){var i=[],n=t.getElementsByTagName("itemref"),r=Array.prototype.slice.call(n);new s;return r.forEach(function(t,e){var n=t.getAttribute("idref"),r=t.getAttribute("properties")||"",o=r.length?r.split(" "):[],s={idref:n,linear:t.getAttribute("linear")||"",properties:o,index:e};i.push(s)}),i},n.prototype.querySelectorByType=function(t,e,i){var n;if("undefined"!=typeof t.querySelector&&(n=t.querySelector(e+'[*|type="'+i+'"]')),n&&0!==n.length)return n;n=o.qsa(t,e);for(var r=0;r1&&n[1],{cfi:s,href:h,packageUrl:r,page:c}):{href:h,page:c}},t.exports=n},function(t,e,i){function n(t,e){var n=this,a=new r,h=e||i(18);this["package"]=t,this.toc=[],this.tocByHref={},this.tocById={},t.navPath&&(this.navUrl=s(t.navPath).absoluteTo(t.baseUrl).toString(),this.nav={},this.nav.load=function(t){var e=new o.defer,i=e.promise;return h(n.navUrl,"xml").then(function(t){n.toc=a.nav(t),n.loaded(n.toc),e.resolve(n.toc)}),i}),t.ncxPath&&(this.ncxUrl=s(t.ncxPath).absoluteTo(t.baseUrl).toString(),this.ncx={},this.ncx.load=function(t){var e=new o.defer,i=e.promise;return h(n.ncxUrl,"xml").then(function(t){n.toc=a.toc(t),n.loaded(n.toc),e.resolve(n.toc)}),i})}var r=(i(11),i(22)),o=i(2),s=i(6);n.prototype.load=function(t){var e,n;t||i(18);return this.nav?e=this.nav.load():this.ncx?e=this.ncx.load():(n=new o.defer,n.resolve([]),e=n.promise),e},n.prototype.loaded=function(t){for(var e,i=0;i-1&&(i=t.substring(t.indexOf("#")+1)),n&&(i=t),this.manager.display(e,i).then(function(){this.trigger("displayed",e)}.bind(this))):(o.reject(new Error("No Section Found")),s)},n.prototype.afterDisplayed=function(t){this.hooks.content.trigger(t,this),this.trigger("rendered",t.section),this.reportLocation()},n.prototype.onResized=function(t){this.location&&this.display(this.location.start),this.trigger("resized",{width:t.width,height:t.height})},n.prototype.moveTo=function(t){this.manager.moveTo(t)},n.prototype.next=function(){return this.q.enqueue(this.manager.next.bind(this.manager)).then(this.reportLocation.bind(this))},n.prototype.prev=function(){return this.q.enqueue(this.manager.prev.bind(this.manager)).then(this.reportLocation.bind(this))},n.prototype.determineLayoutProperties=function(t){var e,i=this.settings.layout||t.layout||"reflowable",n=this.settings.spread||t.spread||"auto",r=this.settings.orientation||t.orientation||"auto",o=this.settings.flow||t.flow||"auto",s=t.viewport||"",a=this.settings.minSpreadWidth||t.minSpreadWidth||800;return this.settings.width>=0&&this.settings.height>=0&&(s="width="+this.settings.width+", height="+this.settings.height),e={layout:i,spread:n,orientation:r,flow:o,viewport:s,minSpreadWidth:a}},n.prototype.flow=function(t){var e;"scrolled-doc"!==t&&"scrolled-continuous"!==t||(e="scrolled"),"auto"!==t&&"paginated"!==t||(e="paginated"),this._layout&&this._layout.flow(e),this.manager&&this.manager.updateFlow(e)},n.prototype.layout=function(t){return t&&(this._layout=new l(t),this._layout.spread(t.spread,this.settings.minSpreadWidth),this.mapping=new p(this._layout)),this.manager&&this._layout&&this.manager.applyLayout(this._layout),this._layout},n.prototype.spread=function(t,e){this._layout.spread(t,e),this.manager.isRendered()&&this.manager.updateLayout()},n.prototype.reportLocation=function(){return this.q.enqueue(function(){var t=this.manager.currentLocation();t&&t.then&&"function"==typeof t.then?t.then(function(t){this.location=t,this.trigger("locationChanged",this.location)}.bind(this)):t&&(this.location=t,this.trigger("locationChanged",this.location))}.bind(this))},n.prototype.destroy=function(){this.q.clear(),this.manager.destroy()},n.prototype.passViewEvents=function(t){t.contents.listenedEvents.forEach(function(e){t.on(e,this.triggerViewEvent.bind(this))}.bind(this)),t.on("selected",this.triggerSelectedEvent.bind(this))},n.prototype.triggerViewEvent=function(t){this.trigger(t.type,t)},n.prototype.triggerSelectedEvent=function(t){this.trigger("selected",t)},n.prototype.replacements=function(){var t,e=this.book["package"].manifest,i=Object.keys(e).map(function(t){return e[t]}),n=i.filter(function(t){if("application/xhtml+xml"!=t.type&&"text/html"!=t.type)return!0}),s=n.filter(function(t){if("text/css"===t.type)return!0}),a=s.map(function(t){return t.href}),h=n.map(function(t){return t.href}.bind(this)),u=h.map(function(t){var e=o(t).absoluteTo(this.book.baseUrl).toString();return this.book.unarchived.createUrl(e,{base64:this.settings.useBase64})}.bind(this));return r.all(u).then(function(e){var i=[];return t=e,a.forEach(function(e){i.push(this.replaceCss(e,h,t))}.bind(this)),r.all(i)}.bind(this)).then(function(){this.book.spine.hooks.serialize.register(function(e,i){this.replaceAssets(i,h,t)}.bind(this))}.bind(this))["catch"](function(t){console.error(t)})},n.prototype.replaceCss=function(t,e,i){var n,h,u=o(t),c=u.absoluteTo(this.book.baseUrl).toString(),l=this.book.unarchived.getText(c),p=e.map(function(t){var e=o(t).absoluteTo(this.book.baseUrl),i=e.relativeTo(c).toString();return i}.bind(this));return l.then(function(o){return o=a.substitute(o,p,i),n=this.settings.useBase64?s.createBase64Url(o,"text/css"):s.createBlobUrl(o,"text/css"),h=e.indexOf(t),h>-1&&(i[h]=n),new r.Promise(function(t,n){t(e,i)})}.bind(this))},n.prototype.replaceAssets=function(t,e,i){var n=o(t.url),r=e.map(function(t){var e=o(t).absoluteTo(this.book.baseUrl),i=e.relativeTo(n).toString();return i}.bind(this));t.output=a.substitute(t.output,r,i)},n.prototype.range=function(t,e){var i=new u(t),n=this.visible().filter(function(t){if(i.spinePos===t.index)return!0});if(n.length)return n[0].range(i,e)},n.prototype.adjustImages=function(t){return t.addStylesheetRules([["img",["max-width",t.layout.spreadWidth+"px"],["max-height",t.layout.height+"px"]]]),new r.Promise(function(t,e){setTimeout(function(){t()},1)})},r.EventTarget.mixin(n.prototype),t.exports=n},function(t,e,i){function n(t){this.name=t.layout||"reflowable",this._spread="none"!==t.spread,this._minSpreadWidth=t.spread||800,this._evenSpreads=t.evenSpreads||!1,"scrolled-continuous"===t.flow||"scrolled-doc"===t.flow?this._flow="scrolled":this._flow="paginated",this.width=0,this.height=0,this.spreadWidth=0,this.delta=0,this.columnWidth=0,this.gap=0,this.divisor=1}i(11),i(2);n.prototype.flow=function(t){this._flow="paginated"===t?"paginated":"scrolled"},n.prototype.spread=function(t,e){this._spread="none"!==t,e>=0&&(this._minSpreadWidth=e)},n.prototype.calculate=function(t,e,i){var n,r,o,s=1,a=i||0,h=(Math.floor(t),t),u=Math.floor(h/8);s=this._spread&&h>=this._minSpreadWidth?2:1,"reflowable"!==this.name||"paginated"!==this._flow||i>=0||(a=u%2===0?u:u-1),"pre-paginated"===this.name&&(a=0),n=s>1?Math.floor((h-a)/s):h,"pre-paginated"===this.name&&s>1&&(h=n),r=n*s,o=(n+a)*s,this.width=h,this.height=e,this.spreadWidth=r,this.delta=o,this.columnWidth=n,this.gap=a,this.divisor=s},n.prototype.format=function(t){var e;return e="pre-paginated"===this.name?t.fit(this.columnWidth,this.height):"paginated"===this._flow?t.columns(this.width,this.height,this.columnWidth,this.gap):t.size(this.width,null)},n.prototype.count=function(t){var e=Math.ceil(t/this.spreadWidth);return{spreads:e,pages:e*this.divisor}},t.exports=n},function(t,e,i){function n(t){this.layout=t}var r=i(15);n.prototype.section=function(t){var e=this.findRanges(t),i=this.rangeListToCfiList(t.section.cfiBase,e);return i},n.prototype.page=function(t,e,i,n){var r=!(!t||!t.document)&&t.document.body;if(r)return this.rangePairToCfiPair(e,{start:this.findStart(r,i,n),end:this.findEnd(r,i,n)})},n.prototype.walk=function(t,e){for(var i,n,r=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,{acceptNode:function(t){return t.data.trim().length>0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}},!1);(i=r.nextNode())&&!(n=e(i)););return n},n.prototype.findRanges=function(t){for(var e,i,n=[],r=t.contents.scrollWidth(),o=this.layout.count(r),s=this.layout.column,a=this.layout.gap,h=0;h=e&&n<=i?t:r>e?t:(s=t,void o.push(t))}))return this.findTextStartRange(r,e,i);return this.findTextStartRange(s,e,i)},n.prototype.findEnd=function(t,e,i){for(var n,r,o=[t],s=t;o.length;)if(n=o.shift(),r=this.walk(n,function(t){var e,n,r,a;return t.nodeType==Node.TEXT_NODE?(a=document.createRange(),a.selectNodeContents(t),r=a.getBoundingClientRect()):r=t.getBoundingClientRect(),e=r.left,n=r.right,e>i&&s?s:n>i?t:(s=t,void o.push(t))}))return this.findTextEndRange(r,e,i);return this.findTextEndRange(s,e,i)},n.prototype.findTextStartRange=function(t,e,i){for(var n,r,o,s=this.splitTextNodeIntoRanges(t),a=0;a=e)return r;n=r}return s[0]},n.prototype.findTextEndRange=function(t,e,i){for(var n,r,o,s=this.splitTextNodeIntoRanges(t),a=0;ai&&n)return n;if(o.right>i)return r;n=r}return s[s.length-1]},n.prototype.splitTextNodeIntoRanges=function(t,e){var i,n=[],r=t.textContent||"",o=r.trim(),s=t.ownerDocument,a=e||" ";if(pos=o.indexOf(a),pos===-1||t.nodeType!=Node.TEXT_NODE)return i=s.createRange(),i.selectNodeContents(t),[i];for(i=s.createRange(),i.setStart(t,0),i.setEnd(t,pos),n.push(i),i=!1;pos!=-1;)pos=o.indexOf(a,pos+1),pos>0&&(i&&(i.setEnd(t,pos),n.push(i)),i=s.createRange(),i.setStart(t,pos+1));return i&&(i.setEnd(t,o.length),n.push(i)),n},n.prototype.rangePairToCfiPair=function(t,e){var i=e.start,n=e.end;return i.collapse(!0),n.collapse(!0),startCfi=new r(i,t).toString(),endCfi=new r(n,t).toString(),{start:startCfi,end:endCfi}},n.prototype.rangeListToCfiList=function(t,e){for(var i,n=[],r=0;r-1&&(id=t.substring(t.indexOf("#")+1),el=this.document.getElementById(id),el&&(i=el.getBoundingClientRect(),n.left=i.left,n.top=i.top)),n},n.prototype.addStylesheet=function(t){return new r.Promise(function(e,i){var n,r=!1;return this.document?(n=this.document.createElement("link"),n.type="text/css",n.rel="stylesheet",n.href=t,n.onload=n.onreadystatechange=function(){r||this.readyState&&"complete"!=this.readyState||(r=!0,setTimeout(function(){e(!0)},1))},void this.document.head.appendChild(n)):void e(!1)}.bind(this))},n.prototype.addStylesheetRules=function(t){var e,i;if(this.document){e=this.document.createElement("style"),this.document.head.appendChild(e),i=e.sheet;for(var n=0,r=t.length;n0&&(e=t.getRangeAt(0),e.collapsed||(i=new s(e,this.cfiBase).toString(),this.trigger("selected",i),this.trigger("selectedRange",e)))},n.prototype.range=function(t,e){var i=new s(t);return i.toRange(this.document,e)},n.prototype.map=function(t){var e=new a(t);return e.section()},n.prototype.size=function(t,e){t>=0&&this.width(t),e>=0&&this.height(e),this.css("margin","0"),this.css("boxSizing","border-box")},n.prototype.columns=function(t,e,i,n){var r=o.prefixed("columnAxis"),s=o.prefixed("columnGap"),a=o.prefixed("columnWidth"),h=o.prefixed("columnFill");this.width(t),this.height(e),this.viewport({width:t,height:e,scale:1}),this.css("overflowY","hidden"),this.css("margin","0"),this.css("boxSizing","border-box"),this.css("maxWidth","inherit"),this.css(r,"horizontal"),this.css(h,"auto"),this.css(s,n+"px"),this.css(a,i+"px")},n.prototype.scale=function(t,e,i){var t="scale("+t+")",n="";this.css("transformOrigin","top left"),(e>=0||i>=0)&&(n=" translate("+(e||0)+"px, "+(i||0)+"px )"),this.css("transform",t+n)},n.prototype.fit=function(t,e){var i=this.viewport(),n=t/i.width,r=e/i.height,o=n1&&"reflowable"===this.settings.layout.name&&e%2>0&&(r+=this.settings.layout.gap+this.settings.layout.columnWidth),this._textWidth=i,this._contentWidth=r):r=this._contentWidth):"vertical"===this.settings.axis&&(n=this.contents.textHeight(),n!=this._textHeight?(o=this.contentHeight(n),this._textHeight=n,this._contentHeight=o):o=this._contentHeight),(this._needsReframe||r!=this._width||o!=this._height)&&this.resize(r,o),this._expanding=!1)},n.prototype.contentWidth=function(t){var e,i;return e=this.iframe.style.width,this.iframe.style.width=(t||0)+"px",i=this.contents.scrollWidth(),this.iframe.style.width=e,i},n.prototype.contentHeight=function(t){var e,i;return e=this.iframe.style.height,this.iframe.style.height=(t||0)+"px",i=this.contents.scrollHeight(),this.iframe.style.height=e,i},n.prototype.resize=function(t,e){this.iframe&&(o.isNumber(t)&&(this.iframe.style.width=t+"px",this._width=t),o.isNumber(e)&&(this.iframe.style.height=e+"px",this._height=e),this.iframeBounds=o.bounds(this.iframe),this.reframe(this.iframeBounds.width,this.iframeBounds.height))},n.prototype.reframe=function(t,e){var i;o.isNumber(t)&&(this.element.style.width=t+"px"),o.isNumber(e)&&(this.element.style.height=e+"px"),this.prevBounds=this.elementBounds,this.elementBounds=o.bounds(this.element),i={width:this.elementBounds.width,height:this.elementBounds.height,widthDelta:this.elementBounds.width-this.prevBounds.width,heightDelta:this.elementBounds.height-this.prevBounds.height},this.onResize(this,i),this.trigger("resized",i)},n.prototype.load=function(t){var e=new r.defer,i=e.promise;if(!this.iframe)return e.reject(new Error("No Iframe Available")),i;if(this.iframe.onload=function(t){this.onLoad(t,e)}.bind(this),this.supportsSrcdoc)this.iframe.srcdoc=t;else{if(this.document=this.iframe.contentDocument,!this.document)return e.reject(new Error("No Document Available")),i;this.iframe.contentDocument.open(),this.iframe.contentDocument.write(t),this.iframe.contentDocument.close()}return i},n.prototype.onLoad=function(t,e){this.window=this.iframe.contentWindow,this.document=this.iframe.contentDocument,this.contents=new a(this.document,this.document.body,this.section.cfiBase),this.rendering=!1;var i=this.document.querySelector("link[rel='canonical']");i?i.setAttribute("href",this.section.url):(i=this.document.createElement("link"),i.setAttribute("rel","canonical"),i.setAttribute("href",this.section.url),this.document.querySelector("head").appendChild(i)),this.contents.on("expand",function(){this.displayed&&this.iframe&&this.expand()}),e.resolve(this.contents)},n.prototype.setLayout=function(t){this.layout=t},n.prototype.setAxis=function(t){this.settings.axis=t},n.prototype.resizeListenters=function(){clearTimeout(this.expanding),this.expanding=setTimeout(this.expand.bind(this),350)},n.prototype.addListeners=function(){},n.prototype.removeListeners=function(t){},n.prototype.display=function(t){var e=new r.defer;return this.displayed?e.resolve(this):this.render(t).then(function(){this.trigger("displayed",this),this.onDisplayed(this),this.displayed=!0,e.resolve(this)}.bind(this)),e.promise},n.prototype.show=function(){this.element.style.visibility="visible",this.iframe&&(this.iframe.style.visibility="visible"),this.trigger("shown",this)},n.prototype.hide=function(){this.element.style.visibility="hidden",this.iframe.style.visibility="hidden",this.stopExpanding=!0,this.trigger("hidden",this)},n.prototype.position=function(){return this.element.getBoundingClientRect()},n.prototype.locationOf=function(t){var e=this.iframe.getBoundingClientRect(),i=this.contents.locationOf(t,this.settings.ignoreClass);return{left:window.scrollX+e.left+i.left,top:window.scrollY+e.top+i.top}},n.prototype.onDisplayed=function(t){},n.prototype.onResize=function(t,e){},n.prototype.bounds=function(){return this.elementBounds||(this.elementBounds=o.bounds(this.element)),this.elementBounds},n.prototype.destroy=function(){this.displayed&&(this.displayed=!1,this.removeListeners(),this.stopExpanding=!0,this.element.removeChild(this.iframe),this.displayed=!1,this.iframe=null,this._textWidth=null,this._textHeight=null,this._width=null,this._height=null)},r.EventTarget.mixin(n.prototype),t.exports=n},function(t,e,i){function n(t){this.name="default",this.View=t.view,this.request=t.request,this.renditionQueue=t.queue,this.q=new a(this),this.settings=o.extend(this.settings||{},{infinite:!0,hidden:!1,width:void 0,height:void 0,axis:"vertical",ignoreClass:""}),o.extend(this.settings,t.settings||{}),this.viewSettings={ignoreClass:this.settings.ignoreClass,axis:this.settings.axis,layout:this.layout,width:0,height:0}}var r=i(2),o=i(11),s=(i(15),i(26)),a=i(21),h=i(33),u=i(34);n.prototype.render=function(t,e){this.stage=new h({width:e.width,height:e.height,overflow:this.settings.overflow,hidden:this.settings.hidden,axis:this.settings.axis}),this.stage.attachTo(t),this.container=this.stage.getContainer(),this.views=new u(this.container),this._bounds=this.bounds(),this._stageSize=this.stage.size(),this.viewSettings.width=this._stageSize.width,this.viewSettings.height=this._stageSize.height,this.stage.onResize(this.onResized.bind(this)),this.addEventListeners(),this.layout&&this.updateLayout()},n.prototype.addEventListeners=function(){window.addEventListener("unload",function(t){this.destroy()}.bind(this))},n.prototype.destroy=function(){},n.prototype.onResized=function(t){clearTimeout(this.resizeTimeout),this.resizeTimeout=setTimeout(function(){this.resize()}.bind(this),150)},n.prototype.resize=function(t,e){this.q.clear(),this._stageSize=this.stage.size(t,e),this._bounds=this.bounds(),this.viewSettings.width=this._stageSize.width,this.viewSettings.height=this._stageSize.height,this.views.each(function(t){t.size(this._stageSize.width,this._stageSize.height)}.bind(this)),this.updateLayout(),this.trigger("resized",{width:this.stage.width,height:this.stage.height})},n.prototype.createView=function(t){return new this.View(t,this.viewSettings)},n.prototype.display=function(t,e){var i=new r.defer,n=i.promise,o=this.views.find(t);return o&&e?(offset=o.locationOf(e),this.moveTo(offset),i.resolve(),n):(this.views.hide(),this.views.clear(),this.add(t).then(function(){var e;if("pre-paginated"===this.layout.name&&this.layout.divisor>1&&(e=t.next()))return this.add(e)}.bind(this)).then(function(t){e&&(offset=t.locationOf(e),this.moveTo(offset)),this.views.show(),i.resolve()}.bind(this)),n)},n.prototype.afterDisplayed=function(t){this.trigger("added",t)},n.prototype.afterResized=function(t){this.trigger("resize",t.section)},n.prototype.moveTo=function(t){var e=0,i=0;"vertical"===this.settings.axis?i=t.top:(e=Math.floor(t.left/this.layout.delta)*this.layout.delta,e+this.layout.delta>this.container.scrollWidth&&(e=this.container.scrollWidth-this.layout.delta)),this.scrollTo(e,i)},n.prototype.add=function(t){var e=this.createView(t);return this.views.append(e),e.onDisplayed=this.afterDisplayed.bind(this),e.onResize=this.afterResized.bind(this),e.display(this.request)},n.prototype.append=function(t){var e=this.createView(t);return this.views.append(e),e.display(this.request)},n.prototype.prepend=function(t){var e=this.createView(t);return this.views.prepend(e),e.display(this.request)},n.prototype.next=function(){var t,e;if(this.views.length)return"horizontal"===this.settings.axis?(this.scrollLeft=this.container.scrollLeft,e=this.container.scrollLeft+this.container.offsetWidth+this.layout.delta,e1&&(e=t.next()))return this.append(e)}.bind(this)).then(function(){this.views.show()}.bind(this))):void 0},n.prototype.prev=function(){var t,e;if(this.views.length)return"horizontal"===this.settings.axis?(this.scrollLeft=this.container.scrollLeft,e=this.container.scrollLeft,e>0?this.scrollBy(-this.layout.delta,0):t=this.views.first().section.prev()):t=this.views.first().section.prev(),t?(this.views.clear(),this.prepend(t).then(function(){var e;if(this.layout.name&&this.layout.divisor>1&&(e=t.prev()))return this.prepend(e)}.bind(this)).then(function(){"horizontal"===this.settings.axis&&this.scrollTo(this.container.scrollWidth-this.layout.delta,0),this.views.show()}.bind(this))):void 0},n.prototype.current=function(){var t=this.visible();return t.length?t[t.length-1]:null},n.prototype.currentLocation=function(){var t,e,i;if(this.views.length)return t=this.views.first(),e=container.left-t.position().left,i=e+this.layout.spread,this.mapping.page(t,t.section.cfiBase)},n.prototype.isVisible=function(t,e,i,n){var r=t.position(),o=n||this.bounds();return"horizontal"===this.settings.axis&&r.right>o.left-e&&r.lefto.top-e&&r.top-1&&this._views.splice(e,1),this.destroy(t),this.length--},i.prototype.destroy=function(t){t.off("resized"),t.displayed&&t.destroy(),this.container&&this.container.removeChild(t.element),t=null},i.prototype.each=function(){return this._views.forEach.apply(this._views,arguments)},i.prototype.clear=function(){var t,e=this.length;if(this.length){for(var i=0;i=f&&(i=this.views.last(),o=i&&i.section.next(),o&&h.push(this.append(o))),p-c<0&&(n=this.views.first(),s=n&&n.section.prev(),s&&h.push(this.prepend(s))),h.length?this.q.enqueue(function(){return this.update(c)}.bind(this)):(a.resolve(!1),a.promise)},n.prototype.trim=function(){for(var t=new r.defer,e=this.views.displayed(),i=e[0],n=e[e.length-1],o=this.views.indexOf(i),s=this.views.indexOf(n),a=this.views.slice(0,o),h=this.views.slice(s+1),u=0;uthis.settings.offsetDelta||this.scrollDeltaHorz>this.settings.offsetDelta)&&(this.q.enqueue(function(){this.check()}.bind(this)),this.scrollDeltaVert=0,this.scrollDeltaHorz=0,this.trigger("scroll",{top:scrollTop,left:scrollLeft}),clearTimeout(this.afterScrolled),this.afterScrolled=setTimeout(function(){this.trigger("scrolled",{top:this.scrollTop,left:this.scrollLeft})}.bind(this))),this.scrollDeltaVert+=Math.abs(scrollTop-this.prevScrollTop),this.scrollDeltaHorz+=Math.abs(scrollLeft-this.prevScrollLeft),this.prevScrollTop=scrollTop,this.prevScrollLeft=scrollLeft,clearTimeout(this.scrollTimeout),this.scrollTimeout=setTimeout(function(){this.scrollDeltaVert=0,this.scrollDeltaHorz=0}.bind(this),150),this.scrolled=!1},n.prototype.currentLocation=function(){return"vertical"===this.settings.axis?this.location=this.scrolledLocation():this.location=this.paginatedLocation(),this.location},n.prototype.scrolledLocation=function(){var t,e,i=this.visible();this.container.getBoundingClientRect();return 1===i.length?this.mapping.page(i[0].contents,i[0].section.cfiBase):i.length>1?(t=this.mapping.page(i[0].contents,i[0].section.cfiBase),e=this.mapping.page(i[i.length-1].contents,i[i.length-1].section.cfiBase),{start:t.start,end:e.end}):void 0},n.prototype.paginatedLocation=function(){var t,e,i,n,r,o,s=this.visible(),a=this.container.getBoundingClientRect();return 1===s.length?(t=a.left-s[0].position().left,i=t+this.layout.spreadWidth,this.mapping.page(s[0].contents,s[0].section.cfiBase,t,i)):s.length>1?(t=a.left-s[0].position().left,i=t+this.layout.columnWidth,e=a.left+this.layout.spreadWidth-s[s.length-1].position().left,n=e+this.layout.columnWidth,r=this.mapping.page(s[0].contents,s[0].section.cfiBase,t,i),o=this.mapping.page(s[s.length-1].contents,s[s.length-1].section.cfiBase,e,n),{start:r.start,end:o.end}):void 0},n.prototype.updateLayout=function(){this.stage&&("vertical"===this.settings.axis?this.layout.calculate(this._stageSize.width,this._stageSize.height):(this.layout.calculate(this._stageSize.width,this._stageSize.height,this.settings.gap),this.settings.offset=this.layout.delta,this.stage.addStyleRules("iframe",[{"margin-right":this.layout.gap+"px"}])),this.viewSettings.width=this.layout.width,this.viewSettings.height=this.layout.height,this.setLayout(this.layout))},n.prototype.next=function(){"horizontal"===this.settings.axis?(this.scrollLeft=this.container.scrollLeft,this.container.scrollLeft+this.container.offsetWidth+this.layout.delta 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.0.14\n */\n\n(function() {\n \"use strict\";\n\n function $$rsvp$events$$indexOf(callbacks, callback) {\n for (var i=0, l=callbacks.length; i 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 $$utils$$F.prototype = o;\n return new $$utils$$F();\n });\n\n var $$instrument$$queue = [];\n\n var $$instrument$$default = function instrument(eventName, promise, child) {\n if (1 === $$instrument$$queue.push({\n name: eventName,\n payload: {\n guid: promise._guidKey + promise._id,\n eventName: eventName,\n detail: promise._result,\n childGuid: child && promise._guidKey + child._id,\n label: promise._label,\n timeStamp: $$utils$$now(),\n stack: new Error(promise._label).stack\n }})) {\n\n setTimeout(function() {\n var entry;\n for (var i = 0; i < $$instrument$$queue.length; i++) {\n entry = $$instrument$$queue[i];\n $$rsvp$config$$config.trigger(entry.name, entry.payload);\n }\n $$instrument$$queue.length = 0;\n }, 50);\n }\n };\n\n function $$$internal$$noop() {}\n var $$$internal$$PENDING = void 0;\n var $$$internal$$FULFILLED = 1;\n var $$$internal$$REJECTED = 2;\n var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject();\n\n function $$$internal$$getThen(promise) {\n try {\n return promise.then;\n } catch(error) {\n $$$internal$$GET_THEN_ERROR.error = error;\n return $$$internal$$GET_THEN_ERROR;\n }\n }\n\n function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {\n try {\n then.call(value, fulfillmentHandler, rejectionHandler);\n } catch(e) {\n return e;\n }\n }\n\n function $$$internal$$handleForeignThenable(promise, thenable, then) {\n $$rsvp$config$$config.async(function(promise) {\n var sealed = false;\n var error = $$$internal$$tryThen(then, thenable, function(value) {\n if (sealed) { return; }\n sealed = true;\n if (thenable !== value) {\n $$$internal$$resolve(promise, value);\n } else {\n $$$internal$$fulfill(promise, value);\n }\n }, function(reason) {\n if (sealed) { return; }\n sealed = true;\n\n $$$internal$$reject(promise, reason);\n }, 'Settle: ' + (promise._label || ' unknown promise'));\n\n if (!sealed && error) {\n sealed = true;\n $$$internal$$reject(promise, error);\n }\n }, promise);\n }\n\n function $$$internal$$handleOwnThenable(promise, thenable) {\n if (thenable._state === $$$internal$$FULFILLED) {\n $$$internal$$fulfill(promise, thenable._result);\n } else if (promise._state === $$$internal$$REJECTED) {\n $$$internal$$reject(promise, thenable._result);\n } else {\n $$$internal$$subscribe(thenable, undefined, function(value) {\n if (thenable !== value) {\n $$$internal$$resolve(promise, value);\n } else {\n $$$internal$$fulfill(promise, value);\n }\n }, function(reason) {\n $$$internal$$reject(promise, reason);\n });\n }\n }\n\n function $$$internal$$handleMaybeThenable(promise, maybeThenable) {\n if (maybeThenable.constructor === promise.constructor) {\n $$$internal$$handleOwnThenable(promise, maybeThenable);\n } else {\n var then = $$$internal$$getThen(maybeThenable);\n\n if (then === $$$internal$$GET_THEN_ERROR) {\n $$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error);\n } else if (then === undefined) {\n $$$internal$$fulfill(promise, maybeThenable);\n } else if ($$utils$$isFunction(then)) {\n $$$internal$$handleForeignThenable(promise, maybeThenable, then);\n } else {\n $$$internal$$fulfill(promise, maybeThenable);\n }\n }\n }\n\n function $$$internal$$resolve(promise, value) {\n if (promise === value) {\n $$$internal$$fulfill(promise, value);\n } else if ($$utils$$objectOrFunction(value)) {\n $$$internal$$handleMaybeThenable(promise, value);\n } else {\n $$$internal$$fulfill(promise, value);\n }\n }\n\n function $$$internal$$publishRejection(promise) {\n if (promise._onerror) {\n promise._onerror(promise._result);\n }\n\n $$$internal$$publish(promise);\n }\n\n function $$$internal$$fulfill(promise, value) {\n if (promise._state !== $$$internal$$PENDING) { return; }\n\n promise._result = value;\n promise._state = $$$internal$$FULFILLED;\n\n if (promise._subscribers.length === 0) {\n if ($$rsvp$config$$config.instrument) {\n $$instrument$$default('fulfilled', promise);\n }\n } else {\n $$rsvp$config$$config.async($$$internal$$publish, promise);\n }\n }\n\n function $$$internal$$reject(promise, reason) {\n if (promise._state !== $$$internal$$PENDING) { return; }\n promise._state = $$$internal$$REJECTED;\n promise._result = reason;\n\n $$rsvp$config$$config.async($$$internal$$publishRejection, promise);\n }\n\n function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) {\n var subscribers = parent._subscribers;\n var length = subscribers.length;\n\n parent._onerror = null;\n\n subscribers[length] = child;\n subscribers[length + $$$internal$$FULFILLED] = onFulfillment;\n subscribers[length + $$$internal$$REJECTED] = onRejection;\n\n if (length === 0 && parent._state) {\n $$rsvp$config$$config.async($$$internal$$publish, parent);\n }\n }\n\n function $$$internal$$publish(promise) {\n var subscribers = promise._subscribers;\n var settled = promise._state;\n\n if ($$rsvp$config$$config.instrument) {\n $$instrument$$default(settled === $$$internal$$FULFILLED ? 'fulfilled' : 'rejected', promise);\n }\n\n if (subscribers.length === 0) { return; }\n\n var child, callback, detail = promise._result;\n\n for (var i = 0; i < subscribers.length; i += 3) {\n child = subscribers[i];\n callback = subscribers[i + settled];\n\n if (child) {\n $$$internal$$invokeCallback(settled, child, callback, detail);\n } else {\n callback(detail);\n }\n }\n\n promise._subscribers.length = 0;\n }\n\n function $$$internal$$ErrorObject() {\n this.error = null;\n }\n\n var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject();\n\n function $$$internal$$tryCatch(callback, detail) {\n try {\n return callback(detail);\n } catch(e) {\n $$$internal$$TRY_CATCH_ERROR.error = e;\n return $$$internal$$TRY_CATCH_ERROR;\n }\n }\n\n function $$$internal$$invokeCallback(settled, promise, callback, detail) {\n var hasCallback = $$utils$$isFunction(callback),\n value, error, succeeded, failed;\n\n if (hasCallback) {\n value = $$$internal$$tryCatch(callback, detail);\n\n if (value === $$$internal$$TRY_CATCH_ERROR) {\n failed = true;\n error = value.error;\n value = null;\n } else {\n succeeded = true;\n }\n\n if (promise === value) {\n $$$internal$$reject(promise, new TypeError('A promises callback cannot return that same promise.'));\n return;\n }\n\n } else {\n value = detail;\n succeeded = true;\n }\n\n if (promise._state !== $$$internal$$PENDING) {\n // noop\n } else if (hasCallback && succeeded) {\n $$$internal$$resolve(promise, value);\n } else if (failed) {\n $$$internal$$reject(promise, error);\n } else if (settled === $$$internal$$FULFILLED) {\n $$$internal$$fulfill(promise, value);\n } else if (settled === $$$internal$$REJECTED) {\n $$$internal$$reject(promise, value);\n }\n }\n\n function $$$internal$$initializePromise(promise, resolver) {\n try {\n resolver(function resolvePromise(value){\n $$$internal$$resolve(promise, value);\n }, function rejectPromise(reason) {\n $$$internal$$reject(promise, reason);\n });\n } catch(e) {\n $$$internal$$reject(promise, e);\n }\n }\n\n function $$enumerator$$makeSettledResult(state, position, value) {\n if (state === $$$internal$$FULFILLED) {\n return {\n state: 'fulfilled',\n value: value\n };\n } else {\n return {\n state: 'rejected',\n reason: value\n };\n }\n }\n\n function $$enumerator$$Enumerator(Constructor, input, abortOnReject, label) {\n this._instanceConstructor = Constructor;\n this.promise = new Constructor($$$internal$$noop, label);\n this._abortOnReject = abortOnReject;\n\n if (this._validateInput(input)) {\n this._input = input;\n this.length = input.length;\n this._remaining = input.length;\n\n this._init();\n\n if (this.length === 0) {\n $$$internal$$fulfill(this.promise, this._result);\n } else {\n this.length = this.length || 0;\n this._enumerate();\n if (this._remaining === 0) {\n $$$internal$$fulfill(this.promise, this._result);\n }\n }\n } else {\n $$$internal$$reject(this.promise, this._validationError());\n }\n }\n\n $$enumerator$$Enumerator.prototype._validateInput = function(input) {\n return $$utils$$isArray(input);\n };\n\n $$enumerator$$Enumerator.prototype._validationError = function() {\n return new Error('Array Methods must be provided an Array');\n };\n\n $$enumerator$$Enumerator.prototype._init = function() {\n this._result = new Array(this.length);\n };\n\n var $$enumerator$$default = $$enumerator$$Enumerator;\n\n $$enumerator$$Enumerator.prototype._enumerate = function() {\n var length = this.length;\n var promise = this.promise;\n var input = this._input;\n\n for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {\n this._eachEntry(input[i], i);\n }\n };\n\n $$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {\n var c = this._instanceConstructor;\n if ($$utils$$isMaybeThenable(entry)) {\n if (entry.constructor === c && entry._state !== $$$internal$$PENDING) {\n entry._onerror = null;\n this._settledAt(entry._state, i, entry._result);\n } else {\n this._willSettleAt(c.resolve(entry), i);\n }\n } else {\n this._remaining--;\n this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry);\n }\n };\n\n $$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {\n var promise = this.promise;\n\n if (promise._state === $$$internal$$PENDING) {\n this._remaining--;\n\n if (this._abortOnReject && state === $$$internal$$REJECTED) {\n $$$internal$$reject(promise, value);\n } else {\n this._result[i] = this._makeResult(state, i, value);\n }\n }\n\n if (this._remaining === 0) {\n $$$internal$$fulfill(promise, this._result);\n }\n };\n\n $$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) {\n return value;\n };\n\n $$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {\n var enumerator = this;\n\n $$$internal$$subscribe(promise, undefined, function(value) {\n enumerator._settledAt($$$internal$$FULFILLED, i, value);\n }, function(reason) {\n enumerator._settledAt($$$internal$$REJECTED, i, reason);\n });\n };\n\n var $$promise$all$$default = function all(entries, label) {\n return new $$enumerator$$default(this, entries, true /* abort on reject */, label).promise;\n };\n\n var $$promise$race$$default = function race(entries, label) {\n /*jshint validthis:true */\n var Constructor = this;\n\n var promise = new Constructor($$$internal$$noop, label);\n\n if (!$$utils$$isArray(entries)) {\n $$$internal$$reject(promise, new TypeError('You must pass an array to race.'));\n return promise;\n }\n\n var length = entries.length;\n\n function onFulfillment(value) {\n $$$internal$$resolve(promise, value);\n }\n\n function onRejection(reason) {\n $$$internal$$reject(promise, reason);\n }\n\n for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {\n $$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);\n }\n\n return promise;\n };\n\n var $$promise$resolve$$default = function resolve(object, label) {\n /*jshint validthis:true */\n var Constructor = this;\n\n if (object && typeof object === 'object' && object.constructor === Constructor) {\n return object;\n }\n\n var promise = new Constructor($$$internal$$noop, label);\n $$$internal$$resolve(promise, object);\n return promise;\n };\n\n var $$promise$reject$$default = function reject(reason, label) {\n /*jshint validthis:true */\n var Constructor = this;\n var promise = new Constructor($$$internal$$noop, label);\n $$$internal$$reject(promise, reason);\n return promise;\n };\n\n var $$rsvp$promise$$guidKey = 'rsvp_' + $$utils$$now() + '-';\n var $$rsvp$promise$$counter = 0;\n\n function $$rsvp$promise$$needsResolver() {\n throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');\n }\n\n function $$rsvp$promise$$needsNew() {\n throw new TypeError(\"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.\");\n }\n\n var $$rsvp$promise$$default = $$rsvp$promise$$Promise;\n\n /**\n Promise objects represent the eventual result of an asynchronous operation. The\n primary way of interacting with a promise is through its `then` method, which\n registers callbacks to receive either a promise’s eventual value or the reason\n why the promise cannot be fulfilled.\n\n Terminology\n -----------\n\n - `promise` is an object or function with a `then` method whose behavior conforms to this specification.\n - `thenable` is an object or function that defines a `then` method.\n - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).\n - `exception` is a value that is thrown using the throw statement.\n - `reason` is a value that indicates why a promise was rejected.\n - `settled` the final resting state of a promise, fulfilled or rejected.\n\n A promise can be in one of three states: pending, fulfilled, or rejected.\n\n Promises that are fulfilled have a fulfillment value and are in the fulfilled\n state. Promises that are rejected have a rejection reason and are in the\n rejected state. A fulfillment value is never a thenable.\n\n Promises can also be said to *resolve* a value. If this value is also a\n promise, then the original promise's settled state will match the value's\n settled state. So a promise that *resolves* a promise that rejects will\n itself reject, and a promise that *resolves* a promise that fulfills will\n itself fulfill.\n\n\n Basic Usage:\n ------------\n\n ```js\n var promise = new Promise(function(resolve, reject) {\n // on success\n resolve(value);\n\n // on failure\n reject(reason);\n });\n\n promise.then(function(value) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Advanced Usage:\n ---------------\n\n Promises shine when abstracting away asynchronous interactions such as\n `XMLHttpRequest`s.\n\n ```js\n function getJSON(url) {\n return new Promise(function(resolve, reject){\n var xhr = new XMLHttpRequest();\n\n xhr.open('GET', url);\n xhr.onreadystatechange = handler;\n xhr.responseType = 'json';\n xhr.setRequestHeader('Accept', 'application/json');\n xhr.send();\n\n function handler() {\n if (this.readyState === this.DONE) {\n if (this.status === 200) {\n resolve(this.response);\n } else {\n reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));\n }\n }\n };\n });\n }\n\n getJSON('/posts.json').then(function(json) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Unlike callbacks, promises are great composable primitives.\n\n ```js\n Promise.all([\n getJSON('/posts'),\n getJSON('/comments')\n ]).then(function(values){\n values[0] // => postsJSON\n values[1] // => commentsJSON\n\n return values;\n });\n ```\n\n @class RSVP.Promise\n @param {function} resolver\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @constructor\n */\n function $$rsvp$promise$$Promise(resolver, label) {\n this._id = $$rsvp$promise$$counter++;\n this._label = label;\n this._state = undefined;\n this._result = undefined;\n this._subscribers = [];\n\n if ($$rsvp$config$$config.instrument) {\n $$instrument$$default('created', this);\n }\n\n if ($$$internal$$noop !== resolver) {\n if (!$$utils$$isFunction(resolver)) {\n $$rsvp$promise$$needsResolver();\n }\n\n if (!(this instanceof $$rsvp$promise$$Promise)) {\n $$rsvp$promise$$needsNew();\n }\n\n $$$internal$$initializePromise(this, resolver);\n }\n }\n\n // deprecated\n $$rsvp$promise$$Promise.cast = $$promise$resolve$$default;\n\n $$rsvp$promise$$Promise.all = $$promise$all$$default;\n $$rsvp$promise$$Promise.race = $$promise$race$$default;\n $$rsvp$promise$$Promise.resolve = $$promise$resolve$$default;\n $$rsvp$promise$$Promise.reject = $$promise$reject$$default;\n\n $$rsvp$promise$$Promise.prototype = {\n constructor: $$rsvp$promise$$Promise,\n\n _guidKey: $$rsvp$promise$$guidKey,\n\n _onerror: function (reason) {\n $$rsvp$config$$config.trigger('error', reason);\n },\n\n /**\n The primary way of interacting with a promise is through its `then` method,\n which registers callbacks to receive either a promise's eventual value or the\n reason why the promise cannot be fulfilled.\n\n ```js\n findUser().then(function(user){\n // user is available\n }, function(reason){\n // user is unavailable, and you are given the reason why\n });\n ```\n\n Chaining\n --------\n\n The return value of `then` is itself a promise. This second, 'downstream'\n promise is resolved with the return value of the first promise's fulfillment\n or rejection handler, or rejected if the handler throws an exception.\n\n ```js\n findUser().then(function (user) {\n return user.name;\n }, function (reason) {\n return 'default name';\n }).then(function (userName) {\n // If `findUser` fulfilled, `userName` will be the user's name, otherwise it\n // will be `'default name'`\n });\n\n findUser().then(function (user) {\n throw new Error('Found user, but still unhappy');\n }, function (reason) {\n throw new Error('`findUser` rejected and we're unhappy');\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.\n // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.\n });\n ```\n If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.\n\n ```js\n findUser().then(function (user) {\n throw new PedagogicalException('Upstream error');\n }).then(function (value) {\n // never reached\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // The `PedgagocialException` is propagated all the way down to here\n });\n ```\n\n Assimilation\n ------------\n\n Sometimes the value you want to propagate to a downstream promise can only be\n retrieved asynchronously. This can be achieved by returning a promise in the\n fulfillment or rejection handler. The downstream promise will then be pending\n until the returned promise is settled. This is called *assimilation*.\n\n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // The user's comments are now available\n });\n ```\n\n If the assimliated promise rejects, then the downstream promise will also reject.\n\n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // If `findCommentsByAuthor` fulfills, we'll have the value here\n }, function (reason) {\n // If `findCommentsByAuthor` rejects, we'll have the reason here\n });\n ```\n\n Simple Example\n --------------\n\n Synchronous Example\n\n ```javascript\n var result;\n\n try {\n result = findResult();\n // success\n } catch(reason) {\n // failure\n }\n ```\n\n Errback Example\n\n ```js\n findResult(function(result, err){\n if (err) {\n // failure\n } else {\n // success\n }\n });\n ```\n\n Promise Example;\n\n ```javascript\n findResult().then(function(result){\n // success\n }, function(reason){\n // failure\n });\n ```\n\n Advanced Example\n --------------\n\n Synchronous Example\n\n ```javascript\n var author, books;\n\n try {\n author = findAuthor();\n books = findBooksByAuthor(author);\n // success\n } catch(reason) {\n // failure\n }\n ```\n\n Errback Example\n\n ```js\n\n function foundBooks(books) {\n\n }\n\n function failure(reason) {\n\n }\n\n findAuthor(function(author, err){\n if (err) {\n failure(err);\n // failure\n } else {\n try {\n findBoooksByAuthor(author, function(books, err) {\n if (err) {\n failure(err);\n } else {\n try {\n foundBooks(books);\n } catch(reason) {\n failure(reason);\n }\n }\n });\n } catch(error) {\n failure(err);\n }\n // success\n }\n });\n ```\n\n Promise Example;\n\n ```javascript\n findAuthor().\n then(findBooksByAuthor).\n then(function(books){\n // found books\n }).catch(function(reason){\n // something went wrong\n });\n ```\n\n @method then\n @param {Function} onFulfilled\n @param {Function} onRejected\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n then: function(onFulfillment, onRejection, label) {\n var parent = this;\n var state = parent._state;\n\n if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) {\n if ($$rsvp$config$$config.instrument) {\n $$instrument$$default('chained', this, this);\n }\n return this;\n }\n\n parent._onerror = null;\n\n var child = new this.constructor($$$internal$$noop, label);\n var result = parent._result;\n\n if ($$rsvp$config$$config.instrument) {\n $$instrument$$default('chained', parent, child);\n }\n\n if (state) {\n var callback = arguments[state - 1];\n $$rsvp$config$$config.async(function(){\n $$$internal$$invokeCallback(state, child, callback, result);\n });\n } else {\n $$$internal$$subscribe(parent, child, onFulfillment, onRejection);\n }\n\n return child;\n },\n\n /**\n `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same\n as the catch block of a try/catch statement.\n\n ```js\n function findAuthor(){\n throw new Error('couldn't find that author');\n }\n\n // synchronous\n try {\n findAuthor();\n } catch(reason) {\n // something went wrong\n }\n\n // async with promises\n findAuthor().catch(function(reason){\n // something went wrong\n });\n ```\n\n @method catch\n @param {Function} onRejection\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'catch': function(onRejection, label) {\n return this.then(null, onRejection, label);\n },\n\n /**\n `finally` will be invoked regardless of the promise's fate just as native\n try/catch/finally behaves\n\n Synchronous example:\n\n ```js\n findAuthor() {\n if (Math.random() > 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 constructor = this.constructor;\n\n return this.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 $$rsvp$node$$Result() {\n this.value = undefined;\n }\n\n var $$rsvp$node$$ERROR = new $$rsvp$node$$Result();\n var $$rsvp$node$$GET_THEN_ERROR = new $$rsvp$node$$Result();\n\n function $$rsvp$node$$getThen(obj) {\n try {\n return obj.then;\n } catch(error) {\n $$rsvp$node$$ERROR.value= error;\n return $$rsvp$node$$ERROR;\n }\n }\n\n function $$rsvp$node$$tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch(error) {\n $$rsvp$node$$ERROR.value = error;\n return $$rsvp$node$$ERROR;\n }\n }\n\n function $$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 $$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 $$rsvp$node$$wrapThenable(then, promise) {\n return {\n then: function(onFulFillment, onRejection) {\n return then.call(promise, onFulFillment, onRejection);\n }\n };\n }\n\n var $$rsvp$node$$default = function 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 = $$rsvp$node$$needsPromiseInput(arg);\n if (promiseInput === $$rsvp$node$$GET_THEN_ERROR) {\n var p = new $$rsvp$promise$$default($$$internal$$noop);\n $$$internal$$reject(p, $$rsvp$node$$GET_THEN_ERROR.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = $$rsvp$node$$wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new $$rsvp$promise$$default($$$internal$$noop);\n\n args[l] = function(err, val) {\n if (err)\n $$$internal$$reject(promise, err);\n else if (options === undefined)\n $$$internal$$resolve(promise, val);\n else if (options === true)\n $$$internal$$resolve(promise, $$rsvp$node$$arrayResult(arguments));\n else if ($$utils$$isArray(options))\n $$$internal$$resolve(promise, $$rsvp$node$$makeObject(arguments, options));\n else\n $$$internal$$resolve(promise, val);\n };\n\n if (promiseInput) {\n return $$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return $$rsvp$node$$handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n };\n\n function $$rsvp$node$$handleValueInput(promise, args, nodeFunc, self) {\n var result = $$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === $$rsvp$node$$ERROR) {\n $$$internal$$reject(promise, result.value);\n }\n return promise;\n }\n\n function $$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self){\n return $$rsvp$promise$$default.all(args).then(function(args){\n var result = $$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === $$rsvp$node$$ERROR) {\n $$$internal$$reject(promise, result.value);\n }\n return promise;\n });\n }\n\n function $$rsvp$node$$needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === $$rsvp$promise$$default) {\n return true;\n } else {\n return $$rsvp$node$$getThen(arg);\n }\n } else {\n return false;\n }\n }\n\n var $$rsvp$all$$default = function all(array, label) {\n return $$rsvp$promise$$default.all(array, label);\n };\n\n function $$rsvp$all$settled$$AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);\n }\n\n $$rsvp$all$settled$$AllSettled.prototype = $$utils$$o_create($$enumerator$$default.prototype);\n $$rsvp$all$settled$$AllSettled.prototype._superConstructor = $$enumerator$$default;\n $$rsvp$all$settled$$AllSettled.prototype._makeResult = $$enumerator$$makeSettledResult;\n\n $$rsvp$all$settled$$AllSettled.prototype._validationError = function() {\n return new Error('allSettled must be called with an array');\n };\n\n var $$rsvp$all$settled$$default = function allSettled(entries, label) {\n return new $$rsvp$all$settled$$AllSettled($$rsvp$promise$$default, entries, label).promise;\n };\n\n var $$rsvp$race$$default = function race(array, label) {\n return $$rsvp$promise$$default.race(array, label);\n };\n\n function $$promise$hash$$PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n }\n\n var $$promise$hash$$default = $$promise$hash$$PromiseHash;\n $$promise$hash$$PromiseHash.prototype = $$utils$$o_create($$enumerator$$default.prototype);\n $$promise$hash$$PromiseHash.prototype._superConstructor = $$enumerator$$default;\n\n $$promise$hash$$PromiseHash.prototype._init = function() {\n this._result = {};\n };\n\n $$promise$hash$$PromiseHash.prototype._validateInput = function(input) {\n return input && typeof input === 'object';\n };\n\n $$promise$hash$$PromiseHash.prototype._validationError = function() {\n return new Error('Promise.hash must be called with an object');\n };\n\n $$promise$hash$$PromiseHash.prototype._enumerate = function() {\n var promise = this.promise;\n var input = this._input;\n var results = [];\n\n for (var key in input) {\n if (promise._state === $$$internal$$PENDING && input.hasOwnProperty(key)) {\n results.push({\n position: key,\n entry: input[key]\n });\n }\n }\n\n var length = results.length;\n this._remaining = length;\n var result;\n\n for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) {\n result = results[i];\n this._eachEntry(result.entry, result.position);\n }\n };\n\n var $$rsvp$hash$$default = function hash(object, label) {\n return new $$promise$hash$$default($$rsvp$promise$$default, object, label).promise;\n };\n\n function $$rsvp$hash$settled$$HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n }\n\n $$rsvp$hash$settled$$HashSettled.prototype = $$utils$$o_create($$promise$hash$$default.prototype);\n $$rsvp$hash$settled$$HashSettled.prototype._superConstructor = $$enumerator$$default;\n $$rsvp$hash$settled$$HashSettled.prototype._makeResult = $$enumerator$$makeSettledResult;\n\n $$rsvp$hash$settled$$HashSettled.prototype._validationError = function() {\n return new Error('hashSettled must be called with an object');\n };\n\n var $$rsvp$hash$settled$$default = function hashSettled(object, label) {\n return new $$rsvp$hash$settled$$HashSettled($$rsvp$promise$$default, object, label).promise;\n };\n\n var $$rsvp$rethrow$$default = function rethrow(reason) {\n setTimeout(function() {\n throw reason;\n });\n throw reason;\n };\n\n var $$rsvp$defer$$default = function defer(label) {\n var deferred = { };\n\n deferred.promise = new $$rsvp$promise$$default(function(resolve, reject) {\n deferred.resolve = resolve;\n deferred.reject = reject;\n }, label);\n\n return deferred;\n };\n\n var $$rsvp$map$$default = function map(promises, mapFn, label) {\n return $$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!$$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 $$rsvp$promise$$default.all(results, label);\n });\n };\n\n var $$rsvp$resolve$$default = function resolve(value, label) {\n return $$rsvp$promise$$default.resolve(value, label);\n };\n\n var $$rsvp$reject$$default = function reject(reason, label) {\n return $$rsvp$promise$$default.reject(reason, label);\n };\n\n var $$rsvp$filter$$default = function filter(promises, filterFn, label) {\n return $$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!$$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 $$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\n var $$rsvp$asap$$len = 0;\n\n var $$rsvp$asap$$default = function asap(callback, arg) {\n $$rsvp$asap$$queue[$$rsvp$asap$$len] = callback;\n $$rsvp$asap$$queue[$$rsvp$asap$$len + 1] = arg;\n $$rsvp$asap$$len += 2;\n if ($$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 $$rsvp$asap$$scheduleFlush();\n }\n };\n\n var $$rsvp$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {};\n var $$rsvp$asap$$BrowserMutationObserver = $$rsvp$asap$$browserGlobal.MutationObserver || $$rsvp$asap$$browserGlobal.WebKitMutationObserver;\n\n // test for web worker but not in IE10\n var $$rsvp$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&\n typeof importScripts !== 'undefined' &&\n typeof MessageChannel !== 'undefined';\n\n // node\n function $$rsvp$asap$$useNextTick() {\n return function() {\n process.nextTick($$rsvp$asap$$flush);\n };\n }\n\n function $$rsvp$asap$$useMutationObserver() {\n var iterations = 0;\n var observer = new $$rsvp$asap$$BrowserMutationObserver($$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 $$rsvp$asap$$useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = $$rsvp$asap$$flush;\n return function () {\n channel.port2.postMessage(0);\n };\n }\n\n function $$rsvp$asap$$useSetTimeout() {\n return function() {\n setTimeout($$rsvp$asap$$flush, 1);\n };\n }\n\n var $$rsvp$asap$$queue = new Array(1000);\n\n function $$rsvp$asap$$flush() {\n for (var i = 0; i < $$rsvp$asap$$len; i+=2) {\n var callback = $$rsvp$asap$$queue[i];\n var arg = $$rsvp$asap$$queue[i+1];\n\n callback(arg);\n\n $$rsvp$asap$$queue[i] = undefined;\n $$rsvp$asap$$queue[i+1] = undefined;\n }\n\n $$rsvp$asap$$len = 0;\n }\n\n var $$rsvp$asap$$scheduleFlush;\n\n // Decide what async method to use to triggering processing of queued callbacks:\n if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {\n $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useNextTick();\n } else if ($$rsvp$asap$$BrowserMutationObserver) {\n $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useMutationObserver();\n } else if ($$rsvp$asap$$isWorker) {\n $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useMessageChannel();\n } else {\n $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useSetTimeout();\n }\n\n // default async is asap;\n $$rsvp$config$$config.async = $$rsvp$asap$$default;\n\n var $$rsvp$$cast = $$rsvp$resolve$$default;\n\n function $$rsvp$$async(callback, arg) {\n $$rsvp$config$$config.async(callback, arg);\n }\n\n function $$rsvp$$on() {\n $$rsvp$config$$config.on.apply($$rsvp$config$$config, arguments);\n }\n\n function $$rsvp$$off() {\n $$rsvp$config$$config.off.apply($$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 $$rsvp$$callbacks = window['__PROMISE_INSTRUMENTATION__'];\n $$rsvp$config$$configure('instrument', true);\n for (var $$rsvp$$eventName in $$rsvp$$callbacks) {\n if ($$rsvp$$callbacks.hasOwnProperty($$rsvp$$eventName)) {\n $$rsvp$$on($$rsvp$$eventName, $$rsvp$$callbacks[$$rsvp$$eventName]);\n }\n }\n }\n\n var rsvp$umd$$RSVP = {\n 'race': $$rsvp$race$$default,\n 'Promise': $$rsvp$promise$$default,\n 'allSettled': $$rsvp$all$settled$$default,\n 'hash': $$rsvp$hash$$default,\n 'hashSettled': $$rsvp$hash$settled$$default,\n 'denodeify': $$rsvp$node$$default,\n 'on': $$rsvp$$on,\n 'off': $$rsvp$$off,\n 'map': $$rsvp$map$$default,\n 'filter': $$rsvp$filter$$default,\n 'resolve': $$rsvp$resolve$$default,\n 'reject': $$rsvp$reject$$default,\n 'all': $$rsvp$all$$default,\n 'rethrow': $$rsvp$rethrow$$default,\n 'defer': $$rsvp$defer$$default,\n 'EventTarget': $$rsvp$events$$default,\n 'configure': $$rsvp$config$$configure,\n 'async': $$rsvp$$async\n };\n\n /* global define:true module:true window: true */\n if (typeof define === 'function' && define.amd) {\n define(function() { return rsvp$umd$$RSVP; });\n } else if (typeof module !== 'undefined' && module.exports) {\n module.exports = rsvp$umd$$RSVP;\n } else if (typeof this !== 'undefined') {\n this['RSVP'] = rsvp$umd$$RSVP;\n }\n}).call(this);","/*!\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 book.packageUrl = packageUri.absoluteTo(book.url).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 = packageUri.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 = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;\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\nfunction EpubCFI(cfiStr){\n if(cfiStr) return this.parse(cfiStr);\n};\n\nEpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {\n var pos = parseInt(_pos),\n spineNodeIndex = _spineNodeIndex + 1,\n cfi = '/'+spineNodeIndex+'/';\n\n cfi += (pos + 1) * 2;\n\n if(id) cfi += \"[\" + id + \"]\";\n\n //cfi += \"!\";\n\n return cfi;\n};\n\nEpubCFI.prototype.generatePathComponent = function(steps) {\n var parts = [];\n\n steps.forEach(function(part){\n var segment = '';\n segment += (part.index + 1) * 2;\n\n if(part.id) {\n segment += \"[\" + part.id + \"]\";\n }\n\n parts.push(segment);\n });\n\n return parts.join('/');\n};\n\nEpubCFI.prototype.generateCfiFromElement = function(element, chapter) {\n var steps = this.pathTo(element);\n var path = this.generatePathComponent(steps);\n if(!path.length) {\n // Start of Chapter\n return \"epubcfi(\" + chapter + \"!/4/)\";\n } else {\n // First Text Node\n return \"epubcfi(\" + chapter + \"!\" + path + \"/1:0)\";\n }\n};\n\nEpubCFI.prototype.pathTo = function(node) {\n var stack = [],\n children;\n\n while(node && node.parentNode !== null && node.parentNode.nodeType != 9) {\n children = node.parentNode.children;\n\n stack.unshift({\n 'id' : node.id,\n // 'classList' : node.classList,\n 'tagName' : node.tagName,\n 'index' : children ? Array.prototype.indexOf.call(children, node) : 0\n });\n\n node = node.parentNode;\n }\n\n return stack;\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n var splitStr = cfiStr.split(\"!\");\n\n return splitStr[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n var splitStr = cfiStr.split(\"!\");\n var pathComponent = splitStr[1] ? splitStr[1].split(\":\") : '';\n\n return pathComponent[0];\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n var splitStr = cfiStr.split(\":\");\n return splitStr[1] || '';\n};\n\n\nEpubCFI.prototype.parse = function(cfiStr) {\n var cfi = {},\n chapSegment,\n chapterComponent,\n pathComponent,\n charecterOffsetComponent,\n assertion,\n chapId,\n path,\n end,\n endInt,\n text,\n parseStep = function(part){\n var type, index, has_brackets, id;\n\n type = \"element\";\n index = parseInt(part) / 2 - 1;\n has_brackets = part.match(/\\[(.*)\\]/);\n if(has_brackets && has_brackets[1]){\n id = has_brackets[1];\n }\n\n return {\n \"type\" : type,\n 'index' : index,\n 'id' : id || false\n };\n };\n\n if(typeof cfiStr !== \"string\") {\n return {spinePos: -1};\n }\n\n cfi.str = cfiStr;\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 chapterComponent = this.getChapterComponent(cfiStr);\n pathComponent = this.getPathComponent(cfiStr) || '';\n charecterOffsetComponent = this.getCharecterOffsetComponent(cfiStr);\n // Make sure this is a valid cfi or return\n if(!chapterComponent) {\n return {spinePos: -1};\n }\n\n // Chapter segment is always the second one\n chapSegment = chapterComponent.split(\"/\")[2] || '';\n if(!chapSegment) return {spinePos:-1};\n\n cfi.spinePos = (parseInt(chapSegment) / 2 - 1 ) || 0;\n\n chapId = chapSegment.match(/\\[(.*)\\]/);\n\n cfi.spineId = chapId ? chapId[1] : false;\n\n if(pathComponent.indexOf(',') != -1) {\n // Handle ranges -- not supported yet\n console.warn(\"CFI Ranges are not supported\");\n }\n\n path = pathComponent.split('/');\n end = path.pop();\n\n cfi.steps = [];\n\n path.forEach(function(part){\n var step;\n\n if(part) {\n step = parseStep(part);\n cfi.steps.push(step);\n }\n });\n\n //-- Check if END is a text node or element\n endInt = parseInt(end);\n if(!isNaN(endInt)) {\n\n if(endInt % 2 === 0) { // Even = is an element\n cfi.steps.push(parseStep(end));\n } else {\n cfi.steps.push({\n \"type\" : \"text\",\n 'index' : (endInt - 1 ) / 2\n });\n }\n\n }\n\n assertion = charecterOffsetComponent.match(/\\[(.*)\\]/);\n if(assertion && assertion[1]){\n cfi.characterOffset = parseInt(charecterOffsetComponent.split('[')[0]);\n // We arent handling these assertions yet\n cfi.textLocationAssertion = assertion[1];\n } else {\n cfi.characterOffset = parseInt(charecterOffsetComponent);\n }\n\n return cfi;\n};\n\nEpubCFI.prototype.addMarker = function(cfi, _doc, _marker) {\n var doc = _doc || document;\n var marker = _marker || this.createMarker(doc);\n var parent;\n var lastStep;\n var text;\n var split;\n\n if(typeof cfi === 'string') {\n cfi = this.parse(cfi);\n }\n // Get the terminal step\n lastStep = cfi.steps[cfi.steps.length-1];\n\n // check spinePos\n if(cfi.spinePos === -1) {\n // Not a valid CFI\n return false;\n }\n\n // Find the CFI elements parent\n parent = this.findParent(cfi, doc);\n\n if(!parent) {\n // CFI didn't return an element\n // Maybe it isnt in the current chapter?\n return false;\n }\n\n if(lastStep && lastStep.type === \"text\") {\n text = parent.childNodes[lastStep.index];\n if(cfi.characterOffset){\n split = text.splitText(cfi.characterOffset);\n marker.classList.add(\"EPUBJS-CFI-SPLIT\");\n parent.insertBefore(marker, split);\n } else {\n parent.insertBefore(marker, text);\n }\n } else {\n parent.insertBefore(marker, parent.firstChild);\n }\n\n return marker;\n};\n\nEpubCFI.prototype.createMarker = function(_doc) {\n var doc = _doc || document;\n var element = doc.createElement('span');\n element.id = \"EPUBJS-CFI-MARKER:\"+ core.uuid();\n element.classList.add(\"EPUBJS-CFI-MARKER\");\n\n return element;\n};\n\nEpubCFI.prototype.removeMarker = function(marker, _doc) {\n var doc = _doc || document;\n // var id = marker.id;\n\n // Cleanup textnodes if they were split\n if(marker.classList.contains(\"EPUBJS-CFI-SPLIT\")){\n nextSib = marker.nextSibling;\n prevSib = marker.previousSibling;\n if(nextSib &&\n prevSib &&\n nextSib.nodeType === 3 &&\n prevSib.nodeType === 3){\n\n prevSib.textContent += nextSib.textContent;\n marker.parentNode.removeChild(nextSib);\n }\n marker.parentNode.removeChild(marker);\n } else if(marker.classList.contains(\"EPUBJS-CFI-MARKER\")) {\n // Remove only elements added as markers\n marker.parentNode.removeChild(marker);\n }\n\n};\n\nEpubCFI.prototype.findParent = function(cfi, _doc) {\n var doc = _doc || document,\n element = doc.getElementsByTagName('html')[0],\n children = Array.prototype.slice.call(element.children),\n num, index, part, sections,\n text, textBegin, textEnd;\n\n if(typeof cfi === 'string') {\n cfi = this.parse(cfi);\n }\n\n sections = cfi.steps.slice(0); // Clone steps array\n if(!sections.length) {\n return doc.getElementsByTagName('body')[0];\n }\n\n while(sections && sections.length > 0) {\n part = sections.shift();\n // Find textNodes Parent\n if(part.type === \"text\") {\n text = element.childNodes[part.index];\n element = text.parentNode || element;\n // Find element by id if present\n } else if(part.id){\n element = doc.getElementById(part.id);\n // Find element in parent\n }else{\n element = children[part.index];\n }\n // Element can't be found\n if(typeof element === \"undefined\") {\n console.error(\"No Element For\", part, cfi.str);\n return false;\n }\n // Get current element children and continue through steps\n children = Array.prototype.slice.call(element.children);\n }\n\n return element;\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.steps.length; i++) {\n if(!cfiTwo.steps[i]) {\n return 1;\n }\n if(cfiOne.steps[i].index > cfiTwo.steps[i].index) {\n return 1;\n }\n if(cfiOne.steps[i].index < cfiTwo.steps[i].index) {\n return -1;\n }\n // Otherwise continue checking\n }\n\n // All steps in First present in Second\n if(cfiOne.steps.length < cfiTwo.steps.length) {\n return -1;\n }\n\n // Compare the charecter offset of the text node\n if(cfiOne.characterOffset > cfiTwo.characterOffset) {\n return 1;\n }\n if(cfiOne.characterOffset < cfiTwo.characterOffset) {\n return -1;\n }\n\n // CFI's are equal\n return 0;\n};\n\nEpubCFI.prototype.generateCfiFromHref = function(href, book) {\n var uri = URI(href);\n var path = uri.path();\n var fragment = uri.fragment();\n var spinePos = book.spineIndexByURL[path];\n var loaded;\n var deferred = new RSVP.defer();\n var epubcfi = new EpubCFI();\n var spineItem;\n\n if(typeof spinePos !== \"undefined\"){\n spineItem = book.spine[spinePos];\n loaded = book.loadXml(spineItem.url);\n loaded.then(function(doc){\n var element = doc.getElementById(fragment);\n var cfi;\n cfi = epubcfi.generateCfiFromElement(element, spineItem.cfiBase);\n deferred.resolve(cfi);\n });\n }\n\n return deferred.promise;\n};\n\nEpubCFI.prototype.generateCfiFromTextNode = function(anchor, offset, base) {\n var parent = anchor.parentNode;\n var steps = this.pathTo(parent);\n var path = this.generatePathComponent(steps);\n var index = 1 + (2 * Array.prototype.indexOf.call(parent.childNodes, anchor));\n return \"epubcfi(\" + base + \"!\" + path + \"/\"+index+\":\"+(offset || 0)+\")\";\n};\n\nEpubCFI.prototype.generateCfiFromRangeAnchor = function(range, base) {\n var anchor = range.anchorNode;\n var offset = range.anchorOffset;\n return this.generateCfiFromTextNode(anchor, offset, base);\n};\n\nEpubCFI.prototype.generateCfiFromRange = function(range, base) {\n var start, startElement, startSteps, startPath, startOffset, startIndex;\n var end, endElement, endSteps, endPath, endOffset, endIndex;\n\n start = range.startContainer;\n\n if(start.nodeType === 3) { // text node\n startElement = start.parentNode;\n //startIndex = 1 + (2 * Array.prototype.indexOf.call(startElement.childNodes, start));\n startIndex = 1 + (2 * core.indexOfTextNode(start));\n startSteps = this.pathTo(startElement);\n } else if(range.collapsed) {\n return this.generateCfiFromElement(start, base); // single element\n } else {\n startSteps = this.pathTo(start);\n }\n\n startPath = this.generatePathComponent(startSteps);\n startOffset = range.startOffset;\n\n if(!range.collapsed) {\n end = range.endContainer;\n\n if(end.nodeType === 3) { // text node\n endElement = end.parentNode;\n // endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));\n endIndex = 1 + (2 * core.indexOfTextNode(end));\n\n endSteps = this.pathTo(endElement);\n } else {\n endSteps = this.pathTo(end);\n }\n\n endPath = this.generatePathComponent(endSteps);\n endOffset = range.endOffset;\n\n // Remove steps present in startPath\n endPath = endPath.replace(startPath, '');\n\n if (endPath.length) {\n endPath = endPath + \"/\";\n }\n\n return \"epubcfi(\" + base + \"!\" + startPath + \"/\" + startIndex + \":\" + startOffset + \",\" + endPath + endIndex + \":\" + endOffset + \")\";\n\n } else {\n return \"epubcfi(\" + base + \"!\" + startPath + \"/\"+ startIndex +\":\"+ startOffset +\")\";\n }\n};\n\nEpubCFI.prototype.generateXpathFromSteps = function(steps) {\n var xpath = [\".\", \"*\"];\n\n steps.forEach(function(step){\n var position = step.index + 1;\n\n if(step.id){\n xpath.push(\"*[position()=\" + position + \" and @id='\" + step.id + \"']\");\n } else if(step.type === \"text\") {\n xpath.push(\"text()[\" + position + \"]\");\n } else {\n xpath.push(\"*[\" + position + \"]\");\n }\n });\n\n return xpath.join(\"/\");\n};\n\nEpubCFI.prototype.generateQueryFromSteps = function(steps) {\n var query = [\"html\"];\n\n steps.forEach(function(step){\n var position = step.index + 1;\n\n if(step.id){\n query.push(\"#\" + step.id);\n } else if(step.type === \"text\") {\n // unsupported in querySelector\n // query.push(\"text()[\" + position + \"]\");\n } else {\n query.push(\"*:nth-child(\" + position + \")\");\n }\n });\n\n return query.join(\">\");\n};\n\n\nEpubCFI.prototype.generateRangeFromCfi = function(cfi, _doc) {\n var doc = _doc || document;\n var range = doc.createRange();\n var lastStep;\n var xpath;\n var startContainer;\n var textLength;\n var query;\n var startContainerParent;\n\n if(typeof cfi === 'string') {\n cfi = this.parse(cfi);\n }\n\n // check spinePos\n if(cfi.spinePos === -1) {\n // Not a valid CFI\n return false;\n }\n\n // Get the terminal step\n lastStep = cfi.steps[cfi.steps.length-1];\n\n if(typeof document.evaluate != 'undefined') {\n xpath = this.generateXpathFromSteps(cfi.steps);\n startContainer = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n } else {\n // Get the query string\n query = this.generateQueryFromSteps(cfi.steps);\n // Find the containing element\n startContainerParent = doc.querySelector(query);\n // Find the text node within that element\n if(startContainerParent && lastStep.type == \"text\") {\n startContainer = startContainerParent.childNodes[lastStep.index];\n }\n }\n\n if(!startContainer) {\n return null;\n }\n\n if(startContainer && cfi.characterOffset >= 0) {\n textLength = startContainer.length;\n\n if(cfi.characterOffset < textLength) {\n range.setStart(startContainer, cfi.characterOffset);\n range.setEnd(startContainer, textLength );\n } else {\n console.debug(\"offset greater than length:\", cfi.characterOffset, textLength);\n range.setStart(startContainer, textLength - 1 );\n range.setEnd(startContainer, textLength );\n }\n } else if(startContainer) {\n range.selectNode(startContainer);\n }\n // doc.defaultView.getSelection().addRange(range);\n return range;\n};\n\nEpubCFI.prototype.isCfiString = function(target) {\n if(typeof target === \"string\" &&\n target.indexOf(\"epubcfi(\") === 0) {\n return true;\n }\n\n return false;\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\nRendition.prototype.triggerViewEvent = function(e){\n this.trigger(e.type, e);\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 this.selectedRange = this.window.getSelection();\n this.trigger(\"selected\", this.selectedRange);\n }.bind(this), 500);\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"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 531dcc7..f8f1b20 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -10,15 +10,27 @@ var onError = function (err) { }; var server = require("./tools/serve.js"); -var browserify = require('browserify'); -var watchify = require('watchify'); var source = require('vinyl-source-stream'); var buffer = require('vinyl-buffer'); var sourcemaps = require('gulp-sourcemaps'); var size = require('gulp-size'); -var URI = require('urijs'); -var mochify = require('mochify'); + +var webpack = require("webpack"); +var WebpackDevServer = require("webpack-dev-server"); +var webpackConfig = require("./webpack.config"); + +var Server = require('karma').Server; + +// modify some webpack config options +var watchConfig = Object.create(webpackConfig); +watchConfig.devtool = "sourcemap"; +watchConfig.debug = true; +watchConfig.watch = true; + +// create a single instance of the compiler to allow caching +var watchCompiler = webpack(watchConfig); + // https://github.com/mishoo/UglifyJS2/pull/265 // uglify.AST_Node.warn_function = function() {}; @@ -29,9 +41,20 @@ gulp.task('lint', function() { .pipe(jshint.reporter('default')); }); -// set up the browserify instance on a task basis -gulp.task('bundle', function () { - return bundle('epub.js'); +gulp.task('bundle', function (cb) { + webpack(webpackConfig, function(err, stats) { + if(err) { + throw new gutil.PluginError("webpack", err); + } + + gutil.log("[webpack-bundle]", stats.toString({ + colors: true, + chunks: true + })); + + cb(); + + }); }); // Minify JS @@ -52,97 +75,75 @@ gulp.task('minify', ['bundle'], function(){ // Watch Our Files gulp.task('watch', function(cb) { - bundle('epub.js', cb); + watchCompiler(watchConfig, function(err, stats) { + if(err) { + throw new gutil.PluginError("webpack", err); + } + + gutil.log("[webpack-watch]", stats.toString({ + colors: true, + chunks: false + })); + + }); + }); -gulp.task('serve', function(cb) { +gulp.task('test', function(done) { + new Server({ + configFile: __dirname + '/karma.conf.js', + singleRun: false + }, done).start(); +}); + +gulp.task('test:once', function(done) { + new Server({ + configFile: __dirname + '/karma.conf.js', + singleRun: true + }, done).start(); +}); + +gulp.task("serve", function(callback) { server(); - bundle('epub.js', cb); -}); + /* + var serverConfig = Object.create(webpackConfig); -gulp.task('serve:no-watch', function(cb) { - server(); -}); + serverConfig.devtool = "eval"; + serverConfig.debug = true; + serverConfig.watch = true; -gulp.task('test', function(cb) { - mochify('./test/*.js', { - reporter: 'spec', - transform: 'brfs', - "web-security": false, - "webSecurityEnabled": false, - // "localUrlAccess": true, - watch: true, - wd: false, - debug: false - }) - .bundle(); -}); + // Start a webpack-dev-server + new WebpackDevServer(webpack(serverConfig), { + stats: { + colors: true, + chunks: false + } + }).listen(8080, "localhost", function(err) { + if(err) throw new gutil.PluginError("webpack-dev-server", err); + gutil.log("[webpack-dev-server]", "http://localhost:8080/webpack-dev-server/examples/index.html"); + }); + */ - -gulp.task('test:once', function(cb) { - mochify('./test/*.js', { - reporter: 'spec', - transform: 'brfs', - "web-security": false, - "webSecurityEnabled": false, - // "localUrlAccess": true, - watch: false, - wd: false, - debug: false - }) - .bundle(); }); // Default gulp.task('default', ['lint', 'bundle']); - -function bundle(file, watch) { - var opt = { - entries: ['src/'+file], - standalone: 'ePub', - debug : true - }; - - var b = browserify(opt); - - // Expose epub module for require - b.require('./src/'+file, {expose: 'epub'}); - - // Keep JSZip library seperate, - // must be loaded to use Unarchive or `require` will throw an error - b.external('jszip'); - - b.external('xmldom'); - - // Ignore optional URI libraries - var urijsPath = URI(require.resolve('urijs')); - ['./punycode.js', './IPv6.js'].forEach(function(lib) { - var libPath = URI(lib).absoluteTo(urijsPath).toString(); - b.ignore(libPath); - }); - - // watchify() if watch requested, otherwise run browserify() once - var bundler = watch ? watchify(b) : b; - - function rebundle() { - var stream = bundler.bundle(); - return stream - .on('error', gutil.log) - .pipe(source(file)) - .pipe(buffer()) - .pipe(sourcemaps.init({loadMaps: true})) - .pipe(sourcemaps.write('./')) - .pipe(size({ showFiles: true })) - .pipe(gulp.dest('./dist/')); +function bundle(done) { + if (!done) { + webpackConfig.watch = true; + } else { + webpackConfig.watch = false; } - // listen for an update and run rebundle - bundler.on('update', function() { - rebundle(); - gutil.log('Rebundle...'); - }); + watchCompiler(watchConfig, function(err, stats) { + if(err) throw new gutil.PluginError("webpack", err); + gutil.log("[webpack]", stats.toString({ + colors: true, + chunks: false + })); - // run it once the first time buildScript is called - return rebundle(); + done && done(); + + }); } diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..ff030f4 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,102 @@ +// Karma configuration +// Generated on Wed Oct 26 2016 10:56:59 GMT+0200 (CEST) + +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'], + + + // list of files / patterns to load in the browser + files: [ + {pattern: 'test/*.js', watched: false}, + // {pattern: 'test/**/*.js', watched: false} + {pattern: 'test/fixtures/**/*', watched: false, included: false, served: true}, + + {pattern: 'node_modules/jszip/dist/jszip.js', watched: false, included: true, served: true}, + + ], + + // list of files to exclude + exclude: [ + ], + + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + // add webpack as preprocessor + 'test/*.js': ['webpack', 'sourcemap'], + // 'test/**/*.js': ['webpack', 'sourcemap'] + }, + + webpack:{ + externals: { + "jszip": "JSZip", + "xmldom": "xmldom" + }, + devtool: 'inline-source-map' + }, + + webpackMiddleware: { + stats: 'errors-only' + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['mocha'], + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_ERROR, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['PhantomJS'], + + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity, + + proxies: { + "/fixtures/": "/base/test/fixtures/" + }, + + client: { + config: { + browserConsoleLogOptions: true + }, + captureConsole: true, + mocha: { + reporter: 'html' + // bail: true + } + } + + }) +} diff --git a/package.json b/package.json index e92344f..43d94b9 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,13 @@ "test": "test" }, "scripts": { - "test": "gulp test" + "test": "./node_modules/.bin/karma start --single-run --browsers PhantomJS", + "start": "webpack-dev-server --inline --hot", + "build" : "gulp minify" }, "author": "fchasen@gmail.com", "license": "MIT", "devDependencies": { - "brfs": "^1.4.1", - "browserify": "^13.0.0", "colors": "^1.1.2", "connect": "^3.0.1", "express": "^4.5.1", @@ -29,19 +29,25 @@ "gulp-uglify": "^1.5.3", "gulp-util": "^3.0.0", "jquery": "^2.1.4", - "mochify": "^2.14.3", + "jshint": "^2.9.3", + "karma": "^1.3.0", + "karma-mocha": "^1.2.0", + "karma-mocha-reporter": "^2.2.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^1.8.0", + "mocha-loader": "^1.0.0", "morgan": "^1.1.1", "optimist": "^0.6.1", - "phantomjs": "^2.1.3", "portfinder": "^1.0.2", - "qunitjs": "^1.14.0", + "raw-loader": "^0.5.1", "serve-static": "^1.3.1", - "sinon": "^1.17.2", "uglify": "^0.1.5", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.1.0", - "watchify": "^3.6.1", - "jshint": "^2.9.3" + "webpack": "^1.13.2", + "webpack-dev-middleware": "^1.8.4", + "webpack-dev-server": "^1.16.2" }, "dependencies": { "jszip": "^3.1.1", diff --git a/src/epub.js b/src/epub.js index 1e0c2a5..550d9a8 100644 --- a/src/epub.js +++ b/src/epub.js @@ -28,7 +28,6 @@ ePub.register = { // Default Views ePub.register.view("iframe", require('./managers/views/iframe')); -// ePub.register.view("inline", require('./managers/views/inline')); // Default View Managers ePub.register.manager("single", require('./managers/default')); diff --git a/src/request.js b/src/request.js index b1eb004..0803bb0 100644 --- a/src/request.js +++ b/src/request.js @@ -77,11 +77,16 @@ function request(url, type, withCredentials, headers) { function handler() { if (this.readyState === XMLHttpRequest.DONE) { + var responseXML = false; - if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls + if(this.responseType === '' || this.responseType === "document") { + responseXML = this.responseXML; + } + + if (this.status === 200 || responseXML ) { //-- Firefox is reporting 0 for blob urls var r; - if (!this.response && !this.responseXML) { + if (!this.response && !responseXML) { deferred.reject({ status: this.status, message : "Empty Response", @@ -100,8 +105,7 @@ function request(url, type, withCredentials, headers) { return deferred.promise; } - if((this.responseType == '' || this.responseType == 'document') - && this.responseXML){ + if(responseXML){ r = this.responseXML; } else if(core.isXml(type)){ diff --git a/test/epub.js b/test/epub.js index f3e5365..326ff28 100644 --- a/test/epub.js +++ b/test/epub.js @@ -1,14 +1,16 @@ var assert = require('assert'); -var sinon = require('sinon'); -var fs = require('fs'); +// var sinon = require('sinon'); describe('ePub', function() { var ePub = require('../src/epub'); var server; before(function(){ - var packageContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/package.opf', 'utf8'); - var tocContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/toc.xhtml', 'utf8'); + /* + // var packageContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/package.opf', 'utf8'); + // var tocContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/toc.xhtml', 'utf8'); + var packageContents = require('raw!./fixtures/moby-dick/OPS/package.opf'); + var tocContents = require('raw!./fixtures/moby-dick/OPS/toc.xhtml'); server = sinon.fakeServer.create(); server.autoRespond = true; @@ -20,20 +22,33 @@ describe('ePub', function() { server.respondWith("moby-dick/OPS/toc.xhtml", [200, { "Content-Type": "application/xhtml+xml" }, tocContents]); - + */ }); after(function(){ - server.restore(); + // server.restore(); }); it('should open a epub', function(done) { - var book = ePub("moby-dick/OPS/package.opf"); + var book = ePub("/fixtures/alice/OPS/package.opf"); book.opened.then(function(){ assert.equal( book.isOpen, true, "book is opened" ); - assert.equal( book.url, "moby-dick/OPS/package.opf", "book url is passed to new Book" ); + assert.equal( book.url, "http://localhost:9876/fixtures/alice/OPS/package.opf", "book url is passed to new Book" ); done(); }); }); + + it('should open a archived epub', function(done) { + var book = ePub("/fixtures/alice.epub"); + + assert(typeof (JSZip) !== "undefined", "JSZip is present" ); + + book.opened.then(function(){ + assert.equal( book.isOpen, true, "book is opened" ); + assert.equal( book.url, "/", "book url is empty as book is archived" ); + done(); + }); + }); + }); diff --git a/test/epubcfi.js b/test/epubcfi.js index df72d00..7af3dac 100644 --- a/test/epubcfi.js +++ b/test/epubcfi.js @@ -1,5 +1,5 @@ var assert = require('assert'); -var fs = require('fs'); +// var fs = require('fs'); if (typeof DOMParser === "undefined") { global.DOMParser = require('xmldom').DOMParser; } @@ -136,7 +136,9 @@ describe('EpubCFI', function() { describe('#fromNode()', function() { var base = "/6/4[chap01ref]"; - var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); + // var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); + var contents = require('raw!./fixtures/chapter1-highlights.xhtml'); + // var serializer = new XMLSerializer(); // var doc = serializer.serializeToString(contents); var doc = new DOMParser().parseFromString(contents, "application/xhtml+xml"); @@ -183,13 +185,17 @@ describe('EpubCFI', function() { describe('#fromRange()', function() { var base = "/6/4[chap01ref]"; - var contentsClean = fs.readFileSync(__dirname + '/fixtures/chapter1.xhtml', 'utf8'); + // var contentsClean = fs.readFileSync(__dirname + '/fixtures/chapter1.xhtml', 'utf8'); + var contentsClean = require('raw!./fixtures/chapter1.xhtml'); + var doc = new DOMParser().parseFromString(contentsClean, "application/xhtml+xml"); - var contentsHighlights = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); + // var contentsHighlights = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); + var contentsHighlights = require('raw!./fixtures/chapter1-highlights.xhtml'); var docHighlights = new DOMParser().parseFromString(contentsHighlights, "application/xhtml+xml"); - var highlightContents = fs.readFileSync(__dirname + '/fixtures/highlight.xhtml', 'utf8'); + // var highlightContents = fs.readFileSync(__dirname + '/fixtures/highlight.xhtml', 'utf8'); + var highlightContents = require('raw!./fixtures/highlight.xhtml'); var docHighlightsAlice = new DOMParser().parseFromString(highlightContents, "application/xhtml+xml"); it('get a cfi from a collapsed range', function() { @@ -295,7 +301,8 @@ describe('EpubCFI', function() { describe('#toRange()', function() { var base = "/6/4[chap01ref]"; - var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); + // var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); + var contents = require('raw!./fixtures/chapter1-highlights.xhtml'); var doc = new DOMParser().parseFromString(contents, "application/xhtml+xml"); // var serializer = new XMLSerializer(); diff --git a/test/fixtures/alice.epub b/test/fixtures/alice.epub new file mode 100644 index 0000000..9ac6ba3 Binary files /dev/null and b/test/fixtures/alice.epub differ diff --git a/test/fixtures/alice/META-INF/container.xml b/test/fixtures/alice/META-INF/container.xml new file mode 100644 index 0000000..f9a37a7 --- /dev/null +++ b/test/fixtures/alice/META-INF/container.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/fixtures/alice/OPS/chapter_001.xhtml b/test/fixtures/alice/OPS/chapter_001.xhtml new file mode 100644 index 0000000..26ac098 --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_001.xhtml @@ -0,0 +1,139 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

Down The Rabbit-Hole

+ +
+ Illo1 +
+ +

Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do. Once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice, "without pictures or conversations?"

+ +

So she was considering in her own mind (as well as she could, for the day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

+ +
+ Illo2 +
+ +

There was nothing so very remarkable in that, nor did Alice think it so + very much out of the way to hear the Rabbit + say to itself, "Oh dear! Oh dear! I shall be too late!" But when the Rabbit actually + took a watch out of its waistcoat-pocket and looked at it and then hurried on, Alice + started to her feet, for it flashed across her mind that she had never before seen a + rabbit with either a waistcoat-pocket, or a watch to take out of it, and, burning with + curiosity, she ran across the field after it and was just in time to see it pop down a + large rabbit-hole, under the hedge. In another moment, down went Alice after it!

+ +

The rabbit-hole went straight on like a tunnel for some way and then dipped suddenly + down, so suddenly that Alice had not a moment to think about stopping herself before + she found herself falling down what seemed to be a very deep well.

+ +

Either the well was very deep, or she fell very slowly, for she had plenty of time, + as she went down, to look about her. First, she tried to make out what she was coming + to, but it was too dark to see anything; then she looked at the sides of the well and + noticed that they were filled with cupboards and book-shelves; here and there she saw + maps and pictures hung upon pegs. She + took down a jar from one of the shelves as she passed. It was labeled "ORANGE + MARMALADE," but, to her great disappointment, it was empty; she did not like to drop + the jar, so managed to put it into one of the cupboards as she fell past it.

+ +

Down, down, down! Would the fall never come to an end? There was nothing else to do, + so Alice soon began talking to herself. "Dinah'll miss me very much to-night, I should + think!" (Dinah was the cat.) "I hope they'll remember her saucer of milk at tea-time. + Dinah, my dear, I wish you were down here with me!" Alice felt that she was dozing off, + when suddenly, thump! thump! down she came upon a heap of sticks and dry leaves, and + the fall was over.

+ +

Alice was not a bit hurt, and she jumped up in a moment. She looked up, but it was + all dark overhead; before her was another long passage and the White Rabbit was still + in sight, hurrying down it. There was not a moment to be lost. Away went Alice like the + wind and was just in time to hear it say, as it turned a corner, "Oh, my ears and + whiskers, how late it's getting!" She was close behind it when she turned the corner, + but the Rabbit was no longer to be seen.

+ +

She found herself in a long, low hall, which was lit up by a row of lamps hanging + from the roof. There were doors all 'round the hall, but they were all locked; and when + Alice had been all the way down one side and up the other, trying every door, she + walked sadly down the middle, wondering how she was ever to get out again.

+ +
+ Illo3 +
+ +

Suddenly she came upon a little table, all made of solid glass. There was nothing on + it but a tiny golden key, and Alice's first idea was that this might belong to one of + the doors of the hall; but, alas! either the locks were too large, or the key was too + small, but, at any rate, it would not open any of them. However, on the second time + 'round, she came upon a low curtain she had not noticed before, and behind it was a + little door about fifteen inches high. She tried the little golden key in the lock, and + to her great delight, it fitted!

+ +

Alice opened the door and found that it led into a small passage, not much larger + than a rat-hole; she knelt down and looked along the passage into the loveliest garden + you ever saw. How she longed to get out of that dark hall and wander about among those + beds of bright flowers and those cool fountains, but she could not even get her head + through the doorway. "Oh," said Alice, "how I wish I could shut up like a telescope! I + think I could, if I only knew how to begin."

+ +

Alice went back to the table, half hoping she might find another key on it, or at + any rate, a book of rules for shutting people up like telescopes. This time she found a little bottle on it ("which + certainly was not here before," said Alice), and tied 'round the neck of the bottle was + a paper label, with the words "DRINK ME" beautifully printed on it in large + letters.

+ +

"No, I'll look first," she said, "and see whether it's marked 'poison' or + not," for she had never forgotten that, if you drink from a bottle marked "poison," it + is almost certain to disagree with you, sooner or later. However, this bottle was + not marked "poison," so Alice ventured to taste it, and, finding it very nice + (it had a sort of mixed flavor of cherry-tart, custard, pineapple, roast turkey, toffy + and hot buttered toast), she very soon finished it off.

+ +

"What a curious feeling!" said Alice. "I must be shutting up like a telescope!"

+ +

And so it was indeed! She was now only ten inches high, and her face brightened up + at the thought that she was now the right size for going through the little door into + that lovely garden.

+ +

After awhile, finding that nothing more happened, she decided on going into the + garden at once; but, alas for poor Alice! When she got to the door, she found she had + forgotten the little golden key, and when she went back to the table for it, she found + she could not possibly reach it: she could see it quite plainly through the glass and + she tried her best to climb up one of the legs of the table, but it was too slippery, + and when she had tired herself out with trying, the poor little thing sat down and + cried.

+ +

"Come, there's no use in crying like that!" said Alice to herself rather sharply. "I + advise you to leave off this minute!" + She generally gave herself very good advice (though she very seldom followed it), and + sometimes she scolded herself so severely as to bring tears into her eyes.

+ +

Soon her eye fell on a little glass box that was lying under the table: she opened + it and found in it a very small cake, on which the words "EAT ME" were beautifully + marked in currants. "Well, I'll eat it," said Alice, "and if it makes me grow larger, I + can reach the key; and if it makes me grow smaller, I can creep under the door: so + either way I'll get into the garden, and I don't care which happens!"

+ +

She ate a little bit and said anxiously to herself, "Which way? Which way?" holding + her hand on the top of her head to feel which way she was growing; and she was quite + surprised to find that she remained the same size. So she set to work and very soon + finished off the cake.

+ +
+ Illo4 +
+ +

+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_002.xhtml b/test/fixtures/alice/OPS/chapter_002.xhtml new file mode 100644 index 0000000..3babe69 --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_002.xhtml @@ -0,0 +1,141 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

The Pool Of Tears

+ +

Curiouser and curiouser!" cried Alice (she was so much + surprised that for the moment she quite forgot how to speak good English). "Now I'm + opening out like the largest telescope that ever was! Good-by, feet! Oh, my poor little + feet, I wonder who will put on your shoes and stockings for you now, dears? I shall be + a great deal too far off to trouble myself about you."

+ +

Just at this moment her head struck against the roof of the hall; in fact, she was + now rather more than nine feet high, and she at once took up the little golden key and + hurried off to the garden door.

+ +

Poor Alice! It was as much as she could do, lying down on one side, to look through + into the garden with one eye; but to get through was more hopeless than ever. She sat + down and began to cry again.

+ +

She went on shedding gallons of tears, until there was a large pool all 'round her + and reaching half down the hall.

+ +

After a time, she heard a little pattering of feet in the distance and she hastily + dried her eyes to see what was coming. It was the White Rabbit returning, splendidly + dressed, with a pair of white kid-gloves in one hand and a large fan in the other. + He came trotting along in a great + hurry, muttering to himself, "Oh! the Duchess, the Duchess! Oh! won't she be + savage if I've kept her waiting!"

+ +
+ Illo5 +
+ +

When the Rabbit came near her, Alice began, in a low, timid voice, "If you please, + sir—" The Rabbit started violently, dropped the white kid-gloves and the fan and + skurried away into the darkness as hard as he could go.

+ +

Alice took up the fan and gloves and she kept fanning herself all the time she went + on talking. "Dear, dear! How queer everything is to-day! And yesterday things went on + just as usual. Was I the same when I got up this morning? But if I'm not the + same, the next question is, 'Who in the world am I?' Ah, that's the great + puzzle!"

+ +

As she said this, she looked down at her hands and was surprised to see that she had + put on one of the Rabbit's little white kid-gloves while she was talking. "How + can I have done that?" she thought. "I must be growing small again." She got up + and went to the table to measure herself by it and found that she was now about two + feet high and was going on shrinking + rapidly. She soon found out that the cause of this was the fan she was holding and she + dropped it hastily, just in time to save herself from shrinking away altogether.

+ +

"That was a narrow escape!" said Alice, a good deal frightened at the sudden + change, but very glad to find herself still in existence. "And now for the garden!" And + she ran with all speed back to the little door; but, alas! the little door was shut + again and the little golden key was lying on the glass table as before. "Things are + worse than ever," thought the poor child, "for I never was so small as this before, + never!"

+ +

As she said these words, her foot slipped, and in another moment, splash! she was up + to her chin in salt-water. Her first idea was that she had somehow fallen into the sea. + However, she soon made out that she was in the pool of tears which she had wept when + she was nine feet high.

+ +
+ Illo6 +
+ +

Just then she heard something splashing about in the pool a little way off, and she + swam nearer to see what it was: she soon made out that it was only a mouse that had + slipped in like herself.

+ +

"Would it be of any use, now," thought Alice, "to speak to this mouse? Everything is + so out-of-the-way down here that I should think very likely it can talk; at any rate, + there's no harm in trying." So she began, "O Mouse, do you know the way out of this + pool? I am very tired of swimming about here, O Mouse!" The Mouse looked at her rather + inquisitively and seemed to her to wink with one of its little eyes, but it said + nothing.

+ +

"Perhaps it doesn't understand English," thought Alice. "I dare say it's a French + mouse, come over with William the Conqueror." So she began again: "Où est ma + chatte?" which was the first sentence in her French lesson-book. The Mouse gave a + sudden leap out of the water and seemed to quiver all over with fright. "Oh, I beg your + pardon!" cried Alice hastily, afraid that she had hurt the poor animal's feelings. "I + quite forgot you didn't like cats."

+ +

"Not like cats!" cried the Mouse in a shrill, passionate voice. "Would you + like cats, if you were me?"

+ +

"Well, perhaps not," said Alice in a soothing tone; "don't be angry about it. And + yet I wish I could show you our cat Dinah. I think you'd take a fancy to cats, if you + could only see her. She is such a dear, quiet thing." The Mouse was bristling all over + and she felt certain it must be really offended. "We won't talk about her any more, if + you'd rather not."

+ +

"We, indeed!" cried the Mouse, who was trembling down to the end of its tail. "As if + I would talk on such a subject! Our family always hated cats—nasty, low, vulgar things! Don't + let me hear the name again!"

+ +
+ Alice at the Mad Tea Party. +
+

Alice at the Mad Tea Party.

+
+
+ +

"I won't indeed!" said Alice, in a great hurry to change the subject of + conversation. "Are you—are you fond—of—of dogs? There is such a nice + little dog near our house, I should like to show you! It kills all the rats + and—oh, dear!" cried Alice in a sorrowful tone. "I'm afraid I've offended it + again!" For the Mouse was swimming away from her as hard as it could go, and making + quite a commotion in the pool as it went.

+ +

So she called softly after it, "Mouse dear! Do come back again, and we won't talk + about cats, or dogs either, if you don't like them!" When the Mouse heard this, it + turned 'round and swam slowly back to her; its face was quite pale, and it said, in a + low, trembling voice, "Let us get to the shore and then I'll tell you my history and + you'll understand why it is I hate cats and dogs."

+ +

It was high time to go, for the pool was getting quite crowded with the birds and + animals that had fallen into it; there were a Duck and a Dodo, a Lory and an Eaglet, + and several other curious creatures. Alice led the way and the whole party swam to the + shore.

+ +
+ Illo7 +
+ +

+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_003.xhtml b/test/fixtures/alice/OPS/chapter_003.xhtml new file mode 100644 index 0000000..6b80493 --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_003.xhtml @@ -0,0 +1,177 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

+ + A Caucus-Race And A Long Tale +

+ +

They were indeed a queer-looking party that assembled on the + bank—the birds with draggled feathers, the animals with their fur clinging close + to them, and all dripping wet, cross and uncomfortable.

+ +
+ Illo8 +
+ +

The first question, of course, was how to get dry again. They had a consultation + about this and after a few minutes, it seemed quite natural to Alice to find herself + talking familiarly with them, as if she had known them all her life.

+ +

At last the Mouse, who seemed to be a person of some authority among them, called out, "Sit down, all of you, and listen + to me! I'll soon make you dry enough!" They all sat down at once, in a large + ring, with the Mouse in the middle.

+ +

"Ahem!" said the Mouse with an important air. "Are you all ready? This is the driest + thing I know. Silence all 'round, if you please! 'William the Conqueror, whose cause + was favored by the pope, was soon submitted to by the English, who wanted leaders, and + had been of late much accustomed to usurpation and conquest. Edwin and Morcar, the + Earls of Mercia and Northumbria'—"

+ +

"Ugh!" said the Lory, with a shiver.

+ +

"—'And even Stigand, the patriotic archbishop of Canterbury, found it + advisable'—"

+ +

"Found what?" said the Duck.

+ +

"Found it," the Mouse replied rather crossly; "of course, you know what 'it' + means."

+ +

"I know what 'it' means well enough, when I find a thing," said the Duck; + "it's generally a frog or a worm. The question is, what did the archbishop find?"

+ +

The Mouse did not notice this question, but hurriedly went on, "'—found it + advisable to go with Edgar Atheling to meet William and offer him the crown.'—How + are you getting on now, my dear?" it continued, turning to Alice as it spoke.

+ +

"As wet as ever," said Alice in a melancholy tone; "it doesn't seem to dry me at + all."

+ +

"In that case," said the Dodo solemnly, rising to its feet, "I move that the meeting + adjourn, for the immediate adoption of more energetic remedies—"

+ +

"Speak English!" said the Eaglet. "I don't know the meaning of half those long + words, and, what's more, I don't believe you do either!"

+ +

"What I was going to say," said the Dodo in an offended tone, "is that the best + thing to get us dry would be a Caucus-race."

+ +

"What is a Caucus-race?" said Alice.

+ +
+ Illo9 +
+ +

"Why," said the Dodo, "the best way to explain it is to do it." First it marked out + a race-course, in a sort of circle, and then all the party were placed along the + course, here and there. There was no "One, two, three and away!" but they began running + when they liked and left off when they liked, so that it was not easy to know when the + race was over. However, when they had been running half an hour or so and were quite + dry again, the Dodo suddenly called out, "The race is over!" and they all crowded + 'round it, panting and asking, "But who has won?"

+ +

This question the Dodo could not answer without a great deal of thought. At last it + said, "Everybody has won, and all must have prizes."

+ +

"But who is to give the prizes?" quite a chorus of voices asked.

+ +

"Why, she, of course," said the Dodo, pointing to Alice with one finger; and + the whole party at once crowded 'round her, calling out, in a confused way, "Prizes! + Prizes!"

+ +

Alice had no idea what to do, and in despair she put her hand into her pocket and + pulled out a box of comfits (luckily the salt-water had not got into it) and handed + them 'round as prizes. There was exactly one a-piece, all 'round.

+ +

The next thing was to eat the comfits; this caused some noise and confusion, as the + large birds complained that they could not taste theirs, and the small ones choked and + had to be patted on the back. However, it was over at last and they sat down again in a + ring and begged the Mouse to tell them something more.

+ +

"You promised to tell me your history, you know," said Alice, "and why it is you + hate—C and D," she added in a whisper, half afraid that it would be offended + again.

+ +

"Mine is a long and a sad tale!" said the Mouse, turning to Alice and sighing.

+ +

"It is a long tail, certainly," said Alice, looking down with wonder at the + Mouse's tail, "but why do you call it sad?" And she kept on puzzling about it while the + Mouse was speaking, so that her idea of the tale was something like this:

+ +
+ "Fury said to
a mouse, + That
he met in the
house, + 'Let
us both go
to law: + I
will prosecute
you.—
Come, I'll
+ take no denial:
We must have
the trial;
+ For really
this + morning
I've
nothing
to do.'
Said the
mouse to
+ the cur,
'Such a
trial, dear
+ sir, With
no jury
+ or judge,
would
+ be wasting
our
+ breath.'
'I'll be
judge,
I'll be
jury,'
said
cunning
old
Fury;
'I'll
try
+ the
whole
+ cause,
and
+ condemn
you to
+ death.'"
+
+ +

"You are not attending!" said the + Mouse to Alice, severely. "What are you thinking of?"

+ +

"I beg your pardon," said Alice very humbly, "you had got to the fifth bend, I + think?"

+ +

"You insult me by talking such nonsense!" said the Mouse, getting up and walking + away.

+ +

"Please come back and finish your story!" Alice called after it. And the others all + joined in chorus, "Yes, please do!" But the Mouse only shook its head impatiently and + walked a little quicker.

+ +

"I wish I had Dinah, our cat, here!" said Alice. This caused a remarkable sensation + among the party. Some of the birds hurried off at once, and a Canary called out in a + trembling voice, to its children, "Come away, my dears! It's high time you were all in + bed!" On various pretexts they all moved off and Alice was soon left alone.

+ +

"I wish I hadn't mentioned Dinah! Nobody seems to like her down here and I'm sure + she's the best cat in the world!" Poor Alice began to cry again, for she felt very + lonely and low-spirited. In a little while, however, she again heard a little pattering + of footsteps in the distance and she looked up eagerly.

+ +
+ Illo10 +
+

+ +
+ Illo11 +
+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_004.xhtml b/test/fixtures/alice/OPS/chapter_004.xhtml new file mode 100644 index 0000000..babbb4e --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_004.xhtml @@ -0,0 +1,159 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

+ The Rabbit Sends In A Little Bill

+ +

It was the White Rabbit, trotting slowly back again and + looking anxiously about as it went, as if it had lost something; Alice heard it + muttering to itself, "The Duchess! The Duchess! Oh, my dear paws! Oh, my fur and + whiskers! She'll get me executed, as sure as ferrets are ferrets! Where can I + have dropped them, I wonder?" Alice guessed in a moment that it was looking for the fan + and the pair of white kid-gloves and she very good-naturedly began hunting about for + them, but they were nowhere to be seen—everything seemed to have changed since + her swim in the pool, and the great hall, with the glass table and the little door, had + vanished completely.

+ +

Very soon the Rabbit noticed Alice, and called to her, in an angry tone, "Why, Mary + Ann, what are you doing out here? Run home this moment and fetch me a pair of + gloves and a fan! Quick, now!"

+ +

"He took me for his housemaid!" said Alice, as she ran off. "How surprised he'll be + when he finds out who I am!" As she said this, she came upon a neat little house, on + the door of which was a bright brass plate with the name "W. RABBIT" engraved upon it. + She went in without knocking and hurried upstairs, in great fear lest she should meet + the real Mary Ann and be turned out of the house before she had found the fan and + gloves.

+ +

By this time, Alice had found her way into a tidy little room with a table in the + window, and on it a fan and two or three pairs of tiny white kid-gloves; she took up + the fan and a pair of the gloves and was just going to leave the room, when her eyes + fell upon a little bottle that stood near the looking-glass. She uncorked it and put it + to her lips, saying to herself, "I do hope it'll make me grow large again, for, really, + I'm quite tired of being such a tiny little thing!"

+ +

Before she had drunk half the bottle, she found her head pressing against the + ceiling, and had to stoop to save her neck from being broken. She hastily put down the + bottle, remarking, "That's quite enough—I hope I sha'n't grow any more."

+ +

Alas! It was too late to wish that! She went on growing and growing and very soon + she had to kneel down on the floor. Still she went on growing, and, as a last resource, + she put one arm out of the window and one foot up the chimney, and said to + herself, "Now I can do no more, + wha tev er happens. What will become of me?"

+ +
+ Illo12 +
+ +

Luckily for Alice, the little mag ic b ottle had now had its full effect and she grew + no larger. After a few minutes she hear d a voice outside and stopped to listen.

+ +

"Mary Ann! Mary Ann!" said the voice . "Fetch me my gloves this moment!" Thencame a + little pattering of feet on the stairs. Alice knew it was the Rabbit coming to look for + her and she trembled till she shoo k th e house, quite forgetting that she was now about + a thousand times as large as the Rabbit and had no reason to be afraid of it.

+ +

Presently the Rabbit came up to the door and tried to open it; but as the door + opened inwards and Alice's elbow was press ed h ard against it, that attempt proved a + failure. Alice heard it sayto itself, "Then I'll g o 'round and get in at the + window."

+ +

"That you won't!" thought Ali ce; and after waiting till she fancied she heard + the Rabbit just under the window, sh e suddenly spread out her hand and made asnatch in the air. She did not get hold of + anything, but she heard a little s hriek and a fall and a crash of bro ken glass, from + which she concluded that it was just possible it had fallen into a c ucumber-frame or + something of that sort.

+ +

Next came an angry voice—the Rabbit's—" Pat!Pat! Where are you?" And + then a voice she had never heard before, "Sure t hen, I'm here! D iggi ng for apples, yer + honor!"

+ +

"Here! Come and help me out of this! Now tell me, Pat, what's that in the + windo w?"

+ +

"Sure, it's an arm, yer honor!"

+ +

"Well, it's got no business the re, at any rate; go and take it away!"

+ +

There was a long silence after this an d Alice could only hear whispers now and then, + and at last she spread out her hand ag ain and made another snatch in the air. This time + there were two little shrieks a nd more sounds of brok en g lass. "I wonder what + they'll do next!" thought Alice. "As for pulling me out of the wi ndow, I only wish they + could!"

+ +

She waited for some time without h earing anything more. At last came a rumbling of + little cart-wheels and the sound of a good many voices all talking together. She made + out the words: "Where's the other lad der? Bill's got the other—Bill! Here, Bill! + Will the roof bear?—Who's to g o do wn the chimney?—Nay, I sha'n't! + You do it! Here, Bill! The master s ays you've got to go down the chimney!"

+ +

Alice drew her foot as far down the c himney as she couldand waited till she heard a + little animal scratching and scrambling a bout in the chimney close above + her; then she gave one sharp kick and waited to see + what would happen next.

+ +

The first thing she heard was a general chorus of "There goes Bill!" then the + Rabbit's voice alone—"Catc h him, you by the hedge!" Then silence a nd t hen another + confusion of voices—"Hold up his head—Brandy now—Don 't choke + him—What happened to you?"

+ +

Lastcame a little f eeble, squeaking voice, "Well, I hardly know—No mor e, + thank ye. I'm better now—all I know is, something comes at me like a + Jack-in-the -box and up I goes like a sky-rocket!"

+ +

Afte r a minute or two of silence, they began moving about again, and Alice heard the + Rabbit say , "A barrowful will do, to begin with."

+ +

"A barrowful of what?" though t Alice. But she had not long to doubt, for the + next moment a shower of little pe bbles came rattling in at the window and some of them + hither in the face. Alice no ticed, with some surprise, that the pebbles were all + turning into little cakes as they lay on the floor and abr ight idea came into her + head. "If Ieat one of these cakes," she thought, "it's sure to m ake some change + in my size."

+ +

So she swallowed one of the cakes an d was delighted to find that she began shrinking + directly. As soon as she was small enough to get through the door, she ran out of the + house and found quite a crowd of lit tle animals and birds waiting outside. They all + m ade a rush at Alice the moment she ap peared, but she ran off as hard as she could and + soon found herself safe in a thick wood.

+ +
+ The Duchess tucked her arm affectionately into Alice's. +
+

"The Duchess tucked her arm affectionately into Alice's."

+
+
+ +

"The first thing I've got to do," said Alice to herself, as she wande red about in the wood, "is to grow to my right + size again; and the second thing i s to find my way into that lovely garden. I suppose I + ought to eat or drink something or other, but the great question is 'What?'"

+ +

Alice looked all arou nd her at the flowers and the blades of grass, but she could + notsee anything that loo kedlike the right thing to eat or drink under the + circumstances. There was a large mushroom growing near her, about the same height as + herself. She stretched herself u p on tiptoe and peeped over the edge and her eyes + immediately met those of a large blue caterpillar, that was sitting on the top, with + its armsfolded, quietly smoking a long hookah a nd taking not the smallest notice of + her or of anything else.

+ +
+ Illo13 +
+ +

+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_005.xhtml b/test/fixtures/alice/OPS/chapter_005.xhtml new file mode 100644 index 0000000..25d3522 --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_005.xhtml @@ -0,0 +1,149 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

+ Advice From A Caterpillar

+ +

At last the Caterpillar took the hookah out of its mouth and + addressed Alice in alanguid, sleepy voice.

+ +

"Who are you?" said the Caterpillar.

+ +
+ Illo14 +
+ +

Alice replied, rather shyly, "I—I hardly know, sir, just at present—at + least I know who I was when I got up this morning, but I think I must have + changed several times since then."

+ +

"Wha t do you mean by that?" said the Caterpillar, sternly. "Explain yourself!"

+ +

"I can't explainmyself, I'm afraid, sir," said Alice,"because I'm not + myself, you see—being so ma nydifferent sizes in a day is very confusing." She + drew hers elf up and said very gravely, "I think you ought to tell me who you + are, first."

+ +

"Why?" said the Caterpillar.

+ +

As Alice could not think of any good reason and the Caterpillar seemed to be in a + very u npleasant state of mind, she turned away.

+ +

"Come back!" the Caterpillar called after her. "I've something important to say!" + Alice turned and came back again.

+ +

"Keep your temper," said the Caterpillar.

+ +

"Is that all?" said Alice, swallowing down her anger as well as she could.

+ +

"No," said the Caterpillar.

+ +

It unfolded its arms, took the hookah out of its mouth again, and said, " So you + think you're changed, do you?"

+ +

"I'm afr aid, I am, sir," said Alice. "I can't remember things as I used—and I + don't keep the same size for ten minutes together!"

+ +

"What size d o you want to be?" asked the Caterpillar.

+ +

"Oh, I'mnot particular as to si ze," Alice hastily replied, "only one doesn't like + changing sooften, you know. I should like to be a little larger, sir, if you + wouldn't mind," said Alice. "Three inches is such a wretched height to be."

+ +

"It is a very good height indeed!" said the Caterpillar an grily, rearing itself + upright as it spoke (it was exactly three inches high).

+ +

In a minute or two, the Caterpillar got down off the mushroom and crawled away in to + the grass,merely remarking, as it went, "One side will make you grow taller, and the + other side will make you grow shorter."

+ +

"One side of what? The other side of what?" thought Alice to + herself.

+ +

"Of the mushroom," said the Caterpillar, just as if she had asked it aloud; and in + another moment, it was out of sight.

+ +

Alice remained looking thoughtfully at the mushroom for a minute, trying to make out + whichwere the two sides of it. At last she stretched her arms 'round it as far as they + would go, and broke off a bit of the edge with each hand.

+ +

"And now which is which?" she said to herself, and nibbled a little of the + right-hand bit to trythe effect. The next moment she felt a violent blow underneath + her chin—it had struck her foot!

+ +

She was a gooddeal frightened b y this very sudden change, as she was shrinking + rapidly; so she set to work at once to eat some of the other bit. Her chin was pressed + so closely against her foo tthat there was hardly room to open her mouth; but she did + it at last and managed to s wallow a morsel of the left-hand bit....

+ +

"Come, my head's free at last!" said Alice; but all she could see, when she loo ked + down, was an immense length of neck, which seemed to rise like a stalk out of a sea of + green leaves that lay far below her.

+ +

"Where have my shoulders got to? And oh, mypoor hands, how is it I can't see + you?"Shewas delighted to find that + her neck would bend about easily in any direction, like a serpent. She had just + succeeded in curving it down into a gr aceful zigzag and was going to dive inamong the + leaves, when a s harp hiss made her draw back in a hurry —a large pigeon had flo wn + into her face and was beating her violently with its wings.

+ +
+ Illo15 +
+ +

"Serpent!" cried the Pigeon.

+ +

"I'm not a serpent!" said Alice indignantly. "Let me alone!"

+ +

"I've tried the roo ts of trees, and I've tried banks, and I've tri ed hedges," the + Pigeon went on, "but those serpents! There's no pleasing them!"

+ +

Alice was more and more puzzled.

+ +

"As if it wasn't trouble enough hatching the eggs," said the Pigeon, "but I must be + on the look-out for serpents, night and day! And just as I'd taken the highest tree in + the wood," continued the Pigeon, raising its voice to a shriek, "and just as I was + thinkingI should be free of them at last, they must needs come wriggling down from the + sky! Ugh, Serpent!"

+ +

"But I'm not a serpent, I tell you!" said Alice. "I'm a—I'm a—I'm + a little girl," she added rather + doubtfully, as she remembered the numbe r of changes she had gone through that day.

+ +

"You're looking for eggs, I know that well enough," said the Pigeon; "and + what does it matter to me whether you're a little girl or a serpent?"

+ +

"It matters a good deal to me," said Alice h astily; "but I'm not looking for + eggs, as it happens, and if I was, I shouldn't want yours—I don't like + them raw."

+ +

"Well, be off, then!" said the Pige on in a sulky tone, as it settled down again into + its nest. Alice crouched down a mong the trees as well as she could, for her neck kept + getting entangled among the bra nches, and every now and then she had to stop and + untwist it. After awhile she rememb ered that she still held the pieces of mushroom in + her hands, and she set to work very carefully, nibbling first at one and then at the + other, and growing sometimes taller and sometimes shorter, until she had succeeded in + bringing herself down to her usual height.

+ +

It was so long since she had been anything near the right size that it felt quite + strange at first. "The next thing is to get into that beautiful garden—how + is that to be done, I wonder?" As she said this, she came suddenly upon an open + place, with a little house in it about four feet high. "Whoever lives there," thought + Alice, "it'll never do to come upon them this size;why, I should frighten them + out of their wits!" She did not venture to go near the house till she had brought + herself down to nine inches high.

+ +

+
+ + diff --git a/test/fixtures/alice/OPS/chapter_006.xhtml b/test/fixtures/alice/OPS/chapter_006.xhtml new file mode 100644 index 0000000..b36f41e --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_006.xhtml @@ -0,0 +1,122 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

Pig And Pepper

+ +

For a minute or twoshe stood looking at the house, when + suddenly a footman in livery came running out of the wood (judging by his face only, + she would have called him a fish)—and rapped loudly at the door with his + knuckles. It was opened by another footman in livery,with a round face and large eyes + like a frog.

+ +
+ Illo15 +
+ +

The Fish-Footman began by producing from under his arm a great letter, and this he + handed over to the other, saying, in a solemn tone, "For the Duchess. An invitation from the Queen to play croquet." The + Frog-Footman repeated, in the same solemn tone, "From the Queen. An invitation for the + Duchess to play croquet." Then they both bowed low and their curls got entangled + together.

+ +

When Alice next peeped out, the Fish-Footman was gone, and the other was sitting on + the ground near the door, staring stupidly up into the sky. Alice went timidly up to + the door and knocked.

+ +

"There's no sortof use in knocking," said the Footman, "and that for two reasons. + First, because I'm on the same side of the door as you are; secondly, because they're + making such a noise inside, no one could possibly hear you." And certainly there + was a most extraordinary noise going on within—a constant howling and + sneezing, and every now and then a great crash, as if a dish or kettle had been broken + to pieces.

+ +

"How am I to get in?" asked Alice.

+ +

"Are you to get in at all?" said the Footman. "That's the first question, you + know."

+ +

Alice opened the door and went in. The door led right into a large kitchen, which + was full of smoke from one end to the other; the Duchess was sitting on a three-legged + stool in the middle, nursing a baby; the cook was leaning over the fire, stirring a + large caldron which seemed to be full of soup.

+ +

"There's certainly too much pepper in that soup!" Alice said to herself, as well as + she could for sneezing. Even the Duchess sneezed occasionally; and asforthe baby, it + was sneezing and howling alternately without a moment'spause. The only two + creatures in the kitchen that did + not sneeze were the cook and a large cat, which was grinning from ear to + ear.

+ +

"Please would you tell me," said Alice, a little timidly, "why your cat grins like + that?"

+ +

"It's a Cheshire-Cat," said the Duchess,"and that's why."

+ +

"I didn't know that Cheshire-Cats always grinned; in fact, I didn't know that cats + could grin," said Alice.

+ +

"You don't know much," said the Duchess, "and that's a fact."

+ +

Just then the cook took the caldron of soupoff the fire, and at once set to work + throwing everything within her reach at the Duchess and the baby—the fire-irons + came first; then followed a shower of saucepans, plates and dishes. The Duchess took no + notice of them, even when they hit her, and the baby was howling so much already that + itwas quite impossible to say whether the blows hurt it or not.

+ +

"Oh, please mind what you're doing!" cried Alice, jumping up and down in an + agony of terror.

+ +

"Here! You may nurse it a bit, if you like!" the Duchess said to Alice, flinging the + baby at her as she spoke. "I must go and get ready to play croquet with the Queen," and + she hurried out of the room.

+ +

Alice caught the baby with some difficulty, as it was a queer-shaped little creature + and held out its arms and legs in all directions. "If I don't take this child away with + me," thought Alice, "they're sure to kill it in a day or two. Wouldn't it be murder to + leave it behind?" She said the last words out loud and the little thing grunted in + reply.

+ +

"If you're going to turn into a pig, my dear," said Alice, "I'll have nothing more + to do with you. Mind now!"

+ +

Alice was just beginning to think to herself, "Now, what am I to do with this + creature, when I get it home?" when it grunted again so violently that Alice looked + down into its face in some alarm. This time there could be no mistake about + it—it was neither more nor less than a pig; so she set the little creature down + and felt quite relieved to see it trot awayquietly into the wood.

+ +

Alice was a little startled by seeing the Cheshire-Catsitting on a bough of a tree + a few yards off. The Cat only grinned when it saw her. "Cheshire-Puss," began Alice, + rather timidly, "would you please tell me which way I ought to gofrom here?"

+ +

"In that direction," the Cat said, waving the right paw 'round, "lives a + Hatter; and in that direction," waving the other paw, "lives a March Hare. Visit + either you like; they're both mad."

+ +

"But I don't want to go among mad people," Alice remarked.

+ +

"Oh, you can't help that," said the Cat; "we're all mad here. Do you play croquet + with the Queen to-day?"

+ +

"I should like it very much," said Alice, "but I haven't been invited yet."

+ +

"You'll see me there," said the Cat, and vanished.

+ +

Alice had not gone much farther before she came in sight of the house of the March + Hare; it was so large a house that she did not like to go near till she had nibbled + some more of the left-hand bit of mushroom.

+ +

+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_007.xhtml b/test/fixtures/alice/OPS/chapter_007.xhtml new file mode 100644 index 0000000..5a79bca --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_007.xhtml @@ -0,0 +1,98 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

A Mad Tea-Party

+ +

There was a table set out under a tree in front of the + house, and the March Hare and the Hatter were having tea at it; a Dormouse was sitting + between them, fast asleep.

+ +

The table was a large one, but the three were all crowded together at one corner of + it. "No room! No room!" they cried out when they saw Alice coming. "There's + plenty of room!" said Alice indignantly, and she sat down in a large arm-chair + at one end of the table.

+ +

The Hatter opened his eyes very wide on hearing this, but all he said was "Why is a + raven like a writing-desk?"

+ +

"I'm glad they've begun asking riddles—I believe I can guess that," she added + aloud.

+ +

"Do you mean that you think you can find out the answer to it?" said the March + Hare.

+ +

"Exactly so," said Alice.

+ +

"Then you should say what you mean," the March Hare went on.

+ +

"I do," Alice hastily replied; "at least—at least I mean what I + say—that's the same thing, you know."

+ +

"You might just as well say," added the Dormouse, which seemed to be talking in its + sleep, "that 'I breathe when I sleep' is the same thing as 'I sleep when I + breathe!'"

+ +

"It is the same thing with you," said the Hatter, and he poured a little hot + tea upon its nose. The Dormouse shook its head impatiently and said, without opening + its eyes,"Ofcourse, of course; just what I was going to remark myself."

+ +
+ Illo17 +
+ +

"Have you guessed the riddle yet?" the Hatter said, turning to Alice again.

+ +

"No, I give it up," Alice replied. "What's theanswer?"

+ +

"I haven't the slightest idea," said the Hatter.

+ +

"Nor I,"said the March Hare.

+ +

Alice gave a weary sigh. "I think you might do something better with the time," she + said, "than wasting it in asking riddles that have no answers."

+ +

"Take some more tea," the March Hare said to Alice, very earnestly.

+ +

"I've had nothing yet," Alice replied in an offended tone, "so I can't take + more."

+ +

"You mean you can't take less," said the Hatter; "it's very easy to take + more than nothing."

+ +

At this, Alice got up and walked off. The Dormouse fell asleep instantly and neither + of the others took the least notice of her going, thoughshe looked back once or twice; the last time she saw them, they + were trying to put the Dormouse into the tea-pot.

+ + +
+ The Trial of the Knave of Hearts. +
+

The Trial of the Knave of Hearts.

+
+
+ +

"At any rate, I'll never go there again!" said Alice, as she picked her way + through the wood. "It's the stupidest tea-party I ever was at in all my life!" Just as + she said this, she noticed that one of the trees had a door leading right into it. + "That's very curious!" she thought. "I think I may as well go in at once." And in she + went.

+ +

Once more she foundherself in the long hall and close to the little glass table. + Taking the little golden key, she unlocked the door that led into the garden. Then she + set to work nibbling at the mushroom (she had kept a piece of it in her pocket) till + she was about a foot high; then she walked down the little passage; and + then—she found herself at last in the beautiful garden, among the bright + flower-beds and the cool fountains.

+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_008.xhtml b/test/fixtures/alice/OPS/chapter_008.xhtml new file mode 100644 index 0000000..06f0522 --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_008.xhtml @@ -0,0 +1,151 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

+ The Queen's Croquet Ground

+ +

A large rose-tree stood near the entrance of the garden; the + roses growing on it were white, but there were threegardeners at it, busily painting + them red. Suddenly their eyes chanced to fall upon Alice, as she stood watching them. + "Would you tell me, please," said Alice, a little timidly, "why you are painting those + roses?"

+ +

Five and Seven said nothing, butlooked at Two. Twobegan, in a low voice, "Why, the fact is, you see, Miss, this here + ought to have been a red rose-tree, and we put a white one in by mistake; and, + if the Queen was to find it out, we should all have our heads cut off, you know. So you + see, Miss, we're doing our best, afore she comes, to—" At this moment, Five, who + had been anxiously looking across the garden, called out, "The Queen! The Queen!" and + the three gardeners instantly threw themselves flat upon their faces. There was a sound + of many footstepsand Alice looked 'round, eager to see the Queen.

+ +

First came ten soldiers carrying clubs, with their hands and feet at the corners: + next the ten courtiers; these were ornamented all over with diamonds. After these came + the royal children; there were ten of them, all ornamented with hearts. Next came the + guests, mostly Kings and Queens, and among them Alice recognized the White Rabbit. Then + followed the Knave of Hearts, carrying the King's crown on a crimson velvet cushion; + and last of all this grand procession came THE KING AND THE QUEEN OF HEARTS.

+ +

When the procession came opposite to Alice, they all stopped and looked at her, and + the Queen said severely, "Who is this?" She said it to the Knave of Hearts, who only + bowed and smiled in reply.

+ +

"My name is Alice, so please Your Majesty," said Alice very politely; but she added + to herself, "Why, they're only a pack of cards, after all!"

+ +

"Can you play croquet?" shouted the Queen. The question was evidently meant for + Alice.

+ +

"Yes!" said Alice loudly.

+ +

"Come on, then!" roared the Queen.

+ +

"It's—it's a very fine day!" said a timid voice to Alice. She was walking by + the White Rabbit, who was peeping anxiously into her face.

+ +

"Very," said Alice. "Where's the Duchess?"

+ +

"Hush! Hush!" said the Rabbit. "She's under sentence of execution."

+ +

"What for?" said Alice.

+ +

"She boxed the Queen's ears—" the Rabbit began.

+ +

"Get to your places!" shouted the Queen in a voice of thunder, and people began + running about in all directions, tumbling up against each other. However, they got + settled down in a minute or two, and the game began.

+ +

Alice thought she had never seen such a curious croquet-ground in her life; it was + all ridges and furrows. The croquet balls were live hedgehogs, and the mallets live + flamingos and the soldiers had to double themselves up and stand on their hands and + feet, to make the arches.

+ +

The players all played at once, without waiting for turns, quarrelling all the while + and fighting for the hedgehogs; and in a very short time, the Queen was in a furious + passion and went stamping about and shouting, "Off with his head!" or "Off with her + head!" about once in a minute.

+ +

"They're dreadfully fond of beheading people here," thought Alice; "the great wonder + is that there's anyone left alive!"

+ +

She was looking about for some way of escape, when she noticed a curious appearance + in the air. "It's the Cheshire-Cat," + she said to herself; "now I shall have somebody to talk to."

+ +

"How are you getting on?" said the Cat.

+ +

"I don't think they play at all fairly," Alice said, in a rather complaining tone; + "and they all quarrel so dreadfully one can't hear oneself speak—and they don't + seem to have any rules in particular."

+ +

"How do you like the Queen?" said the Cat in a low voice.

+ +

"Not at all," said Alice.

+ +
+ Illo18 +
+ +

Alice thought she might as well go back and see how the game was going on. So she + went off in search of her hedgehog. The hedgehog was engaged in a fight with another + hedgehog, which seemed to Alice an excellent opportunity for croqueting one of them + with the other; the only difficulty was that her flamingo was gone across to the other + side of the garden, where Alice could see it trying, in a helpless sort of way, to fly + up into a tree. She caught the flamingo and tucked it away under her arm, that it might + not escape again.

+ +

Just then Alice ran across the Duchess (who was now out of prison). She tucked her + arm affectionately into Alice's and they walked off together. Alice was very glad to + find her in such a pleasant temper. She was a little startled, however, when she heard + the voice of the Duchess close to her ear. "You're thinking about something, my dear, + and that makes you forget to talk."

+ +

"The game's going on rather better now," Alice said, by way of keeping up the + conversation a little.

+ +

"'Tis so," said the Duchess; "and the moral of that is—'Oh, 'tis love, 'tis + love that makes the world go 'round!'"

+ +

"Somebody said," Alice whispered, "that it's done by everybody minding his own + business!"

+ +

"Ah, well! It means much the same thing," said the Duchess, digging her sharp little + chin into Alice's shoulder, as she added "and the moral of that is—'Take + care of the sense and the sounds will take care of themselves.'"

+ +

To Alice's great surprise, the Duchess's arm that was linked into hers began to + tremble. Alice looked up and there stood the Queen in front of them, with her arms + folded, frowning like a thunderstorm!

+ +

"Now, I give you fair warning," shouted the Queen, stamping on the ground as she + spoke, "either you or your head must be off, and that in about half no time. Take your + choice!" The Duchess took her choice, and was gone in a moment.

+ +

"Let's go on with the game," the Queen said to Alice; and Alice was too much + frightened to say a word, but slowly + followed her back to the croquet-ground.

+ +

All the time they were playing, the Queen never left off quarreling with the other + players and shouting, "Off with his head!" or "Off with her head!" By the end of half + an hour or so, all the players, except the King, the Queen and Alice, were in custody + of the soldiers and under sentence of execution.

+ +

Then the Queen left off, quite out of breath, and walked away with Alice.

+ +

Alice heard the King say in a low voice to the company generally, "You are all + pardoned."

+ +

Suddenly the cry "The Trial's beginning!" was heard in the distance, and Alice ran + along with the others.

+ +
+ + diff --git a/test/fixtures/alice/OPS/chapter_009.xhtml b/test/fixtures/alice/OPS/chapter_009.xhtml new file mode 100644 index 0000000..57653ae --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_009.xhtml @@ -0,0 +1,100 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

Who Stole The Tarts?

+ +

The King and Queen of Hearts were seated on their throne + when they arrived, with a great crowd assembled about them—all sorts of little + birds and beasts, as well as the whole pack of cards: the Knave was standing before + them, in chains, with a soldier on each side to guard him; and near the King was the + White Rabbit, with a trumpet in one hand and a scroll of parchment in the other. In the + very middle of the court was a + table, with a large dish of tarts upon it. "I wish they'd get the trial done," Alice + thought, "and hand 'round the refreshments!"

+ +
+ Illo19 +
+ +

The judge, by the way, was the King and he wore his crown over his great wig. + "That's the jury-box," thought Alice; "and those twelve creatures (some were animals + and some were birds) I suppose they are the jurors."

+ +

Just then the White Rabbit cried out "Silence in the court!"

+ +

"Herald, read the accusation!" said the King.

+ +

On this, the White Rabbit blew three blasts on the trumpet, then unrolled the + parchment-scroll and read as follows:

+ +
+ "The Queen of Hearts, she made some tarts,
All on a summer day;
The Knave of Hearts, he stole + those tarts
And took them quite away!"
+
+ +

"Call the first witness," said the King; and the White Rabbit blew three blasts on + the trumpet and called out, "First witness!"

+ +

The first witness was the Hatter. He came in with a teacup in one hand and a piece of bread and butter in the + other.

+ +

"You ought to have finished," said the King. "When did you begin?"

+ +

The Hatter looked at the March Hare, who had followed him into the court, arm in arm + with the Dormouse. "Fourteenth of March, I think it was," he said.

+ +

"Give your evidence," said the King, "and don't be nervous, or I'll have you + executed on the spot."

+ +

This did not seem to encourage the witness at all; he kept shifting from one foot to + the other, looking uneasily at the Queen, and, in his confusion, he bit a large piece + out of his teacup instead of the bread and butter.

+ +

Just at this moment Alice felt a very curious sensation—she was beginning to + grow larger again.

+ +

The miserable Hatter dropped his teacup and bread and butter and went down on one + knee. "I'm a poor man, Your Majesty," he began.

+ +

"You're a very poor speaker," said the King.

+ +

"You may go," said the King, and the Hatter hurriedly left the court.

+ +

"Call the next witness!" said the King.

+ +

The next witness was the Duchess's cook. She carried the pepper-box in her hand and + the people near the door began sneezing all at once.

+ +

"Give your evidence," said the King.

+ +

"Sha'n't," said the cook.

+ +

The King looked anxiously at the White Rabbit, who said, in a low voice, "Your + Majesty must cross-examine this witness."

+ +

"Well, if I must, I must," the King said. "What are tarts made of?"

+ +

"Pepper, mostly," said the cook.

+ +

For some minutes the whole court was in confusion and by the time they had settled + down again, the cook had disappeared.

+ +

"Never mind!" said the King, "call the next witness."

+ +

Alice watched the White Rabbit as he fumbled over the list. Imagine her surprise + when he read out, at the top of his shrill little voice, the name "Alice!"

+ +
+ + \ No newline at end of file diff --git a/test/fixtures/alice/OPS/chapter_010.xhtml b/test/fixtures/alice/OPS/chapter_010.xhtml new file mode 100644 index 0000000..4dc46c5 --- /dev/null +++ b/test/fixtures/alice/OPS/chapter_010.xhtml @@ -0,0 +1,104 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

Alice's Evidence

+ +

"Here!" cried Alice. She jumped up in such a hurry that she + tipped over the jury-box, upsetting all the jurymen on to the heads of the crowd + below.

+ +

"Oh, I beg your pardon!" she exclaimed in a tone of great dismay.

+ +

"The trial cannot proceed," said the King, "until all the jurymen are back in their + proper places—all," he repeated with great emphasis, looking hard at + Alice.

+ +

"What do you know about this business?" the King said to Alice.

+ +

"Nothing whatever," said Alice.

+ +

The King then read from his book: "Rule forty-two. All persons more than a mile high to leave the court."

+ +

"I'm not a mile high," said Alice.

+ +

"Nearly two miles high," said the Queen.

+ +
+ Illo20 +
+ +

"Well, I sha'n't go, at any rate," said Alice.

+ +

The King turned pale and shut his note-book hastily. "Consider your verdict," he + said to the jury, in a low, trembling voice.

+ +

"There's more evidence to come yet, please Your Majesty," said the White Rabbit, + jumping up in a great hurry. "This paper has just been picked up. It seems to be a + letter written by the prisoner to—to somebody." He unfolded the paper as he spoke + and added, "It isn't a letter, after all; it's a set of verses."

+ +

"Please, Your Majesty," said the Knave, "I didn't write it and they can't prove that + I did; there's no name signed at the end."

+ +

"You must have meant some mischief, or else you'd have signed your name like + an honest man," said the King. There was a general clapping of hands at this.

+ +

"Read them," he added, turning to the White Rabbit.

+ +

There was dead silence in the court whilst the White Rabbit read out the verses.

+ +

"That's the most important piece of evidence we've heard yet," said the King.

+ +

"I don't believe there's an atom of meaning in it," ventured Alice.

+ +

"If there's no meaning in it," said the King, "that saves a world of trouble, you + know, as we needn't try to find any. Let the jury consider their verdict."

+ +

"No, no!" said the Queen. "Sentence first—verdict afterwards."

+ +

"Stuff and nonsense!" said Alice loudly. "The idea of having the sentence + first!"

+ +
+ Illo21 +
+ +

"Hold your tongue!" said the Queen, turning purple.

+ +

"I won't!" said Alice.

+ +

"Off with her head!" the Queen shouted at the top of her voice. Nobody moved.

+ +

"Who cares for you?" said Alice (she had grown to her full size by this + time). "You're nothing but a pack of cards!"

+ +

At this, the whole pack rose up in the air and came flying down upon her; she gave a little scream, half of fright and + half of anger, and tried to beat them off, and found herself lying on the bank, with + her head in the lap of her sister, who was gently brushing away some dead leaves that + had fluttered down from the trees upon her face.

+ +

"Wake up, Alice dear!" said her sister. "Why, what a long sleep you've had!"

+ +

"Oh, I've had such a curious dream!" said Alice. And she told her sister, as well as + she could remember them, all these strange adventures of hers that you have just been + reading about. Alice got up and ran off, thinking while she ran, as well she might, + what a wonderful dream it had been.

+ +
+ Illo22 +
+ +
+ + diff --git a/test/fixtures/alice/OPS/cover.xhtml b/test/fixtures/alice/OPS/cover.xhtml new file mode 100644 index 0000000..ac72347 --- /dev/null +++ b/test/fixtures/alice/OPS/cover.xhtml @@ -0,0 +1,12 @@ + + + + + Cover + + + + + Cover Image + + diff --git a/test/fixtures/alice/OPS/css/stylesheet.css b/test/fixtures/alice/OPS/css/stylesheet.css new file mode 100644 index 0000000..57531fe --- /dev/null +++ b/test/fixtures/alice/OPS/css/stylesheet.css @@ -0,0 +1,105 @@ +body { + font-family: Georgia, serif; + font-size: 1em; + line-height: 1.33em; +} + +/* Book Title */ +h1 { + font-size: 1.5em; + line-height: 1.33em; +} + +/* Chapter Title */ +h2 { + font-size: 1.33em; + line-height: 1.2em; +} + +/* Subtitle */ +h3 { + font-size: 1.25em; + line-height: 1.12em; +} + +/* Meta Info */ +h4 { + font-size: 1.1em; + line-height: 1.05em; +} + +/* Chapter Container */ +section { + +} + +section > p { + +} + +/* Drop Cap */ +section > p:first-of-type:first-letter { + float: left; + font-size: 4em; + line-height: .8; + padding: 0 .2em; + font-family: Georgia; +} + +figure.small { + +} + +figure.full { + +} + +figure > img { + +} + +figcaption { + +} + +figcaption > p { + +} + +/* More specific Kindle Eink queries at: http://epubsecrets.com/media-queries-for-kindle-devices.php */ + +/* Amazon Kindle */ +@media amzn-kf8 { + +} + +/* Many device available at: https://css-tricks.com/snippets/css/media-queries-for-standard-devices/ */ + +/* Smartphone - Portrait */ +@media only screen + and (min-device-width: 320px) + and (max-device-width: 667px) + and (orientation: portrait) { + +} + +/* Smartphone - Landscape */ +@media only screen + and (min-device-width: 320px) + and (max-device-width: 667px) + and (orientation: landscape) { + +} + +/* Tablet - Portrait and Landscape */ +@media only screen + and (min-device-width: 768px) + and (max-device-width: 1024px) { + +} + +/* Laptop & Desktops */ +@media only screen + and (min-device-width: 1025px) { + +} \ No newline at end of file diff --git a/test/fixtures/alice/OPS/images/cover_th.jpg b/test/fixtures/alice/OPS/images/cover_th.jpg new file mode 100644 index 0000000..b9cc3b3 Binary files /dev/null and b/test/fixtures/alice/OPS/images/cover_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i001_th.jpg b/test/fixtures/alice/OPS/images/i001_th.jpg new file mode 100644 index 0000000..ab6a9c5 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i001_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i002_th.jpg b/test/fixtures/alice/OPS/images/i002_th.jpg new file mode 100644 index 0000000..df12dc5 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i002_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i003_th.jpg b/test/fixtures/alice/OPS/images/i003_th.jpg new file mode 100644 index 0000000..2005bd2 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i003_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i004_th.jpg b/test/fixtures/alice/OPS/images/i004_th.jpg new file mode 100644 index 0000000..7ad8456 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i004_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i005_th.jpg b/test/fixtures/alice/OPS/images/i005_th.jpg new file mode 100644 index 0000000..3d8cd6a Binary files /dev/null and b/test/fixtures/alice/OPS/images/i005_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i006_th.jpg b/test/fixtures/alice/OPS/images/i006_th.jpg new file mode 100644 index 0000000..786b173 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i006_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i007_th.jpg b/test/fixtures/alice/OPS/images/i007_th.jpg new file mode 100644 index 0000000..ef2cd70 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i007_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i008_th.jpg b/test/fixtures/alice/OPS/images/i008_th.jpg new file mode 100644 index 0000000..7999df7 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i008_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i009_th.jpg b/test/fixtures/alice/OPS/images/i009_th.jpg new file mode 100644 index 0000000..c89542b Binary files /dev/null and b/test/fixtures/alice/OPS/images/i009_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i010_th.jpg b/test/fixtures/alice/OPS/images/i010_th.jpg new file mode 100644 index 0000000..73b480c Binary files /dev/null and b/test/fixtures/alice/OPS/images/i010_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i011_th.jpg b/test/fixtures/alice/OPS/images/i011_th.jpg new file mode 100644 index 0000000..75d7162 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i011_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i012_th.jpg b/test/fixtures/alice/OPS/images/i012_th.jpg new file mode 100644 index 0000000..a95a783 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i012_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i013_th.jpg b/test/fixtures/alice/OPS/images/i013_th.jpg new file mode 100644 index 0000000..b0e5620 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i013_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i014_th.jpg b/test/fixtures/alice/OPS/images/i014_th.jpg new file mode 100644 index 0000000..492169f Binary files /dev/null and b/test/fixtures/alice/OPS/images/i014_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i015_th.jpg b/test/fixtures/alice/OPS/images/i015_th.jpg new file mode 100644 index 0000000..cba87ed Binary files /dev/null and b/test/fixtures/alice/OPS/images/i015_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i016_th.jpg b/test/fixtures/alice/OPS/images/i016_th.jpg new file mode 100644 index 0000000..6e38f32 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i016_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i017_th.jpg b/test/fixtures/alice/OPS/images/i017_th.jpg new file mode 100644 index 0000000..bc22737 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i017_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i018_th.jpg b/test/fixtures/alice/OPS/images/i018_th.jpg new file mode 100644 index 0000000..b0e5de0 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i018_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i019_th.jpg b/test/fixtures/alice/OPS/images/i019_th.jpg new file mode 100644 index 0000000..779d5aa Binary files /dev/null and b/test/fixtures/alice/OPS/images/i019_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i020_th.jpg b/test/fixtures/alice/OPS/images/i020_th.jpg new file mode 100644 index 0000000..3db3517 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i020_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/i022_th.jpg b/test/fixtures/alice/OPS/images/i022_th.jpg new file mode 100644 index 0000000..f8a0b96 Binary files /dev/null and b/test/fixtures/alice/OPS/images/i022_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/ii021_th.jpg b/test/fixtures/alice/OPS/images/ii021_th.jpg new file mode 100644 index 0000000..2f83b7d Binary files /dev/null and b/test/fixtures/alice/OPS/images/ii021_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/plate01_th.jpg b/test/fixtures/alice/OPS/images/plate01_th.jpg new file mode 100644 index 0000000..b8798cc Binary files /dev/null and b/test/fixtures/alice/OPS/images/plate01_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/plate02_th.jpg b/test/fixtures/alice/OPS/images/plate02_th.jpg new file mode 100644 index 0000000..010d94c Binary files /dev/null and b/test/fixtures/alice/OPS/images/plate02_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/plate03_th.jpg b/test/fixtures/alice/OPS/images/plate03_th.jpg new file mode 100644 index 0000000..e96ff78 Binary files /dev/null and b/test/fixtures/alice/OPS/images/plate03_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/plate04_th.jpg b/test/fixtures/alice/OPS/images/plate04_th.jpg new file mode 100644 index 0000000..a8184ea Binary files /dev/null and b/test/fixtures/alice/OPS/images/plate04_th.jpg differ diff --git a/test/fixtures/alice/OPS/images/title.jpg b/test/fixtures/alice/OPS/images/title.jpg new file mode 100644 index 0000000..34a4fb2 Binary files /dev/null and b/test/fixtures/alice/OPS/images/title.jpg differ diff --git a/test/fixtures/alice/OPS/package.opf b/test/fixtures/alice/OPS/package.opf new file mode 100644 index 0000000..da1f41e --- /dev/null +++ b/test/fixtures/alice/OPS/package.opf @@ -0,0 +1,84 @@ + + + + en-US + 2012-01-18T12:47:00Z + + edu.nyu.itp.future-of-publishing.alice-in-wonderland + + Public domain in the USA. + Lewis Carroll + Gordon Robinson + Alice's Adventures in Wonderland + Fantasy + http://www.gutenberg.org/files/19033/19033-h/19033-h.htm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/fixtures/alice/OPS/titlepage.xhtml b/test/fixtures/alice/OPS/titlepage.xhtml new file mode 100644 index 0000000..f7da637 --- /dev/null +++ b/test/fixtures/alice/OPS/titlepage.xhtml @@ -0,0 +1,42 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+ +

+ +

+ Alice's Adventures In Wonderland +

+ +

+ +
+ title +
+ + +

+ +

+ Copyright, 1916,
+ By Sam'l Gabriel Sons & Company
+ New York +

+ +
+ Alice in the Room of the Duchess. +
+

Alice in the Room of the Duchess.

+
+
+ +
+ + diff --git a/test/fixtures/alice/OPS/toc.xhtml b/test/fixtures/alice/OPS/toc.xhtml new file mode 100644 index 0000000..eff8c48 --- /dev/null +++ b/test/fixtures/alice/OPS/toc.xhtml @@ -0,0 +1,33 @@ + + + + + Alice's Adventures in Wonderland + + + + +
+
+

Contents

+
+ + + +
+ + diff --git a/test/fixtures/alice/mimetype b/test/fixtures/alice/mimetype new file mode 100644 index 0000000..57ef03f --- /dev/null +++ b/test/fixtures/alice/mimetype @@ -0,0 +1 @@ +application/epub+zip \ No newline at end of file diff --git a/test/index.html b/test/index.html index 9969dc5..b2a5495 100644 --- a/test/index.html +++ b/test/index.html @@ -1,21 +1,12 @@ - - - EPUB.js QUnit Tests - - - - - - - - -
-
- - - - - + + Mocha + + + + + + + diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..563c20f --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,31 @@ +var webpack = require("webpack"); +var path = require('path'); +var PROD = (process.env.NODE_ENV === 'production') +var hostname = "localhost"; +var port = "8080"; + +module.exports = { + entry: { + epub: "./src/epub.js", + }, + devtool: 'source-map', + output: { + path: path.resolve("./dist"), + filename: "[name].js", + sourceMapFilename: "[name].js.map", + library: "ePub", + libraryTarget: "umd" + }, + externals: { + "jszip": "JSZip", + "xmldom": "xmldom" + }, + plugins: [ + // new webpack.IgnorePlugin(/punycode|IPv6/), + ], + devServer: { + host: hostname, + port: port, + inline: true + } +}