diff --git a/bower.json b/bower.json
index 71f52af..3457eea 100644
--- a/bower.json
+++ b/bower.json
@@ -26,6 +26,7 @@
"devDependencies": {
"qunit": "~1.14.0",
"jquery": "~2.1.1",
- "rsvp": "~3.0.8"
+ "rsvp": "~3.0.8",
+ "uri.js": "~1.13.2"
}
}
diff --git a/dist/epub.js b/dist/epub.js
index 84e22bf..9e3a78a 100644
--- a/dist/epub.js
+++ b/dist/epub.js
@@ -28,8 +28,10 @@ EPUBJS.Render = {};
} else {
root.ePub = ePub;
}
-
+
})(this);
+
+
(function(global) {
/**
@class RSVP
@@ -2228,6 +2230,2013 @@ define('rsvp', [
});
global.RSVP = require('rsvp');
}(self));
+/*!
+ * URI.js - Mutating URLs
+ *
+ * Version: 1.13.2
+ *
+ * Author: Rodney Rehm
+ * Web: http://medialize.github.io/URI.js/
+ *
+ * Licensed under
+ * MIT License http://www.opensource.org/licenses/mit-license
+ * GPL v3 http://opensource.org/licenses/GPL-3.0
+ *
+ */
+(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) {
+ // Allow instantiation without the 'new' keyword
+ if (!(this instanceof URI)) {
+ return new URI(url, base);
+ }
+
+ if (url === undefined) {
+ 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.13.2';
+
+ 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 (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++) {
+ if (lookup[data[i]] !== undefined) {
+ 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;
+ }
+
+ 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"
+ };
+ 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': '='
+ }
+ }
+ }
+ };
+ 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;
+ }
+ };
+ URI.recodePath = function(string) {
+ var segments = (string + '').split('/');
+ for (var i = 0, length = segments.length; i < length; i++) {
+ segments[i] = URI.encodePathSegment(URI.decode(segments[i]));
+ }
+
+ return segments.join('/');
+ };
+ URI.decodePath = function(string) {
+ var segments = (string + '').split('/');
+ for (var i = 0, length = segments.length; i < length; i++) {
+ segments[i] = URI.decodePathSegment(segments[i]);
+ }
+
+ return segments.join('/');
+ };
+ // generate encode/decode path functions
+ var _parts = {'encode':'encode', 'decode':'decode'};
+ var _part;
+ var generateAccessor = function(_group, _part) {
+ return function(string) {
+ return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {
+ return URI.characters[_group][_part].map[c];
+ });
+ };
+ };
+
+ for (_part in _parts) {
+ URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);
+ }
+
+ 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 (parts.protocol === 'file') {
+ // the file scheme: does not contain an authority
+ string = string.substring(pos + 3);
+ } 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) {
+ // 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 if (string.indexOf(':') !== string.lastIndexOf(':')) {
+ // 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('/');
+ /*jshint laxbreak: true */
+ var pos = firstSlash > -1
+ ? string.lastIndexOf('@', firstSlash)
+ : string.indexOf('@');
+ /*jshint laxbreak: false */
+ 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 (items[name]) {
+ if (typeof items[name] === 'string') {
+ 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);
+ }
+
+ 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 (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 (data[name] === value) {
+ data[name] = undefined;
+ } else if (isArray(data[name])) {
+ data[name] = filterArrayValues(data[name], value);
+ }
+ } else {
+ data[name] = undefined;
+ }
+ } else {
+ throw new TypeError('URI.addQuery() accepts an object, string as the first parameter');
+ }
+ };
+ URI.hasQuery = function(data, name, value, withinArray) {
+ if (typeof name === 'object') {
+ for (var key in name) {
+ if (hasOwn.call(name, key)) {
+ if (!URI.hasQuery(data, key, name[key])) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ } else if (typeof name !== 'string') {
+ throw new TypeError('URI.hasQuery() accepts an object, string 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.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;
+ };
+
+ // generate simple accessors
+ _parts = {protocol: 'protocol', username: 'username', password: 'password', hostname: 'hostname', port: 'port'};
+ generateAccessor = function(_part){
+ return function(v, build) {
+ if (v === undefined) {
+ return this._parts[_part] || '';
+ } else {
+ this._parts[_part] = v || null;
+ this.build(!build);
+ return this;
+ }
+ };
+ };
+
+ for (_part in _parts) {
+ p[_part] = generateAccessor(_parts[_part]);
+ }
+
+ // generate accessors with optionally prefixed input
+ _parts = {query: '?', fragment: '#'};
+ generateAccessor = function(_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;
+ }
+ };
+ };
+
+ for (_part in _parts) {
+ p[_part] = generateAccessor(_part, _parts[_part]);
+ }
+
+ // generate accessors with prefixed output
+ _parts = {search: ['?', 'query'], hash: ['#', 'fragment']};
+ generateAccessor = function(_part, _key){
+ return function(v, build) {
+ var t = this[_part](v, build);
+ return typeof t === 'string' && t.length ? (_key + t) : t;
+ };
+ };
+
+ for (_part in _parts) {
+ p[_part] = generateAccessor(_parts[_part][1], _parts[_part][0]);
+ }
+
+ p.pathname = function(v, build) {
+ if (v === undefined || v === true) {
+ var res = this._parts.path || (this._parts.hostname ? '/' : '');
+ return v ? URI.decodePath(res) : res;
+ } 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') {
+ this._parts = URI.parse(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 = {};
+ URI.parseHost(v, x);
+ v = x.hostname;
+ }
+ return _hostname.call(this, v, build);
+ };
+
+ // compound accessors
+ 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 {
+ URI.parseHost(v, this._parts);
+ 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 {
+ URI.parseAuthority(v, this._parts);
+ this.build(!build);
+ return this;
+ }
+ };
+ p.userinfo = function(v, build) {
+ if (this._parts.urn) {
+ return v === undefined ? '' : this;
+ }
+
+ if (v === undefined) {
+ if (!this._parts.username) {
+ return '';
+ }
+
+ var t = URI.buildUserinfo(this._parts);
+ return t.substring(0, t.length -1);
+ } 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(v[i]);
+ }
+ } else if (v || (typeof v === 'string')) {
+ 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 || (typeof v === 'string' && v.length)) {
+ segments[segment] = 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' ? URI.encode(v) : v;
+ } else {
+ for (i = 0, l = v.length; i < l; i++) {
+ v[i] = URI.decode(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 === 'object') {
+ for (var key in name) {
+ if (hasOwn.call(name, key)) {
+ data[key] = name[key];
+ }
+ }
+ } else if (typeof name === 'string') {
+ data[name] = value !== undefined ? value : null;
+ } 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)
+ .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) {
+ if (this._parts.urn) {
+ return this;
+ }
+
+ if (!this._parts.path || this._parts.path === '/') {
+ return this;
+ }
+
+ var _was_relative;
+ var _path = this._parts.path;
+ var _leadingParents = '';
+ var _parent, _pos;
+
+ // handle relative paths
+ if (_path.charAt(0) !== '/') {
+ _was_relative = true;
+ _path = '/' + _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.indexOf('/..');
+ 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);
+ }
+
+ _path = URI.recodePath(_path);
+ 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;
+ this.normalize();
+ 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;
+ this.normalize();
+ 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();
+ 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(relative.path(), base.path());
+
+ // 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;
+}));
+
EPUBJS.Book = function(_url){
// Promises
this.opening = new RSVP.defer();
@@ -2236,7 +4245,7 @@ EPUBJS.Book = function(_url){
this.url = undefined;
- this.spine = undefined;
+ this.spine = new EPUBJS.Spine(this.request);
this.loading = {
manifest: new RSVP.defer(),
@@ -2262,6 +4271,8 @@ EPUBJS.Book = function(_url){
this.isRendered = false;
this._q = EPUBJS.core.queue(this);
+ this.request = this.requestMethod.bind(this);
+
if(_url) {
this.open(_url);
}
@@ -2275,6 +4286,11 @@ EPUBJS.Book.prototype.open = function(_url){
var containerPath = "META-INF/container.xml";
var location;
+ if(!_url) {
+ this.opening.resolve(this);
+ return this.opened;
+ }
+
// Reuse parsed url or create a new uri object
if(typeof(_url) === "object") {
uri = _url;
@@ -2363,7 +4379,7 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
book.package = parse.packageContents(packageXml); // Extract info from contents
book.package.baseUrl = book.url; // Provides a url base for resolving paths
- book.spine = new EPUBJS.Spine(book.package, this.request);
+ this.spine.load(book.package);
book.navigation = new EPUBJS.Navigation(book.package, this.request);
book.navigation.load().then(function(toc){
@@ -2390,20 +4406,23 @@ EPUBJS.Book.prototype.renderTo = function(element, options) {
return rendition;
};
-EPUBJS.Book.prototype.request = function(_url) {
+EPUBJS.Book.prototype.requestMethod = function(_url) {
// Switch request methods
if(this.archived) {
// TODO: handle archived
} else {
- return EPUBJS.core.request(_url, 'xml', this.credentials);
+ return EPUBJS.core.request(_url, 'xml', this.requestCredentials, this.requestHeaders);
}
};
-EPUBJS.Book.prototype.setCredentials = function(_credentials) {
- this.credentials = _credentials;
+EPUBJS.Book.prototype.setRequestCredentials = function(_credentials) {
+ this.requestCredentials = _credentials;
};
+EPUBJS.Book.prototype.setRequestHeaders = function(_headers) {
+ this.requestHeaders = _headers;
+};
//-- Enable binding events to book
RSVP.EventTarget.mixin(EPUBJS.Book.prototype);
@@ -2421,7 +4440,7 @@ RSVP.on('rejected', function(event){
});
EPUBJS.core = {};
-EPUBJS.core.request = function(url, type, withCredentials) {
+EPUBJS.core.request = function(url, type, withCredentials, headers) {
var supportsURL = window.URL;
var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer";
@@ -2433,6 +4452,8 @@ EPUBJS.core.request = function(url, type, withCredentials) {
// 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', {
@@ -2442,7 +4463,13 @@ EPUBJS.core.request = function(url, type, withCredentials) {
if(withCredentials) {
xhr.withCredentials = true;
}
+
xhr.open("GET", url, true);
+
+ for(header in headers) {
+ xhr.setRequestHeader(header, headers[header]);
+ }
+
xhr.onreadystatechange = handler;
if(type == 'blob'){
@@ -2486,6 +4513,7 @@ EPUBJS.core.request = function(url, type, withCredentials) {
deferred.resolve(r);
} else {
deferred.reject({
+ status: this.status,
message : this.response,
stack : new Error().stack
});
@@ -2654,28 +4682,52 @@ EPUBJS.core.values = function(object) {
};
EPUBJS.core.resolveUrl = function(base, path) {
- var url,
+ var url = [],
segments = [],
- // uri = EPUBJS.core.uri(path),
- folders = base.split("/"),
+ baseUri = EPUBJS.core.uri(base),
+ pathUri = EPUBJS.core.uri(path),
+ baseDirectory = baseUri.directory,
+ pathDirectory = pathUri.directory,
+ // folders = base.split("/"),
paths;
// if(uri.host) {
// return path;
// }
-
- folders.pop();
- paths = path.split("/");
- paths.forEach(function(p){
- if(p === ".."){
- folders.pop();
- }else{
- segments.push(p);
+ 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);
+ }
+
+
+ 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.push(part);
}
});
- url = folders.concat(segments);
+ url = url.concat(baseUri.origin, directories, segments, pathUri.filename);
return url.join("/");
};
@@ -2689,6 +4741,10 @@ EPUBJS.core.documentHeight = function() {
document.documentElement.offsetHeight
);
};
+
+EPUBJS.core.isNumber = function(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n);
+}
EPUBJS.EpubCFI = function(cfiStr){
if(cfiStr) return this.parse(cfiStr);
};
@@ -3193,94 +5249,48 @@ EPUBJS.EpubCFI.prototype.generateRangeFromCfi = function(cfi, _doc) {
return range;
};
-EPUBJS.hooks = {};
-EPUBJS.Hooks = (function(){
- function hooks(){}
-
- //-- Get pre-registered hooks
- hooks.prototype.getHooks = function(){
- var plugs, hooks;
- this.hooks = {};
- Array.prototype.slice.call(arguments).forEach(function(arg){
- this.hooks[arg] = [];
- }, this);
+EPUBJS.Hook = function(context){
+ this.context = context || this;
+ this.hooks = [];
+};
- for (var plugType in this.hooks) {
- hooks = EPUBJS.hooks[plugType];
- if(hooks){
- plugs = EPUBJS.core.values();
-
- plugs.forEach(function(hook){
- this.registerHook(plugType, hook);
- }, this);
+//-- Hooks allow for injecting async functions that must all complete in order before finishing
+// Functions must return a promise.
+
+// this.beforeDisplay = new EPUBJS.Hook();
+// this.beforeDisplay.register(function(){});
+// this.beforeDisplay.trigger(args).then(function(){});
+
+// Adds a function to be run before a hook completes
+EPUBJS.Hook.prototype.register = function(func){
+ this.hooks.push(func);
+};
+
+// Triggers a hook to run all functions
+EPUBJS.Hook.prototype.trigger = function(){
+ var length = this.hooks.length;
+ var current = 0;
+ var executing;
+ var defer = new RSVP.defer();
+ var args = arguments;
+
+ if(length) {
+
+ executing = this.hooks[current].apply(this.context, args);
+ executing.then(function(){
+ current += 1;
+ if(current < length) {
+ return this.hooks[current].apply(this.context, args);
}
- }
- };
-
- //-- Hooks allow for injecting async functions that must all complete before continuing
- // Functions must have a callback as their first argument.
- hooks.prototype.registerHook = function(type, toAdd, toFront){
-
- if(typeof(this.hooks[type]) != "undefined"){
-
- if(typeof(toAdd) === "function"){
- if(toFront) {
- this.hooks[type].unshift(toAdd);
- }else{
- this.hooks[type].push(toAdd);
- }
- }else if(Array.isArray(toAdd)){
- toAdd.forEach(function(hook){
- if(toFront) {
- this.hooks[type].unshift(hook);
- }else{
- this.hooks[type].push(hook);
- }
- }, this);
- }
- }else{
- //-- Allows for undefined hooks, but maybe this should error?
- this.hooks[type] = [func];
- }
- };
-
- hooks.prototype.triggerHooks = function(type, callback, passed){
- var hooks, count;
-
- if(typeof(this.hooks[type]) == "undefined") return false;
-
- hooks = this.hooks[type];
-
- count = hooks.length;
- if(count === 0 && callback) {
- callback();
- }
-
- function countdown(){
- count--;
- if(count <= 0 && callback) callback();
- }
-
- hooks.forEach(function(hook){
- hook(countdown, passed);
- });
- };
-
- return {
- register: function(name) {
- if(EPUBJS.hooks[name] === undefined) { EPUBJS.hooks[name] = {}; }
- if(typeof EPUBJS.hooks[name] !== 'object') { throw "Already registered: "+name; }
- return EPUBJS.hooks[name];
- },
- mixin: function(object) {
- for (var prop in hooks.prototype) {
- object[prop] = hooks.prototype[prop];
- }
- }
- };
-})();
-
+ }.bind(this));
+
+ } else {
+ executing = defer.promise;
+ defer.resolve();
+ }
+ return executing;
+};
EPUBJS.Infinite = function(container, renderer){
this.container = container;
this.windowHeight = window.innerHeight;
@@ -3288,7 +5298,7 @@ EPUBJS.Infinite = function(container, renderer){
this.scrolled = false;
this.ignore = false;
this.displaying = false;
- this.offset = 250;
+ this.offset = 350;
this.views = [];
this.renderer = renderer;
this.prevScrollTop = 0;
@@ -3304,7 +5314,6 @@ EPUBJS.Infinite.prototype.start = function() {
} else {
this.ignore = false;
}
- // console.log("scroll", this.container.scrollTop)
}.bind(this));
// Reset to prevent jump
@@ -3328,44 +5337,6 @@ EPUBJS.Infinite.prototype.backwards = function() {
this.trigger("backwards");
};
-/*
-
-// Manage Views
-EPUBJS.Infinite.prototype.jump = function(view){
- this.views.push(view);
-};
-
-EPUBJS.Infinite.prototype.append = function(view){
- this.views.push(view);
- view.appendTo(this.container);
-};
-
-EPUBJS.Infinite.prototype.prepend = function(view){
- this.views.unshift(view);
- view.prependTo(this.container);
-};
-
-// Simple Insert
-EPUBJS.Infinite.prototype.insert = function(view, index){
-
- var position;
- var distanceFront = index - this.positions[0];
- var distanceRear = index - this.positions[this.positions.length-1];
-
- if(distanceFront >= 0 || !this.positions.length) {
- position = this.append(view);
- this.positions.push(index);
- } else if(distanceRear <= 0) {
- position = this.prepend(view);
- this.positions.unshift(index);
- }
-
-
-
- return position;
-};
-
-*/
EPUBJS.Infinite.prototype.check = function(){
@@ -3382,10 +5353,12 @@ EPUBJS.Infinite.prototype.check = function(){
var up = scrollTop + this.offset > scrollHeight-height;
var down = scrollTop < this.offset;
- // console.debug("scroll", scrollTop)
+
+ // Add to bottom
if(up && direction > 0) {
this.forwards();
}
+ // Add to top
else if(down && direction < 0) {
this.backwards();
}
@@ -3640,12 +5613,16 @@ EPUBJS.Navigation = function(_package, _request){
// Load the navigation
EPUBJS.Navigation.prototype.load = function(_request) {
var request = _request || EPUBJS.core.request;
- var loading;
+ 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;
@@ -3868,7 +5845,7 @@ EPUBJS.Parser.prototype.manifest = function(manifestXml){
'type' : type,
'properties' : properties
};
-
+
});
return manifest;
@@ -3891,6 +5868,7 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
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') || '',
@@ -4048,28 +6026,18 @@ EPUBJS.Renderer = function(book, _options) {
var options = _options || {};
this.settings = {
hidden: options.hidden || false,
- viewsLimit: 4,
+ viewsLimit: 6,
width: options.width || false,
height: options.height || false,
};
this.book = book;
- // Listen for load events
- // this.on("render:loaded", this.loaded.bind(this));
-
// Blank Cfi for Parsing
this.epubcfi = new EPUBJS.EpubCFI();
this.layoutSettings = {};
- //-- Adds Hook methods to the Book prototype
- // Hooks will all return before triggering the callback.
- EPUBJS.Hooks.mixin(this);
-
- //-- Get pre-registered hooks for events
- this.getHooks("beforeChapterDisplay");
-
//-- Queue up page changes if page map isn't ready
this._q = EPUBJS.core.queue(this);
@@ -4077,14 +6045,18 @@ EPUBJS.Renderer = function(book, _options) {
this.initialize({
"width" : this.settings.width,
- "height" : this.settings.height,
- "hidden" : true
+ "height" : this.settings.height
});
this.rendering = false;
this.views = [];
this.positions = [];
+ //-- Adds Hook methods to the Renderer prototype
+ this.hooks = {};
+ this.hooks.display = new EPUBJS.Hook(this);
+ this.hooks.replacements = new EPUBJS.Hook(this);
+
};
/**
@@ -4097,7 +6069,6 @@ EPUBJS.Renderer.prototype.initialize = function(_options){
var width = options.width ? options.width + "px" : "100%";
var hidden = options.hidden || false;
-
this.container = document.createElement("div");
this.infinite = new EPUBJS.Infinite(this.container, this);
@@ -4115,7 +6086,7 @@ EPUBJS.Renderer.prototype.initialize = function(_options){
this.wrapper.appendChild(this.container);
return this.wrapper;
}
-
+
return this.container;
};
@@ -4172,15 +6143,27 @@ EPUBJS.Renderer.prototype.attachTo = function(_element){
this.infinite.start();
this.infinite.on("forwards", function(){
- if(!this.rendering) this.forwards();
+ var next = this.last().section.index + 1;
+
+ if(!this.rendering && next < this.book.spine.length){
+ this.forwards();
+ }
+
}.bind(this));
this.infinite.on("backwards", function(){
- if(!this.rendering) this.backwards();
+ var prev = this.first().section.index - 1;
+
+ if(!this.rendering && prev > 0){
+ this.backwards();
+ }
+
}.bind(this));
window.addEventListener("resize", this.onResized.bind(this), false);
+ this.hooks.replacements.register(this.replacements.bind(this));
+
};
EPUBJS.Renderer.prototype.clear = function(){
@@ -4200,14 +6183,20 @@ EPUBJS.Renderer.prototype.display = function(what){
this.book.opened.then(function(){
var section = this.book.spine.get(what);
- var rendered = this.render(section);
+ var rendered;
- rendered.
- then(this.fill.bind(this)).
- then(function(){
- displaying.resolve(this);
- }.bind(this));
-
+ if(section){
+ rendered = this.render(section);
+
+ rendered
+ .then(this.fill.bind(this))
+ .then(function(){
+ displaying.resolve(this);
+ }.bind(this));
+ } else {
+ displaying.reject(new Error("No Section Found"));
+ }
+
}.bind(this));
return displayed;
@@ -4215,28 +6204,35 @@ EPUBJS.Renderer.prototype.display = function(what){
EPUBJS.Renderer.prototype.render = function(section){
var rendered;
- var view = new EPUBJS.View();
+ var view;
if(!section) {
- rendered.reject();
- return;
- };
-
- rendered = section.render();
- view.index = section.index;
+ rendered = new RSVP.defer();
+ rendered.reject(new Error("No Section Provided"));
+ return rendered.promise;
+ };
+ view = new EPUBJS.View(section);
+ // Place view in correct position
+ this.insert(view, section.index);
- return rendered.
- then(function(contents){
- // Place view in correct position
- this.insert(view, section.index);
+ rendered = view.render(this.book.request);
- return view.load(contents);
+ return rendered
+ .then(function(){
+ return this.hooks.display.trigger(view);
+ }.bind(this))
+ .then(function(){
+ return this.hooks.replacements.trigger(view, this);
}.bind(this))
.then(function(){
this.rendering = false;
+ view.show();
return view;
+ }.bind(this))
+ .catch(function(e){
+ this.trigger("loaderror", e);
}.bind(this));
};
@@ -4247,14 +6243,13 @@ EPUBJS.Renderer.prototype.forwards = function(){
var rendered;
var section;
- next = this.last().index + 1;
-
+ next = this.last().section.index + 1;
if(this.rendering || next === this.book.spine.length){
rendered = new RSVP.defer();
- rendered.reject({message: "reject forwards"});
+ rendered.reject(new Error("Reject Forwards"));
return rendered.promise;
}
- console.log("going forwards")
+ // console.log("going forwards")
this.rendering = true;
@@ -4262,11 +6257,8 @@ EPUBJS.Renderer.prototype.forwards = function(){
rendered = this.render(section);
rendered.then(function(){
- // this.rendering = false;
var first = this.first();
var bounds = first.bounds();
- var container = this.container.getBoundingClientRect();
- var offset;
var prev = this.container.scrollTop;
if(this.views.length > this.settings.viewsLimit) {
@@ -4278,6 +6270,7 @@ EPUBJS.Renderer.prototype.forwards = function(){
}
}.bind(this));
+
return rendered;
};
@@ -4288,13 +6281,14 @@ EPUBJS.Renderer.prototype.backwards = function(view){
var section;
- prev = this.first().index - 1;
+ prev = this.first().section.index - 1;
+
if(this.rendering || prev < 0){
rendered = new RSVP.defer();
- rendered.reject({message: "reject backwards"});
+ rendered.reject(new Error("Reject Backwards"));
return rendered.promise;
}
- console.log("going backwards")
+ // console.log("going backwards")
this.rendering = true;
@@ -4303,6 +6297,7 @@ EPUBJS.Renderer.prototype.backwards = function(view){
rendered.then(function(){
// this.container.scrollTop += this.first().height;
+
this.infinite.scrollBy(0, this.first().height, true);
if(this.views.length > this.settings.viewsLimit) {
@@ -4323,21 +6318,25 @@ EPUBJS.Renderer.prototype.fill = function() {
var next = function(){
var bottom = this.last().bounds().bottom;
var defer = new RSVP.defer();
- var promise = defer.promise;
- if (height && bottom && (bottom < height) && (this.last().index + 1 < this.book.spine.length)) {
+ if (height && bottom && (bottom < height)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(next);
} else {
this.rendering = false;
defer.resolve();
- return promise;
+ return defer.promise;
}
}.bind(this);
+ var prev = this.first().section.index - 1;
+ var filling = next();
+
+ if(prev > 0){
+ filling.then(this.backwards.bind(this));
+ }
- return next().
- then(this.backwards.bind(this)).
- then(function(){
+ return filling
+ .then(function(){
this.rendering = false;
}.bind(this));
@@ -4365,12 +6364,11 @@ EPUBJS.Renderer.prototype.insert = function(view, index){
if(!this.first()) {
this.append(view);
- } else if(index - this.first().index >= 0) {
+ } else if(index - this.first().section.index >= 0) {
this.append(view);
- } else if(index - this.last().index <= 0) {
+ } else if(index - this.last().section.index <= 0) {
this.prepend(view);
}
- console.log("insert")
// return position;
};
@@ -4391,36 +6389,152 @@ EPUBJS.Renderer.prototype.last = function() {
return this.views[this.views.length-1];
};
+EPUBJS.Renderer.prototype.replacements = function(view, renderer) {
+ var task = new RSVP.defer();
+ var links = view.document.querySelectorAll("a[href]");
+ var replaceLinks = function(link){
+ var href = link.getAttribute("href");
+ var isRelative = href.search("://");
+ // var directory = EPUBJS.core.uri(view.window.location.href).directory;
+ // var relative;
+
+ if(isRelative != -1){
+
+ link.setAttribute("target", "_blank");
+
+ }else{
+
+ // relative = EPUBJS.core.resolveUrl(directory, href);
+
+ link.onclick = function(){
+ renderer.display(href);
+ return false;
+ };
+
+ }
+ };
+
+ for (var i = 0; i < links.length; i++) {
+ replaceLinks(links[i]);
+ };
+
+ task.resolve();
+ return task.promise;
+};
+
//-- Enable binding events to Renderer
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);
-EPUBJS.Spine = function(_package, _request){
- this.items = _package.spine;
- this.manifest = _package.manifest;
- this.spineNodeIndex = _package.spineNodeIndex;
- this.baseUrl = _package.baseUrl || '';
+EPUBJS.Section = function(item){
+ 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.cfiBase = item.cfiBase;
+
+ this.hooks = {};
+ this.hooks.replacements = new EPUBJS.Hook(this);
+
+ // Register replacements
+ this.hooks.replacements.register(this.replacements);
+};
+
+
+EPUBJS.Section.prototype.load = function(_request){
+ var request = _request || this.request || EPUBJS.core.request;
+ var loading = new RSVP.defer();
+ var loaded = loading.promise;
+
+ if(this.contents) {
+ loading.resolve(this.contents);
+ } else {
+ request(this.url, 'xml')
+ .then(function(xml){
+ var base;
+ var directory = EPUBJS.core.folder(this.url);
+
+ this.document = xml;
+ this.contents = xml.documentElement;
+
+ return this.hooks.replacements.trigger(this.document);
+ }.bind(this))
+ .then(function(){
+ loading.resolve(this.contents);
+ }.bind(this))
+ .catch(function(error){
+ loading.reject(error);
+ });
+ }
+
+ return loaded;
+};
+
+EPUBJS.Section.prototype.replacements = function(_document){
+ var task = new RSVP.defer();
+ var base = _document.createElement("base"); // TODO: check if exists
+
+ base.setAttribute("href", this.url);
+ _document.head.insertBefore(base, _document.head.firstChild);
+
+ task.resolve();
+
+ return task.promise;
+};
+
+EPUBJS.Section.prototype.beforeSectionLoad = function(){
+ // Stub for a hook - replace me for now
+}
+
+EPUBJS.Section.prototype.render = function(_request){
+ var rendering = new RSVP.defer();
+ var rendered = rendering.promise;
+
+ this.load(_request).then(function(contents){
+ var serializer = new XMLSerializer();
+ var output = serializer.serializeToString(contents);
+ rendering.resolve(output);
+ })
+ .catch(function(error){
+ rendering.reject(error);
+ });
+
+ return rendered;
+};
+
+EPUBJS.Section.prototype.find = function(_query){
+
+};
+EPUBJS.Spine = function(_request){
this.request = _request;
- this.length = this.items.length;
- this.epubcfi = new EPUBJS.EpubCFI();
this.spineItems = [];
this.spineByHref = {};
this.spineById = {};
+};
+
+EPUBJS.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.epubcfi = new EPUBJS.EpubCFI();
+
this.items.forEach(function(item, index){
- var cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);
var href, url;
var manifestItem = this.manifest[item.idref];
var spineItem;
+ item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);
if(manifestItem) {
- href = manifestItem.href;
- url = this.baseUrl + href;
+ item.href = manifestItem.href;
+ item.url = this.baseUrl + item.href;
}
- spineItem = new EPUBJS.SpineItem(item, href, url, cfiBase);
- this.spineItems.push(spineItem);
-
- this.spineByHref[spineItem.href] = index;
- this.spineById[spineItem.idref] = index;
+ spineItem = new EPUBJS.Section(item);
+ this.append(spineItem);
}.bind(this));
@@ -4445,118 +6559,51 @@ EPUBJS.Spine.prototype.get = function(target) {
return this.spineItems[index];
};
+EPUBJS.Spine.prototype.append = function(section) {
+ var index = this.spineItems.length;
+ section.index = index;
-EPUBJS.SpineItem = function(item, href, url, cfiBase){
- this.idref = item.idref;
- this.linear = item.linear;
- this.properties = item.properties;
- this.index = item.index;
- this.href = href;
- this.url = url;
- this.cfiBase = cfiBase;
+ this.spineItems.push(section);
+
+ this.spineByHref[section.href] = index;
+ this.spineById[section.idref] = index;
+
+ return index;
};
+EPUBJS.Spine.prototype.prepend = function(section) {
+ var index = this.spineItems.unshift(section);
+ this.spineByHref[section.href] = 0;
+ this.spineById[section.idref] = 0;
-EPUBJS.SpineItem.prototype.load = function(_request){
- var request = _request || this.request || EPUBJS.core.request;
- var loading = new RSVP.defer();
- var loaded = loading.promise;
-
- if(this.contents) {
- loading.resolve(this.contents);
- } else {
- request(this.url, 'xml').then(function(xml){
- var base;
- var directory = EPUBJS.core.folder(this.url);
-
- this.document = xml;
- this.contents = xml.documentElement;
-
- this.replacements(this.document);
-
- loading.resolve(this.contents);
- }.bind(this));
- }
-
- return loaded;
-};
-
-EPUBJS.SpineItem.prototype.replacements = function(_document){
- var base = _document.createElement("base");
- base.setAttribute("href", this.url);
- _document.head.insertBefore(base, _document.head.firstChild);
-};
-
-EPUBJS.SpineItem.prototype.render = function(){
- var rendering = new RSVP.defer();
- var rendered = rendering.promise;
-
- this.load().then(function(contents){
- var serializer = new XMLSerializer();
- var output = serializer.serializeToString(contents);
- rendering.resolve(output);
+ // Re-index
+ this.spineItems.forEach(function(item, index){
+ item.index = index;
});
-
- return rendered;
+
+ return 0;
};
-EPUBJS.SpineItem.prototype.find = function(_query){
+EPUBJS.Spine.prototype.insert = function(section, index) {
};
-EPUBJS.View = function(width, height) {
+
+EPUBJS.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);
+ }
+};
+EPUBJS.View = function(section) {
this.id = "epubjs-view:" + EPUBJS.core.uuid();
- this.loading = new RSVP.defer();
- this.loaded = this.loading.promise;
+ this.rendering = new RSVP.defer();
+ this.rendered = this.rendering.promise;
this.iframe = this.create();
- this.height;
- this.width;
-};
-
-EPUBJS.View.prototype.load = function(contents) {
- var loading = new RSVP.defer();
- var loaded = loading.promise;
-
- this.document = this.iframe.contentDocument;
-
- this.iframe.addEventListener("load", function(event) {
- var layout;
-
- this.window = this.iframe.contentWindow;
- this.document = this.iframe.contentDocument;
-
- this.iframe.style.display = "block";
-
- // Reset Body Styles
- this.document.body.style.margin = "0";
- this.document.body.style.display = "inline-block";
-
- this.layout();
-
- this.iframe.style.visibility = "visible";
-
- setTimeout(function(){
- this.window.addEventListener("resize", this.resized.bind(this), false);
- }.bind(this), 10); // Wait to listen for resize events
-
- this.document.fonts.onloading = function(){
- console.log("loaded fonts");
- // this.layout();
- }.bind(this);
-
- // this.observer = this.observe(this.document);
-
- loading.resolve(this);
- this.loading.resolve(this);
-
- }.bind(this));
-
-
- // this.iframe.srcdoc = contents;
- this.document.open();
- this.document.write(contents);
- this.document.close();
-
- return loaded;
+ this.section = section;
};
EPUBJS.View.prototype.create = function() {
@@ -4588,9 +6635,81 @@ EPUBJS.View.prototype.resized = function(e) {
};
+EPUBJS.View.prototype.render = function(_request) {
+ return this.section.render(_request)
+ .then(function(contents){
+ return this.load(contents);
+ }.bind(this))
+ .then(this.display.bind(this))
+ .then(function(){
+ this.rendering.resolve(this);
+ }.bind(this));
+};
+
+EPUBJS.View.prototype.load = function(contents) {
+ var loading = new RSVP.defer();
+ var loaded = loading.promise;
+
+ this.document = this.iframe.contentDocument;
+
+ this.iframe.addEventListener("load", function(event) {
+ var layout;
+
+ this.window = this.iframe.contentWindow;
+ this.document = this.iframe.contentDocument;
+
+ loading.resolve(this);
+
+ }.bind(this));
+
+
+ // this.iframe.srcdoc = contents;
+ this.document.open();
+ this.document.write(contents);
+ this.document.close();
+
+ return loaded;
+};
+
+EPUBJS.View.prototype.display = function(contents) {
+ var displaying = new RSVP.defer();
+ var displayed = displaying.promise;
+
+ this.iframe.style.display = "block";
+
+ // Reset Body Styles
+ this.document.body.style.margin = "0";
+ this.document.body.style.display = "inline-block";
+
+ // Set Padding -> TODO: apply these from a function
+ this.document.body.style.padding = "0 20px 20px 20px";
+
+
+ setTimeout(function(){
+ this.window.addEventListener("resize", this.resized.bind(this), false);
+ }.bind(this), 10); // Wait to listen for resize events
+
+
+
+ if(this.document.fonts.status !== "loading") {
+ this.layout();
+ displaying.resolve(this);
+ } else {
+ this.document.fonts.onloading = function(){
+ this.layout();
+ displaying.resolve(this);
+ }.bind(this);
+ }
+
+ // this.observer = this.observe(this.document);
+
+ return displayed
+
+};
+
EPUBJS.View.prototype.layout = function() {
var bounds;
- console.log("layout")
+
// Check bounds
bounds = this.document.body.getBoundingClientRect();
@@ -4598,13 +6717,8 @@ EPUBJS.View.prototype.layout = function() {
console.error("View not shown");
}
- // Apply Changes
- this.resizing = true;
- this.iframe.style.height = bounds.height + "px";
- // this.iframe.style.width = bounds.width + "px";
- // Check again
- bounds = this.document.body.getBoundingClientRect();
+ // Apply Changes
this.resizing = true;
this.iframe.style.height = bounds.height + "px";
// this.iframe.style.width = bounds.width + "px";
@@ -4647,10 +6761,20 @@ EPUBJS.View.prototype.bounds = function() {
return this.iframe.getBoundingClientRect();
};
+EPUBJS.View.prototype.show = function() {
+ this.iframe.style.display = "block";
+ this.iframe.style.visibility = "visible";
+};
+
+EPUBJS.View.prototype.hide = function() {
+ this.iframe.style.display = "none";
+ this.iframe.style.visibility = "hidden";
+};
+
EPUBJS.View.prototype.destroy = function() {
// Stop observing
// this.observer.disconnect();
-
+
this.element.removeChild(this.iframe);
};
diff --git a/dist/epub.min.js b/dist/epub.min.js
index eea15e9..a78a14a 100644
--- a/dist/epub.min.js
+++ b/dist/epub.min.js
@@ -1,2 +1,3 @@
-"undefined"==typeof EPUBJS&&(("undefined"!=typeof window?window:this).EPUBJS={}),EPUBJS.VERSION="0.3.0",EPUBJS.Render={},function(e){"use strict";var t=function(e){return new EPUBJS.Book(e)};t.Render={register:function(e,r){t.Render[e]=r}},"object"==typeof exports?(e.RSVP=require("rsvp"),module.exports=t):"function"==typeof define&&define.amd?define(t):e.ePub=t}(this),function(e){var t,r;!function(){var e={},n={};t=function(t,r,n){e[t]={deps:r,callback:n}},r=function(t){function i(e){if("."!==e.charAt(0))return e;for(var r=e.split("/"),n=t.split("/").slice(0,-1),i=0,o=r.length;o>i;i++){var s=r[i];if(".."===s)n.pop();else{if("."===s)continue;n.push(s)}}return n.join("/")}if(n[t])return n[t];if(n[t]={},!e[t])throw new Error("Could not find module "+t);for(var o,s=e[t],a=s.deps,u=s.callback,c=[],h=0,p=a.length;p>h;h++)c.push("exports"===a[h]?o={}:r(i(a[h])));var l=u.apply(this,c);return n[t]=o||l},r.entries=e}(),t("rsvp/-internal",["./utils","./instrument","./config","exports"],function(e,t,r,n){"use strict";function i(){}function o(e){try{return e.then}catch(t){return J.error=t,J}}function s(e,t,r,n){try{e.call(t,r,n)}catch(i){return i}}function a(e,t,r){w.async(function(e){var n=!1,i=s(r,t,function(r){n||(n=!0,t!==r?h(e,r):l(e,r))},function(t){n||(n=!0,f(e,t))},"Settle: "+(e._label||" unknown promise"));!n&&i&&(n=!0,f(e,i))},e)}function u(e,t){e._onerror=null,t._state===x?l(e,t._result):e._state===U?f(e,t._result):d(t,void 0,function(r){t!==r?h(e,r):l(e,r)},function(t){f(e,t)})}function c(e,t){if(t instanceof e.constructor)u(e,t);else{var r=o(t);r===J?f(e,J.error):void 0===r?l(e,t):P(r)?a(e,t,r):l(e,t)}}function h(e,t){e===t?l(e,t):S(t)?c(e,t):l(e,t)}function p(e){e._onerror&&e._onerror(e._result),v(e)}function l(e,t){e._state===B&&(e._result=t,e._state=x,0===e._subscribers.length?w.instrument&&b("fulfilled",e):w.async(v,e))}function f(e,t){e._state===B&&(e._state=U,e._result=t,w.async(p,e))}function d(e,t,r,n){var i=e._subscribers,o=i.length;e._onerror=null,i[o]=t,i[o+x]=r,i[o+U]=n,0===o&&e._state&&w.async(v,e)}function v(e){var t=e._subscribers,r=e._state;if(w.instrument&&b(r===x?"fulfilled":"rejected",e),0!==t.length){for(var n,i,o=e._result,s=0;se;e+=2){var t=p[e],r=p[e+1];t(r),p[e]=void 0,p[e+1]=void 0}s=0}var s=0;e["default"]=function(e,t){p[s]=e,p[s+1]=t,s+=2,2===s&&a()};var a,u="undefined"!=typeof window?window:{},c=u.MutationObserver||u.WebKitMutationObserver,h="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,p=new Array(1e3);a="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?t():c?r():h?n():i()}),t("rsvp/config",["./events","exports"],function(e,t){"use strict";function r(e,t){return"onerror"===e?void i.on("error",t):2!==arguments.length?i[e]:void(i[e]=t)}var n=e["default"],i={instrument:!1};n.mixin(i),t.config=i,t.configure=r}),t("rsvp/defer",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e){var t={};return t.promise=new r(function(e,r){t.resolve=e,t.reject=r},e),t}}),t("rsvp/enumerator",["./utils","./-internal","exports"],function(e,t,r){"use strict";function n(e,t,r){return e===p?{state:"fulfilled",value:r}:{state:"rejected",reason:r}}function i(e,t,r,n){this._instanceConstructor=e,this.promise=new e(a,n),this._abortOnReject=r,this._validateInput(t)?(this._input=t,this.length=t.length,this._remaining=t.length,this._init(),0===this.length?c(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&c(this.promise,this._result))):u(this.promise,this._validationError())}var o=e.isArray,s=e.isMaybeThenable,a=t.noop,u=t.reject,c=t.fulfill,h=t.subscribe,p=t.FULFILLED,l=t.REJECTED,f=t.PENDING,d=!0;r.ABORT_ON_REJECTION=d,r.makeSettledResult=n,i.prototype._validateInput=function(e){return o(e)},i.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},i.prototype._init=function(){this._result=new Array(this.length)},r["default"]=i,i.prototype._enumerate=function(){for(var e=this.length,t=this.promise,r=this._input,n=0;t._state===f&&e>n;n++)this._eachEntry(r[n],n)},i.prototype._eachEntry=function(e,t){var r=this._instanceConstructor;s(e)?e.constructor===r&&e._state!==f?(e._onerror=null,this._settledAt(e._state,t,e._result)):this._willSettleAt(r.resolve(e),t):(this._remaining--,this._result[t]=this._makeResult(p,t,e))},i.prototype._settledAt=function(e,t,r){var n=this.promise;n._state===f&&(this._remaining--,this._abortOnReject&&e===l?u(n,r):this._result[t]=this._makeResult(e,t,r)),0===this._remaining&&c(n,this._result)},i.prototype._makeResult=function(e,t,r){return r},i.prototype._willSettleAt=function(e,t){var r=this;h(e,void 0,function(e){r._settledAt(p,t,e)},function(e){r._settledAt(l,t,e)})}}),t("rsvp/events",["exports"],function(e){"use strict";function t(e,t){for(var r=0,n=e.length;n>r;r++)if(e[r]===t)return r;return-1}function r(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t}e["default"]={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e._promiseCallbacks=void 0,e},on:function(e,n){var i,o=r(this);i=o[e],i||(i=o[e]=[]),-1===t(i,n)&&i.push(n)},off:function(e,n){var i,o,s=r(this);return n?(i=s[e],o=t(i,n),void(-1!==o&&i.splice(o,1))):void(s[e]=[])},trigger:function(e,t){var n,i,o=r(this);if(n=o[e])for(var s=0;sa;a++)s[a]=t(e[a]);return n.all(s,r).then(function(t){for(var r=new Array(o),n=0,i=0;o>i;i++)t[i]&&(r[n]=e[i],n++);return r.length=n,r})})}}),t("rsvp/hash-settled",["./promise","./enumerator","./promise-hash","./utils","exports"],function(e,t,r,n,i){"use strict";function o(e,t,r){this._superConstructor(e,t,!1,r)}var s=e["default"],a=t.makeSettledResult,u=r["default"],c=t["default"],h=n.o_create;o.prototype=h(u.prototype),o.prototype._superConstructor=c,o.prototype._makeResult=a,o.prototype._validationError=function(){return new Error("hashSettled must be called with an object")},i["default"]=function(e,t){return new o(s,e,t).promise}}),t("rsvp/hash",["./promise","./promise-hash","./enumerator","exports"],function(e,t,r,n){"use strict";{var i=e["default"],o=t["default"];r.ABORT_ON_REJECTION}n["default"]=function(e,t){return new o(i,e,t).promise}}),t("rsvp/instrument",["./config","./utils","exports"],function(e,t,r){"use strict";var n=e.config,i=t.now,o=[];r["default"]=function(e,t,r){1===o.push({name:e,payload:{guid:t._guidKey+t._id,eventName:e,detail:t._result,childGuid:r&&t._guidKey+r._id,label:t._label,timeStamp:i(),stack:new Error(t._label).stack}})&&setTimeout(function(){for(var e,t=0;ta;a++)s[a]=t(e[a]);return n.all(s,r)})}}),t("rsvp/node",["./promise","./utils","exports"],function(e,t,r){"use strict";var n=e["default"],i=t.isArray;r["default"]=function(e,t){function r(){for(var r=arguments.length,i=new Array(r),a=0;r>a;a++)i[a]=arguments[a];var u;return o||s||!t?u=this:("object"==typeof console&&console.warn('Deprecation: RSVP.denodeify() doesn\'t allow setting the "this" binding anymore. Use yourFunction.bind(yourThis) instead.'),u=t),n.all(i).then(function(r){function i(n,i){function a(){for(var e=arguments.length,r=new Array(e),a=0;e>a;a++)r[a]=arguments[a];var u=r[0],c=r[1];if(u)i(u);else if(o)n(r.slice(1));else if(s){var h,p,l={},f=r.slice(1);for(p=0;pa;a++)o=r[a],this._eachEntry(o.entry,o.position)}}),t("rsvp/promise",["./config","./events","./instrument","./utils","./-internal","./promise/cast","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"],function(e,t,r,n,i,o,s,a,u,c,h){"use strict";function p(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function l(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function f(e,t){this._id=R++,this._label=t,this._subscribers=[],d.instrument&&v("created",this),y!==e&&(g(e)||p(),this instanceof f||l(),S(this,e))}var d=e.config,v=(t["default"],r["default"]),g=(n.objectOrFunction,n.isFunction),m=n.now,y=i.noop,E=(i.resolve,i.reject,i.fulfill,i.subscribe),S=i.initializePromise,P=i.invokeCallback,b=i.FULFILLED,w=o["default"],B=s["default"],x=a["default"],U=u["default"],J=c["default"],_="rsvp_"+m()+"-",R=0;h["default"]=f,f.cast=w,f.all=B,f.race=x,f.resolve=U,f.reject=J,f.prototype={constructor:f,_id:void 0,_guidKey:_,_label:void 0,_state:void 0,_result:void 0,_subscribers:void 0,_onerror:function(e){d.trigger("error",e)},then:function(e,t,r){var n=this;n._onerror=null;var i=new this.constructor(y,r),o=n._state,s=n._result;return d.instrument&&v("chained",n,i),o===b&&e?d.async(function(){P(o,i,e,s)}):E(n,i,e,t),i},"catch":function(e,t){return this.then(null,e,t)},"finally":function(e,t){var r=this.constructor;return this.then(function(t){return r.resolve(e()).then(function(){return t})},function(t){return r.resolve(e()).then(function(){throw t})},t)}}}),t("rsvp/promise/all",["../enumerator","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return new r(this,e,!0,t).promise}}),t("rsvp/promise/cast",["./resolve","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=r}),t("rsvp/promise/race",["../utils","../-internal","exports"],function(e,t,r){"use strict";var n=e.isArray,i=(e.isFunction,e.isMaybeThenable,t.noop),o=t.resolve,s=t.reject,a=t.subscribe,u=t.PENDING;r["default"]=function(e,t){function r(e){o(p,e)}function c(e){s(p,e)}var h=this,p=new h(i,t);if(!n(e))return s(p,new TypeError("You must pass an array to race.")),p;for(var l=e.length,f=0;p._state===u&&l>f;f++)a(h.resolve(e[f]),void 0,r,c);return p}}),t("rsvp/promise/reject",["../-internal","exports"],function(e,t){"use strict";var r=e.noop,n=e.reject;t["default"]=function(e,t){var i=this,o=new i(r,t);return n(o,e),o}}),t("rsvp/promise/resolve",["../-internal","exports"],function(e,t){"use strict";var r=e.noop,n=e.resolve;t["default"]=function(e,t){var i=this;if(e&&"object"==typeof e&&e.constructor===i)return e;var o=new i(r,t);return n(o,e),o}}),t("rsvp/race",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.race(e,t)}}),t("rsvp/reject",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.reject(e,t)}}),t("rsvp/resolve",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.resolve(e,t)}}),t("rsvp/rethrow",["exports"],function(e){"use strict";e["default"]=function(e){throw setTimeout(function(){throw e}),e}}),t("rsvp/utils",["exports"],function(e){"use strict";function t(e){return"function"==typeof e||"object"==typeof e&&null!==e}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}e.objectOrFunction=t,e.isFunction=r,e.isMaybeThenable=n;var i;i=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var o=i;e.isArray=o;var s=Date.now||function(){return(new Date).getTime()};e.now=s;var a=Object.create||function(e){var t=function(){};return t.prototype=e,t};e.o_create=a}),t("rsvp",["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"],function(e,t,r,n,i,o,s,a,u,c,h,p,l,f,d,v,g){"use strict";function m(e,t){k.async(e,t)}function y(){k.on.apply(k,arguments)}function E(){k.off.apply(k,arguments)}var S=e["default"],P=t["default"],b=r["default"],w=n["default"],B=i["default"],x=o["default"],U=s["default"],J=a["default"],_=u["default"],R=c["default"],k=h.config,C=h.configure,T=p["default"],I=l["default"],N=f["default"],F=d["default"],A=v["default"];if(k.async=A,"undefined"!=typeof window&&"object"==typeof window.__PROMISE_INSTRUMENTATION__){var O=window.__PROMISE_INSTRUMENTATION__;C("instrument",!0);for(var j in O)O.hasOwnProperty(j)&&y(j,O[j])}g.Promise=S,g.EventTarget=P,g.all=w,g.allSettled=B,g.race=x,g.hash=U,g.hashSettled=J,g.rethrow=_,g.defer=R,g.denodeify=b,g.configure=C,g.on=y,g.off=E,g.resolve=I,g.reject=N,g.async=m,g.map=T,g.filter=F}),e.RSVP=r("rsvp")}(self),EPUBJS.Book=function(e){this.opening=new RSVP.defer,this.opened=this.opening.promise,this.isOpen=!1,this.url=void 0,this.spine=void 0,this.loading={manifest:new RSVP.defer,spine:new RSVP.defer,metadata:new RSVP.defer,cover:new RSVP.defer,navigation:new RSVP.defer,pageList:new RSVP.defer},this.loaded={manifest:this.loading.manifest.promise,spine:this.loading.spine.promise,metadata:this.loading.metadata.promise,cover:this.loading.cover.promise,navigation:this.loading.navigation.promise,pageList:this.loading.pageList.promise},this.ready=RSVP.hash(this.loaded),this.isRendered=!1,this._q=EPUBJS.core.queue(this),e&&this.open(e)},EPUBJS.Book.prototype.open=function(e){var t,r,n,i=new EPUBJS.Parser,o=this,s="META-INF/container.xml";return t="object"==typeof e?e:EPUBJS.core.uri(e),"opf"===t.extension?(this.packageUrl=t.href,this.containerUrl="",t.origin?this.url=t.origin+"/"+t.directory:window?(n=EPUBJS.core.uri(window.location.href),this.url=EPUBJS.core.resolveUrl(n.base,t.directory)):this.url=t.directory,r=this.request(this.packageUrl)):"epub"===t.extension||"zip"===t.extension?(this.archived=!0,this.url=""):t.extension||(this.containerUrl=e+s,r=this.request(this.containerUrl).then(function(e){return i.container(e)}).then(function(t){var r=EPUBJS.core.uri(t.packagePath);return o.packageUrl=e+t.packagePath,o.url=e+r.directory,o.encoding=t.encoding,o.request(o.packageUrl)}).catch(function(e){console.error("Could not load book at: "+(this.packageUrl||this.containerPath)),o.trigger("book:loadFailed",this.packageUrl||this.containerPath),o.opening.reject(e)})),r.then(function(e){o.unpack(e),o.loading.manifest.resolve(o.package.manifest),o.loading.metadata.resolve(o.package.metadata),o.loading.spine.resolve(o.spine),o.loading.cover.resolve(o.cover),this.isOpen=!0,o.opening.resolve(o)}).catch(function(e){console.error(e.message,e.stack),o.opening.reject(e)}),this.opened},EPUBJS.Book.prototype.unpack=function(e){var t=this,r=new EPUBJS.Parser;t.package=r.packageContents(e),t.package.baseUrl=t.url,t.spine=new EPUBJS.Spine(t.package,this.request),t.navigation=new EPUBJS.Navigation(t.package,this.request),t.navigation.load().then(function(e){t.toc=e,t.loading.navigation.resolve(t.toc)}),t.cover=t.url+t.package.coverPath},EPUBJS.Book.prototype.section=function(e){return this.spine.get(e)},EPUBJS.Book.prototype.renderTo=function(e,t){var r=new EPUBJS.Renderer(this,t);return r.attachTo(e),r},EPUBJS.Book.prototype.request=function(e){return this.archived?void 0:EPUBJS.core.request(e,"xml",this.credentials)},EPUBJS.Book.prototype.setCredentials=function(e){this.credentials=e},RSVP.EventTarget.mixin(EPUBJS.Book.prototype),RSVP.on("error",function(){}),RSVP.configure("instrument",!0),RSVP.on("rejected",function(e){console.error(e.detail.message,e.detail.stack)}),EPUBJS.core={},EPUBJS.core.request=function(e,t,r){function n(){if(this.readyState===this.DONE)if(200===this.status||this.responseXML){var e;e="xml"==t?this.responseXML:"json"==t?JSON.parse(this.response):"blob"==t?i?this.response:new Blob([this.response]):this.response,s.resolve(e)}else s.reject({message:this.response,stack:(new Error).stack})}var i=window.URL,o=i?"blob":"arraybuffer",s=new RSVP.defer,a=new XMLHttpRequest,u=XMLHttpRequest.prototype;return"overrideMimeType"in u||Object.defineProperty(u,"overrideMimeType",{value:function(){}}),r&&(a.withCredentials=!0),a.open("GET",e,!0),a.onreadystatechange=n,"blob"==t&&(a.responseType=o),"json"==t&&a.setRequestHeader("Accept","application/json"),"xml"==t&&a.overrideMimeType("text/xml"),a.send(),s.promise},EPUBJS.core.uri=function(e){var t,r,n,i={protocol:"",host:"",path:"",origin:"",directory:"",base:"",filename:"",extension:"",fragment:"",href:e},o=e.indexOf("://"),s=e.indexOf("?"),a=e.indexOf("#");return-1!=a&&(i.fragment=e.slice(a+1),e=e.slice(0,a)),-1!=s&&(i.search=e.slice(s+1),e=e.slice(0,s),href=e),-1!=o?(i.protocol=e.slice(0,o),t=e.slice(o+3),n=t.indexOf("/"),-1===n?(i.host=i.path,i.path=""):(i.host=t.slice(0,n),i.path=t.slice(n)),i.origin=i.protocol+"://"+i.host,i.directory=EPUBJS.core.folder(i.path),i.base=i.origin+i.directory):(i.path=e,i.directory=EPUBJS.core.folder(e),i.base=i.directory),i.filename=e.replace(i.base,""),r=i.filename.lastIndexOf("."),-1!=r&&(i.extension=i.filename.slice(r+1)),i},EPUBJS.core.folder=function(e){var t=e.lastIndexOf("/");if(-1==t)var r="";return r=e.slice(0,t+1)},EPUBJS.core.queue=function(e){var t=[],r=e,n=function(e,r,n){return t.push({funcName:e,args:r,context:n}),t},i=function(){var e;t.length&&(e=t.shift(),r[e.funcName].apply(e.context||r,e.args))},o=function(){for(;t.length;)i()},s=function(){t=[]},a=function(){return t.length};return{enqueue:n,dequeue:i,flush:o,clear:s,length:a}},EPUBJS.core.isElement=function(e){return!(!e||1!=e.nodeType)},EPUBJS.core.uuid=function(){var e=(new Date).getTime(),t="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var r=(e+16*Math.random())%16|0;return e=Math.floor(e/16),("x"==t?r:7&r|8).toString(16)});return t},EPUBJS.core.values=function(e){for(var t=-1,r=Object.keys(e),n=r.length,i=Array(n);++t0;){if(r=n.shift(),"text"===r.type?(i=s.childNodes[r.index],s=i.parentNode||s):s=r.id?o.getElementById(r.id):a[r.index],"undefined"==typeof s)return console.error("No Element For",r,e.str),!1;a=Array.prototype.slice.call(s.children)}return s},EPUBJS.EpubCFI.prototype.compare=function(e,t){if("string"==typeof e&&(e=new EPUBJS.EpubCFI(e)),"string"==typeof t&&(t=new EPUBJS.EpubCFI(t)),e.spinePos>t.spinePos)return 1;if(e.spinePost.steps[r].index)return 1;if(e.steps[r].indext.characterOffset?1:e.characterOffset=0?(o=i.length,e.characterOffset=o&&t&&t()}var i,o;return"undefined"==typeof this.hooks[e]?!1:(i=this.hooks[e],o=i.length,0===o&&t&&t(),void i.forEach(function(e){e(n,r)}))},{register:function(e){if(void 0===EPUBJS.hooks[e]&&(EPUBJS.hooks[e]={}),"object"!=typeof EPUBJS.hooks[e])throw"Already registered: "+e;return EPUBJS.hooks[e]},mixin:function(t){for(var r in e.prototype)t[r]=e.prototype[r]}}}(),EPUBJS.Infinite=function(e,t){this.container=e,this.windowHeight=window.innerHeight,this.tick=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,this.scrolled=!1,this.ignore=!1,this.displaying=!1,this.offset=250,this.views=[],this.renderer=t,this.prevScrollTop=0},EPUBJS.Infinite.prototype.start=function(){this.container.addEventListener("scroll",function(){this.ignore?this.ignore=!1:this.scrolled=!0}.bind(this)),window.addEventListener("unload",function(){this.ignore=!0}),this.tick.call(window,this.check.bind(this)),this.scrolled=!1},EPUBJS.Infinite.prototype.forwards=function(){this.trigger("forwards")},EPUBJS.Infinite.prototype.backwards=function(){this.trigger("backwards")},EPUBJS.Infinite.prototype.check=function(){if(this.scrolled&&!this.displaying){var e=this.container.scrollTop,t=(this.container.scrollLeft,this.container.scrollHeight),r=(this.container.scrollWidth,e-this.prevScrollTop),n=this.container.getBoundingClientRect().height,i=e+this.offset>t-n,o=e0?this.forwards():o&&0>r&&this.backwards(),this.prevScrollTop=e,this.scrolled=!1}else this.displaying=!1,this.scrolled=!1;this.tick.call(window,this.check.bind(this))},EPUBJS.Infinite.prototype.scrollBy=function(e,t,r){r&&(this.displaying=!0),this.container.scrollLeft+=e,this.container.scrollTop+=t},EPUBJS.Infinite.prototype.scroll=function(e,t,r){r&&(this.displaying=!0),this.container.scrollLeft=e,this.container.scrollTop=t},RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype),EPUBJS.Layout=function(){},EPUBJS.Layout.prototype.reconcileLayoutSettings=function(e,t){var r={};for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);return t.forEach(function(e){var t,n,i=e.replace("rendition:",""),o=i.indexOf("-");-1!=o&&(t=i.slice(0,o),n=i.slice(o+1),r[t]=n)}),r},EPUBJS.Layout.prototype.determineLayout=function(e){var t=this.determineSpreads(this.minSpreadWidth),r=t?"ReflowableSpreads":"Reflowable",n=!1;return"pre-paginated"===e.layout&&(r="Fixed",n=!0,t=!1),"reflowable"===e.layout&&"none"===e.spread&&(r="Reflowable",n=!1,t=!1),"reflowable"===e.layout&&"both"===e.spread&&(r="ReflowableSpreads",n=!1,t=!0),this.spreads=t,this.render.scroll(n),this.trigger("renderer:spreads",t),r},EPUBJS.Layout.prototype.applyStyles=function(e){for(var t in e)for(var r in this.views)r.setStyle(t,e[t])},EPUBJS.Layout.prototype.setStyle=function(e,t,r){for(var n in this.views)n.setStyle(e,t,r)},EPUBJS.Layout.prototype.removeStyle=function(e){for(var t in this.views)t.removeStyle(e)},EPUBJS.Layout.prototype.applyHeadTags=function(e){for(var t in e)this.render.addHeadTag(t,e[t])},EPUBJS.Navigation=function(e,t){var r=this,n=new EPUBJS.Parser,i=t||EPUBJS.core.request;this.package=e,this.toc=[],this.tocByHref={},this.tocById={},e.navPath&&(this.navUrl=e.baseUrl+e.navPath,this.nav={},this.nav.load=function(){var e=new RSVP.defer,t=e.promise;return i(r.navUrl,"xml").then(function(t){r.toc=n.nav(t),r.loaded(r.toc),e.resolve(r.toc)}),t}),e.ncxPath&&(this.ncxUrl=e.baseUrl+e.ncxPath,this.ncx={},this.ncx.load=function(){var e=new RSVP.defer,t=e.promise;return i(r.ncxUrl,"xml").then(function(t){r.toc=n.ncx(t),r.loaded(r.toc),e.resolve(r.toc)}),t})},EPUBJS.Navigation.prototype.load=function(e){{var t;e||EPUBJS.core.request}return this.nav?t=this.nav.load():this.ncx&&(t=this.ncx.load()),t},EPUBJS.Navigation.prototype.loaded=function(e){for(var t,r=0;r=0;s--){var a=i.snapshotItem(s),u=a.getAttribute("id")||!1,c=a.querySelector("content"),h=c.getAttribute("src"),p=a.querySelector("navLabel"),l=p.textContent?p.textContent:"",f=h.split("#"),d=(f[0],t(a));n.unshift({id:u,href:h,label:l,subitems:d,parent:r?r.getAttribute("id"):null})}return n}var r=e.querySelector("navMap");return r?t(r):[]},EPUBJS.Renderer=function(e,t){var r=t||{};this.settings={hidden:r.hidden||!1,viewsLimit:4,width:r.width||!1,height:r.height||!1},this.book=e,this.epubcfi=new EPUBJS.EpubCFI,this.layoutSettings={},EPUBJS.Hooks.mixin(this),this.getHooks("beforeChapterDisplay"),this._q=EPUBJS.core.queue(this),this.position=1,this.initialize({width:this.settings.width,height:this.settings.height,hidden:!0}),this.rendering=!1,this.views=[],this.positions=[]},EPUBJS.Renderer.prototype.initialize=function(e){{var t=e||{},r=t.height?t.height+"px":"100%",n=t.width?t.width+"px":"100%";t.hidden||!1}return this.container=document.createElement("div"),this.infinite=new EPUBJS.Infinite(this.container,this),this.container.style.width=n,this.container.style.height=r,this.container.style.overflow="scroll",t.hidden?(this.wrapper=document.createElement("div"),this.wrapper.style.visibility="hidden",this.wrapper.style.overflow="hidden",this.wrapper.style.width="0",this.wrapper.style.height="0",this.wrapper.appendChild(this.container),this.wrapper):this.container},EPUBJS.Renderer.prototype.resize=function(e,t){var r=e,n=t;e||(r=window.innerWidth),t||(n=window.innerHeight),this.container.style.width=r+"px",this.container.style.height=n+"px",this.trigger("resized",{width:this.width,height:this.height})},EPUBJS.Renderer.prototype.onResized=function(){var e=this.element.getBoundingClientRect();this.resize(e.width,e.height)},EPUBJS.Renderer.prototype.attachTo=function(e){var t;return EPUBJS.core.isElement(e)?this.element=e:"string"==typeof e&&(this.element=document.getElementById(e)),this.element?(this.element.appendChild(this.container),this.settings.height||this.settings.width||(t=this.element.getBoundingClientRect(),this.resize(t.width,t.height)),this.infinite.start(),this.infinite.on("forwards",function(){this.rendering||this.forwards()}.bind(this)),this.infinite.on("backwards",function(){this.rendering||this.backwards()}.bind(this)),void window.addEventListener("resize",this.onResized.bind(this),!1)):void console.error("Not an Element")},EPUBJS.Renderer.prototype.clear=function(){this.views.forEach(function(e){e.destroy()}),this.views=[]},EPUBJS.Renderer.prototype.display=function(e){var t=new RSVP.defer,r=t.promise;return this.clear(),this.book.opened.then(function(){var r=this.book.spine.get(e),n=this.render(r);n.then(this.fill.bind(this)).then(function(){t.resolve(this)}.bind(this))}.bind(this)),r},EPUBJS.Renderer.prototype.render=function(e){var t,r=new EPUBJS.View;return e?(t=e.render(),r.index=e.index,t.then(function(t){return this.insert(r,e.index),r.load(t)}.bind(this)).then(function(){return this.rendering=!1,r}.bind(this))):void t.reject()},EPUBJS.Renderer.prototype.forwards=function(){var e,t,r;return e=this.last().index+1,this.rendering||e===this.book.spine.length?(t=new RSVP.defer,t.reject({message:"reject forwards"}),t.promise):(console.log("going forwards"),this.rendering=!0,r=this.book.spine.get(e),t=this.render(r),t.then(function(){var e=this.first(),t=e.bounds(),r=(this.container.getBoundingClientRect(),this.container.scrollTop);this.views.length>this.settings.viewsLimit&&(this.remove(e),this.infinite.scroll(0,r-t.height,!0))}.bind(this)),t)},EPUBJS.Renderer.prototype.backwards=function(){var e,t,r;return e=this.first().index-1,this.rendering||0>e?(t=new RSVP.defer,t.reject({message:"reject backwards"}),t.promise):(console.log("going backwards"),this.rendering=!0,r=this.book.spine.get(e),t=this.render(r),t.then(function(){this.infinite.scrollBy(0,this.first().height,!0),this.views.length>this.settings.viewsLimit&&(last=this.last(),this.remove(last))}.bind(this)),t)},EPUBJS.Renderer.prototype.fill=function(){var e=this.container.getBoundingClientRect().height,t=function(){var r=this.last().bounds().bottom,n=new RSVP.defer,i=n.promise;return e&&r&&e>r&&this.last().index+1=0?this.append(e):t-this.last().index<=0&&this.prepend(e):this.append(e),console.log("insert")},EPUBJS.Renderer.prototype.remove=function(e){var t=this.views.indexOf(e);e.destroy(),t>-1&&this.views.splice(t,1)},EPUBJS.Renderer.prototype.first=function(){return this.views[0]},EPUBJS.Renderer.prototype.last=function(){return this.views[this.views.length-1]},RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype),EPUBJS.Spine=function(e,t){this.items=e.spine,this.manifest=e.manifest,this.spineNodeIndex=e.spineNodeIndex,this.baseUrl=e.baseUrl||"",this.request=t,this.length=this.items.length,this.epubcfi=new EPUBJS.EpubCFI,this.spineItems=[],this.spineByHref={},this.spineById={},this.items.forEach(function(e,t){var r,n,i,o=this.epubcfi.generateChapterComponent(this.spineNodeIndex,e.index,e.idref),s=this.manifest[e.idref];s&&(r=s.href,n=this.baseUrl+r),i=new EPUBJS.SpineItem(e,r,n,o),this.spineItems.push(i),this.spineByHref[i.href]=t,this.spineById[i.idref]=t}.bind(this))},EPUBJS.Spine.prototype.get=function(e){var t=0;return!e||"number"!=typeof e&&isNaN(e)!==!1?e&&0===e.indexOf("#")?t=this.spineById[e.substring(1)]:e&&(t=this.spineByHref[e]):t=e,this.spineItems[t]},EPUBJS.SpineItem=function(e,t,r,n){this.idref=e.idref,this.linear=e.linear,this.properties=e.properties,this.index=e.index,this.href=t,this.url=r,this.cfiBase=n},EPUBJS.SpineItem.prototype.load=function(e){var t=e||this.request||EPUBJS.core.request,r=new RSVP.defer,n=r.promise;return this.contents?r.resolve(this.contents):t(this.url,"xml").then(function(e){EPUBJS.core.folder(this.url);this.document=e,this.contents=e.documentElement,this.replacements(this.document),r.resolve(this.contents)}.bind(this)),n},EPUBJS.SpineItem.prototype.replacements=function(e){var t=e.createElement("base");t.setAttribute("href",this.url),e.head.insertBefore(t,e.head.firstChild)},EPUBJS.SpineItem.prototype.render=function(){var e=new RSVP.defer,t=e.promise;return this.load().then(function(t){var r=new XMLSerializer,n=r.serializeToString(t);e.resolve(n)}),t},EPUBJS.SpineItem.prototype.find=function(){},EPUBJS.View=function(){this.id="epubjs-view:"+EPUBJS.core.uuid(),this.loading=new RSVP.defer,this.loaded=this.loading.promise,this.iframe=this.create(),this.height,this.width},EPUBJS.View.prototype.load=function(e){var t=new RSVP.defer,r=t.promise;return this.document=this.iframe.contentDocument,this.iframe.addEventListener("load",function(){this.window=this.iframe.contentWindow,this.document=this.iframe.contentDocument,this.iframe.style.display="block",this.document.body.style.margin="0",this.document.body.style.display="inline-block",this.layout(),this.iframe.style.visibility="visible",setTimeout(function(){this.window.addEventListener("resize",this.resized.bind(this),!1)}.bind(this),10),this.document.fonts.onloading=function(){console.log("loaded fonts")}.bind(this),t.resolve(this),this.loading.resolve(this)}.bind(this)),this.document.open(),this.document.write(e),this.document.close(),r},EPUBJS.View.prototype.create=function(){return this.iframe=document.createElement("iframe"),this.iframe.id=this.id,this.iframe.scrolling="no",this.iframe.seamless="seamless",this.iframe.style.border="none",this.resizing=!0,this.iframe.width="100%",this.iframe.style.height="100%",this.iframe.style.display="none",this.iframe.style.visibility="hidden",this.iframe},EPUBJS.View.prototype.resized=function(){this.resizing?this.resizing=!1:this.layout()},EPUBJS.View.prototype.layout=function(){var e;console.log("layout"),e=this.document.body.getBoundingClientRect(),(!e||0==e.height&&0==e.width)&&console.error("View not shown"),this.resizing=!0,this.iframe.style.height=e.height+"px",e=this.document.body.getBoundingClientRect(),this.resizing=!0,this.iframe.style.height=e.height+"px",this.width=e.width,this.height=e.height},EPUBJS.View.prototype.observe=function(e){var t=this,r=new MutationObserver(function(e){e.forEach(function(){t.layout()})}),n={attributes:!0,childList:!0,characterData:!0,subtree:!0};return r.observe(e,n),r},EPUBJS.View.prototype.appendTo=function(e){this.element=e,this.element.appendChild(this.iframe)},EPUBJS.View.prototype.prependTo=function(e){this.element=e,e.insertBefore(this.iframe,e.firstChild)},EPUBJS.View.prototype.bounds=function(){return this.iframe.getBoundingClientRect()},EPUBJS.View.prototype.destroy=function(){this.element.removeChild(this.iframe)};
\ No newline at end of file
+"undefined"==typeof EPUBJS&&(("undefined"!=typeof window?window:this).EPUBJS={}),EPUBJS.VERSION="0.3.0",EPUBJS.Render={},function(e){"use strict";var t=function(e){return new EPUBJS.Book(e)};t.Render={register:function(e,r){t.Render[e]=r}},"object"==typeof exports?(e.RSVP=require("rsvp"),module.exports=t):"function"==typeof define&&define.amd?define(t):e.ePub=t}(this),function(e){var t,r;!function(){var e={},n={};t=function(t,r,n){e[t]={deps:r,callback:n}},r=function(t){function i(e){if("."!==e.charAt(0))return e;for(var r=e.split("/"),n=t.split("/").slice(0,-1),i=0,s=r.length;s>i;i++){var o=r[i];if(".."===o)n.pop();else{if("."===o)continue;n.push(o)}}return n.join("/")}if(n[t])return n[t];if(n[t]={},!e[t])throw new Error("Could not find module "+t);for(var s,o=e[t],a=o.deps,u=o.callback,h=[],c=0,p=a.length;p>c;c++)h.push("exports"===a[c]?s={}:r(i(a[c])));var l=u.apply(this,h);return n[t]=s||l},r.entries=e}(),t("rsvp/-internal",["./utils","./instrument","./config","exports"],function(e,t,r,n){"use strict";function i(){}function s(e){try{return e.then}catch(t){return U.error=t,U}}function o(e,t,r,n){try{e.call(t,r,n)}catch(i){return i}}function a(e,t,r){E.async(function(e){var n=!1,i=o(r,t,function(r){n||(n=!0,t!==r?c(e,r):l(e,r))},function(t){n||(n=!0,d(e,t))},"Settle: "+(e._label||" unknown promise"));!n&&i&&(n=!0,d(e,i))},e)}function u(e,t){e._onerror=null,t._state===x?l(e,t._result):e._state===B?d(e,t._result):f(t,void 0,function(r){t!==r?c(e,r):l(e,r)},function(t){d(e,t)})}function h(e,t){if(t instanceof e.constructor)u(e,t);else{var r=s(t);r===U?d(e,U.error):void 0===r?l(e,t):_(r)?a(e,t,r):l(e,t)}}function c(e,t){e===t?l(e,t):S(t)?h(e,t):l(e,t)}function p(e){e._onerror&&e._onerror(e._result),m(e)}function l(e,t){e._state===w&&(e._result=t,e._state=x,0===e._subscribers.length?E.instrument&&P("fulfilled",e):E.async(m,e))}function d(e,t){e._state===w&&(e._state=B,e._result=t,E.async(p,e))}function f(e,t,r,n){var i=e._subscribers,s=i.length;e._onerror=null,i[s]=t,i[s+x]=r,i[s+B]=n,0===s&&e._state&&E.async(m,e)}function m(e){var t=e._subscribers,r=e._state;if(E.instrument&&P(r===x?"fulfilled":"rejected",e),0!==t.length){for(var n,i,s=e._result,o=0;oe;e+=2){var t=p[e],r=p[e+1];t(r),p[e]=void 0,p[e+1]=void 0}o=0}var o=0;e["default"]=function(e,t){p[o]=e,p[o+1]=t,o+=2,2===o&&a()};var a,u="undefined"!=typeof window?window:{},h=u.MutationObserver||u.WebKitMutationObserver,c="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,p=new Array(1e3);a="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?t():h?r():c?n():i()}),t("rsvp/config",["./events","exports"],function(e,t){"use strict";function r(e,t){return"onerror"===e?void i.on("error",t):2!==arguments.length?i[e]:void(i[e]=t)}var n=e["default"],i={instrument:!1};n.mixin(i),t.config=i,t.configure=r}),t("rsvp/defer",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e){var t={};return t.promise=new r(function(e,r){t.resolve=e,t.reject=r},e),t}}),t("rsvp/enumerator",["./utils","./-internal","exports"],function(e,t,r){"use strict";function n(e,t,r){return e===p?{state:"fulfilled",value:r}:{state:"rejected",reason:r}}function i(e,t,r,n){this._instanceConstructor=e,this.promise=new e(a,n),this._abortOnReject=r,this._validateInput(t)?(this._input=t,this.length=t.length,this._remaining=t.length,this._init(),0===this.length?h(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&h(this.promise,this._result))):u(this.promise,this._validationError())}var s=e.isArray,o=e.isMaybeThenable,a=t.noop,u=t.reject,h=t.fulfill,c=t.subscribe,p=t.FULFILLED,l=t.REJECTED,d=t.PENDING,f=!0;r.ABORT_ON_REJECTION=f,r.makeSettledResult=n,i.prototype._validateInput=function(e){return s(e)},i.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},i.prototype._init=function(){this._result=new Array(this.length)},r["default"]=i,i.prototype._enumerate=function(){for(var e=this.length,t=this.promise,r=this._input,n=0;t._state===d&&e>n;n++)this._eachEntry(r[n],n)},i.prototype._eachEntry=function(e,t){var r=this._instanceConstructor;o(e)?e.constructor===r&&e._state!==d?(e._onerror=null,this._settledAt(e._state,t,e._result)):this._willSettleAt(r.resolve(e),t):(this._remaining--,this._result[t]=this._makeResult(p,t,e))},i.prototype._settledAt=function(e,t,r){var n=this.promise;n._state===d&&(this._remaining--,this._abortOnReject&&e===l?u(n,r):this._result[t]=this._makeResult(e,t,r)),0===this._remaining&&h(n,this._result)},i.prototype._makeResult=function(e,t,r){return r},i.prototype._willSettleAt=function(e,t){var r=this;c(e,void 0,function(e){r._settledAt(p,t,e)},function(e){r._settledAt(l,t,e)})}}),t("rsvp/events",["exports"],function(e){"use strict";function t(e,t){for(var r=0,n=e.length;n>r;r++)if(e[r]===t)return r;return-1}function r(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t}e["default"]={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e._promiseCallbacks=void 0,e},on:function(e,n){var i,s=r(this);i=s[e],i||(i=s[e]=[]),-1===t(i,n)&&i.push(n)},off:function(e,n){var i,s,o=r(this);return n?(i=o[e],s=t(i,n),void(-1!==s&&i.splice(s,1))):void(o[e]=[])},trigger:function(e,t){var n,i,s=r(this);if(n=s[e])for(var o=0;oa;a++)o[a]=t(e[a]);return n.all(o,r).then(function(t){for(var r=new Array(s),n=0,i=0;s>i;i++)t[i]&&(r[n]=e[i],n++);return r.length=n,r})})}}),t("rsvp/hash-settled",["./promise","./enumerator","./promise-hash","./utils","exports"],function(e,t,r,n,i){"use strict";function s(e,t,r){this._superConstructor(e,t,!1,r)}var o=e["default"],a=t.makeSettledResult,u=r["default"],h=t["default"],c=n.o_create;s.prototype=c(u.prototype),s.prototype._superConstructor=h,s.prototype._makeResult=a,s.prototype._validationError=function(){return new Error("hashSettled must be called with an object")},i["default"]=function(e,t){return new s(o,e,t).promise}}),t("rsvp/hash",["./promise","./promise-hash","./enumerator","exports"],function(e,t,r,n){"use strict";{var i=e["default"],s=t["default"];r.ABORT_ON_REJECTION}n["default"]=function(e,t){return new s(i,e,t).promise}}),t("rsvp/instrument",["./config","./utils","exports"],function(e,t,r){"use strict";var n=e.config,i=t.now,s=[];r["default"]=function(e,t,r){1===s.push({name:e,payload:{guid:t._guidKey+t._id,eventName:e,detail:t._result,childGuid:r&&t._guidKey+r._id,label:t._label,timeStamp:i(),stack:new Error(t._label).stack}})&&setTimeout(function(){for(var e,t=0;ta;a++)o[a]=t(e[a]);return n.all(o,r)})}}),t("rsvp/node",["./promise","./utils","exports"],function(e,t,r){"use strict";var n=e["default"],i=t.isArray;r["default"]=function(e,t){function r(){for(var r=arguments.length,i=new Array(r),a=0;r>a;a++)i[a]=arguments[a];var u;return s||o||!t?u=this:("object"==typeof console&&console.warn('Deprecation: RSVP.denodeify() doesn\'t allow setting the "this" binding anymore. Use yourFunction.bind(yourThis) instead.'),u=t),n.all(i).then(function(r){function i(n,i){function a(){for(var e=arguments.length,r=new Array(e),a=0;e>a;a++)r[a]=arguments[a];var u=r[0],h=r[1];if(u)i(u);else if(s)n(r.slice(1));else if(o){var c,p,l={},d=r.slice(1);for(p=0;pa;a++)s=r[a],this._eachEntry(s.entry,s.position)}}),t("rsvp/promise",["./config","./events","./instrument","./utils","./-internal","./promise/cast","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"],function(e,t,r,n,i,s,o,a,u,h,c){"use strict";function p(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function l(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function d(e,t){this._id=R++,this._label=t,this._subscribers=[],f.instrument&&m("created",this),v!==e&&(g(e)||p(),this instanceof d||l(),S(this,e))}var f=e.config,m=(t["default"],r["default"]),g=(n.objectOrFunction,n.isFunction),y=n.now,v=i.noop,b=(i.resolve,i.reject,i.fulfill,i.subscribe),S=i.initializePromise,_=i.invokeCallback,P=i.FULFILLED,E=s["default"],w=o["default"],x=a["default"],B=u["default"],U=h["default"],J="rsvp_"+y()+"-",R=0;c["default"]=d,d.cast=E,d.all=w,d.race=x,d.resolve=B,d.reject=U,d.prototype={constructor:d,_id:void 0,_guidKey:J,_label:void 0,_state:void 0,_result:void 0,_subscribers:void 0,_onerror:function(e){f.trigger("error",e)},then:function(e,t,r){var n=this;n._onerror=null;var i=new this.constructor(v,r),s=n._state,o=n._result;return f.instrument&&m("chained",n,i),s===P&&e?f.async(function(){_(s,i,e,o)}):b(n,i,e,t),i},"catch":function(e,t){return this.then(null,e,t)},"finally":function(e,t){var r=this.constructor;return this.then(function(t){return r.resolve(e()).then(function(){return t})},function(t){return r.resolve(e()).then(function(){throw t})},t)}}}),t("rsvp/promise/all",["../enumerator","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return new r(this,e,!0,t).promise}}),t("rsvp/promise/cast",["./resolve","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=r}),t("rsvp/promise/race",["../utils","../-internal","exports"],function(e,t,r){"use strict";var n=e.isArray,i=(e.isFunction,e.isMaybeThenable,t.noop),s=t.resolve,o=t.reject,a=t.subscribe,u=t.PENDING;r["default"]=function(e,t){function r(e){s(p,e)}function h(e){o(p,e)}var c=this,p=new c(i,t);if(!n(e))return o(p,new TypeError("You must pass an array to race.")),p;for(var l=e.length,d=0;p._state===u&&l>d;d++)a(c.resolve(e[d]),void 0,r,h);return p}}),t("rsvp/promise/reject",["../-internal","exports"],function(e,t){"use strict";var r=e.noop,n=e.reject;t["default"]=function(e,t){var i=this,s=new i(r,t);return n(s,e),s}}),t("rsvp/promise/resolve",["../-internal","exports"],function(e,t){"use strict";var r=e.noop,n=e.resolve;t["default"]=function(e,t){var i=this;if(e&&"object"==typeof e&&e.constructor===i)return e;var s=new i(r,t);return n(s,e),s}}),t("rsvp/race",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.race(e,t)}}),t("rsvp/reject",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.reject(e,t)}}),t("rsvp/resolve",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.resolve(e,t)}}),t("rsvp/rethrow",["exports"],function(e){"use strict";e["default"]=function(e){throw setTimeout(function(){throw e}),e}}),t("rsvp/utils",["exports"],function(e){"use strict";function t(e){return"function"==typeof e||"object"==typeof e&&null!==e}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}e.objectOrFunction=t,e.isFunction=r,e.isMaybeThenable=n;var i;i=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var s=i;e.isArray=s;var o=Date.now||function(){return(new Date).getTime()};e.now=o;var a=Object.create||function(e){var t=function(){};return t.prototype=e,t};e.o_create=a}),t("rsvp",["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"],function(e,t,r,n,i,s,o,a,u,h,c,p,l,d,f,m,g){"use strict";function y(e,t){A.async(e,t)}function v(){A.on.apply(A,arguments)}function b(){A.off.apply(A,arguments)}var S=e["default"],_=t["default"],P=r["default"],E=n["default"],w=i["default"],x=s["default"],B=o["default"],U=a["default"],J=u["default"],R=h["default"],A=c.config,I=c.configure,C=p["default"],T=l["default"],k=d["default"],F=f["default"],N=m["default"];if(A.async=N,"undefined"!=typeof window&&"object"==typeof window.__PROMISE_INSTRUMENTATION__){var q=window.__PROMISE_INSTRUMENTATION__;I("instrument",!0);for(var O in q)q.hasOwnProperty(O)&&v(O,q[O])}g.Promise=S,g.EventTarget=_,g.all=E,g.allSettled=w,g.race=x,g.hash=B,g.hashSettled=U,g.rethrow=J,g.defer=R,g.denodeify=P,g.configure=I,g.on=v,g.off=b,g.resolve=T,g.reject=k,g.async=y,g.map=C,g.filter=F}),e.RSVP=r("rsvp")}(self),function(e,t){"use strict";"object"==typeof exports?module.exports=t(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"==typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],t):e.URI=t(e.punycode,e.IPv6,e.SecondLevelDomains,e)}(this,function(e,t,r,n){"use strict";function i(e,t){return this instanceof i?(void 0===e&&(e="undefined"!=typeof location?location.href+"":""),this.href(e),void 0!==t?this.absoluteTo(t):this):new i(e,t)}function s(e){return e.replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}function o(e){return void 0===e?"Undefined":String(Object.prototype.toString.call(e)).slice(8,-1)}function a(e){return"Array"===o(e)}function u(e,t){var r,n,i={};if(a(t))for(r=0,n=t.length;n>r;r++)i[t[r]]=!0;else i[t]=!0;for(r=0,n=e.length;n>r;r++)void 0!==i[e[r]]&&(e.splice(r,1),n--,r--);return e}function h(e,t){var r,n;if(a(t)){for(r=0,n=t.length;n>r;r++)if(!h(e,t[r]))return!1;return!0}var i=o(t);for(r=0,n=e.length;n>r;r++)if("RegExp"===i){if("string"==typeof e[r]&&e[r].match(t))return!0}else if(e[r]===t)return!0;return!1}function c(e,t){if(!a(e)||!a(t))return!1;if(e.length!==t.length)return!1;e.sort(),t.sort();for(var r=0,n=e.length;n>r;r++)if(e[r]!==t[r])return!1;return!0}function p(e){return escape(e)}function l(e){return encodeURIComponent(e).replace(/[!'()*]/g,p).replace(/\*/g,"%2A")}var d=n&&n.URI;i.version="1.13.2";var f=i.prototype,m=Object.prototype.hasOwnProperty;i._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:i.duplicateQueryParameters,escapeQuerySpace:i.escapeQuerySpace}},i.duplicateQueryParameters=!1,i.escapeQuerySpace=!0,i.protocol_expression=/^[a-z][a-z0-9.+-]*$/i,i.idn_expression=/[^a-z0-9\.-]/i,i.punycode_expression=/(xn--)/i,i.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,i.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*$/,i.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,i.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?«»“”„‘’]+$/},i.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"},i.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/,i.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"},i.getDomAttribute=function(e){if(!e||!e.nodeName)return void 0;var t=e.nodeName.toLowerCase();return"input"===t&&"image"!==e.type?void 0:i.domAttributes[t]},i.encode=l,i.decode=decodeURIComponent,i.iso8859=function(){i.encode=escape,i.decode=unescape},i.unicode=function(){i.encode=l,i.decode=decodeURIComponent},i.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":"="}}}},i.encodeQuery=function(e,t){var r=i.encode(e+"");return void 0===t&&(t=i.escapeQuerySpace),t?r.replace(/%20/g,"+"):r},i.decodeQuery=function(e,t){e+="",void 0===t&&(t=i.escapeQuerySpace);try{return i.decode(t?e.replace(/\+/g,"%20"):e)}catch(r){return e}},i.recodePath=function(e){for(var t=(e+"").split("/"),r=0,n=t.length;n>r;r++)t[r]=i.encodePathSegment(i.decode(t[r]));return t.join("/")},i.decodePath=function(e){for(var t=(e+"").split("/"),r=0,n=t.length;n>r;r++)t[r]=i.decodePathSegment(t[r]);return t.join("/")};var g,y={encode:"encode",decode:"decode"},v=function(e,t){return function(r){return i[t](r+"").replace(i.characters[e][t].expression,function(r){return i.characters[e][t].map[r]})}};for(g in y)i[g+"PathSegment"]=v("pathname",y[g]);i.encodeReserved=v("reserved","encode"),i.parse=function(e,t){var r;return t||(t={}),r=e.indexOf("#"),r>-1&&(t.fragment=e.substring(r+1)||null,e=e.substring(0,r)),r=e.indexOf("?"),r>-1&&(t.query=e.substring(r+1)||null,e=e.substring(0,r)),"//"===e.substring(0,2)?(t.protocol=null,e=e.substring(2),e=i.parseAuthority(e,t)):(r=e.indexOf(":"),r>-1&&(t.protocol=e.substring(0,r)||null,t.protocol&&!t.protocol.match(i.protocol_expression)?t.protocol=void 0:"file"===t.protocol?e=e.substring(r+3):"//"===e.substring(r+1,r+3)?(e=e.substring(r+3),e=i.parseAuthority(e,t)):(e=e.substring(r+1),t.urn=!0))),t.path=e,t},i.parseHost=function(e,t){var r,n,i=e.indexOf("/");return-1===i&&(i=e.length),"["===e.charAt(0)?(r=e.indexOf("]"),t.hostname=e.substring(1,r)||null,t.port=e.substring(r+2,i)||null,"/"===t.port&&(t.port=null)):e.indexOf(":")!==e.lastIndexOf(":")?(t.hostname=e.substring(0,i)||null,t.port=null):(n=e.substring(0,i).split(":"),t.hostname=n[0]||null,t.port=n[1]||null),t.hostname&&"/"!==e.substring(i).charAt(0)&&(i++,e="/"+e),e.substring(i)||"/"},i.parseAuthority=function(e,t){return e=i.parseUserinfo(e,t),i.parseHost(e,t)},i.parseUserinfo=function(e,t){var r,n=e.indexOf("/"),s=n>-1?e.lastIndexOf("@",n):e.indexOf("@");return s>-1&&(-1===n||n>s)?(r=e.substring(0,s).split(":"),t.username=r[0]?i.decode(r[0]):null,r.shift(),t.password=r[0]?i.decode(r.join(":")):null,e=e.substring(s+1)):(t.username=null,t.password=null),e},i.parseQuery=function(e,t){if(!e)return{};if(e=e.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,""),!e)return{};for(var r,n,s,o={},a=e.split("&"),u=a.length,h=0;u>h;h++)r=a[h].split("="),n=i.decodeQuery(r.shift(),t),s=r.length?i.decodeQuery(r.join("="),t):null,o[n]?("string"==typeof o[n]&&(o[n]=[o[n]]),o[n].push(s)):o[n]=s;return o},i.build=function(e){var t="";return e.protocol&&(t+=e.protocol+":"),e.urn||!t&&!e.hostname||(t+="//"),t+=i.buildAuthority(e)||"","string"==typeof e.path&&("/"!==e.path.charAt(0)&&"string"==typeof e.hostname&&(t+="/"),t+=e.path),"string"==typeof e.query&&e.query&&(t+="?"+e.query),"string"==typeof e.fragment&&e.fragment&&(t+="#"+e.fragment),t},i.buildHost=function(e){var t="";return e.hostname?(t+=i.ip6_expression.test(e.hostname)?"["+e.hostname+"]":e.hostname,e.port&&(t+=":"+e.port),t):""},i.buildAuthority=function(e){return i.buildUserinfo(e)+i.buildHost(e)},i.buildUserinfo=function(e){var t="";return e.username&&(t+=i.encode(e.username),e.password&&(t+=":"+i.encode(e.password)),t+="@"),t},i.buildQuery=function(e,t,r){var n,s,o,u,h="";for(s in e)if(m.call(e,s)&&s)if(a(e[s]))for(n={},o=0,u=e[s].length;u>o;o++)void 0!==e[s][o]&&void 0===n[e[s][o]+""]&&(h+="&"+i.buildQueryParameter(s,e[s][o],r),t!==!0&&(n[e[s][o]+""]=!0));else void 0!==e[s]&&(h+="&"+i.buildQueryParameter(s,e[s],r));return h.substring(1)},i.buildQueryParameter=function(e,t,r){return i.encodeQuery(e,r)+(null!==t?"="+i.encodeQuery(t,r):"")},i.addQuery=function(e,t,r){if("object"==typeof t)for(var n in t)m.call(t,n)&&i.addQuery(e,n,t[n]);else{if("string"!=typeof t)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");if(void 0===e[t])return void(e[t]=r);"string"==typeof e[t]&&(e[t]=[e[t]]),a(r)||(r=[r]),e[t]=e[t].concat(r)}},i.removeQuery=function(e,t,r){var n,s,o;if(a(t))for(n=0,s=t.length;s>n;n++)e[t[n]]=void 0;else if("object"==typeof t)for(o in t)m.call(t,o)&&i.removeQuery(e,o,t[o]);else{if("string"!=typeof t)throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");void 0!==r?e[t]===r?e[t]=void 0:a(e[t])&&(e[t]=u(e[t],r)):e[t]=void 0}},i.hasQuery=function(e,t,r,n){if("object"==typeof t){for(var s in t)if(m.call(t,s)&&!i.hasQuery(e,s,t[s]))return!1;return!0}if("string"!=typeof t)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");switch(o(r)){case"Undefined":return t in e;case"Boolean":var u=Boolean(a(e[t])?e[t].length:e[t]);return r===u;case"Function":return!!r(e[t],t,e);case"Array":if(!a(e[t]))return!1;var p=n?h:c;return p(e[t],r);case"RegExp":return a(e[t])?n?h(e[t],r):!1:Boolean(e[t]&&e[t].match(r));case"Number":r=String(r);case"String":return a(e[t])?n?h(e[t],r):!1:e[t]===r;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter")}},i.commonPath=function(e,t){var r,n=Math.min(e.length,t.length);for(r=0;n>r;r++)if(e.charAt(r)!==t.charAt(r)){r--;break}return 1>r?e.charAt(0)===t.charAt(0)&&"/"===e.charAt(0)?"/":"":(("/"!==e.charAt(r)||"/"!==t.charAt(r))&&(r=e.substring(0,r).lastIndexOf("/")),e.substring(0,r+1))},i.withinString=function(e,t,r){r||(r={});var n=r.start||i.findUri.start,s=r.end||i.findUri.end,o=r.trim||i.findUri.trim,a=/[a-z0-9-]=["']?$/i;for(n.lastIndex=0;;){var u=n.exec(e);if(!u)break;var h=u.index;if(r.ignoreHtml){var c=e.slice(Math.max(h-3,0),h);if(c&&a.test(c))continue}var p=h+e.slice(h).search(s),l=e.slice(h,p).replace(o,"");if(!r.ignore||!r.ignore.test(l)){p=h+l.length;var d=t(l,h,p,e);e=e.slice(0,h)+d+e.slice(p),n.lastIndex=h+d.length}}return n.lastIndex=0,e},i.ensureValidHostname=function(t){if(t.match(i.invalid_hostname_characters)){if(!e)throw new TypeError('Hostname "'+t+'" contains characters other than [A-Z0-9.-] and Punycode.js is not available');if(e.toASCII(t).match(i.invalid_hostname_characters))throw new TypeError('Hostname "'+t+'" contains characters other than [A-Z0-9.-]')}},i.noConflict=function(e){if(e){var t={URI:this.noConflict()};return n.URITemplate&&"function"==typeof n.URITemplate.noConflict&&(t.URITemplate=n.URITemplate.noConflict()),n.IPv6&&"function"==typeof n.IPv6.noConflict&&(t.IPv6=n.IPv6.noConflict()),n.SecondLevelDomains&&"function"==typeof n.SecondLevelDomains.noConflict&&(t.SecondLevelDomains=n.SecondLevelDomains.noConflict()),t}return n.URI===this&&(n.URI=d),this},f.build=function(e){return e===!0?this._deferred_build=!0:(void 0===e||this._deferred_build)&&(this._string=i.build(this._parts),this._deferred_build=!1),this},f.clone=function(){return new i(this)},f.valueOf=f.toString=function(){return this.build(!1)._string},y={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"},v=function(e){return function(t,r){return void 0===t?this._parts[e]||"":(this._parts[e]=t||null,this.build(!r),this)}};for(g in y)f[g]=v(y[g]);y={query:"?",fragment:"#"},v=function(e,t){return function(r,n){return void 0===r?this._parts[e]||"":(null!==r&&(r+="",r.charAt(0)===t&&(r=r.substring(1))),this._parts[e]=r,this.build(!n),this)}};for(g in y)f[g]=v(g,y[g]);y={search:["?","query"],hash:["#","fragment"]},v=function(e,t){return function(r,n){var i=this[e](r,n);return"string"==typeof i&&i.length?t+i:i}};for(g in y)f[g]=v(y[g][1],y[g][0]);f.pathname=function(e,t){if(void 0===e||e===!0){var r=this._parts.path||(this._parts.hostname?"/":"");return e?i.decodePath(r):r}return this._parts.path=e?i.recodePath(e):"/",this.build(!t),this},f.path=f.pathname,f.href=function(e,t){var r;if(void 0===e)return this.toString();this._string="",this._parts=i._parts();var n=e instanceof i,s="object"==typeof e&&(e.hostname||e.path||e.pathname);if(e.nodeName){var o=i.getDomAttribute(e);e=e[o]||"",s=!1}if(!n&&s&&void 0!==e.pathname&&(e=e.toString()),"string"==typeof e)this._parts=i.parse(e,this._parts);else{if(!n&&!s)throw new TypeError("invalid input");var a=n?e._parts:e;for(r in a)m.call(this._parts,r)&&(this._parts[r]=a[r])}return this.build(!t),this},f.is=function(e){var t=!1,n=!1,s=!1,o=!1,a=!1,u=!1,h=!1,c=!this._parts.urn;switch(this._parts.hostname&&(c=!1,n=i.ip4_expression.test(this._parts.hostname),s=i.ip6_expression.test(this._parts.hostname),t=n||s,o=!t,a=o&&r&&r.has(this._parts.hostname),u=o&&i.idn_expression.test(this._parts.hostname),h=o&&i.punycode_expression.test(this._parts.hostname)),e.toLowerCase()){case"relative":return c;case"absolute":return!c;case"domain":case"name":return o;case"sld":return a;case"ip":return t;case"ip4":case"ipv4":case"inet4":return n;case"ip6":case"ipv6":case"inet6":return s;case"idn":return u;case"url":return!this._parts.urn;case"urn":return!!this._parts.urn;case"punycode":return h}return null};var b=f.protocol,S=f.port,_=f.hostname;f.protocol=function(e,t){if(void 0!==e&&e&&(e=e.replace(/:(\/\/)?$/,""),!e.match(i.protocol_expression)))throw new TypeError('Protocol "'+e+"\" contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return b.call(this,e,t)},f.scheme=f.protocol,f.port=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0!==e&&(0===e&&(e=null),e&&(e+="",":"===e.charAt(0)&&(e=e.substring(1)),e.match(/[^0-9]/))))throw new TypeError('Port "'+e+'" contains characters other than [0-9]');return S.call(this,e,t)},f.hostname=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0!==e){var r={};i.parseHost(e,r),e=r.hostname}return _.call(this,e,t)},f.host=function(e,t){return this._parts.urn?void 0===e?"":this:void 0===e?this._parts.hostname?i.buildHost(this._parts):"":(i.parseHost(e,this._parts),this.build(!t),this)},f.authority=function(e,t){return this._parts.urn?void 0===e?"":this:void 0===e?this._parts.hostname?i.buildAuthority(this._parts):"":(i.parseAuthority(e,this._parts),this.build(!t),this)},f.userinfo=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0===e){if(!this._parts.username)return"";var r=i.buildUserinfo(this._parts);return r.substring(0,r.length-1)}return"@"!==e[e.length-1]&&(e+="@"),i.parseUserinfo(e,this._parts),this.build(!t),this},f.resource=function(e,t){var r;return void 0===e?this.path()+this.search()+this.hash():(r=i.parse(e),this._parts.path=r.path,this._parts.query=r.query,this._parts.fragment=r.fragment,this.build(!t),this)},f.subdomain=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0===e){if(!this._parts.hostname||this.is("IP"))return"";var r=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,r)||""}var n=this._parts.hostname.length-this.domain().length,o=this._parts.hostname.substring(0,n),a=new RegExp("^"+s(o));return e&&"."!==e.charAt(e.length-1)&&(e+="."),e&&i.ensureValidHostname(e),this._parts.hostname=this._parts.hostname.replace(a,e),this.build(!t),this},f.domain=function(e,t){if(this._parts.urn)return void 0===e?"":this;if("boolean"==typeof e&&(t=e,e=void 0),void 0===e){if(!this._parts.hostname||this.is("IP"))return"";var r=this._parts.hostname.match(/\./g);if(r&&r.length<2)return this._parts.hostname;var n=this._parts.hostname.length-this.tld(t).length-1;return n=this._parts.hostname.lastIndexOf(".",n-1)+1,this._parts.hostname.substring(n)||""}if(!e)throw new TypeError("cannot set domain empty");if(i.ensureValidHostname(e),!this._parts.hostname||this.is("IP"))this._parts.hostname=e;else{var o=new RegExp(s(this.domain())+"$");this._parts.hostname=this._parts.hostname.replace(o,e)}return this.build(!t),this},f.tld=function(e,t){if(this._parts.urn)return void 0===e?"":this;if("boolean"==typeof e&&(t=e,e=void 0),void 0===e){if(!this._parts.hostname||this.is("IP"))return"";var n=this._parts.hostname.lastIndexOf("."),i=this._parts.hostname.substring(n+1);return t!==!0&&r&&r.list[i.toLowerCase()]?r.get(this._parts.hostname)||i:i}var o;if(!e)throw new TypeError("cannot set TLD empty");
+if(e.match(/[^a-zA-Z0-9-]/)){if(!r||!r.is(e))throw new TypeError('TLD "'+e+'" contains characters other than [A-Z0-9]');o=new RegExp(s(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(o,e)}else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");o=new RegExp(s(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(o,e)}return this.build(!t),this},f.directory=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0===e||e===!0){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var r=this._parts.path.length-this.filename().length-1,n=this._parts.path.substring(0,r)||(this._parts.hostname?"/":"");return e?i.decodePath(n):n}var o=this._parts.path.length-this.filename().length,a=this._parts.path.substring(0,o),u=new RegExp("^"+s(a));return this.is("relative")||(e||(e="/"),"/"!==e.charAt(0)&&(e="/"+e)),e&&"/"!==e.charAt(e.length-1)&&(e+="/"),e=i.recodePath(e),this._parts.path=this._parts.path.replace(u,e),this.build(!t),this},f.filename=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0===e||e===!0){if(!this._parts.path||"/"===this._parts.path)return"";var r=this._parts.path.lastIndexOf("/"),n=this._parts.path.substring(r+1);return e?i.decodePathSegment(n):n}var o=!1;"/"===e.charAt(0)&&(e=e.substring(1)),e.match(/\.?\//)&&(o=!0);var a=new RegExp(s(this.filename())+"$");return e=i.recodePath(e),this._parts.path=this._parts.path.replace(a,e),o?this.normalizePath(t):this.build(!t),this},f.suffix=function(e,t){if(this._parts.urn)return void 0===e?"":this;if(void 0===e||e===!0){if(!this._parts.path||"/"===this._parts.path)return"";var r,n,o=this.filename(),a=o.lastIndexOf(".");return-1===a?"":(r=o.substring(a+1),n=/^[a-z0-9%]+$/i.test(r)?r:"",e?i.decodePathSegment(n):n)}"."===e.charAt(0)&&(e=e.substring(1));var u,h=this.suffix();if(h)u=new RegExp(e?s(h)+"$":s("."+h)+"$");else{if(!e)return this;this._parts.path+="."+i.recodePath(e)}return u&&(e=i.recodePath(e),this._parts.path=this._parts.path.replace(u,e)),this.build(!t),this},f.segment=function(e,t,r){var n=this._parts.urn?":":"/",i=this.path(),s="/"===i.substring(0,1),o=i.split(n);if(void 0!==e&&"number"!=typeof e&&(r=t,t=e,e=void 0),void 0!==e&&"number"!=typeof e)throw new Error('Bad segment "'+e+'", must be 0-based integer');if(s&&o.shift(),0>e&&(e=Math.max(o.length+e,0)),void 0===t)return void 0===e?o:o[e];if(null===e||void 0===o[e])if(a(t)){o=[];for(var u=0,h=t.length;h>u;u++)(t[u].length||o.length&&o[o.length-1].length)&&(o.length&&!o[o.length-1].length&&o.pop(),o.push(t[u]))}else(t||"string"==typeof t)&&(""===o[o.length-1]?o[o.length-1]=t:o.push(t));else t||"string"==typeof t&&t.length?o[e]=t:o.splice(e,1);return s&&o.unshift(""),this.path(o.join(n),r)},f.segmentCoded=function(e,t,r){var n,s,o;if("number"!=typeof e&&(r=t,t=e,e=void 0),void 0===t){if(n=this.segment(e,t,r),a(n))for(s=0,o=n.length;o>s;s++)n[s]=i.decode(n[s]);else n=void 0!==n?i.decode(n):void 0;return n}if(a(t))for(s=0,o=t.length;o>s;s++)t[s]=i.decode(t[s]);else t="string"==typeof t?i.encode(t):t;return this.segment(e,t,r)};var P=f.query;return f.query=function(e,t){if(e===!0)return i.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("function"==typeof e){var r=i.parseQuery(this._parts.query,this._parts.escapeQuerySpace),n=e.call(this,r);return this._parts.query=i.buildQuery(n||r,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!t),this}return void 0!==e&&"string"!=typeof e?(this._parts.query=i.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!t),this):P.call(this,e,t)},f.setQuery=function(e,t,r){var n=i.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("object"==typeof e)for(var s in e)m.call(e,s)&&(n[s]=e[s]);else{if("string"!=typeof e)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");n[e]=void 0!==t?t:null}return this._parts.query=i.buildQuery(n,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof e&&(r=t),this.build(!r),this},f.addQuery=function(e,t,r){var n=i.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return i.addQuery(n,e,void 0===t?null:t),this._parts.query=i.buildQuery(n,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof e&&(r=t),this.build(!r),this},f.removeQuery=function(e,t,r){var n=i.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return i.removeQuery(n,e,t),this._parts.query=i.buildQuery(n,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof e&&(r=t),this.build(!r),this},f.hasQuery=function(e,t,r){var n=i.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return i.hasQuery(n,e,t,r)},f.setSearch=f.setQuery,f.addSearch=f.addQuery,f.removeSearch=f.removeQuery,f.hasSearch=f.hasQuery,f.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()},f.normalizeProtocol=function(e){return"string"==typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!e)),this},f.normalizeHostname=function(r){return this._parts.hostname&&(this.is("IDN")&&e?this._parts.hostname=e.toASCII(this._parts.hostname):this.is("IPv6")&&t&&(this._parts.hostname=t.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!r)),this},f.normalizePort=function(e){return"string"==typeof this._parts.protocol&&this._parts.port===i.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!e)),this},f.normalizePath=function(e){if(this._parts.urn)return this;if(!this._parts.path||"/"===this._parts.path)return this;var t,r,n,s=this._parts.path,o="";for("/"!==s.charAt(0)&&(t=!0,s="/"+s),s=s.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/"),t&&(o=s.substring(1).match(/^(\.\.\/)+/)||"",o&&(o=o[0]));;){if(r=s.indexOf("/.."),-1===r)break;0!==r?(n=s.substring(0,r).lastIndexOf("/"),-1===n&&(n=r),s=s.substring(0,n)+s.substring(r+3)):s=s.substring(3)}return t&&this.is("relative")&&(s=o+s.substring(1)),s=i.recodePath(s),this._parts.path=s,this.build(!e),this},f.normalizePathname=f.normalizePath,f.normalizeQuery=function(e){return"string"==typeof this._parts.query&&(this._parts.query.length?this.query(i.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!e)),this},f.normalizeFragment=function(e){return this._parts.fragment||(this._parts.fragment=null,this.build(!e)),this},f.normalizeSearch=f.normalizeQuery,f.normalizeHash=f.normalizeFragment,f.iso8859=function(){var e=i.encode,t=i.decode;return i.encode=escape,i.decode=decodeURIComponent,this.normalize(),i.encode=e,i.decode=t,this},f.unicode=function(){var e=i.encode,t=i.decode;return i.encode=l,i.decode=unescape,this.normalize(),i.encode=e,i.decode=t,this},f.readable=function(){var t=this.clone();t.username("").password("").normalize();var r="";if(t._parts.protocol&&(r+=t._parts.protocol+"://"),t._parts.hostname&&(t.is("punycode")&&e?(r+=e.toUnicode(t._parts.hostname),t._parts.port&&(r+=":"+t._parts.port)):r+=t.host()),t._parts.hostname&&t._parts.path&&"/"!==t._parts.path.charAt(0)&&(r+="/"),r+=t.path(!0),t._parts.query){for(var n="",s=0,o=t._parts.query.split("&"),a=o.length;a>s;s++){var u=(o[s]||"").split("=");n+="&"+i.decodeQuery(u[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"),void 0!==u[1]&&(n+="="+i.decodeQuery(u[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}r+="?"+n.substring(1)}return r+=i.decodeQuery(t.hash(),!0)},f.absoluteTo=function(e){var t,r,n,s=this.clone(),o=["protocol","username","password","hostname","port"];if(this._parts.urn)throw new Error("URNs do not have any generally defined hierarchical components");if(e instanceof i||(e=new i(e)),s._parts.protocol||(s._parts.protocol=e._parts.protocol),this._parts.hostname)return s;for(r=0;n=o[r];r++)s._parts[n]=e._parts[n];return s._parts.path?".."===s._parts.path.substring(-2)&&(s._parts.path+="/"):(s._parts.path=e._parts.path,s._parts.query||(s._parts.query=e._parts.query)),"/"!==s.path().charAt(0)&&(t=e.directory(),s._parts.path=(t?t+"/":"")+s._parts.path,s.normalizePath()),s.build(),s},f.relativeTo=function(e){var t,r,n,s,o,a=this.clone().normalize();if(a._parts.urn)throw new Error("URNs do not have any generally defined hierarchical components");if(e=new i(e).normalize(),t=a._parts,r=e._parts,s=a.path(),o=e.path(),"/"!==s.charAt(0))throw new Error("URI is already relative");if("/"!==o.charAt(0))throw new Error("Cannot calculate a URI relative to another relative URI");if(t.protocol===r.protocol&&(t.protocol=null),t.username!==r.username||t.password!==r.password)return a.build();if(null!==t.protocol||null!==t.username||null!==t.password)return a.build();if(t.hostname!==r.hostname||t.port!==r.port)return a.build();if(t.hostname=null,t.port=null,s===o)return t.path="",a.build();if(n=i.commonPath(a.path(),e.path()),!n)return a.build();var u=r.path.substring(n.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../");return t.path=u+t.path.substring(n.length),a.build()},f.equals=function(e){var t,r,n,s=this.clone(),o=new i(e),u={},h={},p={};if(s.normalize(),o.normalize(),s.toString()===o.toString())return!0;if(t=s.query(),r=o.query(),s.query(""),o.query(""),s.toString()!==o.toString())return!1;if(t.length!==r.length)return!1;u=i.parseQuery(t,this._parts.escapeQuerySpace),h=i.parseQuery(r,this._parts.escapeQuerySpace);for(n in u)if(m.call(u,n)){if(a(u[n])){if(!c(u[n],h[n]))return!1}else if(u[n]!==h[n])return!1;p[n]=!0}for(n in h)if(m.call(h,n)&&!p[n])return!1;return!0},f.duplicateQueryParameters=function(e){return this._parts.duplicateQueryParameters=!!e,this},f.escapeQuerySpace=function(e){return this._parts.escapeQuerySpace=!!e,this},i}),EPUBJS.Book=function(e){this.opening=new RSVP.defer,this.opened=this.opening.promise,this.isOpen=!1,this.url=void 0,this.spine=new EPUBJS.Spine(this.request),this.loading={manifest:new RSVP.defer,spine:new RSVP.defer,metadata:new RSVP.defer,cover:new RSVP.defer,navigation:new RSVP.defer,pageList:new RSVP.defer},this.loaded={manifest:this.loading.manifest.promise,spine:this.loading.spine.promise,metadata:this.loading.metadata.promise,cover:this.loading.cover.promise,navigation:this.loading.navigation.promise,pageList:this.loading.pageList.promise},this.ready=RSVP.hash(this.loaded),this.isRendered=!1,this._q=EPUBJS.core.queue(this),this.request=this.requestMethod.bind(this),e&&this.open(e)},EPUBJS.Book.prototype.open=function(e){var t,r,n,i=new EPUBJS.Parser,s=this,o="META-INF/container.xml";return e?(t="object"==typeof e?e:EPUBJS.core.uri(e),"opf"===t.extension?(this.packageUrl=t.href,this.containerUrl="",t.origin?this.url=t.origin+"/"+t.directory:window?(n=EPUBJS.core.uri(window.location.href),this.url=EPUBJS.core.resolveUrl(n.base,t.directory)):this.url=t.directory,r=this.request(this.packageUrl)):"epub"===t.extension||"zip"===t.extension?(this.archived=!0,this.url=""):t.extension||(this.containerUrl=e+o,r=this.request(this.containerUrl).then(function(e){return i.container(e)}).then(function(t){var r=EPUBJS.core.uri(t.packagePath);return s.packageUrl=e+t.packagePath,s.url=e+r.directory,s.encoding=t.encoding,s.request(s.packageUrl)}).catch(function(e){console.error("Could not load book at: "+(this.packageUrl||this.containerPath)),s.trigger("book:loadFailed",this.packageUrl||this.containerPath),s.opening.reject(e)})),r.then(function(e){s.unpack(e),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),this.isOpen=!0,s.opening.resolve(s)}).catch(function(e){console.error(e.message,e.stack),s.opening.reject(e)}),this.opened):(this.opening.resolve(this),this.opened)},EPUBJS.Book.prototype.unpack=function(e){var t=this,r=new EPUBJS.Parser;t.package=r.packageContents(e),t.package.baseUrl=t.url,this.spine.load(t.package),t.navigation=new EPUBJS.Navigation(t.package,this.request),t.navigation.load().then(function(e){t.toc=e,t.loading.navigation.resolve(t.toc)}),t.cover=t.url+t.package.coverPath},EPUBJS.Book.prototype.section=function(e){return this.spine.get(e)},EPUBJS.Book.prototype.renderTo=function(e,t){var r=new EPUBJS.Renderer(this,t);return r.attachTo(e),r},EPUBJS.Book.prototype.requestMethod=function(e){return this.archived?void 0:EPUBJS.core.request(e,"xml",this.requestCredentials,this.requestHeaders)},EPUBJS.Book.prototype.setRequestCredentials=function(e){this.requestCredentials=e},EPUBJS.Book.prototype.setRequestHeaders=function(e){this.requestHeaders=e},RSVP.EventTarget.mixin(EPUBJS.Book.prototype),RSVP.on("error",function(){}),RSVP.configure("instrument",!0),RSVP.on("rejected",function(e){console.error(e.detail.message,e.detail.stack)}),EPUBJS.core={},EPUBJS.core.request=function(e,t,r,n){function i(){if(this.readyState===this.DONE)if(200===this.status||this.responseXML){var e;e="xml"==t?this.responseXML:"json"==t?JSON.parse(this.response):"blob"==t?o?this.response:new Blob([this.response]):this.response,u.resolve(e)}else u.reject({status:this.status,message:this.response,stack:(new Error).stack})}var s,o=window.URL,a=o?"blob":"arraybuffer",u=new RSVP.defer,h=new XMLHttpRequest,c=XMLHttpRequest.prototype;"overrideMimeType"in c||Object.defineProperty(c,"overrideMimeType",{value:function(){}}),r&&(h.withCredentials=!0),h.open("GET",e,!0);for(s in n)h.setRequestHeader(s,n[s]);return h.onreadystatechange=i,"blob"==t&&(h.responseType=a),"json"==t&&h.setRequestHeader("Accept","application/json"),"xml"==t&&h.overrideMimeType("text/xml"),h.send(),u.promise},EPUBJS.core.uri=function(e){var t,r,n,i={protocol:"",host:"",path:"",origin:"",directory:"",base:"",filename:"",extension:"",fragment:"",href:e},s=e.indexOf("://"),o=e.indexOf("?"),a=e.indexOf("#");return-1!=a&&(i.fragment=e.slice(a+1),e=e.slice(0,a)),-1!=o&&(i.search=e.slice(o+1),e=e.slice(0,o),href=e),-1!=s?(i.protocol=e.slice(0,s),t=e.slice(s+3),n=t.indexOf("/"),-1===n?(i.host=i.path,i.path=""):(i.host=t.slice(0,n),i.path=t.slice(n)),i.origin=i.protocol+"://"+i.host,i.directory=EPUBJS.core.folder(i.path),i.base=i.origin+i.directory):(i.path=e,i.directory=EPUBJS.core.folder(e),i.base=i.directory),i.filename=e.replace(i.base,""),r=i.filename.lastIndexOf("."),-1!=r&&(i.extension=i.filename.slice(r+1)),i},EPUBJS.core.folder=function(e){var t=e.lastIndexOf("/");if(-1==t)var r="";return r=e.slice(0,t+1)},EPUBJS.core.queue=function(e){var t=[],r=e,n=function(e,r,n){return t.push({funcName:e,args:r,context:n}),t},i=function(){var e;t.length&&(e=t.shift(),r[e.funcName].apply(e.context||r,e.args))},s=function(){for(;t.length;)i()},o=function(){t=[]},a=function(){return t.length};return{enqueue:n,dequeue:i,flush:s,clear:o,length:a}},EPUBJS.core.isElement=function(e){return!(!e||1!=e.nodeType)},EPUBJS.core.uuid=function(){var e=(new Date).getTime(),t="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var r=(e+16*Math.random())%16|0;return e=Math.floor(e/16),("x"==t?r:7&r|8).toString(16)});return t},EPUBJS.core.values=function(e){for(var t=-1,r=Object.keys(e),n=r.length,i=Array(n);++t0;){if(r=n.shift(),"text"===r.type?(i=o.childNodes[r.index],o=i.parentNode||o):o=r.id?s.getElementById(r.id):a[r.index],"undefined"==typeof o)return console.error("No Element For",r,e.str),!1;a=Array.prototype.slice.call(o.children)}return o},EPUBJS.EpubCFI.prototype.compare=function(e,t){if("string"==typeof e&&(e=new EPUBJS.EpubCFI(e)),"string"==typeof t&&(t=new EPUBJS.EpubCFI(t)),e.spinePos>t.spinePos)return 1;if(e.spinePost.steps[r].index)return 1;if(e.steps[r].indext.characterOffset?1:e.characterOffset=0?(s=i.length,e.characterOffsetr?this.hooks[r].apply(this.context,i):void 0}.bind(this))):(e=n.promise,n.resolve()),e},EPUBJS.Infinite=function(e,t){this.container=e,this.windowHeight=window.innerHeight,this.tick=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,this.scrolled=!1,this.ignore=!1,this.displaying=!1,this.offset=350,this.views=[],this.renderer=t,this.prevScrollTop=0},EPUBJS.Infinite.prototype.start=function(){this.container.addEventListener("scroll",function(){this.ignore?this.ignore=!1:this.scrolled=!0}.bind(this)),window.addEventListener("unload",function(){this.ignore=!0}),this.tick.call(window,this.check.bind(this)),this.scrolled=!1},EPUBJS.Infinite.prototype.forwards=function(){this.trigger("forwards")},EPUBJS.Infinite.prototype.backwards=function(){this.trigger("backwards")},EPUBJS.Infinite.prototype.check=function(){if(this.scrolled&&!this.displaying){var e=this.container.scrollTop,t=(this.container.scrollLeft,this.container.scrollHeight),r=(this.container.scrollWidth,e-this.prevScrollTop),n=this.container.getBoundingClientRect().height,i=e+this.offset>t-n,s=e0?this.forwards():s&&0>r&&this.backwards(),this.prevScrollTop=e,this.scrolled=!1}else this.displaying=!1,this.scrolled=!1;this.tick.call(window,this.check.bind(this))},EPUBJS.Infinite.prototype.scrollBy=function(e,t,r){r&&(this.displaying=!0),this.container.scrollLeft+=e,this.container.scrollTop+=t},EPUBJS.Infinite.prototype.scroll=function(e,t,r){r&&(this.displaying=!0),this.container.scrollLeft=e,this.container.scrollTop=t},RSVP.EventTarget.mixin(EPUBJS.Infinite.prototype),EPUBJS.Layout=function(){},EPUBJS.Layout.prototype.reconcileLayoutSettings=function(e,t){var r={};for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);return t.forEach(function(e){var t,n,i=e.replace("rendition:",""),s=i.indexOf("-");-1!=s&&(t=i.slice(0,s),n=i.slice(s+1),r[t]=n)}),r},EPUBJS.Layout.prototype.determineLayout=function(e){var t=this.determineSpreads(this.minSpreadWidth),r=t?"ReflowableSpreads":"Reflowable",n=!1;return"pre-paginated"===e.layout&&(r="Fixed",n=!0,t=!1),"reflowable"===e.layout&&"none"===e.spread&&(r="Reflowable",n=!1,t=!1),"reflowable"===e.layout&&"both"===e.spread&&(r="ReflowableSpreads",n=!1,t=!0),this.spreads=t,this.render.scroll(n),this.trigger("renderer:spreads",t),r},EPUBJS.Layout.prototype.applyStyles=function(e){for(var t in e)for(var r in this.views)r.setStyle(t,e[t])},EPUBJS.Layout.prototype.setStyle=function(e,t,r){for(var n in this.views)n.setStyle(e,t,r)},EPUBJS.Layout.prototype.removeStyle=function(e){for(var t in this.views)t.removeStyle(e)},EPUBJS.Layout.prototype.applyHeadTags=function(e){for(var t in e)this.render.addHeadTag(t,e[t])},EPUBJS.Navigation=function(e,t){var r=this,n=new EPUBJS.Parser,i=t||EPUBJS.core.request;this.package=e,this.toc=[],this.tocByHref={},this.tocById={},e.navPath&&(this.navUrl=e.baseUrl+e.navPath,this.nav={},this.nav.load=function(){var e=new RSVP.defer,t=e.promise;return i(r.navUrl,"xml").then(function(t){r.toc=n.nav(t),r.loaded(r.toc),e.resolve(r.toc)}),t}),e.ncxPath&&(this.ncxUrl=e.baseUrl+e.ncxPath,this.ncx={},this.ncx.load=function(){var e=new RSVP.defer,t=e.promise;return i(r.ncxUrl,"xml").then(function(t){r.toc=n.ncx(t),r.loaded(r.toc),e.resolve(r.toc)}),t})},EPUBJS.Navigation.prototype.load=function(e){{var t,r;e||EPUBJS.core.request}return this.nav?t=this.nav.load():this.ncx?t=this.ncx.load():(r=new RSVP.defer,r.resolve([]),t=r.promise),t},EPUBJS.Navigation.prototype.loaded=function(e){for(var t,r=0;r=0;o--){var a=i.snapshotItem(o),u=a.getAttribute("id")||!1,h=a.querySelector("content"),c=h.getAttribute("src"),p=a.querySelector("navLabel"),l=p.textContent?p.textContent:"",d=c.split("#"),f=(d[0],t(a));n.unshift({id:u,href:c,label:l,subitems:f,parent:r?r.getAttribute("id"):null})}return n}var r=e.querySelector("navMap");return r?t(r):[]},EPUBJS.Renderer=function(e,t){var r=t||{};this.settings={hidden:r.hidden||!1,viewsLimit:6,width:r.width||!1,height:r.height||!1},this.book=e,this.epubcfi=new EPUBJS.EpubCFI,this.layoutSettings={},this._q=EPUBJS.core.queue(this),this.position=1,this.initialize({width:this.settings.width,height:this.settings.height}),this.rendering=!1,this.views=[],this.positions=[],this.hooks={},this.hooks.display=new EPUBJS.Hook(this),this.hooks.replacements=new EPUBJS.Hook(this)},EPUBJS.Renderer.prototype.initialize=function(e){{var t=e||{},r=t.height?t.height+"px":"100%",n=t.width?t.width+"px":"100%";t.hidden||!1}return this.container=document.createElement("div"),this.infinite=new EPUBJS.Infinite(this.container,this),this.container.style.width=n,this.container.style.height=r,this.container.style.overflow="scroll",t.hidden?(this.wrapper=document.createElement("div"),this.wrapper.style.visibility="hidden",this.wrapper.style.overflow="hidden",this.wrapper.style.width="0",this.wrapper.style.height="0",this.wrapper.appendChild(this.container),this.wrapper):this.container},EPUBJS.Renderer.prototype.resize=function(e,t){var r=e,n=t;
+e||(r=window.innerWidth),t||(n=window.innerHeight),this.container.style.width=r+"px",this.container.style.height=n+"px",this.trigger("resized",{width:this.width,height:this.height})},EPUBJS.Renderer.prototype.onResized=function(){var e=this.element.getBoundingClientRect();this.resize(e.width,e.height)},EPUBJS.Renderer.prototype.attachTo=function(e){var t;return EPUBJS.core.isElement(e)?this.element=e:"string"==typeof e&&(this.element=document.getElementById(e)),this.element?(this.element.appendChild(this.container),this.settings.height||this.settings.width||(t=this.element.getBoundingClientRect(),this.resize(t.width,t.height)),this.infinite.start(),this.infinite.on("forwards",function(){var e=this.last().section.index+1;!this.rendering&&e0&&this.backwards()}.bind(this)),window.addEventListener("resize",this.onResized.bind(this),!1),void this.hooks.replacements.register(this.replacements.bind(this))):void console.error("Not an Element")},EPUBJS.Renderer.prototype.clear=function(){this.views.forEach(function(e){e.destroy()}),this.views=[]},EPUBJS.Renderer.prototype.display=function(e){var t=new RSVP.defer,r=t.promise;return this.clear(),this.book.opened.then(function(){var r,n=this.book.spine.get(e);n?(r=this.render(n),r.then(this.fill.bind(this)).then(function(){t.resolve(this)}.bind(this))):t.reject(new Error("No Section Found"))}.bind(this)),r},EPUBJS.Renderer.prototype.render=function(e){var t,r;return e?(r=new EPUBJS.View(e),this.insert(r,e.index),t=r.render(this.book.request),t.then(function(){return this.hooks.display.trigger(r)}.bind(this)).then(function(){return this.hooks.replacements.trigger(r,this)}.bind(this)).then(function(){return this.rendering=!1,r.show(),r}.bind(this)).catch(function(e){this.trigger("loaderror",e)}.bind(this))):(t=new RSVP.defer,t.reject(new Error("No Section Provided")),t.promise)},EPUBJS.Renderer.prototype.forwards=function(){var e,t,r;return e=this.last().section.index+1,this.rendering||e===this.book.spine.length?(t=new RSVP.defer,t.reject(new Error("Reject Forwards")),t.promise):(this.rendering=!0,r=this.book.spine.get(e),t=this.render(r),t.then(function(){var e=this.first(),t=e.bounds(),r=this.container.scrollTop;this.views.length>this.settings.viewsLimit&&(this.remove(e),this.infinite.scroll(0,r-t.height,!0))}.bind(this)),t)},EPUBJS.Renderer.prototype.backwards=function(){var e,t,r;return e=this.first().section.index-1,this.rendering||0>e?(t=new RSVP.defer,t.reject(new Error("Reject Backwards")),t.promise):(this.rendering=!0,r=this.book.spine.get(e),t=this.render(r),t.then(function(){this.infinite.scrollBy(0,this.first().height,!0),this.views.length>this.settings.viewsLimit&&(last=this.last(),this.remove(last))}.bind(this)),t)},EPUBJS.Renderer.prototype.fill=function(){var e=this.container.getBoundingClientRect().height,t=function(){var r=this.last().bounds().bottom,n=new RSVP.defer;return e&&r&&e>r?this.forwards().then(t):(this.rendering=!1,n.resolve(),n.promise)}.bind(this),r=this.first().section.index-1,n=t();return r>0&&n.then(this.backwards.bind(this)),n.then(function(){this.rendering=!1}.bind(this))},EPUBJS.Renderer.prototype.append=function(e){this.views.push(e),e.appendTo(this.container)},EPUBJS.Renderer.prototype.prepend=function(e){this.views.unshift(e),e.prependTo(this.container)},EPUBJS.Renderer.prototype.insert=function(e,t){this.first()?t-this.first().section.index>=0?this.append(e):t-this.last().section.index<=0&&this.prepend(e):this.append(e)},EPUBJS.Renderer.prototype.remove=function(e){var t=this.views.indexOf(e);e.destroy(),t>-1&&this.views.splice(t,1)},EPUBJS.Renderer.prototype.first=function(){return this.views[0]},EPUBJS.Renderer.prototype.last=function(){return this.views[this.views.length-1]},EPUBJS.Renderer.prototype.replacements=function(e,t){for(var r=new RSVP.defer,n=e.document.querySelectorAll("a[href]"),i=function(e){var r=e.getAttribute("href"),n=r.search("://");-1!=n?e.setAttribute("target","_blank"):e.onclick=function(){return t.display(r),!1}},s=0;s-1?(delete this.spineByHref[e.href],delete this.spineById[e.idref],this.spineItems.splice(t,1)):void 0},EPUBJS.View=function(e){this.id="epubjs-view:"+EPUBJS.core.uuid(),this.rendering=new RSVP.defer,this.rendered=this.rendering.promise,this.iframe=this.create(),this.section=e},EPUBJS.View.prototype.create=function(){return this.iframe=document.createElement("iframe"),this.iframe.id=this.id,this.iframe.scrolling="no",this.iframe.seamless="seamless",this.iframe.style.border="none",this.resizing=!0,this.iframe.width="100%",this.iframe.style.height="100%",this.iframe.style.display="none",this.iframe.style.visibility="hidden",this.iframe},EPUBJS.View.prototype.resized=function(){this.resizing?this.resizing=!1:this.layout()},EPUBJS.View.prototype.render=function(e){return this.section.render(e).then(function(e){return this.load(e)}.bind(this)).then(this.display.bind(this)).then(function(){this.rendering.resolve(this)}.bind(this))},EPUBJS.View.prototype.load=function(e){var t=new RSVP.defer,r=t.promise;return this.document=this.iframe.contentDocument,this.iframe.addEventListener("load",function(){this.window=this.iframe.contentWindow,this.document=this.iframe.contentDocument,t.resolve(this)}.bind(this)),this.document.open(),this.document.write(e),this.document.close(),r},EPUBJS.View.prototype.display=function(){var e=new RSVP.defer,t=e.promise;return this.iframe.style.display="block",this.document.body.style.margin="0",this.document.body.style.display="inline-block",this.document.body.style.padding="0 20px 20px 20px",setTimeout(function(){this.window.addEventListener("resize",this.resized.bind(this),!1)}.bind(this),10),"loading"!==this.document.fonts.status?(this.layout(),e.resolve(this)):this.document.fonts.onloading=function(){this.layout(),e.resolve(this)}.bind(this),t},EPUBJS.View.prototype.layout=function(){var e;e=this.document.body.getBoundingClientRect(),(!e||0==e.height&&0==e.width)&&console.error("View not shown"),this.resizing=!0,this.iframe.style.height=e.height+"px",this.width=e.width,this.height=e.height},EPUBJS.View.prototype.observe=function(e){var t=this,r=new MutationObserver(function(e){e.forEach(function(){t.layout()})}),n={attributes:!0,childList:!0,characterData:!0,subtree:!0};return r.observe(e,n),r},EPUBJS.View.prototype.appendTo=function(e){this.element=e,this.element.appendChild(this.iframe)},EPUBJS.View.prototype.prependTo=function(e){this.element=e,e.insertBefore(this.iframe,e.firstChild)},EPUBJS.View.prototype.bounds=function(){return this.iframe.getBoundingClientRect()},EPUBJS.View.prototype.show=function(){this.iframe.style.display="block",this.iframe.style.visibility="visible"},EPUBJS.View.prototype.hide=function(){this.iframe.style.display="none",this.iframe.style.visibility="hidden"},EPUBJS.View.prototype.destroy=function(){this.element.removeChild(this.iframe)};
\ No newline at end of file
diff --git a/examples/basic-render.html b/examples/basic.html
similarity index 74%
rename from examples/basic-render.html
rename to examples/basic.html
index a4e1f33..da3d262 100644
--- a/examples/basic-render.html
+++ b/examples/basic.html
@@ -9,19 +9,26 @@