From d9a19e5a28deef708f7d721f9d5801617e9bc282 Mon Sep 17 00:00:00 2001 From: fchasen Date: Sun, 21 Feb 2016 23:37:18 -0500 Subject: [PATCH] style highlights examples --- dist/epub.js | 388 ++++++++++++++++++++++++++++++++------- dist/epub.js.map | 2 +- examples/highlights.html | 99 ++++++---- gulpfile.js | 9 +- src/book.js | 4 +- src/epubcfi.js | 77 ++++---- src/paginate.js | 4 +- src/rendition.js | 4 +- src/request.js | 12 +- src/view.js | 2 +- 10 files changed, 445 insertions(+), 156 deletions(-) diff --git a/dist/epub.js b/dist/epub.js index 0fe94b2..7847163 100644 --- a/dist/epub.js +++ b/dist/epub.js @@ -1869,6 +1869,249 @@ process.umask = function() { return 0; }; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"_process":3}],5:[function(require,module,exports){ +/*! + * URI.js - Mutating URLs + * Second Level Domain (SLD) Support + * + * Version: 1.17.0 + * + * 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(); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory); + } else { + // Browser globals (root is window) + root.SecondLevelDomains = factory(root); + } +}(this, function (root) { + 'use strict'; + + // save current SecondLevelDomains variable, if any + var _SecondLevelDomains = root && root.SecondLevelDomains; + + var SLD = { + // list of known Second Level Domains + // converted list of SLDs from https://github.com/gavingmiller/second-level-domains + // ---- + // publicsuffix.org is more current and actually used by a couple of browsers internally. + // downside is it also contains domains like "dyndns.org" - which is fine for the security + // issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js + // ---- + list: { + 'ac':' com gov mil net org ', + 'ae':' ac co gov mil name net org pro sch ', + 'af':' com edu gov net org ', + 'al':' com edu gov mil net org ', + 'ao':' co ed gv it og pb ', + 'ar':' com edu gob gov int mil net org tur ', + 'at':' ac co gv or ', + 'au':' asn com csiro edu gov id net org ', + 'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ', + 'bb':' biz co com edu gov info net org store tv ', + 'bh':' biz cc com edu gov info net org ', + 'bn':' com edu gov net org ', + 'bo':' com edu gob gov int mil net org tv ', + 'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ', + 'bs':' com edu gov net org ', + 'bz':' du et om ov rg ', + 'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ', + 'ck':' biz co edu gen gov info net org ', + 'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ', + 'co':' com edu gov mil net nom org ', + 'cr':' ac c co ed fi go or sa ', + 'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ', + 'do':' art com edu gob gov mil net org sld web ', + 'dz':' art asso com edu gov net org pol ', + 'ec':' com edu fin gov info med mil net org pro ', + 'eg':' com edu eun gov mil name net org sci ', + 'er':' com edu gov ind mil net org rochest w ', + 'es':' com edu gob nom org ', + 'et':' biz com edu gov info name net org ', + 'fj':' ac biz com info mil name net org pro ', + 'fk':' ac co gov net nom org ', + 'fr':' asso com f gouv nom prd presse tm ', + 'gg':' co net org ', + 'gh':' com edu gov mil org ', + 'gn':' ac com gov net org ', + 'gr':' com edu gov mil net org ', + 'gt':' com edu gob ind mil net org ', + 'gu':' com edu gov net org ', + 'hk':' com edu gov idv net org ', + 'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ', + 'id':' ac co go mil net or sch web ', + 'il':' ac co gov idf k12 muni net org ', + 'in':' ac co edu ernet firm gen gov i ind mil net nic org res ', + 'iq':' com edu gov i mil net org ', + 'ir':' ac co dnssec gov i id net org sch ', + 'it':' edu gov ', + 'je':' co net org ', + 'jo':' com edu gov mil name net org sch ', + 'jp':' ac ad co ed go gr lg ne or ', + 'ke':' ac co go info me mobi ne or sc ', + 'kh':' com edu gov mil net org per ', + 'ki':' biz com de edu gov info mob net org tel ', + 'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ', + 'kn':' edu gov net org ', + 'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ', + 'kw':' com edu gov net org ', + 'ky':' com edu gov net org ', + 'kz':' com edu gov mil net org ', + 'lb':' com edu gov net org ', + 'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ', + 'lr':' com edu gov net org ', + 'lv':' asn com conf edu gov id mil net org ', + 'ly':' com edu gov id med net org plc sch ', + 'ma':' ac co gov m net org press ', + 'mc':' asso tm ', + 'me':' ac co edu gov its net org priv ', + 'mg':' com edu gov mil nom org prd tm ', + 'mk':' com edu gov inf name net org pro ', + 'ml':' com edu gov net org presse ', + 'mn':' edu gov org ', + 'mo':' com edu gov net org ', + 'mt':' com edu gov net org ', + 'mv':' aero biz com coop edu gov info int mil museum name net org pro ', + 'mw':' ac co com coop edu gov int museum net org ', + 'mx':' com edu gob net org ', + 'my':' com edu gov mil name net org sch ', + 'nf':' arts com firm info net other per rec store web ', + 'ng':' biz com edu gov mil mobi name net org sch ', + 'ni':' ac co com edu gob mil net nom org ', + 'np':' com edu gov mil net org ', + 'nr':' biz com edu gov info net org ', + 'om':' ac biz co com edu gov med mil museum net org pro sch ', + 'pe':' com edu gob mil net nom org sld ', + 'ph':' com edu gov i mil net ngo org ', + 'pk':' biz com edu fam gob gok gon gop gos gov net org web ', + 'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ', + 'pr':' ac biz com edu est gov info isla name net org pro prof ', + 'ps':' com edu gov net org plo sec ', + 'pw':' belau co ed go ne or ', + 'ro':' arts com firm info nom nt org rec store tm www ', + 'rs':' ac co edu gov in org ', + 'sb':' com edu gov net org ', + 'sc':' com edu gov net org ', + 'sh':' co com edu gov net nom org ', + 'sl':' com edu gov net org ', + 'st':' co com consulado edu embaixada gov mil net org principe saotome store ', + 'sv':' com edu gob org red ', + 'sz':' ac co org ', + 'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ', + 'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ', + 'tw':' club com ebiz edu game gov idv mil net org ', + 'mu':' ac co com gov net or org ', + 'mz':' ac co edu gov org ', + 'na':' co com ', + 'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ', + 'pa':' abo ac com edu gob ing med net nom org sld ', + 'pt':' com edu gov int net nome org publ ', + 'py':' com edu gov mil net org ', + 'qa':' com edu gov mil net org ', + 're':' asso com nom ', + 'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ', + 'rw':' ac co com edu gouv gov int mil net ', + 'sa':' com edu gov med net org pub sch ', + 'sd':' com edu gov info med net org tv ', + 'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ', + 'sg':' com edu gov idn net org per ', + 'sn':' art com edu gouv org perso univ ', + 'sy':' com edu gov mil net news org ', + 'th':' ac co go in mi net or ', + 'tj':' ac biz co com edu go gov info int mil name net nic org test web ', + 'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ', + 'tz':' ac co go ne or ', + 'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ', + 'ug':' ac co go ne or org sc ', + 'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ', + 'us':' dni fed isa kids nsn ', + 'uy':' com edu gub mil net org ', + 've':' co com edu gob info mil net org web ', + 'vi':' co com k12 net org ', + 'vn':' ac biz com edu gov health info int name net org pro ', + 'ye':' co com gov ltd me net org plc ', + 'yu':' ac co edu gov org ', + 'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ', + 'zm':' ac co com edu gov net org sch ' + }, + // gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost + // in both performance and memory footprint. No initialization required. + // http://jsperf.com/uri-js-sld-regex-vs-binary-search/4 + // Following methods use lastIndexOf() rather than array.split() in order + // to avoid any memory allocations. + has: function(domain) { + var tldOffset = domain.lastIndexOf('.'); + if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { + return false; + } + var sldOffset = domain.lastIndexOf('.', tldOffset-1); + if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) { + return false; + } + var sldList = SLD.list[domain.slice(tldOffset+1)]; + if (!sldList) { + return false; + } + return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0; + }, + is: function(domain) { + var tldOffset = domain.lastIndexOf('.'); + if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { + return false; + } + var sldOffset = domain.lastIndexOf('.', tldOffset-1); + if (sldOffset >= 0) { + return false; + } + var sldList = SLD.list[domain.slice(tldOffset+1)]; + if (!sldList) { + return false; + } + return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0; + }, + get: function(domain) { + var tldOffset = domain.lastIndexOf('.'); + if (tldOffset <= 0 || tldOffset >= (domain.length-1)) { + return null; + } + var sldOffset = domain.lastIndexOf('.', tldOffset-1); + if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) { + return null; + } + var sldList = SLD.list[domain.slice(tldOffset+1)]; + if (!sldList) { + return null; + } + if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) { + return null; + } + return domain.slice(sldOffset+1); + }, + noConflict: function(){ + if (root.SecondLevelDomains === this) { + root.SecondLevelDomains = _SecondLevelDomains; + } + return this; + } + }; + + return SLD; +})); + +},{}],6:[function(require,module,exports){ /*! * URI.js - Mutating URLs * @@ -4031,7 +4274,7 @@ process.umask = function() { return 0; }; return URI; })); -},{"./IPv6":2,"./SecondLevelDomains":2,"./punycode":2}],6:[function(require,module,exports){ +},{"./IPv6":2,"./SecondLevelDomains":5,"./punycode":2}],7:[function(require,module,exports){ var RSVP = require('rsvp'); var URI = require('urijs'); var core = require('./core'); @@ -4313,9 +4556,9 @@ Book.prototype.coverUrl = function(){ return retrieved; }; -Book.prototype.selectCfiRange = function(cfiRange) { +Book.prototype.range = function(cfiRange) { var cfi = new EpubCFI(cfiRange); - var item = this.spine.get(cfi.spinePos) + var item = this.spine.get(cfi.spinePos); return item.load().then(function (contents) { var range = cfi.toRange(item.document); @@ -4341,7 +4584,7 @@ RSVP.on('rejected', function(event){ console.error(event.detail.message, event.detail.stack); }); -},{"./continuous":7,"./core":8,"./epubcfi":9,"./locations":12,"./navigation":14,"./paginate":15,"./parser":16,"./rendition":18,"./request":20,"./spine":22,"./unarchive":23,"rsvp":4,"urijs":5}],7:[function(require,module,exports){ +},{"./continuous":8,"./core":9,"./epubcfi":10,"./locations":13,"./navigation":15,"./paginate":16,"./parser":17,"./rendition":19,"./request":21,"./spine":23,"./unarchive":24,"rsvp":4,"urijs":6}],8:[function(require,module,exports){ var RSVP = require('rsvp'); var core = require('./core'); var Rendition = require('./rendition'); @@ -4761,7 +5004,7 @@ Continuous.prototype.current = function(what){ module.exports = Continuous; -},{"./core":8,"./rendition":18,"./view":24,"rsvp":4}],8:[function(require,module,exports){ +},{"./core":9,"./rendition":19,"./view":25,"rsvp":4}],9:[function(require,module,exports){ var RSVP = require('rsvp'); var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false; @@ -5202,7 +5445,7 @@ module.exports = { 'type': type }; -},{"rsvp":4}],9:[function(require,module,exports){ +},{"rsvp":4}],10:[function(require,module,exports){ var URI = require('urijs'); var core = require('./core'); @@ -6060,54 +6303,51 @@ EpubCFI.prototype.toRange = function(_doc, ignoreClass) { var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false; var missed; - if (cfi.range) { - start = cfi.start; - startSteps = cfi.path.steps.concat(start.steps); - startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null); - end = cfi.end; - endSteps = cfi.path.steps.concat(end.steps); - endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null); - } else { - start = cfi.path; - startSteps = cfi.path.steps; - startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null); - } + if (cfi.range) { + start = cfi.start; + startSteps = cfi.path.steps.concat(start.steps); + startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null); + end = cfi.end; + endSteps = cfi.path.steps.concat(end.steps); + endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null); + } else { + start = cfi.path; + startSteps = cfi.path.steps; + startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null); + } + if(startContainer) { + try { - - if(startContainer) { - try { - - if(start.terminal.offset != null) { - range.setStart(startContainer, start.terminal.offset); - } else { - range.setStart(startContainer, 0); - } - - } catch (e) { - missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null); - range.setStart(missed.container, missed.offset); + if(start.terminal.offset != null) { + range.setStart(startContainer, start.terminal.offset); + } else { + range.setStart(startContainer, 0); } - } else { - // No start found - return null; + + } catch (e) { + missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null); + range.setStart(missed.container, missed.offset); } + } else { + // No start found + return null; + } + if (endContainer) { + try { - if (endContainer) { - try { - - if(end.terminal.offset != null) { - range.setEnd(endContainer, end.terminal.offset); - } else { - range.setEnd(endContainer, 0); - } - - } catch (e) { - missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null); - range.setEnd(missed.container, missed.offset); + if(end.terminal.offset != null) { + range.setEnd(endContainer, end.terminal.offset); + } else { + range.setEnd(endContainer, 0); } + + } catch (e) { + missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null); + range.setEnd(missed.container, missed.offset); } + } // doc.defaultView.getSelection().addRange(range); @@ -6141,7 +6381,7 @@ EpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) module.exports = EpubCFI; -},{"./core":8,"urijs":5}],10:[function(require,module,exports){ +},{"./core":9,"urijs":6}],11:[function(require,module,exports){ var RSVP = require('rsvp'); //-- Hooks allow for injecting functions that must all complete in order before finishing @@ -6198,7 +6438,7 @@ Hook.prototype.list = function(){ module.exports = Hook; -},{"rsvp":4}],11:[function(require,module,exports){ +},{"rsvp":4}],12:[function(require,module,exports){ var core = require('./core'); function Reflowable(){ @@ -6361,7 +6601,7 @@ module.exports = { 'Scroll': Scroll }; -},{"./core":8}],12:[function(require,module,exports){ +},{"./core":9}],13:[function(require,module,exports){ var core = require('./core'); var Queue = require('./queue'); var EpubCFI = require('./epubcfi'); @@ -6586,7 +6826,7 @@ RSVP.EventTarget.mixin(Locations.prototype); module.exports = Locations; -},{"./core":8,"./epubcfi":9,"./queue":17,"rsvp":4}],13:[function(require,module,exports){ +},{"./core":9,"./epubcfi":10,"./queue":18,"rsvp":4}],14:[function(require,module,exports){ function Map(layout){ this.layout = layout; }; @@ -6875,7 +7115,7 @@ Map.prototype.rangeListToCfiList = function(view, columns){ module.exports = Map; -},{}],14:[function(require,module,exports){ +},{}],15:[function(require,module,exports){ var core = require('./core'); var Parser = require('./parser'); var RSVP = require('rsvp'); @@ -6979,7 +7219,7 @@ Navigation.prototype.get = function(target) { module.exports = Navigation; -},{"./core":8,"./parser":16,"./request":20,"rsvp":4,"urijs":5}],15:[function(require,module,exports){ +},{"./core":9,"./parser":17,"./request":21,"rsvp":4,"urijs":6}],16:[function(require,module,exports){ var RSVP = require('rsvp'); var core = require('./core'); var Continuous = require('./continuous'); @@ -7005,9 +7245,7 @@ function Paginate(book, options) { this.isForcedSingle = this.settings.forceSingle; - this.viewSettings = { - axis: this.settings.axis - }; + this.viewSettings.axis = this.settings.axis; this.start(); }; @@ -7267,7 +7505,7 @@ Paginate.prototype.adjustImages = function(view) { module.exports = Paginate; -},{"./continuous":7,"./core":8,"./layout":11,"./map":13,"rsvp":4}],16:[function(require,module,exports){ +},{"./continuous":8,"./core":9,"./layout":12,"./map":14,"rsvp":4}],17:[function(require,module,exports){ var URI = require('urijs'); var core = require('./core'); var EpubCFI = require('./epubcfi'); @@ -7731,7 +7969,7 @@ Parser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){ module.exports = Parser; -},{"./core":8,"./epubcfi":9,"urijs":5}],17:[function(require,module,exports){ +},{"./core":9,"./epubcfi":10,"urijs":6}],18:[function(require,module,exports){ var RSVP = require('rsvp'); var core = require('./core'); @@ -7926,7 +8164,7 @@ function Task(task, args, context){ module.exports = Queue; -},{"./core":8,"rsvp":4}],18:[function(require,module,exports){ +},{"./core":9,"rsvp":4}],19:[function(require,module,exports){ var RSVP = require('rsvp'); var URI = require('urijs'); var core = require('./core'); @@ -8682,7 +8920,7 @@ Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){ section.output = replace.substitute(section.output, relUrls, replacementUrls); }; -Rendition.prototype.selectCfiRange = function(_cfi, ignoreClass){ +Rendition.prototype.range = function(_cfi, ignoreClass){ var cfi = new EpubCFI(_cfi); var found = this.visible().filter(function (view) { if(cfi.spinePos === view.index) return true; @@ -8690,7 +8928,7 @@ Rendition.prototype.selectCfiRange = function(_cfi, ignoreClass){ // Should only every return 1 item if (found.length) { - return found[0].selectCfiRange(cfi, ignoreClass); + return found[0].range(cfi, ignoreClass); } }; @@ -8699,7 +8937,7 @@ RSVP.EventTarget.mixin(Rendition.prototype); module.exports = Rendition; -},{"./core":8,"./epubcfi":9,"./hook":10,"./layout":11,"./map":13,"./queue":17,"./replacements":19,"./view":24,"./views":25,"rsvp":4,"urijs":5}],19:[function(require,module,exports){ +},{"./core":9,"./epubcfi":10,"./hook":11,"./layout":12,"./map":14,"./queue":18,"./replacements":20,"./view":25,"./views":26,"rsvp":4,"urijs":6}],20:[function(require,module,exports){ var URI = require('urijs'); var core = require('./core'); @@ -8786,7 +9024,7 @@ module.exports = { 'substitute': substitute }; -},{"./core":8,"urijs":5}],20:[function(require,module,exports){ +},{"./core":9,"urijs":6}],21:[function(require,module,exports){ var RSVP = require('rsvp'); var URI = require('urijs'); var core = require('./core'); @@ -8842,7 +9080,7 @@ function request(url, type, withCredentials, headers) { if(core.isXml(type)) { xhr.responseType = "document"; - // xhr.overrideMimeType('text/xml'); // for OPF parsing + xhr.overrideMimeType('text/xml'); // for OPF parsing } if(type == 'xhtml') { @@ -8870,6 +9108,15 @@ function request(url, type, withCredentials, headers) { if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls var r; + if (!this.response && !this.responseXML) { + deferred.reject({ + status: this.status, + message : "Empty Response", + stack : new Error().stack + }); + return deferred.promise; + } + if((this.responseType == '' || this.responseType == 'document') && this.responseXML){ r = this.responseXML; @@ -8880,6 +9127,7 @@ function request(url, type, withCredentials, headers) { r = new DOMParser().parseFromString(this.response, "text/xml"); }else if(type == 'xhtml'){ + console.log(this.response); r = new DOMParser().parseFromString(this.response, "application/xhtml+xml"); }else if(type == 'html' || type == 'htm'){ @@ -8919,7 +9167,7 @@ function request(url, type, withCredentials, headers) { module.exports = request; -},{"./core":8,"rsvp":4,"urijs":5}],21:[function(require,module,exports){ +},{"./core":9,"rsvp":4,"urijs":6}],22:[function(require,module,exports){ var RSVP = require('rsvp'); var URI = require('urijs'); var core = require('./core'); @@ -9070,7 +9318,7 @@ Section.prototype.cfiFromElement = function(el) { module.exports = Section; -},{"./core":8,"./epubcfi":9,"./hook":10,"./replacements":19,"./request":20,"rsvp":4,"urijs":5}],22:[function(require,module,exports){ +},{"./core":9,"./epubcfi":10,"./hook":11,"./replacements":20,"./request":21,"rsvp":4,"urijs":6}],23:[function(require,module,exports){ var RSVP = require('rsvp'); var core = require('./core'); var EpubCFI = require('./epubcfi'); @@ -9194,7 +9442,7 @@ Spine.prototype.each = function() { module.exports = Spine; -},{"./core":8,"./epubcfi":9,"./section":21,"rsvp":4}],23:[function(require,module,exports){ +},{"./core":9,"./epubcfi":10,"./section":22,"rsvp":4}],24:[function(require,module,exports){ var RSVP = require('rsvp'); var URI = require('urijs'); var core = require('./core'); @@ -9344,7 +9592,7 @@ Unarchive.prototype.revokeUrl = function(url){ module.exports = Unarchive; -},{"../libs/mime/mime":1,"./core":8,"./request":20,"jszip":"jszip","rsvp":4,"urijs":5}],24:[function(require,module,exports){ +},{"../libs/mime/mime":1,"./core":9,"./request":21,"jszip":"jszip","rsvp":4,"urijs":6}],25:[function(require,module,exports){ var RSVP = require('rsvp'); var core = require('./core'); var EpubCFI = require('./epubcfi'); @@ -10100,7 +10348,7 @@ View.prototype.triggerSelectedEvent = function(selection){ } }; -View.prototype.selectCfiRange = function(_cfi, ignoreClass){ +View.prototype.range = function(_cfi, ignoreClass){ var cfi = new EpubCFI(_cfi); return cfi.toRange(this.document, ignoreClass || this.settings.ignoreClass); }; @@ -10109,7 +10357,7 @@ RSVP.EventTarget.mixin(View.prototype); module.exports = View; -},{"./core":8,"./epubcfi":9,"rsvp":4}],25:[function(require,module,exports){ +},{"./core":9,"./epubcfi":10,"rsvp":4}],26:[function(require,module,exports){ function Views(container) { this.container = container; this._views = []; @@ -10279,7 +10527,7 @@ ePub.CFI = EpubCFI; module.exports = ePub; -},{"./book":6,"./epubcfi":9}]},{},["epub"])("epub") +},{"./book":7,"./epubcfi":10}]},{},["epub"])("epub") }); diff --git a/dist/epub.js.map b/dist/epub.js.map index f14d47f..f6860c9 100644 --- a/dist/epub.js.map +++ b/dist/epub.js.map @@ -1 +1 @@ -{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","libs/mime/mime.js","node_modules/browserify/lib/_empty.js","node_modules/browserify/node_modules/process/browser.js","node_modules/rsvp/dist/rsvp.js","node_modules/urijs/src/URI.js","src/book.js","src/continuous.js","src/core.js","src/epubcfi.js","src/hook.js","src/layout.js","src/locations.js","src/map.js","src/navigation.js","src/paginate.js","src/parser.js","src/queue.js","src/rendition.js","src/replacements.js","src/request.js","src/section.js","src/spine.js","src/unarchive.js","src/view.js","src/views.js","src/epub.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3KA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7jDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACz6BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9cA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnwBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3vBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"epub.js","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n setTimeout(drainQueue, 0);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n","/*!\n * @overview RSVP - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors\n * @license Licensed under MIT license\n * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE\n * @version 3.1.0\n */\n\n(function() {\n \"use strict\";\n function lib$rsvp$utils$$objectOrFunction(x) {\n return typeof x === 'function' || (typeof x === 'object' && x !== null);\n }\n\n function lib$rsvp$utils$$isFunction(x) {\n return typeof x === 'function';\n }\n\n function lib$rsvp$utils$$isMaybeThenable(x) {\n return typeof x === 'object' && x !== null;\n }\n\n var lib$rsvp$utils$$_isArray;\n if (!Array.isArray) {\n lib$rsvp$utils$$_isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n } else {\n lib$rsvp$utils$$_isArray = Array.isArray;\n }\n\n var lib$rsvp$utils$$isArray = lib$rsvp$utils$$_isArray;\n\n var lib$rsvp$utils$$now = Date.now || function() { return new Date().getTime(); };\n\n function lib$rsvp$utils$$F() { }\n\n var lib$rsvp$utils$$o_create = (Object.create || function (o) {\n if (arguments.length > 1) {\n throw new Error('Second argument not supported');\n }\n if (typeof o !== 'object') {\n throw new TypeError('Argument must be an object');\n }\n lib$rsvp$utils$$F.prototype = o;\n return new lib$rsvp$utils$$F();\n });\n function lib$rsvp$events$$indexOf(callbacks, callback) {\n for (var i=0, l=callbacks.length; i 0.5) {\n throw new Error();\n }\n return new Author();\n }\n\n try {\n return findAuthor(); // succeed or fail\n } catch(error) {\n return findOtherAuther();\n } finally {\n // always runs\n // doesn't affect the return value\n }\n ```\n\n Asynchronous example:\n\n ```js\n findAuthor().catch(function(reason){\n return findOtherAuther();\n }).finally(function(){\n // author was either found, or not\n });\n ```\n\n @method finally\n @param {Function} callback\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'finally': function(callback, label) {\n var promise = this;\n var constructor = promise.constructor;\n\n return promise.then(function(value) {\n return constructor.resolve(callback()).then(function(){\n return value;\n });\n }, function(reason) {\n return constructor.resolve(callback()).then(function(){\n throw reason;\n });\n }, label);\n }\n };\n\n function lib$rsvp$all$settled$$AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);\n }\n\n lib$rsvp$all$settled$$AllSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$all$settled$$AllSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$all$settled$$AllSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n lib$rsvp$all$settled$$AllSettled.prototype._validationError = function() {\n return new Error('allSettled must be called with an array');\n };\n\n function lib$rsvp$all$settled$$allSettled(entries, label) {\n return new lib$rsvp$all$settled$$AllSettled(lib$rsvp$promise$$default, entries, label).promise;\n }\n var lib$rsvp$all$settled$$default = lib$rsvp$all$settled$$allSettled;\n function lib$rsvp$all$$all(array, label) {\n return lib$rsvp$promise$$default.all(array, label);\n }\n var lib$rsvp$all$$default = lib$rsvp$all$$all;\n var lib$rsvp$asap$$len = 0;\n var lib$rsvp$asap$$toString = {}.toString;\n var lib$rsvp$asap$$vertxNext;\n function lib$rsvp$asap$$asap(callback, arg) {\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len] = callback;\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len + 1] = arg;\n lib$rsvp$asap$$len += 2;\n if (lib$rsvp$asap$$len === 2) {\n // If len is 1, that means that we need to schedule an async flush.\n // If additional callbacks are queued before the queue is flushed, they\n // will be processed by this flush that we are scheduling.\n lib$rsvp$asap$$scheduleFlush();\n }\n }\n\n var lib$rsvp$asap$$default = lib$rsvp$asap$$asap;\n\n var lib$rsvp$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;\n var lib$rsvp$asap$$browserGlobal = lib$rsvp$asap$$browserWindow || {};\n var lib$rsvp$asap$$BrowserMutationObserver = lib$rsvp$asap$$browserGlobal.MutationObserver || lib$rsvp$asap$$browserGlobal.WebKitMutationObserver;\n var lib$rsvp$asap$$isNode = typeof self === 'undefined' &&\n typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';\n\n // test for web worker but not in IE10\n var lib$rsvp$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&\n typeof importScripts !== 'undefined' &&\n typeof MessageChannel !== 'undefined';\n\n // node\n function lib$rsvp$asap$$useNextTick() {\n var nextTick = process.nextTick;\n // node version 0.10.x displays a deprecation warning when nextTick is used recursively\n // setImmediate should be used instead instead\n var version = process.versions.node.match(/^(?:(\\d+)\\.)?(?:(\\d+)\\.)?(\\*|\\d+)$/);\n if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {\n nextTick = setImmediate;\n }\n return function() {\n nextTick(lib$rsvp$asap$$flush);\n };\n }\n\n // vertx\n function lib$rsvp$asap$$useVertxTimer() {\n return function() {\n lib$rsvp$asap$$vertxNext(lib$rsvp$asap$$flush);\n };\n }\n\n function lib$rsvp$asap$$useMutationObserver() {\n var iterations = 0;\n var observer = new lib$rsvp$asap$$BrowserMutationObserver(lib$rsvp$asap$$flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function() {\n node.data = (iterations = ++iterations % 2);\n };\n }\n\n // web worker\n function lib$rsvp$asap$$useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = lib$rsvp$asap$$flush;\n return function () {\n channel.port2.postMessage(0);\n };\n }\n\n function lib$rsvp$asap$$useSetTimeout() {\n return function() {\n setTimeout(lib$rsvp$asap$$flush, 1);\n };\n }\n\n var lib$rsvp$asap$$queue = new Array(1000);\n function lib$rsvp$asap$$flush() {\n for (var i = 0; i < lib$rsvp$asap$$len; i+=2) {\n var callback = lib$rsvp$asap$$queue[i];\n var arg = lib$rsvp$asap$$queue[i+1];\n\n callback(arg);\n\n lib$rsvp$asap$$queue[i] = undefined;\n lib$rsvp$asap$$queue[i+1] = undefined;\n }\n\n lib$rsvp$asap$$len = 0;\n }\n\n function lib$rsvp$asap$$attemptVertex() {\n try {\n var r = require;\n var vertx = r('vertx');\n lib$rsvp$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return lib$rsvp$asap$$useVertxTimer();\n } catch(e) {\n return lib$rsvp$asap$$useSetTimeout();\n }\n }\n\n var lib$rsvp$asap$$scheduleFlush;\n // Decide what async method to use to triggering processing of queued callbacks:\n if (lib$rsvp$asap$$isNode) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useNextTick();\n } else if (lib$rsvp$asap$$BrowserMutationObserver) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMutationObserver();\n } else if (lib$rsvp$asap$$isWorker) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMessageChannel();\n } else if (lib$rsvp$asap$$browserWindow === undefined && typeof require === 'function') {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$attemptVertex();\n } else {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useSetTimeout();\n }\n function lib$rsvp$defer$$defer(label) {\n var deferred = {};\n\n deferred['promise'] = new lib$rsvp$promise$$default(function(resolve, reject) {\n deferred['resolve'] = resolve;\n deferred['reject'] = reject;\n }, label);\n\n return deferred;\n }\n var lib$rsvp$defer$$default = lib$rsvp$defer$$defer;\n function lib$rsvp$filter$$filter(promises, filterFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(filterFn)) {\n throw new TypeError(\"You must pass a function as filter's second argument.\");\n }\n\n var length = values.length;\n var filtered = new Array(length);\n\n for (var i = 0; i < length; i++) {\n filtered[i] = filterFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(filtered, label).then(function(filtered) {\n var results = new Array(length);\n var newLength = 0;\n\n for (var i = 0; i < length; i++) {\n if (filtered[i]) {\n results[newLength] = values[i];\n newLength++;\n }\n }\n\n results.length = newLength;\n\n return results;\n });\n });\n }\n var lib$rsvp$filter$$default = lib$rsvp$filter$$filter;\n\n function lib$rsvp$promise$hash$$PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n }\n\n var lib$rsvp$promise$hash$$default = lib$rsvp$promise$hash$$PromiseHash;\n\n lib$rsvp$promise$hash$$PromiseHash.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$promise$hash$$PromiseHash.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$promise$hash$$PromiseHash.prototype._init = function() {\n this._result = {};\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validateInput = function(input) {\n return input && typeof input === 'object';\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validationError = function() {\n return new Error('Promise.hash must be called with an object');\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._enumerate = function() {\n var enumerator = this;\n var promise = enumerator.promise;\n var input = enumerator._input;\n var results = [];\n\n for (var key in input) {\n if (promise._state === lib$rsvp$$internal$$PENDING && Object.prototype.hasOwnProperty.call(input, key)) {\n results.push({\n position: key,\n entry: input[key]\n });\n }\n }\n\n var length = results.length;\n enumerator._remaining = length;\n var result;\n\n for (var i = 0; promise._state === lib$rsvp$$internal$$PENDING && i < length; i++) {\n result = results[i];\n enumerator._eachEntry(result.entry, result.position);\n }\n };\n\n function lib$rsvp$hash$settled$$HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n }\n\n lib$rsvp$hash$settled$$HashSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$promise$hash$$default.prototype);\n lib$rsvp$hash$settled$$HashSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$hash$settled$$HashSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n\n lib$rsvp$hash$settled$$HashSettled.prototype._validationError = function() {\n return new Error('hashSettled must be called with an object');\n };\n\n function lib$rsvp$hash$settled$$hashSettled(object, label) {\n return new lib$rsvp$hash$settled$$HashSettled(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$settled$$default = lib$rsvp$hash$settled$$hashSettled;\n function lib$rsvp$hash$$hash(object, label) {\n return new lib$rsvp$promise$hash$$default(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$$default = lib$rsvp$hash$$hash;\n function lib$rsvp$map$$map(promises, mapFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(mapFn)) {\n throw new TypeError(\"You must pass a function as map's second argument.\");\n }\n\n var length = values.length;\n var results = new Array(length);\n\n for (var i = 0; i < length; i++) {\n results[i] = mapFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(results, label);\n });\n }\n var lib$rsvp$map$$default = lib$rsvp$map$$map;\n\n function lib$rsvp$node$$Result() {\n this.value = undefined;\n }\n\n var lib$rsvp$node$$ERROR = new lib$rsvp$node$$Result();\n var lib$rsvp$node$$GET_THEN_ERROR = new lib$rsvp$node$$Result();\n\n function lib$rsvp$node$$getThen(obj) {\n try {\n return obj.then;\n } catch(error) {\n lib$rsvp$node$$ERROR.value= error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n\n function lib$rsvp$node$$tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch(error) {\n lib$rsvp$node$$ERROR.value = error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n function lib$rsvp$node$$makeObject(_, argumentNames) {\n var obj = {};\n var name;\n var i;\n var length = _.length;\n var args = new Array(length);\n\n for (var x = 0; x < length; x++) {\n args[x] = _[x];\n }\n\n for (i = 0; i < argumentNames.length; i++) {\n name = argumentNames[i];\n obj[name] = args[i + 1];\n }\n\n return obj;\n }\n\n function lib$rsvp$node$$arrayResult(_) {\n var length = _.length;\n var args = new Array(length - 1);\n\n for (var i = 1; i < length; i++) {\n args[i - 1] = _[i];\n }\n\n return args;\n }\n\n function lib$rsvp$node$$wrapThenable(then, promise) {\n return {\n then: function(onFulFillment, onRejection) {\n return then.call(promise, onFulFillment, onRejection);\n }\n };\n }\n\n function lib$rsvp$node$$denodeify(nodeFunc, options) {\n var fn = function() {\n var self = this;\n var l = arguments.length;\n var args = new Array(l + 1);\n var arg;\n var promiseInput = false;\n\n for (var i = 0; i < l; ++i) {\n arg = arguments[i];\n\n if (!promiseInput) {\n // TODO: clean this up\n promiseInput = lib$rsvp$node$$needsPromiseInput(arg);\n if (promiseInput === lib$rsvp$node$$GET_THEN_ERROR) {\n var p = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n lib$rsvp$$internal$$reject(p, lib$rsvp$node$$GET_THEN_ERROR.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = lib$rsvp$node$$wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n\n args[l] = function(err, val) {\n if (err)\n lib$rsvp$$internal$$reject(promise, err);\n else if (options === undefined)\n lib$rsvp$$internal$$resolve(promise, val);\n else if (options === true)\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$arrayResult(arguments));\n else if (lib$rsvp$utils$$isArray(options))\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$makeObject(arguments, options));\n else\n lib$rsvp$$internal$$resolve(promise, val);\n };\n\n if (promiseInput) {\n return lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n }\n\n var lib$rsvp$node$$default = lib$rsvp$node$$denodeify;\n\n function lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self) {\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n }\n\n function lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self){\n return lib$rsvp$promise$$default.all(args).then(function(args){\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n });\n }\n\n function lib$rsvp$node$$needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === lib$rsvp$promise$$default) {\n return true;\n } else {\n return lib$rsvp$node$$getThen(arg);\n }\n } else {\n return false;\n }\n }\n var lib$rsvp$platform$$platform;\n\n /* global self */\n if (typeof self === 'object') {\n lib$rsvp$platform$$platform = self;\n\n /* global global */\n } else if (typeof global === 'object') {\n lib$rsvp$platform$$platform = global;\n } else {\n throw new Error('no global: `self` or `global` found');\n }\n\n var lib$rsvp$platform$$default = lib$rsvp$platform$$platform;\n function lib$rsvp$race$$race(array, label) {\n return lib$rsvp$promise$$default.race(array, label);\n }\n var lib$rsvp$race$$default = lib$rsvp$race$$race;\n function lib$rsvp$reject$$reject(reason, label) {\n return lib$rsvp$promise$$default.reject(reason, label);\n }\n var lib$rsvp$reject$$default = lib$rsvp$reject$$reject;\n function lib$rsvp$resolve$$resolve(value, label) {\n return lib$rsvp$promise$$default.resolve(value, label);\n }\n var lib$rsvp$resolve$$default = lib$rsvp$resolve$$resolve;\n function lib$rsvp$rethrow$$rethrow(reason) {\n setTimeout(function() {\n throw reason;\n });\n throw reason;\n }\n var lib$rsvp$rethrow$$default = lib$rsvp$rethrow$$rethrow;\n\n // defaults\n lib$rsvp$config$$config.async = lib$rsvp$asap$$default;\n lib$rsvp$config$$config.after = function(cb) {\n setTimeout(cb, 0);\n };\n var lib$rsvp$$cast = lib$rsvp$resolve$$default;\n function lib$rsvp$$async(callback, arg) {\n lib$rsvp$config$$config.async(callback, arg);\n }\n\n function lib$rsvp$$on() {\n lib$rsvp$config$$config['on'].apply(lib$rsvp$config$$config, arguments);\n }\n\n function lib$rsvp$$off() {\n lib$rsvp$config$$config['off'].apply(lib$rsvp$config$$config, arguments);\n }\n\n // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`\n if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {\n var lib$rsvp$$callbacks = window['__PROMISE_INSTRUMENTATION__'];\n lib$rsvp$config$$configure('instrument', true);\n for (var lib$rsvp$$eventName in lib$rsvp$$callbacks) {\n if (lib$rsvp$$callbacks.hasOwnProperty(lib$rsvp$$eventName)) {\n lib$rsvp$$on(lib$rsvp$$eventName, lib$rsvp$$callbacks[lib$rsvp$$eventName]);\n }\n }\n }\n\n var lib$rsvp$umd$$RSVP = {\n 'race': lib$rsvp$race$$default,\n 'Promise': lib$rsvp$promise$$default,\n 'allSettled': lib$rsvp$all$settled$$default,\n 'hash': lib$rsvp$hash$$default,\n 'hashSettled': lib$rsvp$hash$settled$$default,\n 'denodeify': lib$rsvp$node$$default,\n 'on': lib$rsvp$$on,\n 'off': lib$rsvp$$off,\n 'map': lib$rsvp$map$$default,\n 'filter': lib$rsvp$filter$$default,\n 'resolve': lib$rsvp$resolve$$default,\n 'reject': lib$rsvp$reject$$default,\n 'all': lib$rsvp$all$$default,\n 'rethrow': lib$rsvp$rethrow$$default,\n 'defer': lib$rsvp$defer$$default,\n 'EventTarget': lib$rsvp$events$$default,\n 'configure': lib$rsvp$config$$configure,\n 'async': lib$rsvp$$async\n };\n\n /* global define:true module:true window: true */\n if (typeof define === 'function' && define['amd']) {\n define(function() { return lib$rsvp$umd$$RSVP; });\n } else if (typeof module !== 'undefined' && module['exports']) {\n module['exports'] = lib$rsvp$umd$$RSVP;\n } else if (typeof lib$rsvp$platform$$default !== 'undefined') {\n lib$rsvp$platform$$default['RSVP'] = lib$rsvp$umd$$RSVP;\n }\n}).call(this);\n\n","/*!\n * URI.js - Mutating URLs\n *\n * Version: 1.17.0\n *\n * Author: Rodney Rehm\n * Web: http://medialize.github.io/URI.js/\n *\n * Licensed under\n * MIT License http://www.opensource.org/licenses/mit-license\n * GPL v3 http://opensource.org/licenses/GPL-3.0\n *\n */\n(function (root, factory) {\n 'use strict';\n // https://github.com/umdjs/umd/blob/master/returnExports.js\n if (typeof exports === 'object') {\n // Node\n module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(['./punycode', './IPv6', './SecondLevelDomains'], factory);\n } else {\n // Browser globals (root is window)\n root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root);\n }\n}(this, function (punycode, IPv6, SLD, root) {\n 'use strict';\n /*global location, escape, unescape */\n // FIXME: v2.0.0 renamce non-camelCase properties to uppercase\n /*jshint camelcase: false */\n\n // save current URI variable, if any\n var _URI = root && root.URI;\n\n function URI(url, base) {\n var _urlSupplied = arguments.length >= 1;\n var _baseSupplied = arguments.length >= 2;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof URI)) {\n if (_urlSupplied) {\n if (_baseSupplied) {\n return new URI(url, base);\n }\n\n return new URI(url);\n }\n\n return new URI();\n }\n\n if (url === undefined) {\n if (_urlSupplied) {\n throw new TypeError('undefined is not a valid argument for URI');\n }\n\n if (typeof location !== 'undefined') {\n url = location.href + '';\n } else {\n url = '';\n }\n }\n\n this.href(url);\n\n // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor\n if (base !== undefined) {\n return this.absoluteTo(base);\n }\n\n return this;\n }\n\n URI.version = '1.17.0';\n\n var p = URI.prototype;\n var hasOwn = Object.prototype.hasOwnProperty;\n\n function escapeRegEx(string) {\n // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963\n return string.replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n }\n\n function getType(value) {\n // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value\n if (value === undefined) {\n return 'Undefined';\n }\n\n return String(Object.prototype.toString.call(value)).slice(8, -1);\n }\n\n function isArray(obj) {\n return getType(obj) === 'Array';\n }\n\n function filterArrayValues(data, value) {\n var lookup = {};\n var i, length;\n\n if (getType(value) === 'RegExp') {\n lookup = null;\n } else if (isArray(value)) {\n for (i = 0, length = value.length; i < length; i++) {\n lookup[value[i]] = true;\n }\n } else {\n lookup[value] = true;\n }\n\n for (i = 0, length = data.length; i < length; i++) {\n /*jshint laxbreak: true */\n var _match = lookup && lookup[data[i]] !== undefined\n || !lookup && value.test(data[i]);\n /*jshint laxbreak: false */\n if (_match) {\n data.splice(i, 1);\n length--;\n i--;\n }\n }\n\n return data;\n }\n\n function arrayContains(list, value) {\n var i, length;\n\n // value may be string, number, array, regexp\n if (isArray(value)) {\n // Note: this can be optimized to O(n) (instead of current O(m * n))\n for (i = 0, length = value.length; i < length; i++) {\n if (!arrayContains(list, value[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n var _type = getType(value);\n for (i = 0, length = list.length; i < length; i++) {\n if (_type === 'RegExp') {\n if (typeof list[i] === 'string' && list[i].match(value)) {\n return true;\n }\n } else if (list[i] === value) {\n return true;\n }\n }\n\n return false;\n }\n\n function arraysEqual(one, two) {\n if (!isArray(one) || !isArray(two)) {\n return false;\n }\n\n // arrays can't be equal if they have different amount of content\n if (one.length !== two.length) {\n return false;\n }\n\n one.sort();\n two.sort();\n\n for (var i = 0, l = one.length; i < l; i++) {\n if (one[i] !== two[i]) {\n return false;\n }\n }\n\n return true;\n }\n\n function trimSlashes(text) {\n var trim_expression = /^\\/+|\\/+$/g;\n return text.replace(trim_expression, '');\n }\n\n URI._parts = function() {\n return {\n protocol: null,\n username: null,\n password: null,\n hostname: null,\n urn: null,\n port: null,\n path: null,\n query: null,\n fragment: null,\n // state\n duplicateQueryParameters: URI.duplicateQueryParameters,\n escapeQuerySpace: URI.escapeQuerySpace\n };\n };\n // state: allow duplicate query parameters (a=1&a=1)\n URI.duplicateQueryParameters = false;\n // state: replaces + with %20 (space in query strings)\n URI.escapeQuerySpace = true;\n // static properties\n URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i;\n URI.idn_expression = /[^a-z0-9\\.-]/i;\n URI.punycode_expression = /(xn--)/i;\n // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?\n URI.ip4_expression = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n // credits to Rich Brown\n // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096\n // specification: http://www.ietf.org/rfc/rfc4291.txt\n URI.ip6_expression = /^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$/;\n // expression used is \"gruber revised\" (@gruber v2) determined to be the\n // best solution in a regex-golf we did a couple of ages ago at\n // * http://mathiasbynens.be/demo/url-regex\n // * http://rodneyrehm.de/t/url-regex.html\n URI.find_uri_expression = /\\b((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))/ig;\n URI.findUri = {\n // valid \"scheme://\" or \"www.\"\n start: /\\b(?:([a-z][a-z0-9.+-]*:\\/\\/)|www\\.)/gi,\n // everything up to the next whitespace\n end: /[\\s\\r\\n]|$/,\n // trim trailing punctuation captured by end RegExp\n trim: /[`!()\\[\\]{};:'\".,<>?«»“”„‘’]+$/\n };\n // http://www.iana.org/assignments/uri-schemes.html\n // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports\n URI.defaultPorts = {\n http: '80',\n https: '443',\n ftp: '21',\n gopher: '70',\n ws: '80',\n wss: '443'\n };\n // allowed hostname characters according to RFC 3986\n // ALPHA DIGIT \"-\" \".\" \"_\" \"~\" \"!\" \"$\" \"&\" \"'\" \"(\" \")\" \"*\" \"+\" \",\" \";\" \"=\" %encoded\n // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . -\n URI.invalid_hostname_characters = /[^a-zA-Z0-9\\.-]/;\n // map DOM Elements to their URI attribute\n URI.domAttributes = {\n 'a': 'href',\n 'blockquote': 'cite',\n 'link': 'href',\n 'base': 'href',\n 'script': 'src',\n 'form': 'action',\n 'img': 'src',\n 'area': 'href',\n 'iframe': 'src',\n 'embed': 'src',\n 'source': 'src',\n 'track': 'src',\n 'input': 'src', // but only if type=\"image\"\n 'audio': 'src',\n 'video': 'src'\n };\n URI.getDomAttribute = function(node) {\n if (!node || !node.nodeName) {\n return undefined;\n }\n\n var nodeName = node.nodeName.toLowerCase();\n // should only expose src for type=\"image\"\n if (nodeName === 'input' && node.type !== 'image') {\n return undefined;\n }\n\n return URI.domAttributes[nodeName];\n };\n\n function escapeForDumbFirefox36(value) {\n // https://github.com/medialize/URI.js/issues/91\n return escape(value);\n }\n\n // encoding / decoding according to RFC3986\n function strictEncodeURIComponent(string) {\n // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent\n return encodeURIComponent(string)\n .replace(/[!'()*]/g, escapeForDumbFirefox36)\n .replace(/\\*/g, '%2A');\n }\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n URI.iso8859 = function() {\n URI.encode = escape;\n URI.decode = unescape;\n };\n URI.unicode = function() {\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n };\n URI.characters = {\n pathname: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,\n map: {\n // -._~!'()*\n '%24': '$',\n '%26': '&',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%3A': ':',\n '%40': '@'\n }\n },\n decode: {\n expression: /[\\/\\?#]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23'\n }\n }\n },\n reserved: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,\n map: {\n // gen-delims\n '%3A': ':',\n '%2F': '/',\n '%3F': '?',\n '%23': '#',\n '%5B': '[',\n '%5D': ']',\n '%40': '@',\n // sub-delims\n '%21': '!',\n '%24': '$',\n '%26': '&',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '='\n }\n }\n },\n urnpath: {\n // The characters under `encode` are the characters called out by RFC 2141 as being acceptable\n // for usage in a URN. RFC2141 also calls out \"-\", \".\", and \"_\" as acceptable characters, but\n // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also\n // note that the colon character is not featured in the encoding map; this is because URI.js\n // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it\n // should not appear unencoded in a segment itself.\n // See also the note above about RFC3986 and capitalalized hex digits.\n encode: {\n expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,\n map: {\n '%21': '!',\n '%24': '$',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%40': '@'\n }\n },\n // These characters are the characters called out by RFC2141 as \"reserved\" characters that\n // should never appear in a URN, plus the colon character (see note above).\n decode: {\n expression: /[\\/\\?#:]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23',\n ':': '%3A'\n }\n }\n }\n };\n URI.encodeQuery = function(string, escapeQuerySpace) {\n var escaped = URI.encode(string + '');\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped;\n };\n URI.decodeQuery = function(string, escapeQuerySpace) {\n string += '';\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n try {\n return URI.decode(escapeQuerySpace ? string.replace(/\\+/g, '%20') : string);\n } catch(e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n // generate encode/decode path functions\n var _parts = {'encode':'encode', 'decode':'decode'};\n var _part;\n var generateAccessor = function(_group, _part) {\n return function(string) {\n try {\n return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {\n return URI.characters[_group][_part].map[c];\n });\n } catch (e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n };\n\n for (_part in _parts) {\n URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);\n URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]);\n }\n\n var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) {\n return function(string) {\n // Why pass in names of functions, rather than the function objects themselves? The\n // definitions of some functions (but in particular, URI.decode) will occasionally change due\n // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure\n // that the functions we use here are \"fresh\".\n var actualCodingFunc;\n if (!_innerCodingFuncName) {\n actualCodingFunc = URI[_codingFuncName];\n } else {\n actualCodingFunc = function(string) {\n return URI[_codingFuncName](URI[_innerCodingFuncName](string));\n };\n }\n\n var segments = (string + '').split(_sep);\n\n for (var i = 0, length = segments.length; i < length; i++) {\n segments[i] = actualCodingFunc(segments[i]);\n }\n\n return segments.join(_sep);\n };\n };\n\n // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.\n URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment');\n URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment');\n URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode');\n URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode');\n\n URI.encodeReserved = generateAccessor('reserved', 'encode');\n\n URI.parse = function(string, parts) {\n var pos;\n if (!parts) {\n parts = {};\n }\n // [protocol\"://\"[username[\":\"password]\"@\"]hostname[\":\"port]\"/\"?][path][\"?\"querystring][\"#\"fragment]\n\n // extract fragment\n pos = string.indexOf('#');\n if (pos > -1) {\n // escaping?\n parts.fragment = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract query\n pos = string.indexOf('?');\n if (pos > -1) {\n // escaping?\n parts.query = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract protocol\n if (string.substring(0, 2) === '//') {\n // relative-scheme\n parts.protocol = null;\n string = string.substring(2);\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n pos = string.indexOf(':');\n if (pos > -1) {\n parts.protocol = string.substring(0, pos) || null;\n if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {\n // : may be within the path\n parts.protocol = undefined;\n } else if (string.substring(pos + 1, pos + 3) === '//') {\n string = string.substring(pos + 3);\n\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n string = string.substring(pos + 1);\n parts.urn = true;\n }\n }\n }\n\n // what's left must be the path\n parts.path = string;\n\n // and we're done\n return parts;\n };\n URI.parseHost = function(string, parts) {\n // Copy chrome, IE, opera backslash-handling behavior.\n // Back slashes before the query string get converted to forward slashes\n // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124\n // See: https://code.google.com/p/chromium/issues/detail?id=25916\n // https://github.com/medialize/URI.js/pull/233\n string = string.replace(/\\\\/g, '/');\n\n // extract host:port\n var pos = string.indexOf('/');\n var bracketPos;\n var t;\n\n if (pos === -1) {\n pos = string.length;\n }\n\n if (string.charAt(0) === '[') {\n // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6\n // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts\n // IPv6+port in the format [2001:db8::1]:80 (for the time being)\n bracketPos = string.indexOf(']');\n parts.hostname = string.substring(1, bracketPos) || null;\n parts.port = string.substring(bracketPos + 2, pos) || null;\n if (parts.port === '/') {\n parts.port = null;\n }\n } else {\n var firstColon = string.indexOf(':');\n var firstSlash = string.indexOf('/');\n var nextColon = string.indexOf(':', firstColon + 1);\n if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {\n // IPv6 host contains multiple colons - but no port\n // this notation is actually not allowed by RFC 3986, but we're a liberal parser\n parts.hostname = string.substring(0, pos) || null;\n parts.port = null;\n } else {\n t = string.substring(0, pos).split(':');\n parts.hostname = t[0] || null;\n parts.port = t[1] || null;\n }\n }\n\n if (parts.hostname && string.substring(pos).charAt(0) !== '/') {\n pos++;\n string = '/' + string;\n }\n\n return string.substring(pos) || '/';\n };\n URI.parseAuthority = function(string, parts) {\n string = URI.parseUserinfo(string, parts);\n return URI.parseHost(string, parts);\n };\n URI.parseUserinfo = function(string, parts) {\n // extract username:password\n var firstSlash = string.indexOf('/');\n var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1);\n var t;\n\n // authority@ must come before /path\n if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {\n t = string.substring(0, pos).split(':');\n parts.username = t[0] ? URI.decode(t[0]) : null;\n t.shift();\n parts.password = t[0] ? URI.decode(t.join(':')) : null;\n string = string.substring(pos + 1);\n } else {\n parts.username = null;\n parts.password = null;\n }\n\n return string;\n };\n URI.parseQuery = function(string, escapeQuerySpace) {\n if (!string) {\n return {};\n }\n\n // throw out the funky business - \"?\"[name\"=\"value\"&\"]+\n string = string.replace(/&+/g, '&').replace(/^\\?*&*|&+$/g, '');\n\n if (!string) {\n return {};\n }\n\n var items = {};\n var splits = string.split('&');\n var length = splits.length;\n var v, name, value;\n\n for (var i = 0; i < length; i++) {\n v = splits[i].split('=');\n name = URI.decodeQuery(v.shift(), escapeQuerySpace);\n // no \"=\" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters\n value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;\n\n if (hasOwn.call(items, name)) {\n if (typeof items[name] === 'string' || items[name] === null) {\n items[name] = [items[name]];\n }\n\n items[name].push(value);\n } else {\n items[name] = value;\n }\n }\n\n return items;\n };\n\n URI.build = function(parts) {\n var t = '';\n\n if (parts.protocol) {\n t += parts.protocol + ':';\n }\n\n if (!parts.urn && (t || parts.hostname)) {\n t += '//';\n }\n\n t += (URI.buildAuthority(parts) || '');\n\n if (typeof parts.path === 'string') {\n if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {\n t += '/';\n }\n\n t += parts.path;\n }\n\n if (typeof parts.query === 'string' && parts.query) {\n t += '?' + parts.query;\n }\n\n if (typeof parts.fragment === 'string' && parts.fragment) {\n t += '#' + parts.fragment;\n }\n return t;\n };\n URI.buildHost = function(parts) {\n var t = '';\n\n if (!parts.hostname) {\n return '';\n } else if (URI.ip6_expression.test(parts.hostname)) {\n t += '[' + parts.hostname + ']';\n } else {\n t += parts.hostname;\n }\n\n if (parts.port) {\n t += ':' + parts.port;\n }\n\n return t;\n };\n URI.buildAuthority = function(parts) {\n return URI.buildUserinfo(parts) + URI.buildHost(parts);\n };\n URI.buildUserinfo = function(parts) {\n var t = '';\n\n if (parts.username) {\n t += URI.encode(parts.username);\n\n if (parts.password) {\n t += ':' + URI.encode(parts.password);\n }\n\n t += '@';\n }\n\n return t;\n };\n URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {\n // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html\n // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed\n // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!\n // URI.js treats the query string as being application/x-www-form-urlencoded\n // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type\n\n var t = '';\n var unique, key, i, length;\n for (key in data) {\n if (hasOwn.call(data, key) && key) {\n if (isArray(data[key])) {\n unique = {};\n for (i = 0, length = data[key].length; i < length; i++) {\n if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace);\n if (duplicateQueryParameters !== true) {\n unique[data[key][i] + ''] = true;\n }\n }\n }\n } else if (data[key] !== undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace);\n }\n }\n }\n\n return t.substring(1);\n };\n URI.buildQueryParameter = function(name, value, escapeQuerySpace) {\n // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded\n // don't append \"=\" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization\n return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '');\n };\n\n URI.addQuery = function(data, name, value) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n URI.addQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (data[name] === undefined) {\n data[name] = value;\n return;\n } else if (typeof data[name] === 'string') {\n data[name] = [data[name]];\n }\n\n if (!isArray(value)) {\n value = [value];\n }\n\n data[name] = (data[name] || []).concat(value);\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n };\n URI.removeQuery = function(data, name, value) {\n var i, length, key;\n\n if (isArray(name)) {\n for (i = 0, length = name.length; i < length; i++) {\n data[name[i]] = undefined;\n }\n } else if (getType(name) === 'RegExp') {\n for (key in data) {\n if (name.test(key)) {\n data[key] = undefined;\n }\n }\n } else if (typeof name === 'object') {\n for (key in name) {\n if (hasOwn.call(name, key)) {\n URI.removeQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (value !== undefined) {\n if (getType(value) === 'RegExp') {\n if (!isArray(data[name]) && value.test(data[name])) {\n data[name] = undefined;\n } else {\n data[name] = filterArrayValues(data[name], value);\n }\n } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) {\n data[name] = undefined;\n } else if (isArray(data[name])) {\n data[name] = filterArrayValues(data[name], value);\n }\n } else {\n data[name] = undefined;\n }\n } else {\n throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter');\n }\n };\n URI.hasQuery = function(data, name, value, withinArray) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n if (!URI.hasQuery(data, key, name[key])) {\n return false;\n }\n }\n }\n\n return true;\n } else if (typeof name !== 'string') {\n throw new TypeError('URI.hasQuery() accepts an object, string as the name parameter');\n }\n\n switch (getType(value)) {\n case 'Undefined':\n // true if exists (but may be empty)\n return name in data; // data[name] !== undefined;\n\n case 'Boolean':\n // true if exists and non-empty\n var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);\n return value === _booly;\n\n case 'Function':\n // allow complex comparison\n return !!value(data[name], name, data);\n\n case 'Array':\n if (!isArray(data[name])) {\n return false;\n }\n\n var op = withinArray ? arrayContains : arraysEqual;\n return op(data[name], value);\n\n case 'RegExp':\n if (!isArray(data[name])) {\n return Boolean(data[name] && data[name].match(value));\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n case 'Number':\n value = String(value);\n /* falls through */\n case 'String':\n if (!isArray(data[name])) {\n return data[name] === value;\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n default:\n throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter');\n }\n };\n\n\n URI.commonPath = function(one, two) {\n var length = Math.min(one.length, two.length);\n var pos;\n\n // find first non-matching character\n for (pos = 0; pos < length; pos++) {\n if (one.charAt(pos) !== two.charAt(pos)) {\n pos--;\n break;\n }\n }\n\n if (pos < 1) {\n return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';\n }\n\n // revert to last /\n if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {\n pos = one.substring(0, pos).lastIndexOf('/');\n }\n\n return one.substring(0, pos + 1);\n };\n\n URI.withinString = function(string, callback, options) {\n options || (options = {});\n var _start = options.start || URI.findUri.start;\n var _end = options.end || URI.findUri.end;\n var _trim = options.trim || URI.findUri.trim;\n var _attributeOpen = /[a-z0-9-]=[\"']?$/i;\n\n _start.lastIndex = 0;\n while (true) {\n var match = _start.exec(string);\n if (!match) {\n break;\n }\n\n var start = match.index;\n if (options.ignoreHtml) {\n // attribut(e=[\"']?$)\n var attributeOpen = string.slice(Math.max(start - 3, 0), start);\n if (attributeOpen && _attributeOpen.test(attributeOpen)) {\n continue;\n }\n }\n\n var end = start + string.slice(start).search(_end);\n var slice = string.slice(start, end).replace(_trim, '');\n if (options.ignore && options.ignore.test(slice)) {\n continue;\n }\n\n end = start + slice.length;\n var result = callback(slice, start, end, string);\n string = string.slice(0, start) + result + string.slice(end);\n _start.lastIndex = start + result.length;\n }\n\n _start.lastIndex = 0;\n return string;\n };\n\n URI.ensureValidHostname = function(v) {\n // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)\n // they are not part of DNS and therefore ignored by URI.js\n\n if (v.match(URI.invalid_hostname_characters)) {\n // test punycode\n if (!punycode) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-] and Punycode.js is not available');\n }\n\n if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n }\n };\n\n // noConflict\n URI.noConflict = function(removeAll) {\n if (removeAll) {\n var unconflicted = {\n URI: this.noConflict()\n };\n\n if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {\n unconflicted.URITemplate = root.URITemplate.noConflict();\n }\n\n if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {\n unconflicted.IPv6 = root.IPv6.noConflict();\n }\n\n if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {\n unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict();\n }\n\n return unconflicted;\n } else if (root.URI === this) {\n root.URI = _URI;\n }\n\n return this;\n };\n\n p.build = function(deferBuild) {\n if (deferBuild === true) {\n this._deferred_build = true;\n } else if (deferBuild === undefined || this._deferred_build) {\n this._string = URI.build(this._parts);\n this._deferred_build = false;\n }\n\n return this;\n };\n\n p.clone = function() {\n return new URI(this);\n };\n\n p.valueOf = p.toString = function() {\n return this.build(false)._string;\n };\n\n\n function generateSimpleAccessor(_part){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n this._parts[_part] = v || null;\n this.build(!build);\n return this;\n }\n };\n }\n\n function generatePrefixAccessor(_part, _key){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n if (v !== null) {\n v = v + '';\n if (v.charAt(0) === _key) {\n v = v.substring(1);\n }\n }\n\n this._parts[_part] = v;\n this.build(!build);\n return this;\n }\n };\n }\n\n p.protocol = generateSimpleAccessor('protocol');\n p.username = generateSimpleAccessor('username');\n p.password = generateSimpleAccessor('password');\n p.hostname = generateSimpleAccessor('hostname');\n p.port = generateSimpleAccessor('port');\n p.query = generatePrefixAccessor('query', '?');\n p.fragment = generatePrefixAccessor('fragment', '#');\n\n p.search = function(v, build) {\n var t = this.query(v, build);\n return typeof t === 'string' && t.length ? ('?' + t) : t;\n };\n p.hash = function(v, build) {\n var t = this.fragment(v, build);\n return typeof t === 'string' && t.length ? ('#' + t) : t;\n };\n\n p.pathname = function(v, build) {\n if (v === undefined || v === true) {\n var res = this._parts.path || (this._parts.hostname ? '/' : '');\n return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res;\n } else {\n if (this._parts.urn) {\n this._parts.path = v ? URI.recodeUrnPath(v) : '';\n } else {\n this._parts.path = v ? URI.recodePath(v) : '/';\n }\n this.build(!build);\n return this;\n }\n };\n p.path = p.pathname;\n p.href = function(href, build) {\n var key;\n\n if (href === undefined) {\n return this.toString();\n }\n\n this._string = '';\n this._parts = URI._parts();\n\n var _URI = href instanceof URI;\n var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname);\n if (href.nodeName) {\n var attribute = URI.getDomAttribute(href);\n href = href[attribute] || '';\n _object = false;\n }\n\n // window.location is reported to be an object, but it's not the sort\n // of object we're looking for:\n // * location.protocol ends with a colon\n // * location.query != object.search\n // * location.hash != object.fragment\n // simply serializing the unknown object should do the trick\n // (for location, not for everything...)\n if (!_URI && _object && href.pathname !== undefined) {\n href = href.toString();\n }\n\n if (typeof href === 'string' || href instanceof String) {\n this._parts = URI.parse(String(href), this._parts);\n } else if (_URI || _object) {\n var src = _URI ? href._parts : href;\n for (key in src) {\n if (hasOwn.call(this._parts, key)) {\n this._parts[key] = src[key];\n }\n }\n } else {\n throw new TypeError('invalid input');\n }\n\n this.build(!build);\n return this;\n };\n\n // identification accessors\n p.is = function(what) {\n var ip = false;\n var ip4 = false;\n var ip6 = false;\n var name = false;\n var sld = false;\n var idn = false;\n var punycode = false;\n var relative = !this._parts.urn;\n\n if (this._parts.hostname) {\n relative = false;\n ip4 = URI.ip4_expression.test(this._parts.hostname);\n ip6 = URI.ip6_expression.test(this._parts.hostname);\n ip = ip4 || ip6;\n name = !ip;\n sld = name && SLD && SLD.has(this._parts.hostname);\n idn = name && URI.idn_expression.test(this._parts.hostname);\n punycode = name && URI.punycode_expression.test(this._parts.hostname);\n }\n\n switch (what.toLowerCase()) {\n case 'relative':\n return relative;\n\n case 'absolute':\n return !relative;\n\n // hostname identification\n case 'domain':\n case 'name':\n return name;\n\n case 'sld':\n return sld;\n\n case 'ip':\n return ip;\n\n case 'ip4':\n case 'ipv4':\n case 'inet4':\n return ip4;\n\n case 'ip6':\n case 'ipv6':\n case 'inet6':\n return ip6;\n\n case 'idn':\n return idn;\n\n case 'url':\n return !this._parts.urn;\n\n case 'urn':\n return !!this._parts.urn;\n\n case 'punycode':\n return punycode;\n }\n\n return null;\n };\n\n // component specific input validation\n var _protocol = p.protocol;\n var _port = p.port;\n var _hostname = p.hostname;\n\n p.protocol = function(v, build) {\n if (v !== undefined) {\n if (v) {\n // accept trailing ://\n v = v.replace(/:(\\/\\/)?$/, '');\n\n if (!v.match(URI.protocol_expression)) {\n throw new TypeError('Protocol \"' + v + '\" contains characters other than [A-Z0-9.+-] or doesn\\'t start with [A-Z]');\n }\n }\n }\n return _protocol.call(this, v, build);\n };\n p.scheme = p.protocol;\n p.port = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n if (v === 0) {\n v = null;\n }\n\n if (v) {\n v += '';\n if (v.charAt(0) === ':') {\n v = v.substring(1);\n }\n\n if (v.match(/[^0-9]/)) {\n throw new TypeError('Port \"' + v + '\" contains characters other than [0-9]');\n }\n }\n }\n return _port.call(this, v, build);\n };\n p.hostname = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n var x = {};\n var res = URI.parseHost(v, x);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n v = x.hostname;\n }\n return _hostname.call(this, v, build);\n };\n\n // compound accessors\n p.origin = function(v, build) {\n var parts;\n\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n var protocol = this.protocol();\n var authority = this.authority();\n if (!authority) return '';\n return (protocol ? protocol + '://' : '') + this.authority();\n } else {\n var origin = URI(v);\n this\n .protocol(origin.protocol())\n .authority(origin.authority())\n .build(!build);\n return this;\n }\n };\n p.host = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildHost(this._parts) : '';\n } else {\n var res = URI.parseHost(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.authority = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildAuthority(this._parts) : '';\n } else {\n var res = URI.parseAuthority(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.userinfo = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n if (!this._parts.username) {\n return '';\n }\n\n var t = URI.buildUserinfo(this._parts);\n return t.substring(0, t.length -1);\n } else {\n if (v[v.length-1] !== '@') {\n v += '@';\n }\n\n URI.parseUserinfo(v, this._parts);\n this.build(!build);\n return this;\n }\n };\n p.resource = function(v, build) {\n var parts;\n\n if (v === undefined) {\n return this.path() + this.search() + this.hash();\n }\n\n parts = URI.parse(v);\n this._parts.path = parts.path;\n this._parts.query = parts.query;\n this._parts.fragment = parts.fragment;\n this.build(!build);\n return this;\n };\n\n // fraction accessors\n p.subdomain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n // convenience, return \"www\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // grab domain and add another segment\n var end = this._parts.hostname.length - this.domain().length - 1;\n return this._parts.hostname.substring(0, end) || '';\n } else {\n var e = this._parts.hostname.length - this.domain().length;\n var sub = this._parts.hostname.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(sub));\n\n if (v && v.charAt(v.length - 1) !== '.') {\n v += '.';\n }\n\n if (v) {\n URI.ensureValidHostname(v);\n }\n\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.domain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // convenience, return \"example.org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // if hostname consists of 1 or 2 segments, it must be the domain\n var t = this._parts.hostname.match(/\\./g);\n if (t && t.length < 2) {\n return this._parts.hostname;\n }\n\n // grab tld and add another segment\n var end = this._parts.hostname.length - this.tld(build).length - 1;\n end = this._parts.hostname.lastIndexOf('.', end -1) + 1;\n return this._parts.hostname.substring(end) || '';\n } else {\n if (!v) {\n throw new TypeError('cannot set domain empty');\n }\n\n URI.ensureValidHostname(v);\n\n if (!this._parts.hostname || this.is('IP')) {\n this._parts.hostname = v;\n } else {\n var replace = new RegExp(escapeRegEx(this.domain()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.tld = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // return \"org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n var pos = this._parts.hostname.lastIndexOf('.');\n var tld = this._parts.hostname.substring(pos + 1);\n\n if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {\n return SLD.get(this._parts.hostname) || tld;\n }\n\n return tld;\n } else {\n var replace;\n\n if (!v) {\n throw new TypeError('cannot set TLD empty');\n } else if (v.match(/[^a-zA-Z0-9-]/)) {\n if (SLD && SLD.is(v)) {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n } else {\n throw new TypeError('TLD \"' + v + '\" contains characters other than [A-Z0-9]');\n }\n } else if (!this._parts.hostname || this.is('IP')) {\n throw new ReferenceError('cannot set TLD on non-domain host');\n } else {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.directory = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path && !this._parts.hostname) {\n return '';\n }\n\n if (this._parts.path === '/') {\n return '/';\n }\n\n var end = this._parts.path.length - this.filename().length - 1;\n var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '');\n\n return v ? URI.decodePath(res) : res;\n\n } else {\n var e = this._parts.path.length - this.filename().length;\n var directory = this._parts.path.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(directory));\n\n // fully qualifier directories begin with a slash\n if (!this.is('relative')) {\n if (!v) {\n v = '/';\n }\n\n if (v.charAt(0) !== '/') {\n v = '/' + v;\n }\n }\n\n // directories always end with a slash\n if (v && v.charAt(v.length - 1) !== '/') {\n v += '/';\n }\n\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.filename = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var pos = this._parts.path.lastIndexOf('/');\n var res = this._parts.path.substring(pos+1);\n\n return v ? URI.decodePathSegment(res) : res;\n } else {\n var mutatedDirectory = false;\n\n if (v.charAt(0) === '/') {\n v = v.substring(1);\n }\n\n if (v.match(/\\.?\\//)) {\n mutatedDirectory = true;\n }\n\n var replace = new RegExp(escapeRegEx(this.filename()) + '$');\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n\n if (mutatedDirectory) {\n this.normalizePath(build);\n } else {\n this.build(!build);\n }\n\n return this;\n }\n };\n p.suffix = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var filename = this.filename();\n var pos = filename.lastIndexOf('.');\n var s, res;\n\n if (pos === -1) {\n return '';\n }\n\n // suffix may only contain alnum characters (yup, I made this up.)\n s = filename.substring(pos+1);\n res = (/^[a-z0-9%]+$/i).test(s) ? s : '';\n return v ? URI.decodePathSegment(res) : res;\n } else {\n if (v.charAt(0) === '.') {\n v = v.substring(1);\n }\n\n var suffix = this.suffix();\n var replace;\n\n if (!suffix) {\n if (!v) {\n return this;\n }\n\n this._parts.path += '.' + URI.recodePath(v);\n } else if (!v) {\n replace = new RegExp(escapeRegEx('.' + suffix) + '$');\n } else {\n replace = new RegExp(escapeRegEx(suffix) + '$');\n }\n\n if (replace) {\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.segment = function(segment, v, build) {\n var separator = this._parts.urn ? ':' : '/';\n var path = this.path();\n var absolute = path.substring(0, 1) === '/';\n var segments = path.split(separator);\n\n if (segment !== undefined && typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (segment !== undefined && typeof segment !== 'number') {\n throw new Error('Bad segment \"' + segment + '\", must be 0-based integer');\n }\n\n if (absolute) {\n segments.shift();\n }\n\n if (segment < 0) {\n // allow negative indexes to address from the end\n segment = Math.max(segments.length + segment, 0);\n }\n\n if (v === undefined) {\n /*jshint laxbreak: true */\n return segment === undefined\n ? segments\n : segments[segment];\n /*jshint laxbreak: false */\n } else if (segment === null || segments[segment] === undefined) {\n if (isArray(v)) {\n segments = [];\n // collapse empty elements within array\n for (var i=0, l=v.length; i < l; i++) {\n if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) {\n continue;\n }\n\n if (segments.length && !segments[segments.length -1].length) {\n segments.pop();\n }\n\n segments.push(trimSlashes(v[i]));\n }\n } else if (v || typeof v === 'string') {\n v = trimSlashes(v);\n if (segments[segments.length -1] === '') {\n // empty trailing elements have to be overwritten\n // to prevent results such as /foo//bar\n segments[segments.length -1] = v;\n } else {\n segments.push(v);\n }\n }\n } else {\n if (v) {\n segments[segment] = trimSlashes(v);\n } else {\n segments.splice(segment, 1);\n }\n }\n\n if (absolute) {\n segments.unshift('');\n }\n\n return this.path(segments.join(separator), build);\n };\n p.segmentCoded = function(segment, v, build) {\n var segments, i, l;\n\n if (typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (v === undefined) {\n segments = this.segment(segment, v, build);\n if (!isArray(segments)) {\n segments = segments !== undefined ? URI.decode(segments) : undefined;\n } else {\n for (i = 0, l = segments.length; i < l; i++) {\n segments[i] = URI.decode(segments[i]);\n }\n }\n\n return segments;\n }\n\n if (!isArray(v)) {\n v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v;\n } else {\n for (i = 0, l = v.length; i < l; i++) {\n v[i] = URI.encode(v[i]);\n }\n }\n\n return this.segment(segment, v, build);\n };\n\n // mutating query string\n var q = p.query;\n p.query = function(v, build) {\n if (v === true) {\n return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n } else if (typeof v === 'function') {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n var result = v.call(this, data);\n this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else if (v !== undefined && typeof v !== 'string') {\n this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else {\n return q.call(this, v, build);\n }\n };\n p.setQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n\n if (typeof name === 'string' || name instanceof String) {\n data[name] = value !== undefined ? value : null;\n } else if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n data[key] = name[key];\n }\n }\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.addQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.addQuery(data, name, value === undefined ? null : value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.removeQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.removeQuery(data, name, value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.hasQuery = function(name, value, withinArray) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n return URI.hasQuery(data, name, value, withinArray);\n };\n p.setSearch = p.setQuery;\n p.addSearch = p.addQuery;\n p.removeSearch = p.removeQuery;\n p.hasSearch = p.hasQuery;\n\n // sanitizing URLs\n p.normalize = function() {\n if (this._parts.urn) {\n return this\n .normalizeProtocol(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n }\n\n return this\n .normalizeProtocol(false)\n .normalizeHostname(false)\n .normalizePort(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n };\n p.normalizeProtocol = function(build) {\n if (typeof this._parts.protocol === 'string') {\n this._parts.protocol = this._parts.protocol.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeHostname = function(build) {\n if (this._parts.hostname) {\n if (this.is('IDN') && punycode) {\n this._parts.hostname = punycode.toASCII(this._parts.hostname);\n } else if (this.is('IPv6') && IPv6) {\n this._parts.hostname = IPv6.best(this._parts.hostname);\n }\n\n this._parts.hostname = this._parts.hostname.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePort = function(build) {\n // remove port of it's the protocol's default\n if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {\n this._parts.port = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePath = function(build) {\n var _path = this._parts.path;\n if (!_path) {\n return this;\n }\n\n if (this._parts.urn) {\n this._parts.path = URI.recodeUrnPath(this._parts.path);\n this.build(!build);\n return this;\n }\n\n if (this._parts.path === '/') {\n return this;\n }\n\n var _was_relative;\n var _leadingParents = '';\n var _parent, _pos;\n\n // handle relative paths\n if (_path.charAt(0) !== '/') {\n _was_relative = true;\n _path = '/' + _path;\n }\n\n // handle relative files (as opposed to directories)\n if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {\n _path += '/';\n }\n\n // resolve simples\n _path = _path\n .replace(/(\\/(\\.\\/)+)|(\\/\\.$)/g, '/')\n .replace(/\\/{2,}/g, '/');\n\n // remember leading parents\n if (_was_relative) {\n _leadingParents = _path.substring(1).match(/^(\\.\\.\\/)+/) || '';\n if (_leadingParents) {\n _leadingParents = _leadingParents[0];\n }\n }\n\n // resolve parents\n while (true) {\n _parent = _path.indexOf('/..');\n if (_parent === -1) {\n // no more ../ to resolve\n break;\n } else if (_parent === 0) {\n // top level cannot be relative, skip it\n _path = _path.substring(3);\n continue;\n }\n\n _pos = _path.substring(0, _parent).lastIndexOf('/');\n if (_pos === -1) {\n _pos = _parent;\n }\n _path = _path.substring(0, _pos) + _path.substring(_parent + 3);\n }\n\n // revert to relative\n if (_was_relative && this.is('relative')) {\n _path = _leadingParents + _path.substring(1);\n }\n\n _path = URI.recodePath(_path);\n this._parts.path = _path;\n this.build(!build);\n return this;\n };\n p.normalizePathname = p.normalizePath;\n p.normalizeQuery = function(build) {\n if (typeof this._parts.query === 'string') {\n if (!this._parts.query.length) {\n this._parts.query = null;\n } else {\n this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace));\n }\n\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeFragment = function(build) {\n if (!this._parts.fragment) {\n this._parts.fragment = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeSearch = p.normalizeQuery;\n p.normalizeHash = p.normalizeFragment;\n\n p.iso8859 = function() {\n // expect unicode input, iso8859 output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = escape;\n URI.decode = decodeURIComponent;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.unicode = function() {\n // expect iso8859 input, unicode output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = strictEncodeURIComponent;\n URI.decode = unescape;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.readable = function() {\n var uri = this.clone();\n // removing username, password, because they shouldn't be displayed according to RFC 3986\n uri.username('').password('').normalize();\n var t = '';\n if (uri._parts.protocol) {\n t += uri._parts.protocol + '://';\n }\n\n if (uri._parts.hostname) {\n if (uri.is('punycode') && punycode) {\n t += punycode.toUnicode(uri._parts.hostname);\n if (uri._parts.port) {\n t += ':' + uri._parts.port;\n }\n } else {\n t += uri.host();\n }\n }\n\n if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {\n t += '/';\n }\n\n t += uri.path(true);\n if (uri._parts.query) {\n var q = '';\n for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {\n var kv = (qp[i] || '').split('=');\n q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n\n if (kv[1] !== undefined) {\n q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n }\n }\n t += '?' + q.substring(1);\n }\n\n t += URI.decodeQuery(uri.hash(), true);\n return t;\n };\n\n // resolving relative and absolute URLs\n p.absoluteTo = function(base) {\n var resolved = this.clone();\n var properties = ['protocol', 'username', 'password', 'hostname', 'port'];\n var basedir, i, p;\n\n if (this._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n if (!(base instanceof URI)) {\n base = new URI(base);\n }\n\n if (!resolved._parts.protocol) {\n resolved._parts.protocol = base._parts.protocol;\n }\n\n if (this._parts.hostname) {\n return resolved;\n }\n\n for (i = 0; (p = properties[i]); i++) {\n resolved._parts[p] = base._parts[p];\n }\n\n if (!resolved._parts.path) {\n resolved._parts.path = base._parts.path;\n if (!resolved._parts.query) {\n resolved._parts.query = base._parts.query;\n }\n } else if (resolved._parts.path.substring(-2) === '..') {\n resolved._parts.path += '/';\n }\n\n if (resolved.path().charAt(0) !== '/') {\n basedir = base.directory();\n basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : '';\n resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;\n resolved.normalizePath();\n }\n\n resolved.build();\n return resolved;\n };\n p.relativeTo = function(base) {\n var relative = this.clone().normalize();\n var relativeParts, baseParts, common, relativePath, basePath;\n\n if (relative._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n base = new URI(base).normalize();\n relativeParts = relative._parts;\n baseParts = base._parts;\n relativePath = relative.path();\n basePath = base.path();\n\n if (relativePath.charAt(0) !== '/') {\n throw new Error('URI is already relative');\n }\n\n if (basePath.charAt(0) !== '/') {\n throw new Error('Cannot calculate a URI relative to another relative URI');\n }\n\n if (relativeParts.protocol === baseParts.protocol) {\n relativeParts.protocol = null;\n }\n\n if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {\n return relative.build();\n }\n\n if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {\n return relative.build();\n }\n\n if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {\n relativeParts.hostname = null;\n relativeParts.port = null;\n } else {\n return relative.build();\n }\n\n if (relativePath === basePath) {\n relativeParts.path = '';\n return relative.build();\n }\n\n // determine common sub path\n common = URI.commonPath(relativePath, basePath);\n\n // If the paths have nothing in common, return a relative URL with the absolute path.\n if (!common) {\n return relative.build();\n }\n\n var parents = baseParts.path\n .substring(common.length)\n .replace(/[^\\/]*$/, '')\n .replace(/.*?\\//g, '../');\n\n relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './';\n\n return relative.build();\n };\n\n // comparing URIs\n p.equals = function(uri) {\n var one = this.clone();\n var two = new URI(uri);\n var one_map = {};\n var two_map = {};\n var checked = {};\n var one_query, two_query, key;\n\n one.normalize();\n two.normalize();\n\n // exact match\n if (one.toString() === two.toString()) {\n return true;\n }\n\n // extract query string\n one_query = one.query();\n two_query = two.query();\n one.query('');\n two.query('');\n\n // definitely not equal if not even non-query parts match\n if (one.toString() !== two.toString()) {\n return false;\n }\n\n // query parameters have the same length, even if they're permuted\n if (one_query.length !== two_query.length) {\n return false;\n }\n\n one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace);\n two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace);\n\n for (key in one_map) {\n if (hasOwn.call(one_map, key)) {\n if (!isArray(one_map[key])) {\n if (one_map[key] !== two_map[key]) {\n return false;\n }\n } else if (!arraysEqual(one_map[key], two_map[key])) {\n return false;\n }\n\n checked[key] = true;\n }\n }\n\n for (key in two_map) {\n if (hasOwn.call(two_map, key)) {\n if (!checked[key]) {\n // two contains a parameter not present in one\n return false;\n }\n }\n }\n\n return true;\n };\n\n // state\n p.duplicateQueryParameters = function(v) {\n this._parts.duplicateQueryParameters = !!v;\n return this;\n };\n\n p.escapeQuerySpace = function(v) {\n this._parts.escapeQuerySpace = !!v;\n return this;\n };\n\n return URI;\n}));\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar Spine = require('./spine');\nvar Locations = require('./locations');\nvar Parser = require('./parser');\nvar Navigation = require('./navigation');\nvar Rendition = require('./rendition');\nvar Continuous = require('./continuous');\nvar Paginate = require('./paginate');\nvar Unarchive = require('./unarchive');\nvar request = require('./request');\nvar EpubCFI = require('./epubcfi');\n\nfunction Book(_url, options){\n // Promises\n this.opening = new RSVP.defer();\n this.opened = this.opening.promise;\n this.isOpen = false;\n\n this.url = undefined;\n\n this.loading = {\n manifest: new RSVP.defer(),\n spine: new RSVP.defer(),\n metadata: new RSVP.defer(),\n cover: new RSVP.defer(),\n navigation: new RSVP.defer(),\n pageList: new RSVP.defer()\n };\n\n this.loaded = {\n manifest: this.loading.manifest.promise,\n spine: this.loading.spine.promise,\n metadata: this.loading.metadata.promise,\n cover: this.loading.cover.promise,\n navigation: this.loading.navigation.promise,\n pageList: this.loading.pageList.promise\n };\n\n this.ready = RSVP.hash(this.loaded);\n\n // Queue for methods used before opening\n this.isRendered = false;\n // this._q = core.queue(this);\n\n this.request = this.requestMethod.bind(this);\n\n this.spine = new Spine(this.request);\n this.locations = new Locations(this.spine, this.request);\n\n if(_url) {\n this.open(_url);\n }\n};\n\nBook.prototype.open = function(_url){\n var uri;\n var parse = new Parser();\n var epubPackage;\n var epubContainer;\n var book = this;\n var containerPath = \"META-INF/container.xml\";\n var location;\n\n if(!_url) {\n this.opening.resolve(this);\n return this.opened;\n }\n\n // Reuse parsed url or create a new uri object\n // if(typeof(_url) === \"object\") {\n // uri = _url;\n // } else {\n // uri = core.uri(_url);\n // }\n uri = URI(_url);\n this.url = _url;\n\n // Find path to the Container\n if(uri.suffix() === \"opf\") {\n // Direct link to package, no container\n this.packageUrl = _url;\n this.containerUrl = '';\n\n if(uri.origin()) {\n this.baseUrl = uri.origin() + \"/\" + uri.directory() + \"/\";\n } else if(window){\n this.baseUrl = uri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n this.baseUrl = uri.directory() + \"/\";\n }\n\n epubPackage = this.request(this.packageUrl);\n\n } else if(this.isArchivedUrl(uri)) {\n // Book is archived\n this.url = '/';\n this.containerUrl = URI(containerPath).absoluteTo(this.url).toString();\n\n epubContainer = this.unarchive(_url).\n then(function() {\n return this.request(this.containerUrl);\n }.bind(this));\n\n }\n // Find the path to the Package from the container\n else if (!uri.suffix()) {\n\n this.containerUrl = this.url + containerPath;\n\n epubContainer = this.request(this.containerUrl)\n .catch(function(error) {\n // handle errors in loading container\n book.opening.reject(error);\n });\n }\n\n if (epubContainer) {\n epubPackage = epubContainer.\n then(function(containerXml){\n return parse.container(containerXml); // Container has path to content\n }).\n then(function(paths){\n var packageUri = URI(paths.packagePath);\n var absPackageUri = packageUri.absoluteTo(book.url);\n book.packageUrl = absPackageUri.toString();\n book.encoding = paths.encoding;\n\n // Set Url relative to the content\n if(packageUri.origin()) {\n book.baseUrl = packageUri.origin() + \"/\" + packageUri.directory() + \"/\";\n } else if(window && !book.isArchivedUrl(uri)){\n book.baseUrl = absPackageUri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n book.baseUrl = \"/\" + packageUri.directory() + \"/\";\n }\n\n return book.request(book.packageUrl);\n }).catch(function(error) {\n // handle errors in either of the two requests\n console.error(\"Could not load book at: \" + (this.packageUrl || this.containerPath));\n book.trigger(\"book:loadFailed\", (this.packageUrl || this.containerPath));\n book.opening.reject(error);\n });\n }\n\n epubPackage.then(function(packageXml) {\n // Get package information from epub opf\n book.unpack(packageXml);\n\n // Resolve promises\n book.loading.manifest.resolve(book.package.manifest);\n book.loading.metadata.resolve(book.package.metadata);\n book.loading.spine.resolve(book.spine);\n book.loading.cover.resolve(book.cover);\n\n book.isOpen = true;\n\n // Clear queue of any waiting book request\n\n // Resolve book opened promise\n book.opening.resolve(book);\n\n }).catch(function(error) {\n // handle errors in parsing the book\n console.error(error.message, error.stack);\n book.opening.reject(error);\n });\n\n return this.opened;\n};\n\nBook.prototype.unpack = function(packageXml){\n var book = this,\n parse = new Parser();\n\n book.package = parse.packageContents(packageXml); // Extract info from contents\n if(!book.package) {\n return;\n }\n\n book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths\n\n this.spine.load(book.package);\n\n book.navigation = new Navigation(book.package, this.request);\n book.navigation.load().then(function(toc){\n book.toc = toc;\n book.loading.navigation.resolve(book.toc);\n });\n\n // //-- Set Global Layout setting based on metadata\n // MOVE TO RENDER\n // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);\n\n book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();\n};\n\n// Alias for book.spine.get\nBook.prototype.section = function(target) {\n return this.spine.get(target);\n};\n\n// Sugar to render a book\nBook.prototype.renderTo = function(element, options) {\n var renderMethod = (options && options.method) ?\n options.method :\n \"rendition\";\n var Renderer = require('./'+renderMethod);\n\n this.rendition = new Renderer(this, options);\n this.rendition.attachTo(element);\n\n return this.rendition;\n};\n\nBook.prototype.requestMethod = function(_url) {\n // Switch request methods\n if(this.archive) {\n return this.archive.request(_url);\n } else {\n return request(_url, null, this.requestCredentials, this.requestHeaders);\n }\n\n};\n\nBook.prototype.setRequestCredentials = function(_credentials) {\n this.requestCredentials = _credentials;\n};\n\nBook.prototype.setRequestHeaders = function(_headers) {\n this.requestHeaders = _headers;\n};\n\nBook.prototype.unarchive = function(bookUrl){\n\tthis.archive = new Unarchive();\n\treturn this.archive.open(bookUrl);\n};\n\n//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)\nBook.prototype.isArchivedUrl = function(bookUrl){\n var uri;\n var extension;\n\n if (bookUrl instanceof ArrayBuffer) {\n\t\treturn true;\n\t}\n\n // Reuse parsed url or create a new uri object\n // if(typeof(bookUrl) === \"object\") {\n // uri = bookUrl;\n // } else {\n // uri = core.uri(bookUrl);\n // }\n uri = URI(bookUrl);\n extension = uri.suffix();\n\n\tif(extension && (extension == \"epub\" || extension == \"zip\")){\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n//-- Returns the cover\nBook.prototype.coverUrl = function(){\n\tvar retrieved = this.loaded.cover.\n\t\tthen(function(url) {\n\t\t\tif(this.archive) {\n\t\t\t\treturn this.archive.createUrl(this.cover);\n\t\t\t}else{\n\t\t\t\treturn this.cover;\n\t\t\t}\n\t\t}.bind(this));\n\n\n\n\treturn retrieved;\n};\n\nBook.prototype.selectCfiRange = function(cfiRange) {\n var cfi = new EpubCFI(cfiRange);\n var item = this.spine.get(cfi.spinePos)\n\n return item.load().then(function (contents) {\n var range = cfi.toRange(item.document);\n return range;\n })\n};\n\nmodule.exports = Book;\n\n//-- Enable binding events to book\nRSVP.EventTarget.mixin(Book.prototype);\n\n//-- Handle RSVP Errors\nRSVP.on('error', function(event) {\n console.error(event);\n});\n\nRSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections\n// RSVP.on('created', listener);\n// RSVP.on('chained', listener);\n// RSVP.on('fulfilled', listener);\nRSVP.on('rejected', function(event){\n console.error(event.detail.message, event.detail.stack);\n});\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Rendition = require('./rendition');\nvar View = require('./view');\n\nfunction Continuous(book, options) {\n\n\tRendition.apply(this, arguments); // call super constructor.\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\toverflow: \"auto\",\n\t\taxis: \"vertical\",\n\t\toffset: 500,\n\t\toffsetDelta: 250\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t}\n\n\n};\n\n// subclass extends superclass\nContinuous.prototype = Object.create(Rendition.prototype);\nContinuous.prototype.constructor = Continuous;\n\nContinuous.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to a percent\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n\n\tif(this.settings.infinite) {\n\t\tthis.start();\n\t}\n\n\n};\n\nContinuous.prototype.parseTarget = function(target){\n\tif(this.epubcfi.isCfiString(target)) {\n cfi = new EpubCFI(target);\n spinePos = cfi.spinePos;\n section = this.book.spine.get(spinePos);\n } else {\n section = this.book.spine.get(target);\n }\n};\n\nContinuous.prototype.moveTo = function(offset){\n // var bounds = this.bounds();\n // var dist = Math.floor(offset.top / bounds.height) * bounds.height;\n return this.check(\n\t\toffset.left+this.settings.offset,\n\t\toffset.top+this.settings.offset)\n\t\t.then(function(){\n\n\t if(this.settings.axis === \"vertical\") {\n\t this.scrollBy(0, offset.top);\n\t } else {\n\t this.scrollBy(offset.left, 0);\n\t }\n\n\t }.bind(this));\n};\n\nContinuous.prototype.afterDisplayed = function(currView){\n\tvar next = currView.section.next();\n\tvar prev = currView.section.prev();\n\tvar index = this.views.indexOf(currView);\n\tvar prevView, nextView;\n\n\tif(index + 1 === this.views.length && next) {\n\t\tnextView = this.createView(next);\n\t\tthis.q.enqueue(this.append, nextView);\n\t}\n\n\tif(index === 0 && prev) {\n\t\tprevView = this.createView(prev, this.viewSettings);\n\t\tthis.q.enqueue(this.prepend, prevView);\n\t}\n\n\t// this.removeShownListeners(currView);\n\t// currView.onShown = this.afterDisplayed.bind(this);\n\tthis.trigger(\"added\", currView.section);\n\n};\n\n\n// Remove Previous Listeners if present\nContinuous.prototype.removeShownListeners = function(view){\n\n\t// view.off(\"shown\", this.afterDisplayed);\n\t// view.off(\"shown\", this.afterDisplayedAbove);\n\tview.onDisplayed = function(){};\n\n};\n\nContinuous.prototype.append = function(view){\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tthis.views.append(view);\n\n //this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.prepend = function(view){\n\t// view.on(\"shown\", this.afterDisplayedAbove.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tview.on(\"resized\", this.counter.bind(this));\n\n\tthis.views.prepend(view);\n\n // this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.counter = function(bounds){\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.scrollBy(0, bounds.heightDelta, true);\n\t} else {\n\t\tthis.scrollBy(bounds.widthDelta, 0, true);\n\t}\n\n};\n\nContinuous.prototype.check = function(_offset){\n\tvar checking = new RSVP.defer();\n\tvar container = this.bounds();\n var promises = [];\n var offset = _offset || this.settings.offset;\n\n\tthis.views.each(function(view){\n\t\tvar visible = this.isVisible(view, offset, offset, container);\n\n\t\tif(visible) {\n\n\t\t\tif(!view.displayed && !view.rendering) {\n // console.log(\"render\",view.section.index)\n\t\t\t\t\tpromises.push(this.render(view));\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif(view.displayed) {\n // console.log(\"destroy\", view.section.index)\n this.q.enqueue(view.destroy.bind(view));\n // view.destroy();\n // this.q.enqueue(this.trim);\n clearTimeout(this.trimTimeout);\n this.trimTimeout = setTimeout(function(){\n this.q.enqueue(this.trim);\n }.bind(this), 250);\n\t\t\t}\n\n\t\t}\n\n\t}.bind(this));\n\n\n if(promises.length){\n\n return RSVP.all(promises)\n .then(function(posts) {\n // Check to see if anything new is on screen after rendering\n this.q.enqueue(this.check);\n\n }.bind(this));\n\n } else {\n checking.resolve();\n\n return checking.promise;\n }\n\n};\n\nContinuous.prototype.trim = function(){\n var task = new RSVP.defer();\n var displayed = this.views.displayed();\n var first = displayed[0];\n var last = displayed[displayed.length-1];\n var firstIndex = this.views.indexOf(first);\n var lastIndex = this.views.indexOf(last);\n var above = this.views.slice(0, firstIndex);\n var below = this.views.slice(lastIndex+1);\n\n // Erase all but last above\n for (var i = 0; i < above.length-1; i++) {\n this.erase(above[i], above);\n }\n\n // Erase all except first below\n for (var j = 1; j < below.length; j++) {\n this.erase(below[j]);\n }\n\n task.resolve();\n return task.promise;\n};\n\nContinuous.prototype.erase = function(view, above){ //Trim\n\n\tvar prevTop;\n\tvar prevLeft;\n\n\tif(this.settings.height) {\n \tprevTop = this.container.scrollTop;\n\t\tprevLeft = this.container.scrollLeft;\n } else {\n \tprevTop = window.scrollY;\n\t\tprevLeft = window.scrollX;\n }\n\n\tvar bounds = view.bounds();\n\n\tthis.views.remove(view);\n\n\tif(above) {\n\n\t\tif(this.settings.axis === \"vertical\") {\n\t\t\tthis.scrollTo(0, prevTop - bounds.height, true);\n\t\t} else {\n\t\t\tthis.scrollTo(prevLeft - bounds.width, 0, true);\n\t\t}\n\t}\n\n};\n\nContinuous.prototype.start = function() {\n var scroller;\n\n this.tick = core.requestAnimationFrame;\n\n if(this.settings.height) {\n \tthis.prevScrollTop = this.container.scrollTop;\n \tthis.prevScrollLeft = this.container.scrollLeft;\n } else {\n \tthis.prevScrollTop = window.scrollY;\n\t\tthis.prevScrollLeft = window.scrollX;\n }\n\n this.scrollDeltaVert = 0;\n this.scrollDeltaHorz = 0;\n\n if(this.settings.height) {\n \tscroller = this.container;\n } else {\n \tscroller = window;\n }\n\n window.addEventListener(\"scroll\", function(e){\n if(!this.ignore) {\n this.scrolled = true;\n } else {\n this.ignore = false;\n }\n }.bind(this));\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n this.tick.call(window, this.onScroll.bind(this));\n\n this.scrolled = false;\n\n};\n\nContinuous.prototype.onScroll = function(){\n\n if(this.scrolled) {\n\n if(this.settings.height) {\n\t \tscrollTop = this.container.scrollTop;\n\t \tscrollLeft = this.container.scrollLeft;\n\t } else {\n\t \tscrollTop = window.scrollY;\n\t\t\tscrollLeft = window.scrollX;\n\t }\n\n if(!this.ignore) {\n\n\t if((this.scrollDeltaVert === 0 &&\n\t \t this.scrollDeltaHorz === 0) ||\n\t \t this.scrollDeltaVert > this.settings.offsetDelta ||\n\t \t this.scrollDeltaHorz > this.settings.offsetDelta) {\n\n\t\t\t\tthis.q.enqueue(this.check);\n\n\t\t\t\tthis.scrollDeltaVert = 0;\n\t \tthis.scrollDeltaHorz = 0;\n\n\t\t\t\tthis.trigger(\"scroll\", {\n\t\t top: scrollTop,\n\t\t left: scrollLeft\n\t\t });\n\n\t\t\t}\n\n\t\t} else {\n\t this.ignore = false;\n\t\t}\n\n this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);\n this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);\n\n\t\tthis.prevScrollTop = scrollTop;\n\t\tthis.prevScrollLeft = scrollLeft;\n\n \tclearTimeout(this.scrollTimeout);\n\t\tthis.scrollTimeout = setTimeout(function(){\n\t\t\tthis.scrollDeltaVert = 0;\n\t this.scrollDeltaHorz = 0;\n\t\t}.bind(this), 150);\n\n\n this.scrolled = false;\n }\n\n this.tick.call(window, this.onScroll.bind(this));\n\n};\n\n\n Continuous.prototype.resizeView = function(view) {\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tview.lock(\"height\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nContinuous.prototype.currentLocation = function(){\n var visible = this.visible();\n var startPage, endPage;\n\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n return this.map.page(visible[0]);\n }\n\n if(visible.length > 1) {\n\n startPage = this.map.page(visible[0]);\n endPage = this.map.page(visible[visible.length-1]);\n\n return {\n start: startPage.start,\n end: endPage.end\n };\n }\n\n};\n\n/*\nContinuous.prototype.current = function(what){\n var view, top;\n var container = this.container.getBoundingClientRect();\n var length = this.views.length - 1;\n\n if(this.settings.axis === \"horizontal\") {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n left = view.position().left;\n\n if(left < container.right) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n break;\n }\n }\n\n } else {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n top = view.bounds().top;\n if(top < container.bottom) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n\n break;\n }\n }\n\n }\n\n return this._current;\n};\n*/\n\nmodule.exports = Continuous;\n","var RSVP = require('rsvp');\n\nvar requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false;\n/*\n//-- Parse the different parts of a url, returning a object\nfunction uri(url){\n var uri = {\n protocol : '',\n host : '',\n path : '',\n origin : '',\n directory : '',\n base : '',\n filename : '',\n extension : '',\n fragment : '',\n href : url\n },\n doubleSlash = url.indexOf('://'),\n search = url.indexOf('?'),\n fragment = url.indexOf(\"#\"),\n withoutProtocol,\n dot,\n firstSlash;\n\n if(fragment != -1) {\n uri.fragment = url.slice(fragment + 1);\n url = url.slice(0, fragment);\n }\n\n if(search != -1) {\n uri.search = url.slice(search + 1);\n url = url.slice(0, search);\n href = url;\n }\n\n if(doubleSlash != -1) {\n uri.protocol = url.slice(0, doubleSlash);\n withoutProtocol = url.slice(doubleSlash+3);\n firstSlash = withoutProtocol.indexOf('/');\n\n if(firstSlash === -1) {\n uri.host = uri.path;\n uri.path = \"\";\n } else {\n uri.host = withoutProtocol.slice(0, firstSlash);\n uri.path = withoutProtocol.slice(firstSlash);\n }\n\n\n uri.origin = uri.protocol + \"://\" + uri.host;\n\n uri.directory = folder(uri.path);\n\n uri.base = uri.origin + uri.directory;\n // return origin;\n } else {\n uri.path = url;\n uri.directory = folder(url);\n uri.base = uri.directory;\n }\n\n //-- Filename\n uri.filename = url.replace(uri.base, '');\n dot = uri.filename.lastIndexOf('.');\n if(dot != -1) {\n uri.extension = uri.filename.slice(dot+1);\n }\n return uri;\n};\n\n//-- Parse out the folder, will return everything before the last slash\nfunction folder(url){\n\n var lastSlash = url.lastIndexOf('/');\n\n if(lastSlash == -1) var folder = '';\n\n folder = url.slice(0, lastSlash + 1);\n\n return folder;\n\n};\n*/\nfunction isElement(obj) {\n return !!(obj && obj.nodeType == 1);\n};\n\n// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\nfunction uuid() {\n var d = new Date().getTime();\n var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (d + Math.random()*16)%16 | 0;\n d = Math.floor(d/16);\n return (c=='x' ? r : (r&0x7|0x8)).toString(16);\n });\n return uuid;\n};\n\n// From Lodash\nfunction values(object) {\n var index = -1,\n props = Object.keys(object),\n length = props.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = object[props[index]];\n }\n return result;\n};\n\nfunction resolveUrl(base, path) {\n var url = [],\n segments = [],\n baseUri = uri(base),\n pathUri = uri(path),\n baseDirectory = baseUri.directory,\n pathDirectory = pathUri.directory,\n directories = [],\n // folders = base.split(\"/\"),\n paths;\n\n // if(uri.host) {\n // return path;\n // }\n\n if(baseDirectory[0] === \"/\") {\n baseDirectory = baseDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n baseDirectory = baseDirectory.substring(0, baseDirectory.length-1);\n }\n\n if(pathDirectory[0] === \"/\") {\n pathDirectory = pathDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n pathDirectory = pathDirectory.substring(0, pathDirectory.length-1);\n }\n\n if(baseDirectory) {\n directories = baseDirectory.split(\"/\");\n }\n\n paths = pathDirectory.split(\"/\");\n\n paths.reverse().forEach(function(part, index){\n if(part === \"..\"){\n directories.pop();\n } else if(part === directories[directories.length-1]) {\n directories.pop();\n segments.unshift(part);\n } else {\n segments.unshift(part);\n }\n });\n\n url = [baseUri.origin];\n\n if(directories.length) {\n url = url.concat(directories);\n }\n\n if(segments) {\n url = url.concat(segments);\n }\n\n url = url.concat(pathUri.filename);\n\n return url.join(\"/\");\n};\n\nfunction documentHeight() {\n return Math.max(\n document.documentElement.clientHeight,\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight\n );\n};\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n};\n\nfunction prefixed(unprefixed) {\n var vendors = [\"Webkit\", \"Moz\", \"O\", \"ms\" ],\n prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],\n upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),\n length = vendors.length;\n\n if (typeof(document.body.style[unprefixed]) != 'undefined') {\n return unprefixed;\n }\n\n for ( var i=0; i < length; i++ ) {\n if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {\n return vendors[i] + upper;\n }\n }\n\n return unprefixed;\n};\n\nfunction defaults(obj) {\n for (var i = 1, length = arguments.length; i < length; i++) {\n var source = arguments[i];\n for (var prop in source) {\n if (obj[prop] === void 0) obj[prop] = source[prop];\n }\n }\n return obj;\n};\n\nfunction extend(target) {\n var sources = [].slice.call(arguments, 1);\n sources.forEach(function (source) {\n if(!source) return;\n Object.getOwnPropertyNames(source).forEach(function(propName) {\n Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));\n });\n });\n return target;\n};\n\n// Fast quicksort insert for sorted array -- based on:\n// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers\nfunction insert(item, array, compareFunction) {\n var location = locationOf(item, array, compareFunction);\n array.splice(location, 0, item);\n\n return location;\n};\n// Returns where something would fit in\nfunction locationOf(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return pivot;\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared > 0 ? pivot : pivot + 1;\n }\n\n if(compared === 0) {\n return pivot;\n }\n if(compared === -1) {\n return locationOf(item, array, compareFunction, pivot, end);\n } else{\n return locationOf(item, array, compareFunction, start, pivot);\n }\n};\n// Returns -1 of mpt found\nfunction indexOfSorted(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return -1; // Not found\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared === 0 ? pivot : -1;\n }\n if(compared === 0) {\n return pivot; // Found\n }\n if(compared === -1) {\n return indexOfSorted(item, array, compareFunction, pivot, end);\n } else{\n return indexOfSorted(item, array, compareFunction, start, pivot);\n }\n};\n\nfunction bounds(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"width\", \"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"height\", \"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction borders(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction windowBounds() {\n\n var width = window.innerWidth;\n var height = window.innerHeight;\n\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width: width,\n height: height\n };\n\n};\n\n//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496\nfunction cleanStringForXpath(str) {\n var parts = str.match(/[^'\"]+|['\"]/g);\n parts = parts.map(function(part){\n if (part === \"'\") {\n return '\\\"\\'\\\"'; // output \"'\"\n }\n\n if (part === '\"') {\n return \"\\'\\\"\\'\"; // output '\"'\n }\n return \"\\'\" + part + \"\\'\";\n });\n return \"concat(\\'\\',\" + parts.join(\",\") + \")\";\n};\n\nfunction indexOfTextNode(textNode){\n var parent = textNode.parentNode;\n var children = parent.childNodes;\n var sib;\n var index = -1;\n for (var i = 0; i < children.length; i++) {\n sib = children[i];\n if(sib.nodeType === Node.TEXT_NODE){\n index++;\n }\n if(sib == textNode) break;\n }\n\n return index;\n};\n\nfunction isXml(ext) {\n return ['xml', 'opf', 'ncx'].indexOf(ext) > -1;\n}\n\nfunction createBlobUrl(content, mime){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob = new Blob([content], {type : mime });\n\n tempUrl = _URL.createObjectURL(blob);\n\n return tempUrl;\n};\n\nfunction type(obj){\n return Object.prototype.toString.call(obj).slice(8, -1);\n}\n\nmodule.exports = {\n // 'uri': uri,\n // 'folder': folder,\n 'isElement': isElement,\n 'uuid': uuid,\n 'values': values,\n 'resolveUrl': resolveUrl,\n 'indexOfSorted': indexOfSorted,\n 'documentHeight': documentHeight,\n 'isNumber': isNumber,\n 'prefixed': prefixed,\n 'defaults': defaults,\n 'extend': extend,\n 'insert': insert,\n 'locationOf': locationOf,\n 'indexOfSorted': indexOfSorted,\n 'requestAnimationFrame': requestAnimationFrame,\n 'bounds': bounds,\n 'borders': borders,\n 'windowBounds': windowBounds,\n 'cleanStringForXpath': cleanStringForXpath,\n 'indexOfTextNode': indexOfTextNode,\n 'isXml': isXml,\n 'createBlobUrl': createBlobUrl,\n 'type': type\n};\n","var URI = require('urijs');\nvar core = require('./core');\n\n/**\n EPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html\n\n Implements:\n - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)\n - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)\n\n Does Not Implement:\n - Temporal Offset (~)\n - Spatial Offset (@)\n - Temporal-Spatial Offset (~ + @)\n - Text Location Assertion ([)\n*/\n\nfunction EpubCFI(cfiFrom, base, ignoreClass){\n var type;\n\n this.str = '';\n\n this.base = {};\n this.spinePos = 0; // For compatibility\n\n this.range = false; // true || false;\n\n this.path = {};\n this.start = null;\n this.end = null;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof EpubCFI)) {\n return new EpubCFI(cfiFrom, base, ignoreClass);\n }\n\n if(typeof base === 'string') {\n this.base = this.parseComponent(base);\n } else if(typeof base === 'object' && base.steps) {\n this.base = base;\n }\n\n type = this.checkType(cfiFrom);\n\n\n if(type === 'string') {\n this.str = cfiFrom;\n return core.extend(this, this.parse(cfiFrom));\n } else if (type === 'range') {\n return core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));\n } else if (type === 'node') {\n return core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));\n } else if (type === 'EpubCFI' && cfiFrom.path) {\n return cfiFrom;\n } else if (!cfiFrom) {\n return this;\n } else {\n throw new TypeError('not a valid argument for EpubCFI');\n }\n\n};\n\nEpubCFI.prototype.checkType = function(cfi) {\n\n if (this.isCfiString(cfi)) {\n return 'string';\n // Is a range object\n } else if (typeof cfi === 'object' && core.type(cfi) === \"Range\"){\n return 'range';\n } else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function'\n return 'node';\n } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){\n return 'EpubCFI';\n } else {\n return false;\n }\n};\n\nEpubCFI.prototype.parse = function(cfiStr) {\n var cfi = {\n spinePos: -1,\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n var baseComponent, pathComponent, range;\n\n if(typeof cfiStr !== \"string\") {\n return {spinePos: -1};\n }\n\n if(cfiStr.indexOf(\"epubcfi(\") === 0 && cfiStr[cfiStr.length-1] === \")\") {\n // Remove intial epubcfi( and ending )\n cfiStr = cfiStr.slice(8, cfiStr.length-1);\n }\n\n baseComponent = this.getChapterComponent(cfiStr);\n\n // Make sure this is a valid cfi or return\n if(!baseComponent) {\n return {spinePos: -1};\n }\n\n cfi.base = this.parseComponent(baseComponent);\n\n pathComponent = this.getPathComponent(cfiStr);\n cfi.path = this.parseComponent(pathComponent);\n\n range = this.getRange(cfiStr);\n\n if(range) {\n cfi.range = true;\n cfi.start = this.parseComponent(range[0]);\n cfi.end = this.parseComponent(range[1]);\n }\n\n // Get spine node position\n // cfi.spineSegment = cfi.base.steps[1];\n\n // Chapter segment is always the second step\n cfi.spinePos = cfi.base.steps[1].index;\n\n return cfi;\n};\n\nEpubCFI.prototype.parseComponent = function(componentStr){\n var component = {\n steps: [],\n terminal: {\n offset: null,\n assertion: null\n }\n };\n var parts = componentStr.split(':');\n var steps = parts[0].split('/');\n var terminal;\n\n if(parts.length > 1) {\n terminal = parts[1];\n component.terminal = this.parseTerminal(terminal);\n }\n\n if (steps[0] === '') {\n steps.shift(); // Ignore the first slash\n }\n\n component.steps = steps.map(function(step){\n return this.parseStep(step);\n }.bind(this));\n\n return component;\n};\n\nEpubCFI.prototype.parseStep = function(stepStr){\n var type, num, index, has_brackets, id;\n\n has_brackets = stepStr.match(/\\[(.*)\\]/);\n if(has_brackets && has_brackets[1]){\n id = has_brackets[1];\n }\n\n //-- Check if step is a text node or element\n num = parseInt(stepStr);\n\n if(isNaN(num)) {\n return;\n }\n\n if(num % 2 === 0) { // Even = is an element\n type = \"element\";\n index = num / 2 - 1;\n } else {\n type = \"text\";\n index = (num - 1 ) / 2;\n }\n\n return {\n \"type\" : type,\n 'index' : index,\n 'id' : id || null\n };\n};\n\nEpubCFI.prototype.parseTerminal = function(termialStr){\n var characterOffset, textLocationAssertion;\n var assertion = termialStr.match(/\\[(.*)\\]/);\n\n if(assertion && assertion[1]){\n characterOffset = parseInt(termialStr.split('[')[0]) || null;\n textLocationAssertion = assertion[1];\n } else {\n characterOffset = parseInt(termialStr) || null;\n }\n\n return {\n 'offset': characterOffset,\n 'assertion': textLocationAssertion\n };\n\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n return indirection[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n if(indirection[1]) {\n ranges = indirection[1].split(',');\n return ranges[0];\n }\n\n};\n\nEpubCFI.prototype.getRange = function(cfiStr) {\n\n var ranges = cfiStr.split(\",\");\n\n if(ranges.length === 3){\n return [\n ranges[1],\n ranges[2]\n ];\n }\n\n return false;\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n var splitStr = cfiStr.split(\":\");\n return splitStr[1] || '';\n};\n\nEpubCFI.prototype.joinSteps = function(steps) {\n return steps.map(function(part){\n var segment = '';\n\n if(part.type === 'element') {\n segment += (part.index + 1) * 2;\n }\n\n if(part.type === 'text') {\n segment += 1 + (2 * part.index); // TODO: double check that this is odd\n }\n\n if(part.id) {\n segment += \"[\" + part.id + \"]\";\n }\n\n return segment;\n\n }).join('/');\n\n};\n\nEpubCFI.prototype.segmentString = function(segment) {\n var segmentString = '/';\n\n segmentString += this.joinSteps(segment.steps);\n\n if(segment.terminal && segment.terminal.offset != null){\n segmentString += ':' + segment.terminal.offset;\n }\n\n if(segment.terminal && segment.terminal.assertion != null){\n segmentString += '[' + segment.terminal.assertion + ']';\n }\n\n return segmentString;\n};\n\nEpubCFI.prototype.toString = function() {\n var cfiString = 'epubcfi(';\n\n cfiString += this.segmentString(this.base);\n\n cfiString += '!';\n cfiString += this.segmentString(this.path);\n\n // Add Range, if present\n if(this.start) {\n cfiString += ',';\n cfiString += this.segmentString(this.start);\n }\n\n if(this.end) {\n cfiString += ',';\n cfiString += this.segmentString(this.end);\n }\n\n cfiString += \")\";\n\n return cfiString;\n};\n\nEpubCFI.prototype.compare = function(cfiOne, cfiTwo) {\n if(typeof cfiOne === 'string') {\n cfiOne = new EpubCFI(cfiOne);\n }\n if(typeof cfiTwo === 'string') {\n cfiTwo = new EpubCFI(cfiTwo);\n }\n // Compare Spine Positions\n if(cfiOne.spinePos > cfiTwo.spinePos) {\n return 1;\n }\n if(cfiOne.spinePos < cfiTwo.spinePos) {\n return -1;\n }\n\n\n // Compare Each Step in the First item\n for (var i = 0; i < cfiOne.path.steps.length; i++) {\n if(!cfiTwo.path.steps[i]) {\n return 1;\n }\n if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {\n return 1;\n }\n if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {\n return -1;\n }\n // Otherwise continue checking\n }\n\n // All steps in First equal to Second and First is Less Specific\n if(cfiOne.path.steps.length < cfiTwo.path.steps.length) {\n return 1;\n }\n\n // Compare the charecter offset of the text node\n if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {\n return 1;\n }\n if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {\n return -1;\n }\n\n // TODO: compare ranges\n\n // CFI's are equal\n return 0;\n};\n\nEpubCFI.prototype.step = function(node) {\n var nodeType = (node.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n return {\n 'id' : node.id,\n 'tagName' : node.tagName,\n 'type' : nodeType,\n 'index' : this.position(node)\n };\n};\n\nEpubCFI.prototype.filteredStep = function(node, ignoreClass) {\n var filteredNode = this.filter(node, ignoreClass);\n var nodeType;\n\n // Node filtered, so ignore\n if (!filteredNode) {\n return;\n }\n\n // Otherwise add the filter node in\n nodeType = (filteredNode.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n return {\n 'id' : filteredNode.id,\n 'tagName' : filteredNode.tagName,\n 'type' : nodeType,\n 'index' : this.filteredPosition(filteredNode, ignoreClass)\n };\n};\n\nEpubCFI.prototype.pathTo = function(node, offset, ignoreClass) {\n var segment = {\n steps: [],\n terminal: {\n offset: null,\n assertion: null\n }\n };\n var currentNode = node;\n var step;\n\n while(currentNode && currentNode.parentNode &&\n currentNode.parentNode.nodeType != Node.DOCUMENT_NODE) {\n\n if (ignoreClass) {\n step = this.filteredStep(currentNode, ignoreClass);\n } else {\n step = this.step(currentNode);\n }\n\n if (step) {\n segment.steps.unshift(step);\n }\n\n currentNode = currentNode.parentNode;\n\n }\n\n if (offset != null && offset >= 0) {\n\n segment.terminal.offset = offset;\n\n // Make sure we are getting to a textNode if there is an offset\n if(segment.steps[segment.steps.length-1].type != \"text\") {\n segment.steps.push({\n 'type' : \"text\",\n 'index' : 0\n });\n }\n\n }\n\n\n return segment;\n}\n\nEpubCFI.prototype.equalStep = function(stepA, stepB) {\n if (!stepA || !stepB) {\n return false;\n }\n\n if(stepA.index === stepB.index &&\n stepA.id === stepB.id &&\n stepA.type === stepB.type) {\n return true;\n }\n\n return false;\n};\nEpubCFI.prototype.fromRange = function(range, base, ignoreClass) {\n var cfi = {\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n\n var start = range.startContainer;\n var end = range.endContainer;\n\n var startOffset = range.startOffset;\n var endOffset = range.endOffset;\n\n var needsIgnoring = false;\n\n if (ignoreClass) {\n // Tell pathTo if / what to ignore\n needsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null);\n }\n\n\n if (typeof base === 'string') {\n cfi.base = this.parseComponent(base);\n cfi.spinePos = cfi.base.steps[1].index;\n } else if (typeof base === 'object') {\n cfi.base = base;\n }\n\n if (range.collapsed) {\n if (needsIgnoring) {\n startOffset = this.patchOffset(start, startOffset, ignoreClass);\n }\n cfi.path = this.pathTo(start, startOffset, ignoreClass);\n } else {\n cfi.range = true;\n\n if (needsIgnoring) {\n startOffset = this.patchOffset(start, startOffset, ignoreClass);\n }\n\n cfi.start = this.pathTo(start, startOffset, ignoreClass);\n\n if (needsIgnoring) {\n endOffset = this.patchOffset(end, endOffset, ignoreClass);\n }\n\n cfi.end = this.pathTo(end, endOffset, ignoreClass);\n\n // Create a new empty path\n cfi.path = {\n steps: [],\n terminal: null\n };\n\n // Push steps that are shared between start and end to the common path\n var len = cfi.start.steps.length;\n var i;\n\n for (i = 0; i < len; i++) {\n if (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {\n if(i == len-1) {\n // Last step is equal, check terminals\n if(cfi.start.terminal === cfi.end.terminal) {\n // CFI's are equal\n cfi.path.steps.push(cfi.start.steps[i]);\n // Not a range\n cfi.range = false;\n }\n } else {\n cfi.path.steps.push(cfi.start.steps[i]);\n }\n\n } else {\n break;\n }\n };\n\n cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);\n cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length);\n\n // TODO: Add Sanity check to make sure that the end if greater than the start\n }\n\n return cfi;\n}\n\nEpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) {\n var cfi = {\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n\n var needsIgnoring = false;\n\n if (ignoreClass) {\n // Tell pathTo if / what to ignore\n needsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null);\n }\n\n if (typeof base === 'string') {\n cfi.base = this.parseComponent(base);\n cfi.spinePos = cfi.base.steps[1].index;\n } else if (typeof base === 'object') {\n cfi.base = base;\n }\n\n cfi.path = this.pathTo(anchor, null, ignoreClass);\n\n return cfi;\n};\n\n\nEpubCFI.prototype.filter = function(anchor, ignoreClass) {\n var needsIgnoring;\n var sibling; // to join with\n var parent, prevSibling, nextSibling;\n var isText = false;\n\n if (anchor.nodeType === Node.TEXT_NODE) {\n isText = true;\n parent = anchor.parentNode;\n needsIgnoring = anchor.parentNode.classList.contains(ignoreClass);\n } else {\n isText = false;\n needsIgnoring = anchor.classList.contains(ignoreClass);\n }\n\n if (needsIgnoring && isText) {\n previousSibling = parent.previousSibling;\n nextSibling = parent.nextSibling;\n\n // If the sibling is a text node, join the nodes\n if (previousSibling && previousSibling.nodeType === Node.TEXT_NODE) {\n sibling = previousSibling;\n } else if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n sibling = nextSibling;\n }\n\n if (sibling) {\n return sibling;\n } else {\n // Parent will be ignored on next step\n return anchor;\n }\n\n } else if (needsIgnoring && !isText) {\n // Otherwise just skip the element node\n return false;\n } else {\n // No need to filter\n return anchor;\n }\n\n};\n\nEpubCFI.prototype.patchOffset = function(anchor, offset, ignoreClass) {\n var needsIgnoring;\n var sibling;\n\n if (anchor.nodeType != Node.TEXT_NODE) {\n console.error(\"Anchor must be a text node\");\n return;\n }\n\n var curr = anchor;\n var totalOffset = offset;\n\n // If the parent is a ignored node, get offset from it's start\n if (anchor.parentNode.classList.contains(ignoreClass)) {\n curr = anchor.parentNode;\n }\n\n while (curr.previousSibling) {\n if(curr.previousSibling.nodeType === Node.ELEMENT_NODE) {\n // Originally a text node, so join\n if(curr.previousSibling.classList.contains(ignoreClass)){\n totalOffset += curr.previousSibling.textContent.length;\n } else {\n break; // Normal node, dont join\n }\n } else {\n // If the previous sibling is a text node, join the nodes\n totalOffset += curr.previousSibling.textContent.length;\n }\n\n curr = curr.previousSibling;\n }\n\n return totalOffset;\n\n};\n\nEpubCFI.prototype.normalizedMap = function(children, nodeType, ignoreClass) {\n var output = {};\n var prevIndex = -1;\n var i, len = children.length;\n var currNodeType;\n var prevNodeType;\n\n for (i = 0; i < len; i++) {\n\n currNodeType = children[i].nodeType;\n\n // Check if needs ignoring\n if (currNodeType === Node.ELEMENT_NODE &&\n children[i].classList.contains(ignoreClass)) {\n currNodeType = Node.TEXT_NODE;\n }\n\n if (i > 0 &&\n currNodeType === Node.TEXT_NODE &&\n prevNodeType === Node.TEXT_NODE) {\n // join text nodes\n output[i] = prevIndex;\n } else if (nodeType === currNodeType){\n prevIndex = prevIndex + 1;\n output[i] = prevIndex;\n }\n\n prevNodeType = currNodeType;\n\n }\n\n return output;\n};\n\nEpubCFI.prototype.position = function(anchor) {\n var children, index, map;\n\n if (anchor.nodeType === Node.ELEMENT_NODE) {\n children = anchor.parentNode.children;\n index = Array.prototype.indexOf.call(children, anchor);\n } else {\n children = this.textNodes(anchor.parentNode);\n index = children.indexOf(anchor);\n }\n\n return index;\n};\n\nEpubCFI.prototype.filteredPosition = function(anchor, ignoreClass) {\n var children, index, map;\n\n if (anchor.nodeType === Node.ELEMENT_NODE) {\n children = anchor.parentNode.children;\n map = this.normalizedMap(children, Node.ELEMENT_NODE, ignoreClass);\n } else {\n children = anchor.parentNode.childNodes;\n // Inside an ignored node\n if(anchor.parentNode.classList.contains(ignoreClass)) {\n anchor = anchor.parentNode;\n children = anchor.parentNode.childNodes;\n }\n map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n }\n\n\n index = Array.prototype.indexOf.call(children, anchor);\n\n return map[index];\n};\n\nEpubCFI.prototype.stepsToXpath = function(steps) {\n var xpath = [\".\", \"*\"];\n\n steps.forEach(function(step){\n var position = step.index + 1;\n\n if(step.id){\n xpath.push(\"*[position()=\" + position + \" and @id='\" + step.id + \"']\");\n } else if(step.type === \"text\") {\n xpath.push(\"text()[\" + position + \"]\");\n } else {\n xpath.push(\"*[\" + position + \"]\");\n }\n });\n\n return xpath.join(\"/\");\n};\n\n\n/*\n\nTo get the last step if needed:\n\n// Get the terminal step\nlastStep = steps[steps.length-1];\n// Get the query string\nquery = this.stepsToQuery(steps);\n// Find the containing element\nstartContainerParent = doc.querySelector(query);\n// Find the text node within that element\nif(startContainerParent && lastStep.type == \"text\") {\n container = startContainerParent.childNodes[lastStep.index];\n}\n*/\nEpubCFI.prototype.stepsToQuerySelector = function(steps) {\n var query = [\"html\"];\n\n steps.forEach(function(step){\n var position = step.index + 1;\n\n if(step.id){\n query.push(\"#\" + step.id);\n } else if(step.type === \"text\") {\n // unsupported in querySelector\n // query.push(\"text()[\" + position + \"]\");\n } else {\n query.push(\"*:nth-child(\" + position + \")\");\n }\n });\n\n return query.join(\">\");\n\n};\n\nEpubCFI.prototype.textNodes = function(container, ignoreClass) {\n return Array.prototype.slice.call(container.childNodes).\n filter(function (node) {\n if (node.nodeType === Node.TEXT_NODE) {\n return true;\n } else if (ignoreClass && node.classList.contains(ignoreClass)) {\n return true;\n }\n return false;\n });\n};\n\nEpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) {\n var doc = _doc || document;\n var container = doc.documentElement;\n var step;\n var len = steps.length;\n var i;\n\n for (i = 0; i < len; i++) {\n step = steps[i];\n\n if(step.type === \"element\") {\n container = container.children[step.index];\n } else if(step.type === \"text\"){\n container = this.textNodes(container, ignoreClass)[step.index];\n }\n\n };\n\n return container;\n};\n\nEpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) {\n var doc = _doc || document;\n var container;\n var xpath;\n\n if(!ignoreClass && typeof doc.evaluate != 'undefined') {\n xpath = this.stepsToXpath(steps);\n container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n } else if(ignoreClass) {\n container = this.walkToNode(steps, doc, ignoreClass);\n } else {\n container = this.walkToNode(steps, doc);\n }\n\n return container;\n};\n\nEpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {\n var container = this.findNode(steps.slice(0,-1), _doc, ignoreClass);\n var children = container.childNodes;\n var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n var i;\n var child;\n var len;\n var childIndex;\n var lastStepIndex = steps[steps.length-1].index;\n\n for (var childIndex in map) {\n if (!map.hasOwnProperty(childIndex)) return;\n\n if(map[childIndex] === lastStepIndex) {\n child = children[childIndex];\n len = child.textContent.length;\n if(offset > len) {\n offset = offset - len;\n } else {\n if (child.nodeType === Node.ELEMENT_NODE) {\n container = child.childNodes[0];\n } else {\n container = child;\n }\n break;\n }\n }\n }\n\n return {\n container: container,\n offset: offset\n };\n\n};\n\nEpubCFI.prototype.toRange = function(_doc, ignoreClass) {\n var doc = _doc || document;\n var range = doc.createRange();\n var start, end, startContainer, endContainer;\n var cfi = this;\n var startSteps, endSteps;\n var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false;\n var missed;\n\n if (cfi.range) {\n start = cfi.start;\n startSteps = cfi.path.steps.concat(start.steps);\n startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);\n end = cfi.end;\n endSteps = cfi.path.steps.concat(end.steps);\n endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);\n } else {\n start = cfi.path;\n startSteps = cfi.path.steps;\n startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);\n }\n\n\n\n if(startContainer) {\n try {\n\n if(start.terminal.offset != null) {\n range.setStart(startContainer, start.terminal.offset);\n } else {\n range.setStart(startContainer, 0);\n }\n\n } catch (e) {\n missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n range.setStart(missed.container, missed.offset);\n }\n } else {\n // No start found\n return null;\n }\n\n\n if (endContainer) {\n try {\n\n if(end.terminal.offset != null) {\n range.setEnd(endContainer, end.terminal.offset);\n } else {\n range.setEnd(endContainer, 0);\n }\n\n } catch (e) {\n missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n range.setEnd(missed.container, missed.offset);\n }\n }\n\n\n // doc.defaultView.getSelection().addRange(range);\n return range;\n};\n\n// is a cfi string, should be wrapped with \"epubcfi()\"\nEpubCFI.prototype.isCfiString = function(str) {\n if(typeof str === 'string' &&\n str.indexOf(\"epubcfi(\") === 0 &&\n str[str.length-1] === \")\") {\n return true;\n }\n\n return false;\n};\n\nEpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {\n var pos = parseInt(_pos),\n spineNodeIndex = _spineNodeIndex + 1,\n cfi = '/'+spineNodeIndex+'/';\n\n cfi += (pos + 1) * 2;\n\n if(id) {\n cfi += \"[\" + id + \"]\";\n }\n\n return cfi;\n};\n\nmodule.exports = EpubCFI;\n","var RSVP = require('rsvp');\n\n//-- Hooks allow for injecting functions that must all complete in order before finishing\n// They will execute in parallel but all must finish before continuing\n// Functions may return a promise if they are asycn.\n\n// this.content = new EPUBJS.Hook();\n// this.content.register(function(){});\n// this.content.trigger(args).then(function(){});\n\nfunction Hook(context){\n this.context = context || this;\n this.hooks = [];\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.register = function(){\n for(var i = 0; i < arguments.length; ++i) {\n if (typeof arguments[i] === \"function\") {\n this.hooks.push(arguments[i]);\n } else {\n // unpack array\n for(var j = 0; j < arguments[i].length; ++j) {\n this.hooks.push(arguments[i][j]);\n }\n }\n }\n};\n\n// Triggers a hook to run all functions\nHook.prototype.trigger = function(){\n var args = arguments;\n var context = this.context;\n var promises = [];\n\n this.hooks.forEach(function(task, i) {\n var executing = task.apply(context, args);\n\n if(executing && typeof executing[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n promises.push(executing);\n }\n // Otherwise Task resolves immediately, continue\n });\n\n\n return RSVP.all(promises);\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.list = function(){\n return this.hooks;\n};\n\nmodule.exports = Hook;\n","var core = require('./core');\n\nfunction Reflowable(){\n\n};\n\nReflowable.prototype.calculate = function(_width, _height, _gap, _devisor){\n\n var divisor = _devisor || 1;\n\n //-- Check the width and create even width columns\n var fullWidth = Math.floor(_width);\n var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;\n\n var section = Math.floor(width / 8);\n var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);\n\n var colWidth;\n var spreadWidth;\n var delta;\n\n //-- Double Page\n if(divisor > 1) {\n colWidth = Math.floor((width - gap) / divisor);\n } else {\n colWidth = width;\n }\n\n spreadWidth = colWidth * divisor;\n\n delta = (colWidth + gap) * divisor;\n\n\n\n this.columnAxis = core.prefixed('columnAxis');\n this.columnGap = core.prefixed('columnGap');\n this.columnWidth = core.prefixed('columnWidth');\n this.columnFill = core.prefixed('columnFill');\n\n this.width = width;\n this.height = _height;\n this.spread = spreadWidth;\n this.delta = delta;\n\n this.column = colWidth;\n this.gap = gap;\n this.divisor = divisor;\n\n};\n\nReflowable.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n var $body = view.document.body;//view.document.querySelector(\"body\");\n\n $doc.style.overflow = \"hidden\";\n\n // Must be set to the new calculated width or the columns will be off\n // $body.style.width = this.width + \"px\";\n $doc.style.width = this.width + \"px\";\n\n //-- Adjust height\n $body.style.height = this.height + \"px\";\n\n //-- Add columns\n $body.style[this.columnAxis] = \"horizontal\";\n $body.style[this.columnFill] = \"auto\";\n $body.style[this.columnGap] = this.gap+\"px\";\n $body.style[this.columnWidth] = this.column+\"px\";\n\n // Add extra padding for the gap between this and the next view\n view.iframe.style.marginRight = this.gap+\"px\";\n};\n\nReflowable.prototype.count = function(view) {\n var totalWidth = view.root().scrollWidth;\n var spreads = Math.ceil(totalWidth / this.spread);\n\n return {\n spreads : spreads,\n pages : spreads * this.divisor\n };\n};\n\nfunction Fixed(_width, _height){\n\n};\n\nFixed.prototype.calculate = function(_width, _height){\n\n};\n\nFixed.prototype.format = function(view){\n var width, height;\n\n var $doc = view.document.documentElement;\n var $viewport = documentElement.querySelector(\"[name=viewport\");\n\n /**\n * check for the viewport size\n * \n */\n if($viewport && $viewport.hasAttribute(\"content\")) {\n content = $viewport.getAttribute(\"content\");\n contents = content.split(',');\n if(contents[0]){\n width = contents[0].replace(\"width=\", '');\n }\n if(contents[1]){\n height = contents[1].replace(\"height=\", '');\n }\n }\n\n //-- Adjust width and height\n // $doc.style.width = width + \"px\" || \"auto\";\n // $doc.style.height = height + \"px\" || \"auto\";\n view.resize(width, height);\n\n //-- Scroll\n $doc.style.overflow = \"auto\";\n\n};\n\nFixed.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nfunction Scroll(){\n\n};\n\nScroll.prototype.calculate = function(_width, _height){\n this.spread = _width;\n this.column = _width;\n this.gap = 0;\n};\n\nScroll.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n\n $doc.style.width = \"auto\";\n $doc.style.height = \"auto\";\n\n};\n\nScroll.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nmodule.exports = {\n 'Reflowable': Reflowable,\n 'Fixed': Fixed,\n 'Scroll': Scroll\n};\n","var core = require('./core');\nvar Queue = require('./queue');\nvar EpubCFI = require('./epubcfi');\nvar RSVP = require('rsvp');\n\nfunction Locations(spine, request) {\n this.spine = spine;\n this.request = request;\n\n this.q = new Queue(this);\n this.epubcfi = new EpubCFI();\n\n this._locations = [];\n this.total = 0;\n\n this.break = 150;\n\n this._current = 0;\n\n};\n\n// Load all of sections in the book\nLocations.prototype.generate = function(chars) {\n\n if (chars) {\n this.break = chars;\n }\n\n this.q.pause();\n\n this.spine.each(function(section) {\n\n this.q.enqueue(this.process, section);\n\n }.bind(this));\n\n return this.q.run().then(function() {\n this.total = this._locations.length-1;\n\n if (this._currentCfi) {\n this.currentLocation = this._currentCfi;\n }\n\n return this._locations;\n // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));\n }.bind(this));\n\n};\n\nLocations.prototype.process = function(section) {\n\n return section.load(this.request)\n .then(function(contents) {\n\n var range;\n var doc = contents.ownerDocument;\n var counter = 0;\n\n this.sprint(contents, function(node) {\n var len = node.length;\n var dist;\n var pos = 0;\n\n // Start range\n if (counter == 0) {\n range = doc.createRange();\n range.setStart(node, 0);\n }\n\n dist = this.break - counter;\n\n // Node is smaller than a break\n if(dist > len){\n counter += len;\n pos = len;\n }\n\n while (pos < len) {\n counter = this.break;\n pos += this.break;\n\n // Gone over\n if(pos >= len){\n // Continue counter for next node\n counter = len - (pos - this.break);\n\n // At End\n } else {\n // End the previous range\n range.setEnd(node, pos);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi);\n counter = 0;\n\n // Start new range\n pos += 1;\n range = doc.createRange();\n range.setStart(node, pos);\n }\n }\n\n\n\n }.bind(this));\n\n // Close remaining\n if (range) {\n range.setEnd(prev, prev.length);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi)\n counter = 0;\n }\n\n }.bind(this));\n\n};\n\nLocations.prototype.sprint = function(root, func) {\n\tvar treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);\n\n\twhile ((node = treeWalker.nextNode())) {\n\t\tfunc(node);\n\t}\n\n};\n\nLocations.prototype.locationFromCfi = function(cfi){\n // Check if the location has not been set yet\n\tif(this._locations.length === 0) {\n\t\treturn -1;\n\t}\n\n return core.locationOf(cfi, this._locations, this.epubcfi.compare);\n};\n\nLocations.prototype.precentageFromCfi = function(cfi) {\n // Find closest cfi\n var loc = this.locationFromCfi(cfi);\n // Get percentage in total\n return this.precentageFromLocation(loc);\n};\n\nLocations.prototype.percentageFromLocation = function(loc) {\n if (!loc || !this.total) {\n return 0;\n }\n return (loc / this.total);\n};\n\nLocations.prototype.cfiFromLocation = function(loc){\n\tvar cfi = -1;\n\t// check that pg is an int\n\tif(typeof loc != \"number\"){\n\t\tloc = parseInt(pg);\n\t}\n\n\tif(loc >= 0 && loc < this._locations.length) {\n\t\tcfi = this._locations[loc];\n\t}\n\n\treturn cfi;\n};\n\nLocations.prototype.cfiFromPercentage = function(value){\n var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1\n\tvar loc = Math.ceil(this.total * percentage);\n\n\treturn this.cfiFromLocation(loc);\n};\n\nLocations.prototype.load = function(locations){\n\tthis._locations = JSON.parse(locations);\n this.total = this._locations.length-1;\n return this._locations;\n};\n\nLocations.prototype.save = function(json){\n\treturn JSON.stringify(this._locations);\n};\n\nLocations.prototype.getCurrent = function(json){\n\treturn this._current;\n};\n\nLocations.prototype.setCurrent = function(curr){\n var loc;\n\n if(typeof curr == \"string\"){\n this._currentCfi = curr;\n } else if (typeof curr == \"number\") {\n this._current = curr;\n } else {\n return;\n }\n\n if(this._locations.length === 0) {\n return;\n\t}\n\n if(typeof curr == \"string\"){\n loc = this.locationFromCfi(curr);\n this._current = loc;\n } else {\n loc = curr;\n }\n\n this.trigger(\"changed\", {\n percentage: this.precentageFromLocation(loc)\n });\n};\n\nObject.defineProperty(Locations.prototype, 'currentLocation', {\n get: function () {\n return this._current;\n },\n set: function (curr) {\n this.setCurrent(curr);\n }\n});\n\nRSVP.EventTarget.mixin(Locations.prototype);\n\nmodule.exports = Locations;\n","function Map(layout){\n this.layout = layout;\n};\n\nMap.prototype.section = function(view) {\n var ranges = this.findRanges(view);\n var map = this.rangeListToCfiList(view, ranges);\n\n return map;\n};\n\nMap.prototype.page = function(view, start, end) {\n var root = view.document.body;\n return this.rangePairToCfiPair(view.section, {\n start: this.findStart(root, start, end),\n end: this.findEnd(root, start, end)\n });\n};\n\nMap.prototype.walk = function(root, func) {\n //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);\n var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode: function (node) {\n if ( node.data.trim().length > 0 ) {\n return NodeFilter.FILTER_ACCEPT;\n } else {\n return NodeFilter.FILTER_REJECT;\n }\n }\n }, false);\n var node;\n var result;\n while ((node = treeWalker.nextNode())) {\n result = func(node);\n if(result) break;\n }\n\n return result;\n};\n\nMap.prototype.findRanges = function(view){\n var columns = [];\n var count = this.layout.count(view);\n var column = this.layout.column;\n var gap = this.layout.gap;\n var start, end;\n\n for (var i = 0; i < count.pages; i++) {\n start = (column + gap) * i;\n end = (column * (i+1)) + (gap * i);\n columns.push({\n start: this.findStart(view.document.body, start, end),\n end: this.findEnd(view.document.body, start, end)\n });\n }\n\n return columns;\n};\n\nMap.prototype.findStart = function(root, start, end){\n var stack = [root];\n var $el;\n var found;\n var $prev = root;\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if( left >= start && left <= end ) {\n return node;\n } else if (right > start) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n if(found) {\n return this.findTextStartRange(found, start, end);\n }\n\n }\n\n // Return last element\n return this.findTextStartRange($prev, start, end);\n};\n\nMap.prototype.findEnd = function(root, start, end){\n var stack = [root];\n var $el;\n var $prev = root;\n var found;\n\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if(left > end && $prev) {\n return $prev;\n } else if(right > end) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n\n if(found){\n return this.findTextEndRange(found, start, end);\n }\n\n }\n\n // end of chapter\n return this.findTextEndRange($prev, start, end);\n};\n\n\nMap.prototype.findTextStartRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if( pos.left >= start ) {\n return range;\n }\n\n prev = range;\n\n }\n\n return ranges[0];\n};\n\nMap.prototype.findTextEndRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if(pos.left > end && prev) {\n return prev;\n } else if(pos.right > end) {\n return range;\n }\n\n prev = range;\n\n }\n\n // Ends before limit\n return ranges[ranges.length-1];\n\n};\n\nMap.prototype.splitTextNodeIntoRanges = function(node, _splitter){\n var ranges = [];\n var textContent = node.textContent || \"\";\n var text = textContent.trim();\n var range;\n var rect;\n var list;\n var doc = node.ownerDocument;\n var splitter = _splitter || \" \";\n\n pos = text.indexOf(splitter);\n\n if(pos === -1 || node.nodeType != Node.TEXT_NODE) {\n range = doc.createRange();\n range.selectNodeContents(node);\n return [range];\n }\n\n range = doc.createRange();\n range.setStart(node, 0);\n range.setEnd(node, pos);\n ranges.push(range);\n range = false;\n\n while ( pos != -1 ) {\n\n pos = text.indexOf(splitter, pos + 1);\n if(pos > 0) {\n\n if(range) {\n range.setEnd(node, pos);\n ranges.push(range);\n }\n\n range = doc.createRange();\n range.setStart(node, pos+1);\n }\n }\n\n if(range) {\n range.setEnd(node, text.length);\n ranges.push(range);\n }\n\n return ranges;\n};\n\n\n\nMap.prototype.rangePairToCfiPair = function(section, rangePair){\n\n var startRange = rangePair.start;\n var endRange = rangePair.end;\n\n startRange.collapse(true);\n endRange.collapse(true);\n\n startCfi = section.cfiFromRange(startRange);\n endCfi = section.cfiFromRange(endRange);\n\n return {\n start: startCfi,\n end: endCfi\n };\n\n};\n\nMap.prototype.rangeListToCfiList = function(view, columns){\n var map = [];\n var rangePair, cifPair;\n\n for (var i = 0; i < columns.length; i++) {\n cifPair = this.rangePairToCfiPair(view.section, columns[i]);\n\n map.push(cifPair);\n\n }\n\n return map;\n};\n\nmodule.exports = Map;\n","var core = require('./core');\nvar Parser = require('./parser');\nvar RSVP = require('rsvp');\nvar URI = require('urijs');\n\nfunction Navigation(_package, _request){\n var navigation = this;\n var parse = new Parser();\n var request = _request || require('./request');\n\n this.package = _package;\n this.toc = [];\n this.tocByHref = {};\n this.tocById = {};\n\n if(_package.navPath) {\n this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();\n this.nav = {};\n\n this.nav.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.navUrl, 'xml').then(function(xml){\n navigation.toc = parse.nav(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n\n if(_package.ncxPath) {\n this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();\n this.ncx = {};\n\n this.ncx.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.ncxUrl, 'xml').then(function(xml){\n navigation.toc = parse.ncx(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n};\n\n// Load the navigation\nNavigation.prototype.load = function(_request) {\n var request = _request || require('./request');\n var loading, loaded;\n\n if(this.nav) {\n loading = this.nav.load();\n } else if(this.ncx) {\n loading = this.ncx.load();\n } else {\n loaded = new RSVP.defer();\n loaded.resolve([]);\n loading = loaded.promise;\n }\n\n return loading;\n\n};\n\nNavigation.prototype.loaded = function(toc) {\n var item;\n\n for (var i = 0; i < toc.length; i++) {\n item = toc[i];\n this.tocByHref[item.href] = i;\n this.tocById[item.id] = i;\n }\n\n};\n\n// Get an item from the navigation\nNavigation.prototype.get = function(target) {\n var index;\n\n if(!target) {\n return this.toc;\n }\n\n if(target.indexOf(\"#\") === 0) {\n index = this.tocById[target.substring(1)];\n } else if(target in this.tocByHref){\n index = this.tocByHref[target];\n }\n\n return this.toc[index];\n};\n\nmodule.exports = Navigation;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Continuous = require('./continuous');\nvar Map = require('./map');\nvar Layout = require('./layout');\n\nfunction Paginate(book, options) {\n\n Continuous.apply(this, arguments);\n\n this.settings = core.extend(this.settings || {}, {\n width: 600,\n height: 400,\n axis: \"horizontal\",\n forceSingle: false,\n minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)\n gap: \"auto\", //-- \"auto\" or int\n overflow: \"hidden\",\n infinite: false\n });\n\n core.extend(this.settings, options);\n\n this.isForcedSingle = this.settings.forceSingle;\n\n this.viewSettings = {\n axis: this.settings.axis\n };\n\n this.start();\n};\n\nPaginate.prototype = Object.create(Continuous.prototype);\nPaginate.prototype.constructor = Paginate;\n\n\nPaginate.prototype.determineSpreads = function(cutoff){\n if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) {\n return 1; //-- Single Page\n }else{\n return 2; //-- Double Page\n }\n};\n\nPaginate.prototype.forceSingle = function(bool){\n if(bool === false) {\n this.isForcedSingle = false;\n // this.spreads = false;\n } else {\n this.isForcedSingle = true;\n // this.spreads = this.determineSpreads(this.minSpreadWidth);\n }\n this.applyLayoutMethod();\n};\n\n/**\n* Uses the settings to determine which Layout Method is needed\n* Triggers events based on the method choosen\n* Takes: Layout settings object\n* Returns: String of appropriate for EPUBJS.Layout function\n*/\n// Paginate.prototype.determineLayout = function(settings){\n// // Default is layout: reflowable & spread: auto\n// var spreads = this.determineSpreads(this.settings.minSpreadWidth);\n// console.log(\"spreads\", spreads, this.settings.minSpreadWidth)\n// var layoutMethod = spreads ? \"ReflowableSpreads\" : \"Reflowable\";\n// var scroll = false;\n//\n// if(settings.layout === \"pre-paginated\") {\n// layoutMethod = \"Fixed\";\n// scroll = true;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"none\") {\n// layoutMethod = \"Reflowable\";\n// scroll = false;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"both\") {\n// layoutMethod = \"ReflowableSpreads\";\n// scroll = false;\n// spreads = true;\n// }\n//\n// this.spreads = spreads;\n//\n// return layoutMethod;\n// };\n\nPaginate.prototype.start = function(){\n // On display\n // this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);\n // this.layoutMethod = this.determineLayout(this.layoutSettings);\n // this.layout = new EPUBJS.Layout[this.layoutMethod]();\n //this.hooks.display.register(this.registerLayoutMethod.bind(this));\n // this.hooks.display.register(this.reportLocation);\n this.on('displayed', this.reportLocation.bind(this));\n\n // this.hooks.content.register(this.adjustImages.bind(this));\n\n this.currentPage = 0;\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n};\n\n// EPUBJS.Rendition.prototype.createView = function(section) {\n// var view = new EPUBJS.View(section, this.viewSettings);\n\n\n// return view;\n// };\n\nPaginate.prototype.applyLayoutMethod = function() {\n //var task = new RSVP.defer();\n\n // this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout = new Layout.Reflowable();\n\n this.updateLayout();\n\n // Set the look ahead offset for what is visible\n\n this.map = new Map(this.layout);\n\n // this.hooks.layout.register(this.layout.format.bind(this));\n\n //task.resolve();\n //return task.promise;\n // return layout;\n};\n\nPaginate.prototype.updateLayout = function() {\n\n this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout.calculate(\n this.stage.width,\n this.stage.height,\n this.settings.gap,\n this.spreads\n );\n\n this.settings.offset = this.layout.delta;\n\n};\n\nPaginate.prototype.moveTo = function(offset){\n var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n return this.check(0, dist+this.settings.offset).then(function(){\n this.scrollBy(dist, 0);\n }.bind(this));\n};\n\nPaginate.prototype.page = function(pg){\n\n // this.currentPage = pg;\n // this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0);\n //-- Return false if page is greater than the total\n // return false;\n};\n\nPaginate.prototype.next = function(){\n\n return this.q.enqueue(function(){\n // console.log(this.container.scrollWidth, this.container.scrollLeft + this.container.offsetWidth + this.layout.delta)\n if(this.container.scrollLeft +\n this.container.offsetWidth +\n this.layout.delta < this.container.scrollWidth) {\n this.scrollBy(this.layout.delta, 0);\n } else {\n this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n }\n this.reportLocation();\n return this.check();\n });\n\n // return this.page(this.currentPage + 1);\n};\n\nPaginate.prototype.prev = function(){\n\n return this.q.enqueue(function(){\n this.scrollBy(-this.layout.delta, 0);\n this.reportLocation();\n return this.check();\n });\n // return this.page(this.currentPage - 1);\n};\n\n// Paginate.prototype.reportLocation = function(){\n// return this.q.enqueue(function(){\n// this.location = this.currentLocation();\n// this.trigger(\"locationChanged\", this.location);\n// }.bind(this));\n// };\n\nPaginate.prototype.currentLocation = function(){\n var visible = this.visible();\n var startA, startB, endA, endB;\n var pageLeft, pageRight;\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.spread;\n\n return this.map.page(visible[0], startA, endA);\n }\n\n if(visible.length > 1) {\n\n // Left Col\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.column;\n\n // Right Col\n startB = container.left + this.layout.spread - visible[visible.length-1].position().left;\n endB = startB + this.layout.column;\n\n pageLeft = this.map.page(visible[0], startA, endA);\n pageRight = this.map.page(visible[visible.length-1], startB, endB);\n\n return {\n start: pageLeft.start,\n end: pageRight.end\n };\n }\n};\n\nPaginate.prototype.resize = function(width, height){\n // Clear the queue\n this.q.clear();\n\n this.stageSize(width, height);\n\n this.updateLayout();\n\n if(this.location) {\n this.display(this.location.start);\n }\n\n this.trigger(\"resized\", {\n width: this.stage.width,\n height: this.stage.height\n });\n\n};\n\nPaginate.prototype.onResized = function(e) {\n\n this.views.clear();\n\n clearTimeout(this.resizeTimeout);\n this.resizeTimeout = setTimeout(function(){\n this.resize();\n }.bind(this), 150);\n};\n\nPaginate.prototype.adjustImages = function(view) {\n\n view.addStylesheetRules([\n [\"img\",\n [\"max-width\", (this.layout.spread) + \"px\"],\n [\"max-height\", (this.layout.height) + \"px\"]\n ]\n ]);\n return new RSVP.Promise(function(resolve, reject){\n // Wait to apply\n setTimeout(function() {\n resolve();\n }, 1);\n });\n};\n\n// Paginate.prototype.display = function(what){\n// return this.display(what);\n// };\n\nmodule.exports = Paginate;\n","var URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction Parser(){};\n\nParser.prototype.container = function(containerXml){\n //-- \n var rootfile, fullpath, folder, encoding;\n\n if(!containerXml) {\n console.error(\"Container File Not Found\");\n return;\n }\n\n rootfile = containerXml.querySelector(\"rootfile\");\n\n if(!rootfile) {\n console.error(\"No RootFile Found\");\n return;\n }\n\n fullpath = rootfile.getAttribute('full-path');\n folder = URI(fullpath).directory();\n encoding = containerXml.xmlEncoding;\n\n //-- Now that we have the path we can parse the contents\n return {\n 'packagePath' : fullpath,\n 'basePath' : folder,\n 'encoding' : encoding\n };\n};\n\nParser.prototype.identifier = function(packageXml){\n var metadataNode;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n return this.getElementText(metadataNode, \"identifier\");\n};\n\nParser.prototype.packageContents = function(packageXml){\n var parse = this;\n var metadataNode, manifestNode, spineNode;\n var manifest, navPath, ncxPath, coverPath;\n var spineNodeIndex;\n var spine;\n var spineIndexByURL;\n var metadata;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n manifestNode = packageXml.querySelector(\"manifest\");\n if(!manifestNode) {\n console.error(\"No Manifest Found\");\n return;\n }\n\n spineNode = packageXml.querySelector(\"spine\");\n if(!spineNode) {\n console.error(\"No Spine Found\");\n return;\n }\n\n manifest = parse.manifest(manifestNode);\n navPath = parse.findNavPath(manifestNode);\n ncxPath = parse.findNcxPath(manifestNode, spineNode);\n coverPath = parse.findCoverPath(packageXml);\n\n spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);\n\n spine = parse.spine(spineNode, manifest);\n\n metadata = parse.metadata(metadataNode);\n\n\tmetadata.direction = spineNode.getAttribute(\"page-progression-direction\");\n\n return {\n 'metadata' : metadata,\n 'spine' : spine,\n 'manifest' : manifest,\n 'navPath' : navPath,\n 'ncxPath' : ncxPath,\n 'coverPath': coverPath,\n 'spineNodeIndex' : spineNodeIndex\n };\n};\n\n//-- Find TOC NAV\nParser.prototype.findNavPath = function(manifestNode){\n\t// Find item with property 'nav'\n\t// Should catch nav irregardless of order\n var node = manifestNode.querySelector(\"item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']\");\n return node ? node.getAttribute('href') : false;\n};\n\n//-- Find TOC NCX: media-type=\"application/x-dtbncx+xml\" href=\"toc.ncx\"\nParser.prototype.findNcxPath = function(manifestNode, spineNode){\n\tvar node = manifestNode.querySelector(\"item[media-type='application/x-dtbncx+xml']\");\n\tvar tocId;\n\n\t// If we can't find the toc by media-type then try to look for id of the item in the spine attributes as\n\t// according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2,\n\t// \"The item that describes the NCX must be referenced by the spine toc attribute.\"\n\tif (!node) {\n\t\ttocId = spineNode.getAttribute(\"toc\");\n\t\tif(tocId) {\n\t\t\tnode = manifestNode.querySelector(\"item[id='\" + tocId + \"']\");\n\t\t}\n\t}\n\n\treturn node ? node.getAttribute('href') : false;\n};\n\n//-- Expanded to match Readium web components\nParser.prototype.metadata = function(xml){\n var metadata = {},\n p = this;\n\n metadata.title = p.getElementText(xml, 'title');\n metadata.creator = p.getElementText(xml, 'creator');\n metadata.description = p.getElementText(xml, 'description');\n\n metadata.pubdate = p.getElementText(xml, 'date');\n\n metadata.publisher = p.getElementText(xml, 'publisher');\n\n metadata.identifier = p.getElementText(xml, \"identifier\");\n metadata.language = p.getElementText(xml, \"language\");\n metadata.rights = p.getElementText(xml, \"rights\");\n\n metadata.modified_date = p.querySelectorText(xml, \"meta[property='dcterms:modified']\");\n metadata.layout = p.querySelectorText(xml, \"meta[property='rendition:layout']\");\n metadata.orientation = p.querySelectorText(xml, \"meta[property='rendition:orientation']\");\n metadata.spread = p.querySelectorText(xml, \"meta[property='rendition:spread']\");\n // metadata.page_prog_dir = packageXml.querySelector(\"spine\").getAttribute(\"page-progression-direction\");\n\n return metadata;\n};\n\n//-- Find Cover: \n//-- Fallback for Epub 2.0\nParser.prototype.findCoverPath = function(packageXml){\n\n\tvar epubVersion = packageXml.querySelector('package').getAttribute('version');\n\n\tif (epubVersion === '2.0') {\n\t\tvar metaCover = packageXml.querySelector('meta[name=\"cover\"]');\n\t\tif (metaCover) {\n\t\t\tvar coverId = metaCover.getAttribute('content');\n\t\t\tvar cover = packageXml.querySelector(\"item[id='\" + coverId + \"']\");\n\t\t\treturn cover ? cover.getAttribute('href') : false;\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\telse {\n\t\tvar node = packageXml.querySelector(\"item[properties='cover-image']\");\n\t\treturn node ? node.getAttribute('href') : false;\n\t}\n};\n\nParser.prototype.getElementText = function(xml, tag){\n var found = xml.getElementsByTagNameNS(\"http://purl.org/dc/elements/1.1/\", tag),\n el;\n\n if(!found || found.length === 0) return '';\n\n el = found[0];\n\n if(el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n\n};\n\nParser.prototype.querySelectorText = function(xml, q){\n var el = xml.querySelector(q);\n\n if(el && el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n};\n\nParser.prototype.manifest = function(manifestXml){\n var manifest = {};\n\n //-- Turn items into an array\n var selected = manifestXml.querySelectorAll(\"item\"),\n items = Array.prototype.slice.call(selected);\n\n //-- Create an object with the id as key\n items.forEach(function(item){\n var id = item.getAttribute('id'),\n href = item.getAttribute('href') || '',\n type = item.getAttribute('media-type') || '',\n properties = item.getAttribute('properties') || '';\n\n manifest[id] = {\n 'href' : href,\n // 'url' : href,\n 'type' : type,\n 'properties' : properties.length ? properties.split(' ') : []\n };\n\n });\n\n return manifest;\n\n};\n\nParser.prototype.spine = function(spineXml, manifest){\n var spine = [];\n\n var selected = spineXml.getElementsByTagName(\"itemref\"),\n items = Array.prototype.slice.call(selected);\n\n var epubcfi = new EpubCFI();\n\n //-- Add to array to mantain ordering and cross reference with manifest\n items.forEach(function(item, index){\n var idref = item.getAttribute('idref');\n // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);\n var props = item.getAttribute('properties') || '';\n var propArray = props.length ? props.split(' ') : [];\n // var manifestProps = manifest[Id].properties;\n // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];\n\n var itemref = {\n 'idref' : idref,\n 'linear' : item.getAttribute('linear') || '',\n 'properties' : propArray,\n // 'href' : manifest[Id].href,\n // 'url' : manifest[Id].url,\n 'index' : index\n // 'cfiBase' : cfiBase\n };\n spine.push(itemref);\n });\n\n return spine;\n};\n\nParser.prototype.querySelectorByType = function(html, element, type){\n\tvar query = html.querySelector(element+'[*|type=\"'+type+'\"]');\n\t// Handle IE not supporting namespaced epub:type in querySelector\n\tif(query === null || query.length === 0) {\n\t\tquery = html.querySelectorAll(element);\n\t\tfor (var i = 0; i < query.length; i++) {\n\t\t\tif(query[i].getAttributeNS(\"http://www.idpf.org/2007/ops\", \"type\") === type) {\n\t\t\t\treturn query[i];\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn query;\n\t}\n};\n\nParser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"toc\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.navItem(navItems[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.navItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"a, span\"),\n\t\t\tsrc = content.getAttribute('href') || '',\n\t\t\ttext = content.textContent || \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.toc = function(tocXml, spineIndexByURL, bookSpine){\n\tvar navPoints = tocXml.querySelectorAll(\"navMap navPoint\");\n\tvar length = navPoints.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navPoints || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.tocItem(navPoints[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.tocItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"content\"),\n\t\t\tsrc = content.getAttribute('src'),\n\t\t\tnavLabel = item.querySelector(\"navLabel\"),\n\t\t\ttext = navLabel.textContent ? navLabel.textContent : \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"page-list\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.pageListItem(navItems[i], spineIndexByURL, bookSpine);\n\t\tlist.push(item);\n\t}\n\n\treturn list;\n};\n\nParser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\tcontent = item.querySelector(\"a\"),\n\t\thref = content.getAttribute('href') || '',\n\t\ttext = content.textContent || \"\",\n\t\tpage = parseInt(text),\n\t\tisCfi = href.indexOf(\"epubcfi\"),\n\t\tsplit,\n\t\tpackageUrl,\n\t\tcfi;\n\n\tif(isCfi != -1) {\n\t\tsplit = href.split(\"#\");\n\t\tpackageUrl = split[0];\n\t\tcfi = split.length > 1 ? split[1] : false;\n\t\treturn {\n\t\t\t\"cfi\" : cfi,\n\t\t\t\"href\" : href,\n\t\t\t\"packageUrl\" : packageUrl,\n\t\t\t\"page\" : page\n\t\t};\n\t} else {\n\t\treturn {\n\t\t\t\"href\" : href,\n\t\t\t\"page\" : page\n\t\t};\n\t}\n};\n\nmodule.exports = Parser;\n","var RSVP = require('rsvp');\nvar core = require('./core');\n\nfunction Queue(_context){\n this._q = [];\n this.context = _context;\n this.tick = core.requestAnimationFrame;\n this.running = false;\n this.paused = false;\n};\n\n// Add an item to the queue\nQueue.prototype.enqueue = function() {\n var deferred, promise;\n var queued;\n var task = [].shift.call(arguments);\n var args = arguments;\n\n // Handle single args without context\n // if(args && !Array.isArray(args)) {\n // args = [args];\n // }\n if(!task) {\n return console.error(\"No Task Provided\");\n }\n\n if(typeof task === \"function\"){\n\n deferred = new RSVP.defer();\n promise = deferred.promise;\n\n queued = {\n \"task\" : task,\n \"args\" : args,\n //\"context\" : context,\n \"deferred\" : deferred,\n \"promise\" : promise\n };\n\n } else {\n // Task is a promise\n queued = {\n \"promise\" : task\n };\n\n }\n\n this._q.push(queued);\n\n // Wait to start queue flush\n if (this.paused == false && !this.running) {\n // setTimeout(this.flush.bind(this), 0);\n // this.tick.call(window, this.run.bind(this));\n this.run();\n }\n\n return queued.promise;\n};\n\n// Run one item\nQueue.prototype.dequeue = function(){\n var inwait, task, result;\n\n if(this._q.length) {\n inwait = this._q.shift();\n task = inwait.task;\n if(task){\n // console.log(task)\n\n result = task.apply(this.context, inwait.args);\n\n if(result && typeof result[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n return result.then(function(){\n inwait.deferred.resolve.apply(this.context, arguments);\n }.bind(this));\n } else {\n // Task resolves immediately\n inwait.deferred.resolve.apply(this.context, result);\n return inwait.promise;\n }\n\n\n\n } else if(inwait.promise) {\n // Task is a promise\n return inwait.promise;\n }\n\n } else {\n inwait = new RSVP.defer();\n inwait.deferred.resolve();\n return inwait.promise;\n }\n\n};\n\n// Run All Immediately\nQueue.prototype.dump = function(){\n while(this._q.length) {\n this.dequeue();\n }\n};\n\n// Run all sequentially, at convince\n\nQueue.prototype.run = function(){\n\n if(!this.running){\n this.running = true;\n this.defered = new RSVP.defer();\n }\n\n this.tick.call(window, function() {\n\n if(this._q.length) {\n\n this.dequeue()\n .then(function(){\n this.run();\n }.bind(this));\n\n } else {\n this.defered.resolve();\n this.running = undefined;\n }\n\n }.bind(this));\n\n // Unpause\n if(this.paused == true) {\n this.paused = false;\n }\n\n return this.defered.promise;\n};\n\n// Flush all, as quickly as possible\nQueue.prototype.flush = function(){\n\n if(this.running){\n return this.running;\n }\n\n if(this._q.length) {\n this.running = this.dequeue()\n .then(function(){\n this.running = undefined;\n return this.flush();\n }.bind(this));\n\n return this.running;\n }\n\n};\n\n// Clear all items in wait\nQueue.prototype.clear = function(){\n this._q = [];\n this.running = false;\n};\n\nQueue.prototype.length = function(){\n return this._q.length;\n};\n\nQueue.prototype.pause = function(){\n this.paused = true;\n};\n\n// Create a new task from a callback\nfunction Task(task, args, context){\n\n return function(){\n var toApply = arguments || [];\n\n return new RSVP.Promise(function(resolve, reject) {\n var callback = function(value){\n resolve(value);\n };\n // Add the callback to the arguments list\n toApply.push(callback);\n\n // Apply all arguments to the functions\n task.apply(this, toApply);\n\n }.bind(this));\n\n };\n\n};\n\nmodule.exports = Queue;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar replace = require('./replacements');\nvar Hook = require('./hook');\nvar EpubCFI = require('./epubcfi');\nvar Queue = require('./queue');\nvar View = require('./view');\nvar Views = require('./views');\nvar Layout = require('./layout');\nvar Map = require('./map');\n\nfunction Rendition(book, options) {\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\thidden: false,\n\t\twidth: false,\n\t\theight: null,\n\t\tlayoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},\n\t\taxis: \"vertical\",\n\t\tignoreClass: ''\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass\n\t};\n\n\tthis.book = book;\n\n\tthis.views = null;\n\n\t//-- Adds Hook methods to the Rendition prototype\n\tthis.hooks = {};\n\tthis.hooks.display = new Hook(this);\n\tthis.hooks.serialize = new Hook(this);\n\tthis.hooks.content = new Hook(this);\n\tthis.hooks.layout = new Hook(this);\n\tthis.hooks.render = new Hook(this);\n\tthis.hooks.show = new Hook(this);\n\n\tthis.hooks.content.register(replace.links.bind(this));\n\tthis.hooks.content.register(this.passViewEvents.bind(this));\n\n\t// this.hooks.display.register(this.afterDisplay.bind(this));\n\n this.epubcfi = new EpubCFI();\n\n\tthis.q = new Queue(this);\n\n\tthis.q.enqueue(this.book.opened);\n\n\tthis.q.enqueue(this.parseLayoutProperties);\n\n\tif(this.book.archive) {\n\t\tthis.replacements();\n\t}\n};\n\n/**\n* Creates an element to render to.\n* Resizes to passed width and height or to the elements size\n*/\nRendition.prototype.initialize = function(_options){\n\tvar options = _options || {};\n\tvar height = options.height;// !== false ? options.height : \"100%\";\n\tvar width = options.width;// !== false ? options.width : \"100%\";\n\tvar hidden = options.hidden || false;\n\tvar container;\n\tvar wrapper;\n\n\tif(options.height && core.isNumber(options.height)) {\n\t\theight = options.height + \"px\";\n\t}\n\n\tif(options.width && core.isNumber(options.width)) {\n\t\twidth = options.width + \"px\";\n\t}\n\n\t// Create new container element\n\tcontainer = document.createElement(\"div\");\n\n\tcontainer.id = \"epubjs-container:\" + core.uuid();\n\tcontainer.classList.add(\"epub-container\");\n\n\t// Style Element\n\tcontainer.style.fontSize = \"0\";\n\tcontainer.style.wordSpacing = \"0\";\n\tcontainer.style.lineHeight = \"0\";\n\tcontainer.style.verticalAlign = \"top\";\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tcontainer.style.whiteSpace = \"nowrap\";\n\t}\n\n\tif(width){\n\t\tcontainer.style.width = width;\n\t}\n\n\tif(height){\n\t\tcontainer.style.height = height;\n\t}\n\n\tcontainer.style.overflow = this.settings.overflow;\n\n\treturn container;\n};\n\nRendition.wrap = function(container) {\n\tvar wrapper = document.createElement(\"div\");\n\n\twrapper.style.visibility = \"hidden\";\n\twrapper.style.overflow = \"hidden\";\n\twrapper.style.width = \"0\";\n\twrapper.style.height = \"0\";\n\n\twrapper.appendChild(container);\n\treturn wrapper;\n};\n\n// Call to attach the container to an element in the dom\n// Container must be attached before rendering can begin\nRendition.prototype.attachTo = function(_element){\n\tvar bounds;\n\n\tthis.container = this.initialize({\n\t\t\"width\" : this.settings.width,\n\t\t\"height\" : this.settings.height\n\t});\n\n\tif(core.isElement(_element)) {\n\t\tthis.element = _element;\n\t} else if (typeof _element === \"string\") {\n\t\tthis.element = document.getElementById(_element);\n\t}\n\n\tif(!this.element){\n\t\tconsole.error(\"Not an Element\");\n\t\treturn;\n\t}\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t\tthis.element.appendChild(this.wrapper);\n\t} else {\n\t\tthis.element.appendChild(this.container);\n\t}\n\n\tthis.views = new Views(this.container);\n\n\t// Attach Listeners\n\tthis.attachListeners();\n\n\t// Calculate Stage Size\n\tthis.stageSize();\n\n\t// Add Layout method\n\tthis.applyLayoutMethod();\n\n\t// Trigger Attached\n\tthis.trigger(\"attached\");\n\n\t// Start processing queue\n\t// this.q.run();\n\n};\n\nRendition.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to 100%\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n};\n\nRendition.prototype.bounds = function() {\n\treturn this.container.getBoundingClientRect();\n};\n\nRendition.prototype.display = function(target){\n\n\treturn this.q.enqueue(this._display, target);\n\n};\n\nRendition.prototype._display = function(target){\n\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\n\tvar section;\n var view;\n var offset;\n\tvar fragment;\n\tvar cfi = this.epubcfi.isCfiString(target);\n\n\tvar visible;\n\n\tsection = this.book.spine.get(target);\n\n\tif(!section){\n\t\tdisplaying.reject(new Error(\"No Section Found\"));\n\t\treturn displayed;\n\t}\n\n\t// Check to make sure the section we want isn't already shown\n\tvisible = this.views.find(section);\n\n\tif(visible) {\n\t\toffset = visible.locationOf(target);\n\t\tthis.moveTo(offset);\n\t\tdisplaying.resolve();\n\n\t} else {\n\n\t\t// Hide all current views\n\t\tthis.views.hide();\n\n\t\t// Create a new view\n\t\t// view = new View(section, this.viewSettings);\n\t\tview = this.createView(section);\n\n\t\t// This will clear all previous views\n\t\tdisplayed = this.fill(view)\n\t\t\t.then(function(){\n\n\t\t\t\t// Parse the target fragment\n\t\t\t\tif(typeof target === \"string\" &&\n\t\t\t\t\ttarget.indexOf(\"#\") > -1) {\n\t\t\t\t\t\tfragment = target.substring(target.indexOf(\"#\")+1);\n\t\t\t\t}\n\n\t\t\t\t// Move to correct place within the section, if needed\n\t\t\t\tif(cfi || fragment) {\n\t\t\t\t\toffset = view.locationOf(target);\n\t\t\t\t\treturn this.moveTo(offset);\n\t\t\t\t}\n\n\t\t\t\tif(typeof this.check === 'function') {\n\t\t\t\t\treturn this.check();\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\treturn this.hooks.display.trigger(view);\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tthis.views.show();\n\t\t\t}.bind(this));\n\t}\n\n\tdisplayed.then(function(){\n\n\t\tthis.trigger(\"displayed\", section);\n\n\t}.bind(this));\n\n\n\treturn displayed;\n};\n\n// Takes a cfi, fragment or page?\nRendition.prototype.moveTo = function(offset){\n\tthis.scrollTo(offset.left, offset.top);\n};\n\nRendition.prototype.render = function(view, show) {\n\n\tview.create();\n\n\tview.onLayout = this.layout.format.bind(this.layout);\n\n\t// Fit to size of the container, apply padding\n\tthis.resizeView(view);\n\n\t// Render Chain\n\treturn view.render(this.book.request)\n\t\t.then(function(){\n\t\t\treturn this.hooks.content.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.layout.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn view.display();\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.render.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\tif(show !== false && this.views.hidden === false) {\n\t\t\t\tthis.q.enqueue(function(view){\n\t\t\t\t\tview.show();\n\t\t\t\t}, view);\n\t\t\t}\n\n\n\t\t\t// this.map = new Map(view, this.layout);\n\t\t\tthis.hooks.show.trigger(view, this);\n\t\t\tthis.trigger(\"rendered\", view.section);\n\n\t\t}.bind(this))\n\t\t.catch(function(e){\n\t\t\tthis.trigger(\"loaderror\", e);\n\t\t}.bind(this));\n\n};\n\n\nRendition.prototype.afterDisplayed = function(view){\n\tthis.trigger(\"added\", view.section);\n\tthis.reportLocation();\n};\n\nRendition.prototype.fill = function(view){\n\n\tthis.views.clear();\n\n\tthis.views.append(view);\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\treturn this.render(view);\n};\n\nRendition.prototype.resizeView = function(view) {\n\n\tif(this.globalLayoutProperties.layout === \"pre-paginated\") {\n\t\tview.lock(\"both\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nRendition.prototype.stageSize = function(_width, _height){\n\tvar bounds;\n\tvar width = _width || this.settings.width;\n\tvar height = _height || this.settings.height;\n\n\t// If width or height are set to false, inherit them from containing element\n\tif(width === false) {\n\t\tbounds = this.element.getBoundingClientRect();\n\n\t\tif(bounds.width) {\n\t\t\twidth = bounds.width;\n\t\t\tthis.container.style.width = bounds.width + \"px\";\n\t\t}\n\t}\n\n\tif(height === false) {\n\t\tbounds = bounds || this.element.getBoundingClientRect();\n\n\t\tif(bounds.height) {\n\t\t\theight = bounds.height;\n\t\t\tthis.container.style.height = bounds.height + \"px\";\n\t\t}\n\n\t}\n\n\tif(width && !core.isNumber(width)) {\n\t\tbounds = this.container.getBoundingClientRect();\n\t\twidth = bounds.width;\n\t\t//height = bounds.height;\n\t}\n\n\tif(height && !core.isNumber(height)) {\n\t\tbounds = bounds || this.container.getBoundingClientRect();\n\t\t//width = bounds.width;\n\t\theight = bounds.height;\n\t}\n\n\n\tthis.containerStyles = window.getComputedStyle(this.container);\n\tthis.containerPadding = {\n\t\tleft: parseFloat(this.containerStyles[\"padding-left\"]) || 0,\n\t\tright: parseFloat(this.containerStyles[\"padding-right\"]) || 0,\n\t\ttop: parseFloat(this.containerStyles[\"padding-top\"]) || 0,\n\t\tbottom: parseFloat(this.containerStyles[\"padding-bottom\"]) || 0\n\t};\n\n\tthis.stage = {\n\t\twidth: width -\n\t\t\t\t\t\tthis.containerPadding.left -\n\t\t\t\t\t\tthis.containerPadding.right,\n\t\theight: height -\n\t\t\t\t\t\tthis.containerPadding.top -\n\t\t\t\t\t\tthis.containerPadding.bottom\n\t};\n\n\treturn this.stage;\n\n};\n\nRendition.prototype.applyLayoutMethod = function() {\n\n\tthis.layout = new Layout.Scroll();\n\tthis.updateLayout();\n\n\tthis.map = new Map(this.layout);\n};\n\nRendition.prototype.updateLayout = function() {\n\n\tthis.layout.calculate(this.stage.width, this.stage.height);\n\n};\n\nRendition.prototype.resize = function(width, height){\n\n\tthis.stageSize(width, height);\n\n\tthis.updateLayout();\n\n\tthis.views.each(this.resizeView.bind(this));\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nRendition.prototype.onResized = function(e) {\n\tthis.resize();\n};\n\nRendition.prototype.createView = function(section) {\n\t// Transfer the existing hooks\n\tsection.hooks.serialize.register(this.hooks.serialize.list());\n\n\treturn new View(section, this.viewSettings);\n};\n\nRendition.prototype.next = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar next;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tnext = this.views.last().section.next();\n\n\t\tif(next) {\n\t\t\tview = this.createView(next);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\nRendition.prototype.prev = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar prev;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tprev = this.views.first().section.prev();\n\t\tif(prev) {\n\t\t\tview = this.createView(prev);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\n//-- http://www.idpf.org/epub/fxl/\nRendition.prototype.parseLayoutProperties = function(_metadata){\n\tvar metadata = _metadata || this.book.package.metadata;\n\tvar layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || \"reflowable\";\n\tvar spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || \"auto\";\n\tvar orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || \"auto\";\n\tthis.globalLayoutProperties = {\n\t\tlayout : layout,\n\t\tspread : spread,\n\t\torientation : orientation\n\t};\n\treturn this.globalLayoutProperties;\n};\n\n\nRendition.prototype.current = function(){\n\tvar visible = this.visible();\n\tif(visible.length){\n\t\t// Current is the last visible view\n\t\treturn visible[visible.length-1];\n\t}\n return null;\n};\n\nRendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){\n\tvar position = view.position();\n\tvar container = _container || this.container.getBoundingClientRect();\n\n\tif(this.settings.axis === \"horizontal\" &&\n\t\tposition.right > container.left - offsetPrev &&\n\t\tposition.left < container.right + offsetNext) {\n\n\t\treturn true;\n\n } else if(this.settings.axis === \"vertical\" &&\n \tposition.bottom > container.top - offsetPrev &&\n\t\tposition.top < container.bottom + offsetNext) {\n\n\t\treturn true;\n }\n\n\treturn false;\n\n};\n\nRendition.prototype.visible = function(){\n\tvar container = this.bounds();\n\tvar displayedViews = this.views.displayed();\n var visible = [];\n var isVisible;\n var view;\n\n for (var i = 0; i < displayedViews.length; i++) {\n view = displayedViews[i];\n isVisible = this.isVisible(view, 0, 0, container);\n\n if(isVisible === true) {\n visible.push(view);\n }\n\n }\n return visible;\n\n};\n\nRendition.prototype.bounds = function(func) {\n var bounds;\n\n if(!this.settings.height) {\n bounds = core.windowBounds();\n } else {\n bounds = this.container.getBoundingClientRect();\n }\n\n return bounds;\n};\n\nRendition.prototype.destroy = function(){\n // Clear the queue\n\tthis.q.clear();\n\n\tthis.views.clear();\n\n\tclearTimeout(this.trimTimeout);\n\tif(this.settings.hidden) {\n\t\tthis.element.removeChild(this.wrapper);\n\t} else {\n\t\tthis.element.removeChild(this.container);\n\t}\n\n};\n\nRendition.prototype.reportLocation = function(){\n return this.q.enqueue(function(){\n this.location = this.currentLocation();\n this.trigger(\"locationChanged\", this.location);\n }.bind(this));\n};\n\nRendition.prototype.currentLocation = function(){\n var view;\n var start, end;\n\n if(this.views.length) {\n \tview = this.views.first();\n // start = container.left - view.position().left;\n // end = start + this.layout.spread;\n\n return this.map.page(view);\n }\n\n};\n\nRendition.prototype.scrollBy = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n\n if(x) this.container.scrollLeft += x;\n \tif(y) this.container.scrollTop += y;\n\n } else {\n \twindow.scrollBy(x,y);\n }\n // console.log(\"scrollBy\", x, y);\n this.scrolled = true;\n};\n\nRendition.prototype.scrollTo = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n \tthis.container.scrollLeft = x;\n \tthis.container.scrollTop = y;\n } else {\n \twindow.scrollTo(x,y);\n }\n // console.log(\"scrollTo\", x, y);\n this.scrolled = true;\n // if(this.container.scrollLeft != x){\n // setTimeout(function() {\n // this.scrollTo(x, y, silent);\n // }.bind(this), 10);\n // return;\n // };\n };\n\nRendition.prototype.passViewEvents = function(view){\n view.listenedEvents.forEach(function(e){\n\t\tview.on(e, this.triggerViewEvent.bind(this));\n\t}.bind(this));\n\n\tview.on(\"selected\", this.triggerSelectedEvent.bind(this));\n};\n\nRendition.prototype.triggerViewEvent = function(e){\n this.trigger(e.type, e);\n};\n\nRendition.prototype.triggerSelectedEvent = function(cfirange){\n this.trigger(\"selected\", cfirange);\n};\n\nRendition.prototype.replacements = function(){\n\t// Wait for loading\n\treturn this.q.enqueue(function () {\n\t\t// Get thes books manifest\n\t\tvar manifest = this.book.package.manifest;\n\t var manifestArray = Object.keys(manifest).\n\t map(function (key){\n\t return manifest[key];\n\t });\n\n\t // Exclude HTML\n\t var items = manifestArray.\n\t filter(function (item){\n\t if (item.type != \"application/xhtml+xml\" &&\n\t item.type != \"text/html\") {\n\t return true;\n\t }\n\t });\n\n\t // Only CSS\n\t var css = items.\n\t filter(function (item){\n\t if (item.type === \"text/css\") {\n\t return true;\n\t }\n\t });\n\n\t\t// Css Urls\n\t\tvar cssUrls = css.map(function(item) {\n\t\t\treturn item.href;\n\t\t});\n\n\t\t// All Assets Urls\n\t var urls = items.\n\t map(function(item) {\n\t return item.href;\n\t }.bind(this));\n\n\t\t// Create blob urls for all the assets\n\t var processing = urls.\n\t map(function(url) {\n\t\t\t\tvar absolute = URI(url).absoluteTo(this.book.baseUrl).toString();\n\t\t\t\t// Full url from archive base\n\t return this.book.archive.createUrl(absolute);\n\t }.bind(this));\n\n\t\t// After all the urls are created\n\t return RSVP.all(processing).\n\t then(function(replacementUrls) {\n\n\t\t\t\t// Replace Asset Urls in the text of all css files\n\t\t\t\tcssUrls.forEach(function(href) {\n\t\t\t\t\tthis.replaceCss(href, urls, replacementUrls);\n\t\t }.bind(this));\n\n\t\t\t\t// Replace Asset Urls in chapters\n\t\t\t\t// by registering a hook after the sections contents has been serialized\n\t this.hooks.serialize.register(function(output, section) {\n\t\t\t\t\tthis.replaceAssets(section, urls, replacementUrls);\n\t }.bind(this));\n\n\t }.bind(this)).catch(function(reason){\n\t console.error(reason);\n\t });\n\t}.bind(this));\n};\n\nRendition.prototype.replaceCss = function(href, urls, replacementUrls){\n\t\tvar newUrl;\n\t\tvar indexInUrls;\n\n\t\t// Find the absolute url of the css file\n\t\tvar fileUri = URI(href);\n\t\tvar absolute = fileUri.absoluteTo(this.book.baseUrl).toString();\n\t\t// Get the text of the css file from the archive\n\t\tvar text = this.book.archive.getText(absolute);\n\t\t// Get asset links relative to css file\n\t\tvar relUrls = urls.\n\t\t\tmap(function(assetHref) {\n\t\t\t\tvar assetUri = URI(assetHref).absoluteTo(this.book.baseUrl);\n\t\t\t\tvar relative = assetUri.relativeTo(absolute).toString();\n\t\t\t\treturn relative;\n\t\t\t}.bind(this));\n\n\t\t// Replacements in the css text\n\t\ttext = replace.substitute(text, relUrls, replacementUrls);\n\n\t\t// Get the new url\n\t\tnewUrl = core.createBlobUrl(text, 'text/css');\n\n\t\t// switch the url in the replacementUrls\n\t\tindexInUrls = urls.indexOf(href);\n\t\tif (indexInUrls > -1) {\n\t\t\treplacementUrls[indexInUrls] = newUrl;\n\t\t}\n};\n\nRendition.prototype.replaceAssets = function(section, urls, replacementUrls){\n\tvar fileUri = URI(section.url);\n\t// Get Urls relative to current sections\n\tvar relUrls = urls.\n\t\tmap(function(href) {\n\t\t\tvar assetUri = URI(href).absoluteTo(this.book.baseUrl);\n\t\t\tvar relative = assetUri.relativeTo(fileUri).toString();\n\t\t\treturn relative;\n\t\t}.bind(this));\n\n\n\tsection.output = replace.substitute(section.output, relUrls, replacementUrls);\n};\n\nRendition.prototype.selectCfiRange = function(_cfi, ignoreClass){\n var cfi = new EpubCFI(_cfi);\n var found = this.visible().filter(function (view) {\n\t\tif(cfi.spinePos === view.index) return true;\n\t});\n\n\t// Should only every return 1 item\n if (found.length) {\n return found[0].selectCfiRange(cfi, ignoreClass);\n }\n};\n\n//-- Enable binding events to Renderer\nRSVP.EventTarget.mixin(Rendition.prototype);\n\nmodule.exports = Rendition;\n","var URI = require('urijs');\nvar core = require('./core');\n\nfunction base(doc, section){\n var base;\n var head;\n\n if(!doc){\n return;\n }\n\n head = doc.querySelector(\"head\");\n base = head.querySelector(\"base\");\n\n if(!base) {\n base = doc.createElement(\"base\");\n }\n\n base.setAttribute(\"href\", section.url);\n head.insertBefore(base, head.firstChild);\n\n}\n\nfunction links(view, renderer) {\n\n var links = view.document.querySelectorAll(\"a[href]\");\n var replaceLinks = function(link){\n var href = link.getAttribute(\"href\");\n var linkUri = URI(href);\n var absolute = linkUri.absoluteTo(view.section.url);\n var relative = absolute.relativeTo(this.book.baseUrl).toString();\n\n if(linkUri.protocol()){\n\n link.setAttribute(\"target\", \"_blank\");\n\n }else{\n /*\n if(baseDirectory) {\n\t\t\t\t// We must ensure that the file:// protocol is preserved for\n\t\t\t\t// local file links, as in certain contexts (such as under\n\t\t\t\t// Titanium), file links without the file:// protocol will not\n\t\t\t\t// work\n\t\t\t\tif (baseUri.protocol === \"file\") {\n\t\t\t\t\trelative = core.resolveUrl(baseUri.base, href);\n\t\t\t\t} else {\n\t\t\t\t\trelative = core.resolveUrl(baseDirectory, href);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trelative = href;\n\t\t\t}\n */\n\n if(linkUri.fragment()) {\n // do nothing with fragment yet\n } else {\n link.onclick = function(){\n renderer.display(relative);\n return false;\n };\n }\n\n }\n };\n\n for (var i = 0; i < links.length; i++) {\n replaceLinks(links[i]);\n }\n\n\n};\n\nfunction substitute(content, urls, replacements) {\n urls.forEach(function(url, i){\n if (url && replacements[i]) {\n content = content.replace(new RegExp(url, 'g'), replacements[i]);\n }\n });\n return content;\n}\nmodule.exports = {\n 'base': base,\n 'links': links,\n 'substitute': substitute\n};\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\n\nfunction request(url, type, withCredentials, headers) {\n var supportsURL = (typeof window != \"undefined\") ? window.URL : false; // TODO: fallback for url if window isn't defined\n var BLOB_RESPONSE = supportsURL ? \"blob\" : \"arraybuffer\";\n var uri;\n\n var deferred = new RSVP.defer();\n\n var xhr = new XMLHttpRequest();\n\n //-- Check from PDF.js:\n // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js\n var xhrPrototype = XMLHttpRequest.prototype;\n\n var header;\n\n if (!('overrideMimeType' in xhrPrototype)) {\n // IE10 might have response, but not overrideMimeType\n Object.defineProperty(xhrPrototype, 'overrideMimeType', {\n value: function xmlHttpRequestOverrideMimeType(mimeType) {}\n });\n }\n if(withCredentials) {\n xhr.withCredentials = true;\n }\n\n xhr.onreadystatechange = handler;\n xhr.onerror = err;\n\n xhr.open(\"GET\", url, true);\n\n for(header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n\n if(type == \"json\") {\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n }\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n xhr.responseType = BLOB_RESPONSE;\n }\n\n\n if(core.isXml(type)) {\n\t\txhr.responseType = \"document\";\n\t\t// xhr.overrideMimeType('text/xml'); // for OPF parsing\n\t}\n\n\tif(type == 'xhtml') {\n\t\txhr.responseType = \"document\";\n\t}\n\n\tif(type == 'html' || type == 'htm') {\n\t\txhr.responseType = \"document\";\n \t}\n\n if(type == \"binary\") {\n xhr.responseType = \"arraybuffer\";\n }\n\n xhr.send();\n\n function err(e) {\n console.error(e);\n deferred.reject(e);\n }\n\n function handler() {\n if (this.readyState === XMLHttpRequest.DONE) {\n\n if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls\n var r;\n\n if((this.responseType == '' || this.responseType == 'document')\n && this.responseXML){\n r = this.responseXML;\n } else\n if(core.isXml(type)){\n // xhr.overrideMimeType('text/xml'); // for OPF parsing\n // If this.responseXML wasn't set, try to parse using a DOMParser from text\n r = new DOMParser().parseFromString(this.response, \"text/xml\");\n }else\n if(type == 'xhtml'){\n r = new DOMParser().parseFromString(this.response, \"application/xhtml+xml\");\n }else\n if(type == 'html' || type == 'htm'){\n r = new DOMParser().parseFromString(this.response, \"text/html\");\n }else\n if(type == 'json'){\n r = JSON.parse(this.response);\n }else\n if(type == 'blob'){\n\n if(supportsURL) {\n r = this.response;\n } else {\n //-- Safari doesn't support responseType blob, so create a blob from arraybuffer\n r = new Blob([this.response]);\n }\n\n }else{\n r = this.response;\n }\n\n deferred.resolve(r);\n } else {\n\n deferred.reject({\n status: this.status,\n message : this.response,\n stack : new Error().stack\n });\n\n }\n }\n }\n\n return deferred.promise;\n};\n\nmodule.exports = request;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\nvar replacements = require('./replacements');\n\nfunction Section(item, hooks){\n this.idref = item.idref;\n this.linear = item.linear;\n this.properties = item.properties;\n this.index = item.index;\n this.href = item.href;\n this.url = item.url;\n this.next = item.next;\n this.prev = item.prev;\n\n this.cfiBase = item.cfiBase;\n\n this.hooks = {};\n this.hooks.serialize = new Hook(this);\n this.hooks.content = new Hook(this);\n\n // Register replacements\n this.hooks.content.register(replacements.base);\n};\n\n\nSection.prototype.load = function(_request){\n var request = _request || this.request || require('./request');\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(this.contents) {\n loading.resolve(this.contents);\n } else {\n request(this.url)\n .then(function(xml){\n var base;\n var directory = URI(this.url).directory();\n\n this.document = xml;\n this.contents = xml.documentElement;\n\n return this.hooks.content.trigger(this.document, this);\n }.bind(this))\n .then(function(){\n loading.resolve(this.contents);\n }.bind(this))\n .catch(function(error){\n loading.reject(error);\n });\n }\n\n return loaded;\n};\n\nSection.prototype.base = function(_document){\n var task = new RSVP.defer();\n var base = _document.createElement(\"base\"); // TODO: check if exists\n var head;\n\n base.setAttribute(\"href\", this.url);\n\n if(_document) {\n head = _document.querySelector(\"head\");\n }\n if(head) {\n head.insertBefore(base, head.firstChild);\n task.resolve();\n } else {\n task.reject(new Error(\"No head to insert into\"));\n }\n\n\n return task.promise;\n};\n\nSection.prototype.beforeSectionLoad = function(){\n // Stub for a hook - replace me for now\n};\n\nSection.prototype.render = function(_request){\n var rendering = new RSVP.defer();\n var rendered = rendering.promise;\n this.output; // TODO: better way to return this from hooks?\n\n this.load(_request).\n then(function(contents){\n var serializer = new XMLSerializer();\n this.output = serializer.serializeToString(contents);\n return this.output;\n }.bind(this)).\n then(function(){\n return this.hooks.serialize.trigger(this.output, this);\n }.bind(this)).\n then(function(){\n rendering.resolve(this.output);\n }.bind(this))\n .catch(function(error){\n rendering.reject(error);\n });\n\n return rendered;\n};\n\nSection.prototype.find = function(_query){\n\n};\n\n/**\n* Reconciles the current chapters layout properies with\n* the global layout properities.\n* Takes: global layout settings object, chapter properties string\n* Returns: Object with layout properties\n*/\nSection.prototype.reconcileLayoutSettings = function(global){\n //-- Get the global defaults\n var settings = {\n layout : global.layout,\n spread : global.spread,\n orientation : global.orientation\n };\n\n //-- Get the chapter's display type\n this.properties.forEach(function(prop){\n var rendition = prop.replace(\"rendition:\", '');\n var split = rendition.indexOf(\"-\");\n var property, value;\n\n if(split != -1){\n property = rendition.slice(0, split);\n value = rendition.slice(split+1);\n\n settings[property] = value;\n }\n });\n return settings;\n};\n\nSection.prototype.cfiFromRange = function(_range) {\n return new EpubCFI(_range, this.cfiBase).toString();\n};\n\nSection.prototype.cfiFromElement = function(el) {\n return new EpubCFI(el, this.cfiBase).toString();\n};\n\nmodule.exports = Section;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Section = require('./section');\n\nfunction Spine(_request){\n this.request = _request;\n this.spineItems = [];\n this.spineByHref = {};\n this.spineById = {};\n\n};\n\nSpine.prototype.load = function(_package) {\n\n this.items = _package.spine;\n this.manifest = _package.manifest;\n this.spineNodeIndex = _package.spineNodeIndex;\n this.baseUrl = _package.baseUrl || '';\n this.length = this.items.length;\n this.epubcfi = new EpubCFI();\n\n this.items.forEach(function(item, index){\n var href, url;\n var manifestItem = this.manifest[item.idref];\n var spineItem;\n\n item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);\n\n if(manifestItem) {\n item.href = manifestItem.href;\n item.url = this.baseUrl + item.href;\n\n if(manifestItem.properties.length){\n item.properties.push.apply(item.properties, manifestItem.properties);\n }\n }\n\n // if(index > 0) {\n item.prev = function(){ return this.get(index-1); }.bind(this);\n // }\n\n // if(index+1 < this.items.length) {\n item.next = function(){ return this.get(index+1); }.bind(this);\n // }\n\n spineItem = new Section(item);\n this.append(spineItem);\n\n\n }.bind(this));\n\n};\n\n// book.spine.get();\n// book.spine.get(1);\n// book.spine.get(\"chap1.html\");\n// book.spine.get(\"#id1234\");\nSpine.prototype.get = function(target) {\n var index = 0;\n\n if(this.epubcfi.isCfiString(target)) {\n cfi = new EpubCFI(target);\n index = cfi.spinePos;\n } else if(target && (typeof target === \"number\" || isNaN(target) === false)){\n index = target;\n } else if(target && target.indexOf(\"#\") === 0) {\n index = this.spineById[target.substring(1)];\n } else if(target) {\n // Remove fragments\n target = target.split(\"#\")[0];\n index = this.spineByHref[target];\n }\n\n return this.spineItems[index] || null;\n};\n\nSpine.prototype.append = function(section) {\n var index = this.spineItems.length;\n section.index = index;\n\n this.spineItems.push(section);\n\n this.spineByHref[section.href] = index;\n this.spineById[section.idref] = index;\n\n return index;\n};\n\nSpine.prototype.prepend = function(section) {\n var index = this.spineItems.unshift(section);\n this.spineByHref[section.href] = 0;\n this.spineById[section.idref] = 0;\n\n // Re-index\n this.spineItems.forEach(function(item, index){\n item.index = index;\n });\n\n return 0;\n};\n\nSpine.prototype.insert = function(section, index) {\n\n};\n\nSpine.prototype.remove = function(section) {\n var index = this.spineItems.indexOf(section);\n\n if(index > -1) {\n delete this.spineByHref[section.href];\n delete this.spineById[section.idref];\n\n return this.spineItems.splice(index, 1);\n }\n};\n\nSpine.prototype.each = function() {\n\treturn this.spineItems.forEach.apply(this.spineItems, arguments);\n};\n\nmodule.exports = Spine;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar request = require('./request');\nvar mime = require('../libs/mime/mime');\n\nfunction Unarchive() {\n\n this.checkRequirements();\n this.urlCache = {};\n\n}\n\nUnarchive.prototype.checkRequirements = function(callback){\n try {\n if (typeof JSZip !== 'undefined') {\n this.zip = new JSZip();\n } else {\n JSZip = require('jszip');\n this.zip = new JSZip();\n }\n } catch (e) {\n console.error(\"JSZip lib not loaded\");\n }\n};\n\nUnarchive.prototype.open = function(zipUrl){\n\tif (zipUrl instanceof ArrayBuffer) {\n return new RSVP.Promise(function(resolve, reject) {\n this.zip = new JSZip(zipUrl);\n resolve(this.zip);\n });\n\t} else {\n\t\treturn request(zipUrl, \"binary\")\n .then(function(data){\n\t\t\t this.zip = new JSZip(data);\n return this.zip;\n\t\t }.bind(this));\n\t}\n};\n\nUnarchive.prototype.request = function(url, type){\n var deferred = new RSVP.defer();\n var response;\n var r;\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n response = this.getBlob(url);\n } else {\n response = this.getText(url);\n }\n\n if (response) {\n r = this.handleResponse(response, type);\n deferred.resolve(r);\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n return deferred.promise;\n};\n\nUnarchive.prototype.handleResponse = function(response, type){\n var r;\n\n if(type == \"json\") {\n r = JSON.parse(response);\n }\n else\n if(core.isXml(type)) {\n r = new DOMParser().parseFromString(response, \"text/xml\");\n\t}\n else\n\tif(type == 'xhtml') {\n r = new DOMParser().parseFromString(response, \"application/xhtml+xml\");\n\t}\n else\n\tif(type == 'html' || type == 'htm') {\n r = new DOMParser().parseFromString(response, \"text/html\");\n \t} else {\n \t r = response;\n \t}\n\n return r;\n};\n\nUnarchive.prototype.getBlob = function(url, _mimeType){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n var mimeType;\n\n\tif(entry) {\n mimeType = _mimeType || mime.lookup(entry.name);\n return new Blob([entry.asUint8Array()], {type : mimeType});\n\t}\n};\n\nUnarchive.prototype.getText = function(url, encoding){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n\n\tif(entry) {\n return entry.asText();\n\t}\n};\n\nUnarchive.prototype.createUrl = function(url, mime){\n\tvar deferred = new RSVP.defer();\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob;\n\n\tif(url in this.urlCache) {\n\t\tdeferred.resolve(this.urlCache[url]);\n\t\treturn deferred.promise;\n\t}\n\n\tblob = this.getBlob(url);\n\n if (blob) {\n tempUrl = _URL.createObjectURL(blob);\n deferred.resolve(tempUrl);\n this.urlCache[url] = tempUrl;\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n\n\treturn deferred.promise;\n};\n\nUnarchive.prototype.revokeUrl = function(url){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar fromCache = this.urlCache[url];\n\tif(fromCache) _URL.revokeObjectURL(fromCache);\n};\n\nmodule.exports = Unarchive;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction View(section, options) {\n this.settings = core.extend({\n ignoreClass : ''\n }, options || {});\n\n this.id = \"epubjs-view:\" + core.uuid();\n this.section = section;\n this.index = section.index;\n\n this.element = document.createElement('div');\n this.element.classList.add(\"epub-view\");\n\n\n // this.element.style.minHeight = \"100px\";\n this.element.style.height = \"0px\";\n this.element.style.width = \"0px\";\n this.element.style.overflow = \"hidden\";\n\n this.added = false;\n this.displayed = false;\n this.rendered = false;\n\n //this.width = 0;\n //this.height = 0;\n\n // Blank Cfi for Parsing\n this.epubcfi = new EpubCFI();\n\n if(this.settings.axis && this.settings.axis == \"horizontal\"){\n this.element.style.display = \"inline-block\";\n } else {\n this.element.style.display = \"block\";\n }\n\n // Dom events to listen for\n this.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n\n};\n\nView.prototype.create = function() {\n\n if(this.iframe) {\n return this.iframe;\n }\n\n this.iframe = document.createElement('iframe');\n this.iframe.id = this.id;\n this.iframe.scrolling = \"no\"; // Might need to be removed: breaks ios width calculations\n this.iframe.style.overflow = \"hidden\";\n this.iframe.seamless = \"seamless\";\n // Back up if seamless isn't supported\n this.iframe.style.border = \"none\";\n\n this.resizing = true;\n\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.iframe.style.width = \"0\";\n this.iframe.style.height = \"0\";\n this._width = 0;\n this._height = 0;\n\n this.element.appendChild(this.iframe);\n this.added = true;\n\n this.elementBounds = core.bounds(this.element);\n\n // if(width || height){\n // this.resize(width, height);\n // } else if(this.width && this.height){\n // this.resize(this.width, this.height);\n // } else {\n // this.iframeBounds = core.bounds(this.iframe);\n // }\n\n // Firefox has trouble with baseURI and srcdoc\n // Disabled for now\n /*\n if(!!(\"srcdoc\" in this.iframe)) {\n this.supportsSrcdoc = true;\n } else {\n this.supportsSrcdoc = false;\n }\n */\n this.supportsSrcdoc = false;\n\n return this.iframe;\n};\n\n\nView.prototype.lock = function(what, width, height) {\n\n var elBorders = core.borders(this.element);\n var iframeBorders;\n\n if(this.iframe) {\n iframeBorders = core.borders(this.iframe);\n } else {\n iframeBorders = {width: 0, height: 0};\n }\n\n if(what == \"width\" && core.isNumber(width)){\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.resize(this.lockedWidth, width); // width keeps ratio correct\n }\n\n if(what == \"height\" && core.isNumber(height)){\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n this.resize(width, this.lockedHeight);\n }\n\n if(what === \"both\" &&\n core.isNumber(width) &&\n core.isNumber(height)){\n\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n\n this.resize(this.lockedWidth, this.lockedHeight);\n }\n\n if(this.displayed && this.iframe) {\n\n this.layout();\n this.expand();\n\n }\n\n\n\n};\n\nView.prototype.expand = function(force) {\n var width = this.lockedWidth;\n var height = this.lockedHeight;\n\n var textWidth, textHeight;\n // console.log(\"expanding a\")\n if(!this.iframe || this._expanding) return;\n\n this._expanding = true;\n\n // Expand Horizontally\n if(height && !width) {\n // Get the width of the text\n textWidth = this.textWidth();\n // Check if the textWidth has changed\n if(textWidth != this._textWidth){\n // Get the contentWidth by resizing the iframe\n // Check with a min reset of the textWidth\n width = this.contentWidth(textWidth);\n // Save the textWdith\n this._textWidth = textWidth;\n // Save the contentWidth\n this._contentWidth = width;\n } else {\n // Otherwise assume content height hasn't changed\n width = this._contentWidth;\n }\n }\n\n // Expand Vertically\n if(width && !height) {\n textHeight = this.textHeight();\n if(textHeight != this._textHeight){\n height = this.contentHeight(textHeight);\n this._textHeight = textHeight;\n this._contentHeight = height;\n } else {\n height = this._contentHeight;\n }\n }\n\n // Only Resize if dimensions have changed or\n // if Frame is still hidden, so needs reframing\n if(this._needsReframe || width != this._width || height != this._height){\n this.resize(width, height);\n }\n\n this._expanding = false;\n};\n\nView.prototype.contentWidth = function(min) {\n var prev;\n var width;\n\n // Save previous width\n prev = this.iframe.style.width;\n // Set the iframe size to min, width will only ever be greater\n // Will preserve the aspect ratio\n this.iframe.style.width = (min || 0) + \"px\";\n // Get the scroll overflow width\n width = this.document.body.scrollWidth;\n // Reset iframe size back\n this.iframe.style.width = prev;\n return width;\n};\n\nView.prototype.contentHeight = function(min) {\n var prev;\n var height;\n\n prev = this.iframe.style.height;\n this.iframe.style.height = (min || 0) + \"px\";\n height = this.document.body.scrollHeight;\n this.iframe.style.height = prev;\n return height;\n};\n\nView.prototype.textWidth = function() {\n var width;\n var range = this.document.createRange();\n\n // Select the contents of frame\n range.selectNodeContents(this.document.body);\n\n // get the width of the text content\n width = range.getBoundingClientRect().width;\n return width;\n\n};\n\nView.prototype.textHeight = function() {\n var height;\n var range = this.document.createRange();\n\n range.selectNodeContents(this.document.body);\n\n height = range.getBoundingClientRect().height;\n return height;\n};\n\nView.prototype.resize = function(width, height) {\n\n if(!this.iframe) return;\n\n if(core.isNumber(width)){\n this.iframe.style.width = width + \"px\";\n this._width = width;\n }\n\n if(core.isNumber(height)){\n this.iframe.style.height = height + \"px\";\n this._height = height;\n }\n\n this.iframeBounds = core.bounds(this.iframe);\n\n this.reframe(this.iframeBounds.width, this.iframeBounds.height);\n\n};\n\nView.prototype.reframe = function(width, height) {\n //var prevBounds;\n\n if(!this.displayed) {\n this._needsReframe = true;\n return;\n }\n\n if(core.isNumber(width)){\n this.element.style.width = width + \"px\";\n }\n\n if(core.isNumber(height)){\n this.element.style.height = height + \"px\";\n }\n\n this.prevBounds = this.elementBounds;\n\n this.elementBounds = core.bounds(this.element);\n\n this.trigger(\"resized\", {\n width: this.elementBounds.width,\n height: this.elementBounds.height,\n widthDelta: this.elementBounds.width - this.prevBounds.width,\n heightDelta: this.elementBounds.height - this.prevBounds.height,\n });\n\n};\n\nView.prototype.resized = function(e) {\n /*\n if (!this.resizing) {\n if(this.iframe) {\n // this.expand();\n }\n } else {\n this.resizing = false;\n }*/\n\n};\n\nView.prototype.render = function(_request) {\n\n // if(this.rendering){\n // return this.displayed;\n // }\n\n this.rendering = true;\n // this.displayingDefer = new RSVP.defer();\n // this.displayedPromise = this.displaying.promise;\n\n return this.section.render(_request)\n .then(function(contents){\n return this.load(contents);\n }.bind(this));\n};\n\nView.prototype.load = function(contents) {\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(!this.iframe) {\n loading.reject(new Error(\"No Iframe Available\"));\n return loaded;\n }\n\n this.iframe.onload = function(event) {\n\n this.window = this.iframe.contentWindow;\n this.document = this.iframe.contentDocument;\n this.rendering = false;\n loading.resolve(this);\n\n }.bind(this);\n\n if(this.supportsSrcdoc){\n this.iframe.srcdoc = contents;\n } else {\n\n this.document = this.iframe.contentDocument;\n\n if(!this.document) {\n loading.reject(new Error(\"No Document Available\"));\n return loaded;\n }\n\n this.document.open();\n this.document.write(contents);\n this.document.close();\n\n }\n\n return loaded;\n};\n\n\nView.prototype.layout = function(layoutFunc) {\n\n this.iframe.style.display = \"inline-block\";\n\n // Reset Body Styles\n this.document.body.style.margin = \"0\";\n //this.document.body.style.display = \"inline-block\";\n //this.document.documentElement.style.width = \"auto\";\n\n if(layoutFunc){\n layoutFunc(this);\n }\n\n this.onLayout(this);\n\n};\n\nView.prototype.onLayout = function(view) {\n // stub\n};\n\nView.prototype.listeners = function() {\n /*\n setTimeout(function(){\n this.window.addEventListener(\"resize\", this.resized.bind(this), false);\n }.bind(this), 10); // Wait to listen for resize events\n */\n\n // Wait for fonts to load to finish\n // http://dev.w3.org/csswg/css-font-loading/\n // Not implemented fully except in chrome\n\n if(this.document.fonts && this.document.fonts.status === \"loading\") {\n // console.log(\"fonts unloaded\");\n this.document.fonts.onloadingdone = function(){\n // console.log(\"loaded fonts\");\n this.expand();\n }.bind(this);\n }\n\n if(this.section.properties.indexOf(\"scripted\") > -1){\n this.observer = this.observe(this.document.body);\n }\n\n this.imageLoadListeners();\n\n this.mediaQueryListeners();\n\n // this.resizeListenters();\n\n this.addEventListeners();\n\n this.addSelectionListeners();\n};\n\nView.prototype.removeListeners = function() {\n\n this.removeEventListeners();\n\n this.removeSelectionListeners();\n};\n\nView.prototype.resizeListenters = function() {\n // Test size again\n clearTimeout(this.expanding);\n this.expanding = setTimeout(this.expand.bind(this), 350);\n};\n\n//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js\nView.prototype.mediaQueryListeners = function() {\n var sheets = this.document.styleSheets;\n var mediaChangeHandler = function(m){\n if(m.matches && !this._expanding) {\n setTimeout(this.expand.bind(this), 1);\n // this.expand();\n }\n }.bind(this);\n\n for (var i = 0; i < sheets.length; i += 1) {\n var rules = sheets[i].cssRules;\n if(!rules) return; // Stylesheets changed\n for (var j = 0; j < rules.length; j += 1) {\n //if (rules[j].constructor === CSSMediaRule) {\n if(rules[j].media){\n var mql = this.window.matchMedia(rules[j].media.mediaText);\n mql.addListener(mediaChangeHandler);\n //mql.onchange = mediaChangeHandler;\n }\n }\n }\n};\n\nView.prototype.observe = function(target) {\n var renderer = this;\n\n // create an observer instance\n var observer = new MutationObserver(function(mutations) {\n if(renderer._expanding) {\n renderer.expand();\n }\n // mutations.forEach(function(mutation) {\n // console.log(mutation);\n // });\n });\n\n // configuration of the observer:\n var config = { attributes: true, childList: true, characterData: true, subtree: true };\n\n // pass in the target node, as well as the observer options\n observer.observe(target, config);\n\n return observer;\n};\n\n// View.prototype.appendTo = function(element) {\n// this.element = element;\n// this.element.appendChild(this.iframe);\n// };\n//\n// View.prototype.prependTo = function(element) {\n// this.element = element;\n// element.insertBefore(this.iframe, element.firstChild);\n// };\n\nView.prototype.imageLoadListeners = function(target) {\n var images = this.document.body.querySelectorAll(\"img\");\n var img;\n for (var i = 0; i < images.length; i++) {\n img = images[i];\n\n if (typeof img.naturalWidth !== \"undefined\" &&\n img.naturalWidth === 0) {\n img.onload = this.expand.bind(this);\n }\n }\n};\n\nView.prototype.display = function() {\n var displayed = new RSVP.defer();\n\n this.displayed = true;\n\n this.layout();\n\n this.listeners();\n\n this.expand();\n\n this.trigger(\"displayed\", this);\n this.onDisplayed(this);\n\n displayed.resolve(this);\n\n return displayed.promise;\n};\n\nView.prototype.show = function() {\n\n this.element.style.visibility = \"visible\";\n\n if(this.iframe){\n this.iframe.style.visibility = \"visible\";\n }\n\n this.trigger(\"shown\", this);\n};\n\nView.prototype.hide = function() {\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.stopExpanding = true;\n this.trigger(\"hidden\", this);\n};\n\nView.prototype.position = function() {\n return this.element.getBoundingClientRect();\n};\n\nView.prototype.onDisplayed = function(view) {\n // Stub, override with a custom functions\n};\n\nView.prototype.bounds = function() {\n if(!this.elementBounds) {\n this.elementBounds = core.bounds(this.element);\n }\n return this.elementBounds;\n};\n\nView.prototype.destroy = function() {\n // Stop observing\n if(this.observer) {\n this.observer.disconnect();\n }\n\n if(this.displayed){\n this.removeListeners();\n\n this.stopExpanding = true;\n this.element.removeChild(this.iframe);\n this.displayed = false;\n this.iframe = null;\n\n this._textWidth = null;\n this._textHeight = null;\n this._width = null;\n this._height = null;\n }\n // this.element.style.height = \"0px\";\n // this.element.style.width = \"0px\";\n};\n\nView.prototype.root = function() {\n if(!this.document) return null;\n return this.document.documentElement;\n};\n\nView.prototype.locationOf = function(target) {\n var parentPos = this.iframe.getBoundingClientRect();\n var targetPos = {\"left\": 0, \"top\": 0};\n\n if(!this.document) return;\n\n if(this.epubcfi.isCfiString(target)) {\n range = new EpubCFI(cfi).toRange(this.document, this.settings.ignoreClass);\n if(range) {\n targetPos = range.getBoundingClientRect();\n }\n\n } else if(typeof target === \"string\" &&\n target.indexOf(\"#\") > -1) {\n\n id = target.substring(target.indexOf(\"#\")+1);\n el = this.document.getElementById(id);\n\n if(el) {\n targetPos = el.getBoundingClientRect();\n }\n }\n\n return {\n \"left\": window.scrollX + parentPos.left + targetPos.left,\n \"top\": window.scrollY + parentPos.top + targetPos.top\n };\n};\n\nView.prototype.addCss = function(src) {\n return new RSVP.Promise(function(resolve, reject){\n var $stylesheet;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $stylesheet = this.document.createElement('link');\n $stylesheet.type = 'text/css';\n $stylesheet.rel = \"stylesheet\";\n $stylesheet.href = src;\n $stylesheet.onload = $stylesheet.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n // Let apply\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($stylesheet);\n\n }.bind(this));\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule\nView.prototype.addStylesheetRules = function(rules) {\n var styleEl;\n var styleSheet;\n\n if(!this.document) return;\n\n styleEl = this.document.createElement('style');\n\n // Append style element to head\n this.document.head.appendChild(styleEl);\n\n // Grab style sheet\n styleSheet = styleEl.sheet;\n\n for (var i = 0, rl = rules.length; i < rl; i++) {\n var j = 1, rule = rules[i], selector = rules[i][0], propStr = '';\n // If the second argument of a rule is an array of arrays, correct our variables.\n if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {\n rule = rule[1];\n j = 0;\n }\n\n for (var pl = rule.length; j < pl; j++) {\n var prop = rule[j];\n propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\\n';\n }\n\n // Insert CSS Rule\n styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);\n }\n};\n\nView.prototype.addScript = function(src) {\n\n return new RSVP.Promise(function(resolve, reject){\n var $script;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $script = this.document.createElement('script');\n $script.type = 'text/javascript';\n $script.async = true;\n $script.src = src;\n $script.onload = $script.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($script);\n\n }.bind(this));\n};\n\nView.prototype.addEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);\n }, this);\n\n};\n\nView.prototype.removeEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.removeEventListener(eventName, this.triggerEvent, false);\n }, this);\n\n};\n\n// Pass browser events\nView.prototype.triggerEvent = function(e){\n this.trigger(e.type, e);\n};\n\nView.prototype.addSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.addEventListener(\"selectionchange\", this.onSelectionChange.bind(this), false);\n};\n\nView.prototype.removeSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.removeEventListener(\"selectionchange\", this.onSelectionChange, false);\n};\n\nView.prototype.onSelectionChange = function(e){\n if (this.selectionEndTimeout) {\n clearTimeout(this.selectionEndTimeout);\n }\n this.selectionEndTimeout = setTimeout(function() {\n var selection = this.window.getSelection();\n this.triggerSelectedEvent(selection);\n }.bind(this), 500);\n};\n\nView.prototype.triggerSelectedEvent = function(selection){\n\tvar range, cfirange;\n\n if (selection && selection.rangeCount > 0) {\n range = selection.getRangeAt(0);\n if(!range.collapsed) {\n cfirange = this.section.cfiFromRange(range);\n this.trigger(\"selected\", cfirange);\n this.trigger(\"selectedRange\", range);\n }\n }\n};\n\nView.prototype.selectCfiRange = function(_cfi, ignoreClass){\n var cfi = new EpubCFI(_cfi);\n return cfi.toRange(this.document, ignoreClass || this.settings.ignoreClass);\n};\n\nRSVP.EventTarget.mixin(View.prototype);\n\nmodule.exports = View;\n","function Views(container) {\n this.container = container;\n this._views = [];\n this.length = 0;\n this.hidden = false;\n};\n\nViews.prototype.first = function() {\n\treturn this._views[0];\n};\n\nViews.prototype.last = function() {\n\treturn this._views[this._views.length-1];\n};\n\nViews.prototype.each = function() {\n\treturn this._views.forEach.apply(this._views, arguments);\n};\n\nViews.prototype.indexOf = function(view) {\n\treturn this._views.indexOf(view);\n};\n\nViews.prototype.slice = function() {\n\treturn this._views.slice.apply(this._views, arguments);\n};\n\nViews.prototype.get = function(i) {\n\treturn this._views[i];\n};\n\nViews.prototype.append = function(view){\n\tthis._views.push(view);\n\tthis.container.appendChild(view.element);\n this.length++;\n return view;\n};\n\nViews.prototype.prepend = function(view){\n\tthis._views.unshift(view);\n\tthis.container.insertBefore(view.element, this.container.firstChild);\n this.length++;\n return view;\n};\n\nViews.prototype.insert = function(view, index) {\n\tthis._views.splice(index, 0, view);\n\n\tif(index < this.container.children.length){\n\t\tthis.container.insertBefore(view.element, this.container.children[index]);\n\t} else {\n\t\tthis.container.appendChild(view.element);\n\t}\n this.length++;\n return view;\n};\n\nViews.prototype.remove = function(view) {\n\tvar index = this._views.indexOf(view);\n\n\tif(index > -1) {\n\t\tthis._views.splice(index, 1);\n\t}\n\n\n\tthis.destroy(view);\n\n this.length--;\n};\n\nViews.prototype.destroy = function(view) {\n\tview.off(\"resized\");\n\n\tif(view.displayed){\n\t\tview.destroy();\n\t}\n\n\tthis.container.removeChild(view.element);\n\tview = null;\n};\n\n// Iterators\n\nViews.prototype.clear = function(){\n\t// Remove all views\n var view;\n var len = this.length;\n\n if(!this.length) return;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tthis.destroy(view);\n }\n\n this._views = [];\n this.length = 0;\n};\n\nViews.prototype.find = function(section){\n\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tif(view.displayed && view.section.index == section.index) {\n\t\t\treturn view;\n\t\t}\n }\n\n};\n\nViews.prototype.displayed = function(){\n var displayed = [];\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n displayed.push(view);\n }\n }\n return displayed;\n};\n\nViews.prototype.show = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.show();\n }\n }\n this.hidden = false;\n};\n\nViews.prototype.hide = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.hide();\n }\n }\n this.hidden = true;\n};\n\nmodule.exports = Views;\n","var Book = require('./book');\nvar EpubCFI = require('./epubcfi');\n\nfunction ePub(_url) {\n\treturn new Book(_url);\n};\n\nePub.VERSION = \"0.3.0\";\n\nePub.CFI = EpubCFI;\n\nmodule.exports = ePub;\n"]} \ No newline at end of file +{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","libs/mime/mime.js","node_modules/browserify/lib/_empty.js","node_modules/browserify/node_modules/process/browser.js","node_modules/rsvp/dist/rsvp.js","node_modules/urijs/src/SecondLevelDomains.js","node_modules/urijs/src/URI.js","src/book.js","src/continuous.js","src/core.js","src/epubcfi.js","src/hook.js","src/layout.js","src/locations.js","src/map.js","src/navigation.js","src/paginate.js","src/parser.js","src/queue.js","src/rendition.js","src/replacements.js","src/request.js","src/section.js","src/spine.js","src/unarchive.js","src/view.js","src/views.js","src/epub.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3KA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7jDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACt6BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9cA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnwBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3vBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"epub.js","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n setTimeout(drainQueue, 0);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n","/*!\n * @overview RSVP - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors\n * @license Licensed under MIT license\n * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE\n * @version 3.1.0\n */\n\n(function() {\n \"use strict\";\n function lib$rsvp$utils$$objectOrFunction(x) {\n return typeof x === 'function' || (typeof x === 'object' && x !== null);\n }\n\n function lib$rsvp$utils$$isFunction(x) {\n return typeof x === 'function';\n }\n\n function lib$rsvp$utils$$isMaybeThenable(x) {\n return typeof x === 'object' && x !== null;\n }\n\n var lib$rsvp$utils$$_isArray;\n if (!Array.isArray) {\n lib$rsvp$utils$$_isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n } else {\n lib$rsvp$utils$$_isArray = Array.isArray;\n }\n\n var lib$rsvp$utils$$isArray = lib$rsvp$utils$$_isArray;\n\n var lib$rsvp$utils$$now = Date.now || function() { return new Date().getTime(); };\n\n function lib$rsvp$utils$$F() { }\n\n var lib$rsvp$utils$$o_create = (Object.create || function (o) {\n if (arguments.length > 1) {\n throw new Error('Second argument not supported');\n }\n if (typeof o !== 'object') {\n throw new TypeError('Argument must be an object');\n }\n lib$rsvp$utils$$F.prototype = o;\n return new lib$rsvp$utils$$F();\n });\n function lib$rsvp$events$$indexOf(callbacks, callback) {\n for (var i=0, l=callbacks.length; i 0.5) {\n throw new Error();\n }\n return new Author();\n }\n\n try {\n return findAuthor(); // succeed or fail\n } catch(error) {\n return findOtherAuther();\n } finally {\n // always runs\n // doesn't affect the return value\n }\n ```\n\n Asynchronous example:\n\n ```js\n findAuthor().catch(function(reason){\n return findOtherAuther();\n }).finally(function(){\n // author was either found, or not\n });\n ```\n\n @method finally\n @param {Function} callback\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise}\n */\n 'finally': function(callback, label) {\n var promise = this;\n var constructor = promise.constructor;\n\n return promise.then(function(value) {\n return constructor.resolve(callback()).then(function(){\n return value;\n });\n }, function(reason) {\n return constructor.resolve(callback()).then(function(){\n throw reason;\n });\n }, label);\n }\n };\n\n function lib$rsvp$all$settled$$AllSettled(Constructor, entries, label) {\n this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);\n }\n\n lib$rsvp$all$settled$$AllSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$all$settled$$AllSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$all$settled$$AllSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n lib$rsvp$all$settled$$AllSettled.prototype._validationError = function() {\n return new Error('allSettled must be called with an array');\n };\n\n function lib$rsvp$all$settled$$allSettled(entries, label) {\n return new lib$rsvp$all$settled$$AllSettled(lib$rsvp$promise$$default, entries, label).promise;\n }\n var lib$rsvp$all$settled$$default = lib$rsvp$all$settled$$allSettled;\n function lib$rsvp$all$$all(array, label) {\n return lib$rsvp$promise$$default.all(array, label);\n }\n var lib$rsvp$all$$default = lib$rsvp$all$$all;\n var lib$rsvp$asap$$len = 0;\n var lib$rsvp$asap$$toString = {}.toString;\n var lib$rsvp$asap$$vertxNext;\n function lib$rsvp$asap$$asap(callback, arg) {\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len] = callback;\n lib$rsvp$asap$$queue[lib$rsvp$asap$$len + 1] = arg;\n lib$rsvp$asap$$len += 2;\n if (lib$rsvp$asap$$len === 2) {\n // If len is 1, that means that we need to schedule an async flush.\n // If additional callbacks are queued before the queue is flushed, they\n // will be processed by this flush that we are scheduling.\n lib$rsvp$asap$$scheduleFlush();\n }\n }\n\n var lib$rsvp$asap$$default = lib$rsvp$asap$$asap;\n\n var lib$rsvp$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;\n var lib$rsvp$asap$$browserGlobal = lib$rsvp$asap$$browserWindow || {};\n var lib$rsvp$asap$$BrowserMutationObserver = lib$rsvp$asap$$browserGlobal.MutationObserver || lib$rsvp$asap$$browserGlobal.WebKitMutationObserver;\n var lib$rsvp$asap$$isNode = typeof self === 'undefined' &&\n typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';\n\n // test for web worker but not in IE10\n var lib$rsvp$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&\n typeof importScripts !== 'undefined' &&\n typeof MessageChannel !== 'undefined';\n\n // node\n function lib$rsvp$asap$$useNextTick() {\n var nextTick = process.nextTick;\n // node version 0.10.x displays a deprecation warning when nextTick is used recursively\n // setImmediate should be used instead instead\n var version = process.versions.node.match(/^(?:(\\d+)\\.)?(?:(\\d+)\\.)?(\\*|\\d+)$/);\n if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {\n nextTick = setImmediate;\n }\n return function() {\n nextTick(lib$rsvp$asap$$flush);\n };\n }\n\n // vertx\n function lib$rsvp$asap$$useVertxTimer() {\n return function() {\n lib$rsvp$asap$$vertxNext(lib$rsvp$asap$$flush);\n };\n }\n\n function lib$rsvp$asap$$useMutationObserver() {\n var iterations = 0;\n var observer = new lib$rsvp$asap$$BrowserMutationObserver(lib$rsvp$asap$$flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function() {\n node.data = (iterations = ++iterations % 2);\n };\n }\n\n // web worker\n function lib$rsvp$asap$$useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = lib$rsvp$asap$$flush;\n return function () {\n channel.port2.postMessage(0);\n };\n }\n\n function lib$rsvp$asap$$useSetTimeout() {\n return function() {\n setTimeout(lib$rsvp$asap$$flush, 1);\n };\n }\n\n var lib$rsvp$asap$$queue = new Array(1000);\n function lib$rsvp$asap$$flush() {\n for (var i = 0; i < lib$rsvp$asap$$len; i+=2) {\n var callback = lib$rsvp$asap$$queue[i];\n var arg = lib$rsvp$asap$$queue[i+1];\n\n callback(arg);\n\n lib$rsvp$asap$$queue[i] = undefined;\n lib$rsvp$asap$$queue[i+1] = undefined;\n }\n\n lib$rsvp$asap$$len = 0;\n }\n\n function lib$rsvp$asap$$attemptVertex() {\n try {\n var r = require;\n var vertx = r('vertx');\n lib$rsvp$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return lib$rsvp$asap$$useVertxTimer();\n } catch(e) {\n return lib$rsvp$asap$$useSetTimeout();\n }\n }\n\n var lib$rsvp$asap$$scheduleFlush;\n // Decide what async method to use to triggering processing of queued callbacks:\n if (lib$rsvp$asap$$isNode) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useNextTick();\n } else if (lib$rsvp$asap$$BrowserMutationObserver) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMutationObserver();\n } else if (lib$rsvp$asap$$isWorker) {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useMessageChannel();\n } else if (lib$rsvp$asap$$browserWindow === undefined && typeof require === 'function') {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$attemptVertex();\n } else {\n lib$rsvp$asap$$scheduleFlush = lib$rsvp$asap$$useSetTimeout();\n }\n function lib$rsvp$defer$$defer(label) {\n var deferred = {};\n\n deferred['promise'] = new lib$rsvp$promise$$default(function(resolve, reject) {\n deferred['resolve'] = resolve;\n deferred['reject'] = reject;\n }, label);\n\n return deferred;\n }\n var lib$rsvp$defer$$default = lib$rsvp$defer$$defer;\n function lib$rsvp$filter$$filter(promises, filterFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(filterFn)) {\n throw new TypeError(\"You must pass a function as filter's second argument.\");\n }\n\n var length = values.length;\n var filtered = new Array(length);\n\n for (var i = 0; i < length; i++) {\n filtered[i] = filterFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(filtered, label).then(function(filtered) {\n var results = new Array(length);\n var newLength = 0;\n\n for (var i = 0; i < length; i++) {\n if (filtered[i]) {\n results[newLength] = values[i];\n newLength++;\n }\n }\n\n results.length = newLength;\n\n return results;\n });\n });\n }\n var lib$rsvp$filter$$default = lib$rsvp$filter$$filter;\n\n function lib$rsvp$promise$hash$$PromiseHash(Constructor, object, label) {\n this._superConstructor(Constructor, object, true, label);\n }\n\n var lib$rsvp$promise$hash$$default = lib$rsvp$promise$hash$$PromiseHash;\n\n lib$rsvp$promise$hash$$PromiseHash.prototype = lib$rsvp$utils$$o_create(lib$rsvp$enumerator$$default.prototype);\n lib$rsvp$promise$hash$$PromiseHash.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$promise$hash$$PromiseHash.prototype._init = function() {\n this._result = {};\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validateInput = function(input) {\n return input && typeof input === 'object';\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._validationError = function() {\n return new Error('Promise.hash must be called with an object');\n };\n\n lib$rsvp$promise$hash$$PromiseHash.prototype._enumerate = function() {\n var enumerator = this;\n var promise = enumerator.promise;\n var input = enumerator._input;\n var results = [];\n\n for (var key in input) {\n if (promise._state === lib$rsvp$$internal$$PENDING && Object.prototype.hasOwnProperty.call(input, key)) {\n results.push({\n position: key,\n entry: input[key]\n });\n }\n }\n\n var length = results.length;\n enumerator._remaining = length;\n var result;\n\n for (var i = 0; promise._state === lib$rsvp$$internal$$PENDING && i < length; i++) {\n result = results[i];\n enumerator._eachEntry(result.entry, result.position);\n }\n };\n\n function lib$rsvp$hash$settled$$HashSettled(Constructor, object, label) {\n this._superConstructor(Constructor, object, false, label);\n }\n\n lib$rsvp$hash$settled$$HashSettled.prototype = lib$rsvp$utils$$o_create(lib$rsvp$promise$hash$$default.prototype);\n lib$rsvp$hash$settled$$HashSettled.prototype._superConstructor = lib$rsvp$enumerator$$default;\n lib$rsvp$hash$settled$$HashSettled.prototype._makeResult = lib$rsvp$enumerator$$makeSettledResult;\n\n lib$rsvp$hash$settled$$HashSettled.prototype._validationError = function() {\n return new Error('hashSettled must be called with an object');\n };\n\n function lib$rsvp$hash$settled$$hashSettled(object, label) {\n return new lib$rsvp$hash$settled$$HashSettled(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$settled$$default = lib$rsvp$hash$settled$$hashSettled;\n function lib$rsvp$hash$$hash(object, label) {\n return new lib$rsvp$promise$hash$$default(lib$rsvp$promise$$default, object, label).promise;\n }\n var lib$rsvp$hash$$default = lib$rsvp$hash$$hash;\n function lib$rsvp$map$$map(promises, mapFn, label) {\n return lib$rsvp$promise$$default.all(promises, label).then(function(values) {\n if (!lib$rsvp$utils$$isFunction(mapFn)) {\n throw new TypeError(\"You must pass a function as map's second argument.\");\n }\n\n var length = values.length;\n var results = new Array(length);\n\n for (var i = 0; i < length; i++) {\n results[i] = mapFn(values[i]);\n }\n\n return lib$rsvp$promise$$default.all(results, label);\n });\n }\n var lib$rsvp$map$$default = lib$rsvp$map$$map;\n\n function lib$rsvp$node$$Result() {\n this.value = undefined;\n }\n\n var lib$rsvp$node$$ERROR = new lib$rsvp$node$$Result();\n var lib$rsvp$node$$GET_THEN_ERROR = new lib$rsvp$node$$Result();\n\n function lib$rsvp$node$$getThen(obj) {\n try {\n return obj.then;\n } catch(error) {\n lib$rsvp$node$$ERROR.value= error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n\n function lib$rsvp$node$$tryApply(f, s, a) {\n try {\n f.apply(s, a);\n } catch(error) {\n lib$rsvp$node$$ERROR.value = error;\n return lib$rsvp$node$$ERROR;\n }\n }\n\n function lib$rsvp$node$$makeObject(_, argumentNames) {\n var obj = {};\n var name;\n var i;\n var length = _.length;\n var args = new Array(length);\n\n for (var x = 0; x < length; x++) {\n args[x] = _[x];\n }\n\n for (i = 0; i < argumentNames.length; i++) {\n name = argumentNames[i];\n obj[name] = args[i + 1];\n }\n\n return obj;\n }\n\n function lib$rsvp$node$$arrayResult(_) {\n var length = _.length;\n var args = new Array(length - 1);\n\n for (var i = 1; i < length; i++) {\n args[i - 1] = _[i];\n }\n\n return args;\n }\n\n function lib$rsvp$node$$wrapThenable(then, promise) {\n return {\n then: function(onFulFillment, onRejection) {\n return then.call(promise, onFulFillment, onRejection);\n }\n };\n }\n\n function lib$rsvp$node$$denodeify(nodeFunc, options) {\n var fn = function() {\n var self = this;\n var l = arguments.length;\n var args = new Array(l + 1);\n var arg;\n var promiseInput = false;\n\n for (var i = 0; i < l; ++i) {\n arg = arguments[i];\n\n if (!promiseInput) {\n // TODO: clean this up\n promiseInput = lib$rsvp$node$$needsPromiseInput(arg);\n if (promiseInput === lib$rsvp$node$$GET_THEN_ERROR) {\n var p = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n lib$rsvp$$internal$$reject(p, lib$rsvp$node$$GET_THEN_ERROR.value);\n return p;\n } else if (promiseInput && promiseInput !== true) {\n arg = lib$rsvp$node$$wrapThenable(promiseInput, arg);\n }\n }\n args[i] = arg;\n }\n\n var promise = new lib$rsvp$promise$$default(lib$rsvp$$internal$$noop);\n\n args[l] = function(err, val) {\n if (err)\n lib$rsvp$$internal$$reject(promise, err);\n else if (options === undefined)\n lib$rsvp$$internal$$resolve(promise, val);\n else if (options === true)\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$arrayResult(arguments));\n else if (lib$rsvp$utils$$isArray(options))\n lib$rsvp$$internal$$resolve(promise, lib$rsvp$node$$makeObject(arguments, options));\n else\n lib$rsvp$$internal$$resolve(promise, val);\n };\n\n if (promiseInput) {\n return lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self);\n } else {\n return lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self);\n }\n };\n\n fn.__proto__ = nodeFunc;\n\n return fn;\n }\n\n var lib$rsvp$node$$default = lib$rsvp$node$$denodeify;\n\n function lib$rsvp$node$$handleValueInput(promise, args, nodeFunc, self) {\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n }\n\n function lib$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self){\n return lib$rsvp$promise$$default.all(args).then(function(args){\n var result = lib$rsvp$node$$tryApply(nodeFunc, self, args);\n if (result === lib$rsvp$node$$ERROR) {\n lib$rsvp$$internal$$reject(promise, result.value);\n }\n return promise;\n });\n }\n\n function lib$rsvp$node$$needsPromiseInput(arg) {\n if (arg && typeof arg === 'object') {\n if (arg.constructor === lib$rsvp$promise$$default) {\n return true;\n } else {\n return lib$rsvp$node$$getThen(arg);\n }\n } else {\n return false;\n }\n }\n var lib$rsvp$platform$$platform;\n\n /* global self */\n if (typeof self === 'object') {\n lib$rsvp$platform$$platform = self;\n\n /* global global */\n } else if (typeof global === 'object') {\n lib$rsvp$platform$$platform = global;\n } else {\n throw new Error('no global: `self` or `global` found');\n }\n\n var lib$rsvp$platform$$default = lib$rsvp$platform$$platform;\n function lib$rsvp$race$$race(array, label) {\n return lib$rsvp$promise$$default.race(array, label);\n }\n var lib$rsvp$race$$default = lib$rsvp$race$$race;\n function lib$rsvp$reject$$reject(reason, label) {\n return lib$rsvp$promise$$default.reject(reason, label);\n }\n var lib$rsvp$reject$$default = lib$rsvp$reject$$reject;\n function lib$rsvp$resolve$$resolve(value, label) {\n return lib$rsvp$promise$$default.resolve(value, label);\n }\n var lib$rsvp$resolve$$default = lib$rsvp$resolve$$resolve;\n function lib$rsvp$rethrow$$rethrow(reason) {\n setTimeout(function() {\n throw reason;\n });\n throw reason;\n }\n var lib$rsvp$rethrow$$default = lib$rsvp$rethrow$$rethrow;\n\n // defaults\n lib$rsvp$config$$config.async = lib$rsvp$asap$$default;\n lib$rsvp$config$$config.after = function(cb) {\n setTimeout(cb, 0);\n };\n var lib$rsvp$$cast = lib$rsvp$resolve$$default;\n function lib$rsvp$$async(callback, arg) {\n lib$rsvp$config$$config.async(callback, arg);\n }\n\n function lib$rsvp$$on() {\n lib$rsvp$config$$config['on'].apply(lib$rsvp$config$$config, arguments);\n }\n\n function lib$rsvp$$off() {\n lib$rsvp$config$$config['off'].apply(lib$rsvp$config$$config, arguments);\n }\n\n // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`\n if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {\n var lib$rsvp$$callbacks = window['__PROMISE_INSTRUMENTATION__'];\n lib$rsvp$config$$configure('instrument', true);\n for (var lib$rsvp$$eventName in lib$rsvp$$callbacks) {\n if (lib$rsvp$$callbacks.hasOwnProperty(lib$rsvp$$eventName)) {\n lib$rsvp$$on(lib$rsvp$$eventName, lib$rsvp$$callbacks[lib$rsvp$$eventName]);\n }\n }\n }\n\n var lib$rsvp$umd$$RSVP = {\n 'race': lib$rsvp$race$$default,\n 'Promise': lib$rsvp$promise$$default,\n 'allSettled': lib$rsvp$all$settled$$default,\n 'hash': lib$rsvp$hash$$default,\n 'hashSettled': lib$rsvp$hash$settled$$default,\n 'denodeify': lib$rsvp$node$$default,\n 'on': lib$rsvp$$on,\n 'off': lib$rsvp$$off,\n 'map': lib$rsvp$map$$default,\n 'filter': lib$rsvp$filter$$default,\n 'resolve': lib$rsvp$resolve$$default,\n 'reject': lib$rsvp$reject$$default,\n 'all': lib$rsvp$all$$default,\n 'rethrow': lib$rsvp$rethrow$$default,\n 'defer': lib$rsvp$defer$$default,\n 'EventTarget': lib$rsvp$events$$default,\n 'configure': lib$rsvp$config$$configure,\n 'async': lib$rsvp$$async\n };\n\n /* global define:true module:true window: true */\n if (typeof define === 'function' && define['amd']) {\n define(function() { return lib$rsvp$umd$$RSVP; });\n } else if (typeof module !== 'undefined' && module['exports']) {\n module['exports'] = lib$rsvp$umd$$RSVP;\n } else if (typeof lib$rsvp$platform$$default !== 'undefined') {\n lib$rsvp$platform$$default['RSVP'] = lib$rsvp$umd$$RSVP;\n }\n}).call(this);\n\n","/*!\n * URI.js - Mutating URLs\n * Second Level Domain (SLD) Support\n *\n * Version: 1.17.0\n *\n * Author: Rodney Rehm\n * Web: http://medialize.github.io/URI.js/\n *\n * Licensed under\n * MIT License http://www.opensource.org/licenses/mit-license\n * GPL v3 http://opensource.org/licenses/GPL-3.0\n *\n */\n\n(function (root, factory) {\n 'use strict';\n // https://github.com/umdjs/umd/blob/master/returnExports.js\n if (typeof exports === 'object') {\n // Node\n module.exports = factory();\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory);\n } else {\n // Browser globals (root is window)\n root.SecondLevelDomains = factory(root);\n }\n}(this, function (root) {\n 'use strict';\n\n // save current SecondLevelDomains variable, if any\n var _SecondLevelDomains = root && root.SecondLevelDomains;\n\n var SLD = {\n // list of known Second Level Domains\n // converted list of SLDs from https://github.com/gavingmiller/second-level-domains\n // ----\n // publicsuffix.org is more current and actually used by a couple of browsers internally.\n // downside is it also contains domains like \"dyndns.org\" - which is fine for the security\n // issues browser have to deal with (SOP for cookies, etc) - but is way overboard for URI.js\n // ----\n list: {\n 'ac':' com gov mil net org ',\n 'ae':' ac co gov mil name net org pro sch ',\n 'af':' com edu gov net org ',\n 'al':' com edu gov mil net org ',\n 'ao':' co ed gv it og pb ',\n 'ar':' com edu gob gov int mil net org tur ',\n 'at':' ac co gv or ',\n 'au':' asn com csiro edu gov id net org ',\n 'ba':' co com edu gov mil net org rs unbi unmo unsa untz unze ',\n 'bb':' biz co com edu gov info net org store tv ',\n 'bh':' biz cc com edu gov info net org ',\n 'bn':' com edu gov net org ',\n 'bo':' com edu gob gov int mil net org tv ',\n 'br':' adm adv agr am arq art ato b bio blog bmd cim cng cnt com coop ecn edu eng esp etc eti far flog fm fnd fot fst g12 ggf gov imb ind inf jor jus lel mat med mil mus net nom not ntr odo org ppg pro psc psi qsl rec slg srv tmp trd tur tv vet vlog wiki zlg ',\n 'bs':' com edu gov net org ',\n 'bz':' du et om ov rg ',\n 'ca':' ab bc mb nb nf nl ns nt nu on pe qc sk yk ',\n 'ck':' biz co edu gen gov info net org ',\n 'cn':' ac ah bj com cq edu fj gd gov gs gx gz ha hb he hi hl hn jl js jx ln mil net nm nx org qh sc sd sh sn sx tj tw xj xz yn zj ',\n 'co':' com edu gov mil net nom org ',\n 'cr':' ac c co ed fi go or sa ',\n 'cy':' ac biz com ekloges gov ltd name net org parliament press pro tm ',\n 'do':' art com edu gob gov mil net org sld web ',\n 'dz':' art asso com edu gov net org pol ',\n 'ec':' com edu fin gov info med mil net org pro ',\n 'eg':' com edu eun gov mil name net org sci ',\n 'er':' com edu gov ind mil net org rochest w ',\n 'es':' com edu gob nom org ',\n 'et':' biz com edu gov info name net org ',\n 'fj':' ac biz com info mil name net org pro ',\n 'fk':' ac co gov net nom org ',\n 'fr':' asso com f gouv nom prd presse tm ',\n 'gg':' co net org ',\n 'gh':' com edu gov mil org ',\n 'gn':' ac com gov net org ',\n 'gr':' com edu gov mil net org ',\n 'gt':' com edu gob ind mil net org ',\n 'gu':' com edu gov net org ',\n 'hk':' com edu gov idv net org ',\n 'hu':' 2000 agrar bolt casino city co erotica erotika film forum games hotel info ingatlan jogasz konyvelo lakas media news org priv reklam sex shop sport suli szex tm tozsde utazas video ',\n 'id':' ac co go mil net or sch web ',\n 'il':' ac co gov idf k12 muni net org ',\n 'in':' ac co edu ernet firm gen gov i ind mil net nic org res ',\n 'iq':' com edu gov i mil net org ',\n 'ir':' ac co dnssec gov i id net org sch ',\n 'it':' edu gov ',\n 'je':' co net org ',\n 'jo':' com edu gov mil name net org sch ',\n 'jp':' ac ad co ed go gr lg ne or ',\n 'ke':' ac co go info me mobi ne or sc ',\n 'kh':' com edu gov mil net org per ',\n 'ki':' biz com de edu gov info mob net org tel ',\n 'km':' asso com coop edu gouv k medecin mil nom notaires pharmaciens presse tm veterinaire ',\n 'kn':' edu gov net org ',\n 'kr':' ac busan chungbuk chungnam co daegu daejeon es gangwon go gwangju gyeongbuk gyeonggi gyeongnam hs incheon jeju jeonbuk jeonnam k kg mil ms ne or pe re sc seoul ulsan ',\n 'kw':' com edu gov net org ',\n 'ky':' com edu gov net org ',\n 'kz':' com edu gov mil net org ',\n 'lb':' com edu gov net org ',\n 'lk':' assn com edu gov grp hotel int ltd net ngo org sch soc web ',\n 'lr':' com edu gov net org ',\n 'lv':' asn com conf edu gov id mil net org ',\n 'ly':' com edu gov id med net org plc sch ',\n 'ma':' ac co gov m net org press ',\n 'mc':' asso tm ',\n 'me':' ac co edu gov its net org priv ',\n 'mg':' com edu gov mil nom org prd tm ',\n 'mk':' com edu gov inf name net org pro ',\n 'ml':' com edu gov net org presse ',\n 'mn':' edu gov org ',\n 'mo':' com edu gov net org ',\n 'mt':' com edu gov net org ',\n 'mv':' aero biz com coop edu gov info int mil museum name net org pro ',\n 'mw':' ac co com coop edu gov int museum net org ',\n 'mx':' com edu gob net org ',\n 'my':' com edu gov mil name net org sch ',\n 'nf':' arts com firm info net other per rec store web ',\n 'ng':' biz com edu gov mil mobi name net org sch ',\n 'ni':' ac co com edu gob mil net nom org ',\n 'np':' com edu gov mil net org ',\n 'nr':' biz com edu gov info net org ',\n 'om':' ac biz co com edu gov med mil museum net org pro sch ',\n 'pe':' com edu gob mil net nom org sld ',\n 'ph':' com edu gov i mil net ngo org ',\n 'pk':' biz com edu fam gob gok gon gop gos gov net org web ',\n 'pl':' art bialystok biz com edu gda gdansk gorzow gov info katowice krakow lodz lublin mil net ngo olsztyn org poznan pwr radom slupsk szczecin torun warszawa waw wroc wroclaw zgora ',\n 'pr':' ac biz com edu est gov info isla name net org pro prof ',\n 'ps':' com edu gov net org plo sec ',\n 'pw':' belau co ed go ne or ',\n 'ro':' arts com firm info nom nt org rec store tm www ',\n 'rs':' ac co edu gov in org ',\n 'sb':' com edu gov net org ',\n 'sc':' com edu gov net org ',\n 'sh':' co com edu gov net nom org ',\n 'sl':' com edu gov net org ',\n 'st':' co com consulado edu embaixada gov mil net org principe saotome store ',\n 'sv':' com edu gob org red ',\n 'sz':' ac co org ',\n 'tr':' av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ',\n 'tt':' aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ',\n 'tw':' club com ebiz edu game gov idv mil net org ',\n 'mu':' ac co com gov net or org ',\n 'mz':' ac co edu gov org ',\n 'na':' co com ',\n 'nz':' ac co cri geek gen govt health iwi maori mil net org parliament school ',\n 'pa':' abo ac com edu gob ing med net nom org sld ',\n 'pt':' com edu gov int net nome org publ ',\n 'py':' com edu gov mil net org ',\n 'qa':' com edu gov mil net org ',\n 're':' asso com nom ',\n 'ru':' ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ',\n 'rw':' ac co com edu gouv gov int mil net ',\n 'sa':' com edu gov med net org pub sch ',\n 'sd':' com edu gov info med net org tv ',\n 'se':' a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ',\n 'sg':' com edu gov idn net org per ',\n 'sn':' art com edu gouv org perso univ ',\n 'sy':' com edu gov mil net news org ',\n 'th':' ac co go in mi net or ',\n 'tj':' ac biz co com edu go gov info int mil name net nic org test web ',\n 'tn':' agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ',\n 'tz':' ac co go ne or ',\n 'ua':' biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ',\n 'ug':' ac co go ne or org sc ',\n 'uk':' ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ',\n 'us':' dni fed isa kids nsn ',\n 'uy':' com edu gub mil net org ',\n 've':' co com edu gob info mil net org web ',\n 'vi':' co com k12 net org ',\n 'vn':' ac biz com edu gov health info int name net org pro ',\n 'ye':' co com gov ltd me net org plc ',\n 'yu':' ac co edu gov org ',\n 'za':' ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ',\n 'zm':' ac co com edu gov net org sch '\n },\n // gorhill 2013-10-25: Using indexOf() instead Regexp(). Significant boost\n // in both performance and memory footprint. No initialization required.\n // http://jsperf.com/uri-js-sld-regex-vs-binary-search/4\n // Following methods use lastIndexOf() rather than array.split() in order\n // to avoid any memory allocations.\n has: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return false;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {\n return false;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return false;\n }\n return sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') >= 0;\n },\n is: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return false;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset >= 0) {\n return false;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return false;\n }\n return sldList.indexOf(' ' + domain.slice(0, tldOffset) + ' ') >= 0;\n },\n get: function(domain) {\n var tldOffset = domain.lastIndexOf('.');\n if (tldOffset <= 0 || tldOffset >= (domain.length-1)) {\n return null;\n }\n var sldOffset = domain.lastIndexOf('.', tldOffset-1);\n if (sldOffset <= 0 || sldOffset >= (tldOffset-1)) {\n return null;\n }\n var sldList = SLD.list[domain.slice(tldOffset+1)];\n if (!sldList) {\n return null;\n }\n if (sldList.indexOf(' ' + domain.slice(sldOffset+1, tldOffset) + ' ') < 0) {\n return null;\n }\n return domain.slice(sldOffset+1);\n },\n noConflict: function(){\n if (root.SecondLevelDomains === this) {\n root.SecondLevelDomains = _SecondLevelDomains;\n }\n return this;\n }\n };\n\n return SLD;\n}));\n","/*!\n * URI.js - Mutating URLs\n *\n * Version: 1.17.0\n *\n * Author: Rodney Rehm\n * Web: http://medialize.github.io/URI.js/\n *\n * Licensed under\n * MIT License http://www.opensource.org/licenses/mit-license\n * GPL v3 http://opensource.org/licenses/GPL-3.0\n *\n */\n(function (root, factory) {\n 'use strict';\n // https://github.com/umdjs/umd/blob/master/returnExports.js\n if (typeof exports === 'object') {\n // Node\n module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains'));\n } else if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(['./punycode', './IPv6', './SecondLevelDomains'], factory);\n } else {\n // Browser globals (root is window)\n root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root);\n }\n}(this, function (punycode, IPv6, SLD, root) {\n 'use strict';\n /*global location, escape, unescape */\n // FIXME: v2.0.0 renamce non-camelCase properties to uppercase\n /*jshint camelcase: false */\n\n // save current URI variable, if any\n var _URI = root && root.URI;\n\n function URI(url, base) {\n var _urlSupplied = arguments.length >= 1;\n var _baseSupplied = arguments.length >= 2;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof URI)) {\n if (_urlSupplied) {\n if (_baseSupplied) {\n return new URI(url, base);\n }\n\n return new URI(url);\n }\n\n return new URI();\n }\n\n if (url === undefined) {\n if (_urlSupplied) {\n throw new TypeError('undefined is not a valid argument for URI');\n }\n\n if (typeof location !== 'undefined') {\n url = location.href + '';\n } else {\n url = '';\n }\n }\n\n this.href(url);\n\n // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor\n if (base !== undefined) {\n return this.absoluteTo(base);\n }\n\n return this;\n }\n\n URI.version = '1.17.0';\n\n var p = URI.prototype;\n var hasOwn = Object.prototype.hasOwnProperty;\n\n function escapeRegEx(string) {\n // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963\n return string.replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n }\n\n function getType(value) {\n // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value\n if (value === undefined) {\n return 'Undefined';\n }\n\n return String(Object.prototype.toString.call(value)).slice(8, -1);\n }\n\n function isArray(obj) {\n return getType(obj) === 'Array';\n }\n\n function filterArrayValues(data, value) {\n var lookup = {};\n var i, length;\n\n if (getType(value) === 'RegExp') {\n lookup = null;\n } else if (isArray(value)) {\n for (i = 0, length = value.length; i < length; i++) {\n lookup[value[i]] = true;\n }\n } else {\n lookup[value] = true;\n }\n\n for (i = 0, length = data.length; i < length; i++) {\n /*jshint laxbreak: true */\n var _match = lookup && lookup[data[i]] !== undefined\n || !lookup && value.test(data[i]);\n /*jshint laxbreak: false */\n if (_match) {\n data.splice(i, 1);\n length--;\n i--;\n }\n }\n\n return data;\n }\n\n function arrayContains(list, value) {\n var i, length;\n\n // value may be string, number, array, regexp\n if (isArray(value)) {\n // Note: this can be optimized to O(n) (instead of current O(m * n))\n for (i = 0, length = value.length; i < length; i++) {\n if (!arrayContains(list, value[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n var _type = getType(value);\n for (i = 0, length = list.length; i < length; i++) {\n if (_type === 'RegExp') {\n if (typeof list[i] === 'string' && list[i].match(value)) {\n return true;\n }\n } else if (list[i] === value) {\n return true;\n }\n }\n\n return false;\n }\n\n function arraysEqual(one, two) {\n if (!isArray(one) || !isArray(two)) {\n return false;\n }\n\n // arrays can't be equal if they have different amount of content\n if (one.length !== two.length) {\n return false;\n }\n\n one.sort();\n two.sort();\n\n for (var i = 0, l = one.length; i < l; i++) {\n if (one[i] !== two[i]) {\n return false;\n }\n }\n\n return true;\n }\n\n function trimSlashes(text) {\n var trim_expression = /^\\/+|\\/+$/g;\n return text.replace(trim_expression, '');\n }\n\n URI._parts = function() {\n return {\n protocol: null,\n username: null,\n password: null,\n hostname: null,\n urn: null,\n port: null,\n path: null,\n query: null,\n fragment: null,\n // state\n duplicateQueryParameters: URI.duplicateQueryParameters,\n escapeQuerySpace: URI.escapeQuerySpace\n };\n };\n // state: allow duplicate query parameters (a=1&a=1)\n URI.duplicateQueryParameters = false;\n // state: replaces + with %20 (space in query strings)\n URI.escapeQuerySpace = true;\n // static properties\n URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i;\n URI.idn_expression = /[^a-z0-9\\.-]/i;\n URI.punycode_expression = /(xn--)/i;\n // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?\n URI.ip4_expression = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n // credits to Rich Brown\n // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096\n // specification: http://www.ietf.org/rfc/rfc4291.txt\n URI.ip6_expression = /^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$/;\n // expression used is \"gruber revised\" (@gruber v2) determined to be the\n // best solution in a regex-golf we did a couple of ages ago at\n // * http://mathiasbynens.be/demo/url-regex\n // * http://rodneyrehm.de/t/url-regex.html\n URI.find_uri_expression = /\\b((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))/ig;\n URI.findUri = {\n // valid \"scheme://\" or \"www.\"\n start: /\\b(?:([a-z][a-z0-9.+-]*:\\/\\/)|www\\.)/gi,\n // everything up to the next whitespace\n end: /[\\s\\r\\n]|$/,\n // trim trailing punctuation captured by end RegExp\n trim: /[`!()\\[\\]{};:'\".,<>?«»“”„‘’]+$/\n };\n // http://www.iana.org/assignments/uri-schemes.html\n // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports\n URI.defaultPorts = {\n http: '80',\n https: '443',\n ftp: '21',\n gopher: '70',\n ws: '80',\n wss: '443'\n };\n // allowed hostname characters according to RFC 3986\n // ALPHA DIGIT \"-\" \".\" \"_\" \"~\" \"!\" \"$\" \"&\" \"'\" \"(\" \")\" \"*\" \"+\" \",\" \";\" \"=\" %encoded\n // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . -\n URI.invalid_hostname_characters = /[^a-zA-Z0-9\\.-]/;\n // map DOM Elements to their URI attribute\n URI.domAttributes = {\n 'a': 'href',\n 'blockquote': 'cite',\n 'link': 'href',\n 'base': 'href',\n 'script': 'src',\n 'form': 'action',\n 'img': 'src',\n 'area': 'href',\n 'iframe': 'src',\n 'embed': 'src',\n 'source': 'src',\n 'track': 'src',\n 'input': 'src', // but only if type=\"image\"\n 'audio': 'src',\n 'video': 'src'\n };\n URI.getDomAttribute = function(node) {\n if (!node || !node.nodeName) {\n return undefined;\n }\n\n var nodeName = node.nodeName.toLowerCase();\n // should only expose src for type=\"image\"\n if (nodeName === 'input' && node.type !== 'image') {\n return undefined;\n }\n\n return URI.domAttributes[nodeName];\n };\n\n function escapeForDumbFirefox36(value) {\n // https://github.com/medialize/URI.js/issues/91\n return escape(value);\n }\n\n // encoding / decoding according to RFC3986\n function strictEncodeURIComponent(string) {\n // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent\n return encodeURIComponent(string)\n .replace(/[!'()*]/g, escapeForDumbFirefox36)\n .replace(/\\*/g, '%2A');\n }\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n URI.iso8859 = function() {\n URI.encode = escape;\n URI.decode = unescape;\n };\n URI.unicode = function() {\n URI.encode = strictEncodeURIComponent;\n URI.decode = decodeURIComponent;\n };\n URI.characters = {\n pathname: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,\n map: {\n // -._~!'()*\n '%24': '$',\n '%26': '&',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%3A': ':',\n '%40': '@'\n }\n },\n decode: {\n expression: /[\\/\\?#]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23'\n }\n }\n },\n reserved: {\n encode: {\n // RFC3986 2.1: For consistency, URI producers and normalizers should\n // use uppercase hexadecimal digits for all percent-encodings.\n expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,\n map: {\n // gen-delims\n '%3A': ':',\n '%2F': '/',\n '%3F': '?',\n '%23': '#',\n '%5B': '[',\n '%5D': ']',\n '%40': '@',\n // sub-delims\n '%21': '!',\n '%24': '$',\n '%26': '&',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '='\n }\n }\n },\n urnpath: {\n // The characters under `encode` are the characters called out by RFC 2141 as being acceptable\n // for usage in a URN. RFC2141 also calls out \"-\", \".\", and \"_\" as acceptable characters, but\n // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also\n // note that the colon character is not featured in the encoding map; this is because URI.js\n // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it\n // should not appear unencoded in a segment itself.\n // See also the note above about RFC3986 and capitalalized hex digits.\n encode: {\n expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,\n map: {\n '%21': '!',\n '%24': '$',\n '%27': '\\'',\n '%28': '(',\n '%29': ')',\n '%2A': '*',\n '%2B': '+',\n '%2C': ',',\n '%3B': ';',\n '%3D': '=',\n '%40': '@'\n }\n },\n // These characters are the characters called out by RFC2141 as \"reserved\" characters that\n // should never appear in a URN, plus the colon character (see note above).\n decode: {\n expression: /[\\/\\?#:]/g,\n map: {\n '/': '%2F',\n '?': '%3F',\n '#': '%23',\n ':': '%3A'\n }\n }\n }\n };\n URI.encodeQuery = function(string, escapeQuerySpace) {\n var escaped = URI.encode(string + '');\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped;\n };\n URI.decodeQuery = function(string, escapeQuerySpace) {\n string += '';\n if (escapeQuerySpace === undefined) {\n escapeQuerySpace = URI.escapeQuerySpace;\n }\n\n try {\n return URI.decode(escapeQuerySpace ? string.replace(/\\+/g, '%20') : string);\n } catch(e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n // generate encode/decode path functions\n var _parts = {'encode':'encode', 'decode':'decode'};\n var _part;\n var generateAccessor = function(_group, _part) {\n return function(string) {\n try {\n return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {\n return URI.characters[_group][_part].map[c];\n });\n } catch (e) {\n // we're not going to mess with weird encodings,\n // give up and return the undecoded original string\n // see https://github.com/medialize/URI.js/issues/87\n // see https://github.com/medialize/URI.js/issues/92\n return string;\n }\n };\n };\n\n for (_part in _parts) {\n URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]);\n URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]);\n }\n\n var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) {\n return function(string) {\n // Why pass in names of functions, rather than the function objects themselves? The\n // definitions of some functions (but in particular, URI.decode) will occasionally change due\n // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure\n // that the functions we use here are \"fresh\".\n var actualCodingFunc;\n if (!_innerCodingFuncName) {\n actualCodingFunc = URI[_codingFuncName];\n } else {\n actualCodingFunc = function(string) {\n return URI[_codingFuncName](URI[_innerCodingFuncName](string));\n };\n }\n\n var segments = (string + '').split(_sep);\n\n for (var i = 0, length = segments.length; i < length; i++) {\n segments[i] = actualCodingFunc(segments[i]);\n }\n\n return segments.join(_sep);\n };\n };\n\n // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.\n URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment');\n URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment');\n URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode');\n URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode');\n\n URI.encodeReserved = generateAccessor('reserved', 'encode');\n\n URI.parse = function(string, parts) {\n var pos;\n if (!parts) {\n parts = {};\n }\n // [protocol\"://\"[username[\":\"password]\"@\"]hostname[\":\"port]\"/\"?][path][\"?\"querystring][\"#\"fragment]\n\n // extract fragment\n pos = string.indexOf('#');\n if (pos > -1) {\n // escaping?\n parts.fragment = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract query\n pos = string.indexOf('?');\n if (pos > -1) {\n // escaping?\n parts.query = string.substring(pos + 1) || null;\n string = string.substring(0, pos);\n }\n\n // extract protocol\n if (string.substring(0, 2) === '//') {\n // relative-scheme\n parts.protocol = null;\n string = string.substring(2);\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n pos = string.indexOf(':');\n if (pos > -1) {\n parts.protocol = string.substring(0, pos) || null;\n if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {\n // : may be within the path\n parts.protocol = undefined;\n } else if (string.substring(pos + 1, pos + 3) === '//') {\n string = string.substring(pos + 3);\n\n // extract \"user:pass@host:port\"\n string = URI.parseAuthority(string, parts);\n } else {\n string = string.substring(pos + 1);\n parts.urn = true;\n }\n }\n }\n\n // what's left must be the path\n parts.path = string;\n\n // and we're done\n return parts;\n };\n URI.parseHost = function(string, parts) {\n // Copy chrome, IE, opera backslash-handling behavior.\n // Back slashes before the query string get converted to forward slashes\n // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124\n // See: https://code.google.com/p/chromium/issues/detail?id=25916\n // https://github.com/medialize/URI.js/pull/233\n string = string.replace(/\\\\/g, '/');\n\n // extract host:port\n var pos = string.indexOf('/');\n var bracketPos;\n var t;\n\n if (pos === -1) {\n pos = string.length;\n }\n\n if (string.charAt(0) === '[') {\n // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6\n // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts\n // IPv6+port in the format [2001:db8::1]:80 (for the time being)\n bracketPos = string.indexOf(']');\n parts.hostname = string.substring(1, bracketPos) || null;\n parts.port = string.substring(bracketPos + 2, pos) || null;\n if (parts.port === '/') {\n parts.port = null;\n }\n } else {\n var firstColon = string.indexOf(':');\n var firstSlash = string.indexOf('/');\n var nextColon = string.indexOf(':', firstColon + 1);\n if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {\n // IPv6 host contains multiple colons - but no port\n // this notation is actually not allowed by RFC 3986, but we're a liberal parser\n parts.hostname = string.substring(0, pos) || null;\n parts.port = null;\n } else {\n t = string.substring(0, pos).split(':');\n parts.hostname = t[0] || null;\n parts.port = t[1] || null;\n }\n }\n\n if (parts.hostname && string.substring(pos).charAt(0) !== '/') {\n pos++;\n string = '/' + string;\n }\n\n return string.substring(pos) || '/';\n };\n URI.parseAuthority = function(string, parts) {\n string = URI.parseUserinfo(string, parts);\n return URI.parseHost(string, parts);\n };\n URI.parseUserinfo = function(string, parts) {\n // extract username:password\n var firstSlash = string.indexOf('/');\n var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1);\n var t;\n\n // authority@ must come before /path\n if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {\n t = string.substring(0, pos).split(':');\n parts.username = t[0] ? URI.decode(t[0]) : null;\n t.shift();\n parts.password = t[0] ? URI.decode(t.join(':')) : null;\n string = string.substring(pos + 1);\n } else {\n parts.username = null;\n parts.password = null;\n }\n\n return string;\n };\n URI.parseQuery = function(string, escapeQuerySpace) {\n if (!string) {\n return {};\n }\n\n // throw out the funky business - \"?\"[name\"=\"value\"&\"]+\n string = string.replace(/&+/g, '&').replace(/^\\?*&*|&+$/g, '');\n\n if (!string) {\n return {};\n }\n\n var items = {};\n var splits = string.split('&');\n var length = splits.length;\n var v, name, value;\n\n for (var i = 0; i < length; i++) {\n v = splits[i].split('=');\n name = URI.decodeQuery(v.shift(), escapeQuerySpace);\n // no \"=\" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters\n value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;\n\n if (hasOwn.call(items, name)) {\n if (typeof items[name] === 'string' || items[name] === null) {\n items[name] = [items[name]];\n }\n\n items[name].push(value);\n } else {\n items[name] = value;\n }\n }\n\n return items;\n };\n\n URI.build = function(parts) {\n var t = '';\n\n if (parts.protocol) {\n t += parts.protocol + ':';\n }\n\n if (!parts.urn && (t || parts.hostname)) {\n t += '//';\n }\n\n t += (URI.buildAuthority(parts) || '');\n\n if (typeof parts.path === 'string') {\n if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {\n t += '/';\n }\n\n t += parts.path;\n }\n\n if (typeof parts.query === 'string' && parts.query) {\n t += '?' + parts.query;\n }\n\n if (typeof parts.fragment === 'string' && parts.fragment) {\n t += '#' + parts.fragment;\n }\n return t;\n };\n URI.buildHost = function(parts) {\n var t = '';\n\n if (!parts.hostname) {\n return '';\n } else if (URI.ip6_expression.test(parts.hostname)) {\n t += '[' + parts.hostname + ']';\n } else {\n t += parts.hostname;\n }\n\n if (parts.port) {\n t += ':' + parts.port;\n }\n\n return t;\n };\n URI.buildAuthority = function(parts) {\n return URI.buildUserinfo(parts) + URI.buildHost(parts);\n };\n URI.buildUserinfo = function(parts) {\n var t = '';\n\n if (parts.username) {\n t += URI.encode(parts.username);\n\n if (parts.password) {\n t += ':' + URI.encode(parts.password);\n }\n\n t += '@';\n }\n\n return t;\n };\n URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {\n // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html\n // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed\n // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!\n // URI.js treats the query string as being application/x-www-form-urlencoded\n // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type\n\n var t = '';\n var unique, key, i, length;\n for (key in data) {\n if (hasOwn.call(data, key) && key) {\n if (isArray(data[key])) {\n unique = {};\n for (i = 0, length = data[key].length; i < length; i++) {\n if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace);\n if (duplicateQueryParameters !== true) {\n unique[data[key][i] + ''] = true;\n }\n }\n }\n } else if (data[key] !== undefined) {\n t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace);\n }\n }\n }\n\n return t.substring(1);\n };\n URI.buildQueryParameter = function(name, value, escapeQuerySpace) {\n // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded\n // don't append \"=\" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization\n return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '');\n };\n\n URI.addQuery = function(data, name, value) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n URI.addQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (data[name] === undefined) {\n data[name] = value;\n return;\n } else if (typeof data[name] === 'string') {\n data[name] = [data[name]];\n }\n\n if (!isArray(value)) {\n value = [value];\n }\n\n data[name] = (data[name] || []).concat(value);\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n };\n URI.removeQuery = function(data, name, value) {\n var i, length, key;\n\n if (isArray(name)) {\n for (i = 0, length = name.length; i < length; i++) {\n data[name[i]] = undefined;\n }\n } else if (getType(name) === 'RegExp') {\n for (key in data) {\n if (name.test(key)) {\n data[key] = undefined;\n }\n }\n } else if (typeof name === 'object') {\n for (key in name) {\n if (hasOwn.call(name, key)) {\n URI.removeQuery(data, key, name[key]);\n }\n }\n } else if (typeof name === 'string') {\n if (value !== undefined) {\n if (getType(value) === 'RegExp') {\n if (!isArray(data[name]) && value.test(data[name])) {\n data[name] = undefined;\n } else {\n data[name] = filterArrayValues(data[name], value);\n }\n } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) {\n data[name] = undefined;\n } else if (isArray(data[name])) {\n data[name] = filterArrayValues(data[name], value);\n }\n } else {\n data[name] = undefined;\n }\n } else {\n throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter');\n }\n };\n URI.hasQuery = function(data, name, value, withinArray) {\n if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n if (!URI.hasQuery(data, key, name[key])) {\n return false;\n }\n }\n }\n\n return true;\n } else if (typeof name !== 'string') {\n throw new TypeError('URI.hasQuery() accepts an object, string as the name parameter');\n }\n\n switch (getType(value)) {\n case 'Undefined':\n // true if exists (but may be empty)\n return name in data; // data[name] !== undefined;\n\n case 'Boolean':\n // true if exists and non-empty\n var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]);\n return value === _booly;\n\n case 'Function':\n // allow complex comparison\n return !!value(data[name], name, data);\n\n case 'Array':\n if (!isArray(data[name])) {\n return false;\n }\n\n var op = withinArray ? arrayContains : arraysEqual;\n return op(data[name], value);\n\n case 'RegExp':\n if (!isArray(data[name])) {\n return Boolean(data[name] && data[name].match(value));\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n case 'Number':\n value = String(value);\n /* falls through */\n case 'String':\n if (!isArray(data[name])) {\n return data[name] === value;\n }\n\n if (!withinArray) {\n return false;\n }\n\n return arrayContains(data[name], value);\n\n default:\n throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter');\n }\n };\n\n\n URI.commonPath = function(one, two) {\n var length = Math.min(one.length, two.length);\n var pos;\n\n // find first non-matching character\n for (pos = 0; pos < length; pos++) {\n if (one.charAt(pos) !== two.charAt(pos)) {\n pos--;\n break;\n }\n }\n\n if (pos < 1) {\n return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : '';\n }\n\n // revert to last /\n if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {\n pos = one.substring(0, pos).lastIndexOf('/');\n }\n\n return one.substring(0, pos + 1);\n };\n\n URI.withinString = function(string, callback, options) {\n options || (options = {});\n var _start = options.start || URI.findUri.start;\n var _end = options.end || URI.findUri.end;\n var _trim = options.trim || URI.findUri.trim;\n var _attributeOpen = /[a-z0-9-]=[\"']?$/i;\n\n _start.lastIndex = 0;\n while (true) {\n var match = _start.exec(string);\n if (!match) {\n break;\n }\n\n var start = match.index;\n if (options.ignoreHtml) {\n // attribut(e=[\"']?$)\n var attributeOpen = string.slice(Math.max(start - 3, 0), start);\n if (attributeOpen && _attributeOpen.test(attributeOpen)) {\n continue;\n }\n }\n\n var end = start + string.slice(start).search(_end);\n var slice = string.slice(start, end).replace(_trim, '');\n if (options.ignore && options.ignore.test(slice)) {\n continue;\n }\n\n end = start + slice.length;\n var result = callback(slice, start, end, string);\n string = string.slice(0, start) + result + string.slice(end);\n _start.lastIndex = start + result.length;\n }\n\n _start.lastIndex = 0;\n return string;\n };\n\n URI.ensureValidHostname = function(v) {\n // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)\n // they are not part of DNS and therefore ignored by URI.js\n\n if (v.match(URI.invalid_hostname_characters)) {\n // test punycode\n if (!punycode) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-] and Punycode.js is not available');\n }\n\n if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n }\n };\n\n // noConflict\n URI.noConflict = function(removeAll) {\n if (removeAll) {\n var unconflicted = {\n URI: this.noConflict()\n };\n\n if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {\n unconflicted.URITemplate = root.URITemplate.noConflict();\n }\n\n if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {\n unconflicted.IPv6 = root.IPv6.noConflict();\n }\n\n if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {\n unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict();\n }\n\n return unconflicted;\n } else if (root.URI === this) {\n root.URI = _URI;\n }\n\n return this;\n };\n\n p.build = function(deferBuild) {\n if (deferBuild === true) {\n this._deferred_build = true;\n } else if (deferBuild === undefined || this._deferred_build) {\n this._string = URI.build(this._parts);\n this._deferred_build = false;\n }\n\n return this;\n };\n\n p.clone = function() {\n return new URI(this);\n };\n\n p.valueOf = p.toString = function() {\n return this.build(false)._string;\n };\n\n\n function generateSimpleAccessor(_part){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n this._parts[_part] = v || null;\n this.build(!build);\n return this;\n }\n };\n }\n\n function generatePrefixAccessor(_part, _key){\n return function(v, build) {\n if (v === undefined) {\n return this._parts[_part] || '';\n } else {\n if (v !== null) {\n v = v + '';\n if (v.charAt(0) === _key) {\n v = v.substring(1);\n }\n }\n\n this._parts[_part] = v;\n this.build(!build);\n return this;\n }\n };\n }\n\n p.protocol = generateSimpleAccessor('protocol');\n p.username = generateSimpleAccessor('username');\n p.password = generateSimpleAccessor('password');\n p.hostname = generateSimpleAccessor('hostname');\n p.port = generateSimpleAccessor('port');\n p.query = generatePrefixAccessor('query', '?');\n p.fragment = generatePrefixAccessor('fragment', '#');\n\n p.search = function(v, build) {\n var t = this.query(v, build);\n return typeof t === 'string' && t.length ? ('?' + t) : t;\n };\n p.hash = function(v, build) {\n var t = this.fragment(v, build);\n return typeof t === 'string' && t.length ? ('#' + t) : t;\n };\n\n p.pathname = function(v, build) {\n if (v === undefined || v === true) {\n var res = this._parts.path || (this._parts.hostname ? '/' : '');\n return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res;\n } else {\n if (this._parts.urn) {\n this._parts.path = v ? URI.recodeUrnPath(v) : '';\n } else {\n this._parts.path = v ? URI.recodePath(v) : '/';\n }\n this.build(!build);\n return this;\n }\n };\n p.path = p.pathname;\n p.href = function(href, build) {\n var key;\n\n if (href === undefined) {\n return this.toString();\n }\n\n this._string = '';\n this._parts = URI._parts();\n\n var _URI = href instanceof URI;\n var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname);\n if (href.nodeName) {\n var attribute = URI.getDomAttribute(href);\n href = href[attribute] || '';\n _object = false;\n }\n\n // window.location is reported to be an object, but it's not the sort\n // of object we're looking for:\n // * location.protocol ends with a colon\n // * location.query != object.search\n // * location.hash != object.fragment\n // simply serializing the unknown object should do the trick\n // (for location, not for everything...)\n if (!_URI && _object && href.pathname !== undefined) {\n href = href.toString();\n }\n\n if (typeof href === 'string' || href instanceof String) {\n this._parts = URI.parse(String(href), this._parts);\n } else if (_URI || _object) {\n var src = _URI ? href._parts : href;\n for (key in src) {\n if (hasOwn.call(this._parts, key)) {\n this._parts[key] = src[key];\n }\n }\n } else {\n throw new TypeError('invalid input');\n }\n\n this.build(!build);\n return this;\n };\n\n // identification accessors\n p.is = function(what) {\n var ip = false;\n var ip4 = false;\n var ip6 = false;\n var name = false;\n var sld = false;\n var idn = false;\n var punycode = false;\n var relative = !this._parts.urn;\n\n if (this._parts.hostname) {\n relative = false;\n ip4 = URI.ip4_expression.test(this._parts.hostname);\n ip6 = URI.ip6_expression.test(this._parts.hostname);\n ip = ip4 || ip6;\n name = !ip;\n sld = name && SLD && SLD.has(this._parts.hostname);\n idn = name && URI.idn_expression.test(this._parts.hostname);\n punycode = name && URI.punycode_expression.test(this._parts.hostname);\n }\n\n switch (what.toLowerCase()) {\n case 'relative':\n return relative;\n\n case 'absolute':\n return !relative;\n\n // hostname identification\n case 'domain':\n case 'name':\n return name;\n\n case 'sld':\n return sld;\n\n case 'ip':\n return ip;\n\n case 'ip4':\n case 'ipv4':\n case 'inet4':\n return ip4;\n\n case 'ip6':\n case 'ipv6':\n case 'inet6':\n return ip6;\n\n case 'idn':\n return idn;\n\n case 'url':\n return !this._parts.urn;\n\n case 'urn':\n return !!this._parts.urn;\n\n case 'punycode':\n return punycode;\n }\n\n return null;\n };\n\n // component specific input validation\n var _protocol = p.protocol;\n var _port = p.port;\n var _hostname = p.hostname;\n\n p.protocol = function(v, build) {\n if (v !== undefined) {\n if (v) {\n // accept trailing ://\n v = v.replace(/:(\\/\\/)?$/, '');\n\n if (!v.match(URI.protocol_expression)) {\n throw new TypeError('Protocol \"' + v + '\" contains characters other than [A-Z0-9.+-] or doesn\\'t start with [A-Z]');\n }\n }\n }\n return _protocol.call(this, v, build);\n };\n p.scheme = p.protocol;\n p.port = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n if (v === 0) {\n v = null;\n }\n\n if (v) {\n v += '';\n if (v.charAt(0) === ':') {\n v = v.substring(1);\n }\n\n if (v.match(/[^0-9]/)) {\n throw new TypeError('Port \"' + v + '\" contains characters other than [0-9]');\n }\n }\n }\n return _port.call(this, v, build);\n };\n p.hostname = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v !== undefined) {\n var x = {};\n var res = URI.parseHost(v, x);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n v = x.hostname;\n }\n return _hostname.call(this, v, build);\n };\n\n // compound accessors\n p.origin = function(v, build) {\n var parts;\n\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n var protocol = this.protocol();\n var authority = this.authority();\n if (!authority) return '';\n return (protocol ? protocol + '://' : '') + this.authority();\n } else {\n var origin = URI(v);\n this\n .protocol(origin.protocol())\n .authority(origin.authority())\n .build(!build);\n return this;\n }\n };\n p.host = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildHost(this._parts) : '';\n } else {\n var res = URI.parseHost(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.authority = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n return this._parts.hostname ? URI.buildAuthority(this._parts) : '';\n } else {\n var res = URI.parseAuthority(v, this._parts);\n if (res !== '/') {\n throw new TypeError('Hostname \"' + v + '\" contains characters other than [A-Z0-9.-]');\n }\n\n this.build(!build);\n return this;\n }\n };\n p.userinfo = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined) {\n if (!this._parts.username) {\n return '';\n }\n\n var t = URI.buildUserinfo(this._parts);\n return t.substring(0, t.length -1);\n } else {\n if (v[v.length-1] !== '@') {\n v += '@';\n }\n\n URI.parseUserinfo(v, this._parts);\n this.build(!build);\n return this;\n }\n };\n p.resource = function(v, build) {\n var parts;\n\n if (v === undefined) {\n return this.path() + this.search() + this.hash();\n }\n\n parts = URI.parse(v);\n this._parts.path = parts.path;\n this._parts.query = parts.query;\n this._parts.fragment = parts.fragment;\n this.build(!build);\n return this;\n };\n\n // fraction accessors\n p.subdomain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n // convenience, return \"www\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // grab domain and add another segment\n var end = this._parts.hostname.length - this.domain().length - 1;\n return this._parts.hostname.substring(0, end) || '';\n } else {\n var e = this._parts.hostname.length - this.domain().length;\n var sub = this._parts.hostname.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(sub));\n\n if (v && v.charAt(v.length - 1) !== '.') {\n v += '.';\n }\n\n if (v) {\n URI.ensureValidHostname(v);\n }\n\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.domain = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // convenience, return \"example.org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n // if hostname consists of 1 or 2 segments, it must be the domain\n var t = this._parts.hostname.match(/\\./g);\n if (t && t.length < 2) {\n return this._parts.hostname;\n }\n\n // grab tld and add another segment\n var end = this._parts.hostname.length - this.tld(build).length - 1;\n end = this._parts.hostname.lastIndexOf('.', end -1) + 1;\n return this._parts.hostname.substring(end) || '';\n } else {\n if (!v) {\n throw new TypeError('cannot set domain empty');\n }\n\n URI.ensureValidHostname(v);\n\n if (!this._parts.hostname || this.is('IP')) {\n this._parts.hostname = v;\n } else {\n var replace = new RegExp(escapeRegEx(this.domain()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.tld = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (typeof v === 'boolean') {\n build = v;\n v = undefined;\n }\n\n // return \"org\" from \"www.example.org\"\n if (v === undefined) {\n if (!this._parts.hostname || this.is('IP')) {\n return '';\n }\n\n var pos = this._parts.hostname.lastIndexOf('.');\n var tld = this._parts.hostname.substring(pos + 1);\n\n if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {\n return SLD.get(this._parts.hostname) || tld;\n }\n\n return tld;\n } else {\n var replace;\n\n if (!v) {\n throw new TypeError('cannot set TLD empty');\n } else if (v.match(/[^a-zA-Z0-9-]/)) {\n if (SLD && SLD.is(v)) {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n } else {\n throw new TypeError('TLD \"' + v + '\" contains characters other than [A-Z0-9]');\n }\n } else if (!this._parts.hostname || this.is('IP')) {\n throw new ReferenceError('cannot set TLD on non-domain host');\n } else {\n replace = new RegExp(escapeRegEx(this.tld()) + '$');\n this._parts.hostname = this._parts.hostname.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.directory = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path && !this._parts.hostname) {\n return '';\n }\n\n if (this._parts.path === '/') {\n return '/';\n }\n\n var end = this._parts.path.length - this.filename().length - 1;\n var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '');\n\n return v ? URI.decodePath(res) : res;\n\n } else {\n var e = this._parts.path.length - this.filename().length;\n var directory = this._parts.path.substring(0, e);\n var replace = new RegExp('^' + escapeRegEx(directory));\n\n // fully qualifier directories begin with a slash\n if (!this.is('relative')) {\n if (!v) {\n v = '/';\n }\n\n if (v.charAt(0) !== '/') {\n v = '/' + v;\n }\n }\n\n // directories always end with a slash\n if (v && v.charAt(v.length - 1) !== '/') {\n v += '/';\n }\n\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n this.build(!build);\n return this;\n }\n };\n p.filename = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var pos = this._parts.path.lastIndexOf('/');\n var res = this._parts.path.substring(pos+1);\n\n return v ? URI.decodePathSegment(res) : res;\n } else {\n var mutatedDirectory = false;\n\n if (v.charAt(0) === '/') {\n v = v.substring(1);\n }\n\n if (v.match(/\\.?\\//)) {\n mutatedDirectory = true;\n }\n\n var replace = new RegExp(escapeRegEx(this.filename()) + '$');\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n\n if (mutatedDirectory) {\n this.normalizePath(build);\n } else {\n this.build(!build);\n }\n\n return this;\n }\n };\n p.suffix = function(v, build) {\n if (this._parts.urn) {\n return v === undefined ? '' : this;\n }\n\n if (v === undefined || v === true) {\n if (!this._parts.path || this._parts.path === '/') {\n return '';\n }\n\n var filename = this.filename();\n var pos = filename.lastIndexOf('.');\n var s, res;\n\n if (pos === -1) {\n return '';\n }\n\n // suffix may only contain alnum characters (yup, I made this up.)\n s = filename.substring(pos+1);\n res = (/^[a-z0-9%]+$/i).test(s) ? s : '';\n return v ? URI.decodePathSegment(res) : res;\n } else {\n if (v.charAt(0) === '.') {\n v = v.substring(1);\n }\n\n var suffix = this.suffix();\n var replace;\n\n if (!suffix) {\n if (!v) {\n return this;\n }\n\n this._parts.path += '.' + URI.recodePath(v);\n } else if (!v) {\n replace = new RegExp(escapeRegEx('.' + suffix) + '$');\n } else {\n replace = new RegExp(escapeRegEx(suffix) + '$');\n }\n\n if (replace) {\n v = URI.recodePath(v);\n this._parts.path = this._parts.path.replace(replace, v);\n }\n\n this.build(!build);\n return this;\n }\n };\n p.segment = function(segment, v, build) {\n var separator = this._parts.urn ? ':' : '/';\n var path = this.path();\n var absolute = path.substring(0, 1) === '/';\n var segments = path.split(separator);\n\n if (segment !== undefined && typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (segment !== undefined && typeof segment !== 'number') {\n throw new Error('Bad segment \"' + segment + '\", must be 0-based integer');\n }\n\n if (absolute) {\n segments.shift();\n }\n\n if (segment < 0) {\n // allow negative indexes to address from the end\n segment = Math.max(segments.length + segment, 0);\n }\n\n if (v === undefined) {\n /*jshint laxbreak: true */\n return segment === undefined\n ? segments\n : segments[segment];\n /*jshint laxbreak: false */\n } else if (segment === null || segments[segment] === undefined) {\n if (isArray(v)) {\n segments = [];\n // collapse empty elements within array\n for (var i=0, l=v.length; i < l; i++) {\n if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) {\n continue;\n }\n\n if (segments.length && !segments[segments.length -1].length) {\n segments.pop();\n }\n\n segments.push(trimSlashes(v[i]));\n }\n } else if (v || typeof v === 'string') {\n v = trimSlashes(v);\n if (segments[segments.length -1] === '') {\n // empty trailing elements have to be overwritten\n // to prevent results such as /foo//bar\n segments[segments.length -1] = v;\n } else {\n segments.push(v);\n }\n }\n } else {\n if (v) {\n segments[segment] = trimSlashes(v);\n } else {\n segments.splice(segment, 1);\n }\n }\n\n if (absolute) {\n segments.unshift('');\n }\n\n return this.path(segments.join(separator), build);\n };\n p.segmentCoded = function(segment, v, build) {\n var segments, i, l;\n\n if (typeof segment !== 'number') {\n build = v;\n v = segment;\n segment = undefined;\n }\n\n if (v === undefined) {\n segments = this.segment(segment, v, build);\n if (!isArray(segments)) {\n segments = segments !== undefined ? URI.decode(segments) : undefined;\n } else {\n for (i = 0, l = segments.length; i < l; i++) {\n segments[i] = URI.decode(segments[i]);\n }\n }\n\n return segments;\n }\n\n if (!isArray(v)) {\n v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v;\n } else {\n for (i = 0, l = v.length; i < l; i++) {\n v[i] = URI.encode(v[i]);\n }\n }\n\n return this.segment(segment, v, build);\n };\n\n // mutating query string\n var q = p.query;\n p.query = function(v, build) {\n if (v === true) {\n return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n } else if (typeof v === 'function') {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n var result = v.call(this, data);\n this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else if (v !== undefined && typeof v !== 'string') {\n this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n this.build(!build);\n return this;\n } else {\n return q.call(this, v, build);\n }\n };\n p.setQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n\n if (typeof name === 'string' || name instanceof String) {\n data[name] = value !== undefined ? value : null;\n } else if (typeof name === 'object') {\n for (var key in name) {\n if (hasOwn.call(name, key)) {\n data[key] = name[key];\n }\n }\n } else {\n throw new TypeError('URI.addQuery() accepts an object, string as the name parameter');\n }\n\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.addQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.addQuery(data, name, value === undefined ? null : value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.removeQuery = function(name, value, build) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n URI.removeQuery(data, name, value);\n this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace);\n if (typeof name !== 'string') {\n build = value;\n }\n\n this.build(!build);\n return this;\n };\n p.hasQuery = function(name, value, withinArray) {\n var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace);\n return URI.hasQuery(data, name, value, withinArray);\n };\n p.setSearch = p.setQuery;\n p.addSearch = p.addQuery;\n p.removeSearch = p.removeQuery;\n p.hasSearch = p.hasQuery;\n\n // sanitizing URLs\n p.normalize = function() {\n if (this._parts.urn) {\n return this\n .normalizeProtocol(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n }\n\n return this\n .normalizeProtocol(false)\n .normalizeHostname(false)\n .normalizePort(false)\n .normalizePath(false)\n .normalizeQuery(false)\n .normalizeFragment(false)\n .build();\n };\n p.normalizeProtocol = function(build) {\n if (typeof this._parts.protocol === 'string') {\n this._parts.protocol = this._parts.protocol.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeHostname = function(build) {\n if (this._parts.hostname) {\n if (this.is('IDN') && punycode) {\n this._parts.hostname = punycode.toASCII(this._parts.hostname);\n } else if (this.is('IPv6') && IPv6) {\n this._parts.hostname = IPv6.best(this._parts.hostname);\n }\n\n this._parts.hostname = this._parts.hostname.toLowerCase();\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePort = function(build) {\n // remove port of it's the protocol's default\n if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {\n this._parts.port = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizePath = function(build) {\n var _path = this._parts.path;\n if (!_path) {\n return this;\n }\n\n if (this._parts.urn) {\n this._parts.path = URI.recodeUrnPath(this._parts.path);\n this.build(!build);\n return this;\n }\n\n if (this._parts.path === '/') {\n return this;\n }\n\n var _was_relative;\n var _leadingParents = '';\n var _parent, _pos;\n\n // handle relative paths\n if (_path.charAt(0) !== '/') {\n _was_relative = true;\n _path = '/' + _path;\n }\n\n // handle relative files (as opposed to directories)\n if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {\n _path += '/';\n }\n\n // resolve simples\n _path = _path\n .replace(/(\\/(\\.\\/)+)|(\\/\\.$)/g, '/')\n .replace(/\\/{2,}/g, '/');\n\n // remember leading parents\n if (_was_relative) {\n _leadingParents = _path.substring(1).match(/^(\\.\\.\\/)+/) || '';\n if (_leadingParents) {\n _leadingParents = _leadingParents[0];\n }\n }\n\n // resolve parents\n while (true) {\n _parent = _path.indexOf('/..');\n if (_parent === -1) {\n // no more ../ to resolve\n break;\n } else if (_parent === 0) {\n // top level cannot be relative, skip it\n _path = _path.substring(3);\n continue;\n }\n\n _pos = _path.substring(0, _parent).lastIndexOf('/');\n if (_pos === -1) {\n _pos = _parent;\n }\n _path = _path.substring(0, _pos) + _path.substring(_parent + 3);\n }\n\n // revert to relative\n if (_was_relative && this.is('relative')) {\n _path = _leadingParents + _path.substring(1);\n }\n\n _path = URI.recodePath(_path);\n this._parts.path = _path;\n this.build(!build);\n return this;\n };\n p.normalizePathname = p.normalizePath;\n p.normalizeQuery = function(build) {\n if (typeof this._parts.query === 'string') {\n if (!this._parts.query.length) {\n this._parts.query = null;\n } else {\n this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace));\n }\n\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeFragment = function(build) {\n if (!this._parts.fragment) {\n this._parts.fragment = null;\n this.build(!build);\n }\n\n return this;\n };\n p.normalizeSearch = p.normalizeQuery;\n p.normalizeHash = p.normalizeFragment;\n\n p.iso8859 = function() {\n // expect unicode input, iso8859 output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = escape;\n URI.decode = decodeURIComponent;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.unicode = function() {\n // expect iso8859 input, unicode output\n var e = URI.encode;\n var d = URI.decode;\n\n URI.encode = strictEncodeURIComponent;\n URI.decode = unescape;\n try {\n this.normalize();\n } finally {\n URI.encode = e;\n URI.decode = d;\n }\n return this;\n };\n\n p.readable = function() {\n var uri = this.clone();\n // removing username, password, because they shouldn't be displayed according to RFC 3986\n uri.username('').password('').normalize();\n var t = '';\n if (uri._parts.protocol) {\n t += uri._parts.protocol + '://';\n }\n\n if (uri._parts.hostname) {\n if (uri.is('punycode') && punycode) {\n t += punycode.toUnicode(uri._parts.hostname);\n if (uri._parts.port) {\n t += ':' + uri._parts.port;\n }\n } else {\n t += uri.host();\n }\n }\n\n if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {\n t += '/';\n }\n\n t += uri.path(true);\n if (uri._parts.query) {\n var q = '';\n for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {\n var kv = (qp[i] || '').split('=');\n q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n\n if (kv[1] !== undefined) {\n q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace)\n .replace(/&/g, '%26');\n }\n }\n t += '?' + q.substring(1);\n }\n\n t += URI.decodeQuery(uri.hash(), true);\n return t;\n };\n\n // resolving relative and absolute URLs\n p.absoluteTo = function(base) {\n var resolved = this.clone();\n var properties = ['protocol', 'username', 'password', 'hostname', 'port'];\n var basedir, i, p;\n\n if (this._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n if (!(base instanceof URI)) {\n base = new URI(base);\n }\n\n if (!resolved._parts.protocol) {\n resolved._parts.protocol = base._parts.protocol;\n }\n\n if (this._parts.hostname) {\n return resolved;\n }\n\n for (i = 0; (p = properties[i]); i++) {\n resolved._parts[p] = base._parts[p];\n }\n\n if (!resolved._parts.path) {\n resolved._parts.path = base._parts.path;\n if (!resolved._parts.query) {\n resolved._parts.query = base._parts.query;\n }\n } else if (resolved._parts.path.substring(-2) === '..') {\n resolved._parts.path += '/';\n }\n\n if (resolved.path().charAt(0) !== '/') {\n basedir = base.directory();\n basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : '';\n resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path;\n resolved.normalizePath();\n }\n\n resolved.build();\n return resolved;\n };\n p.relativeTo = function(base) {\n var relative = this.clone().normalize();\n var relativeParts, baseParts, common, relativePath, basePath;\n\n if (relative._parts.urn) {\n throw new Error('URNs do not have any generally defined hierarchical components');\n }\n\n base = new URI(base).normalize();\n relativeParts = relative._parts;\n baseParts = base._parts;\n relativePath = relative.path();\n basePath = base.path();\n\n if (relativePath.charAt(0) !== '/') {\n throw new Error('URI is already relative');\n }\n\n if (basePath.charAt(0) !== '/') {\n throw new Error('Cannot calculate a URI relative to another relative URI');\n }\n\n if (relativeParts.protocol === baseParts.protocol) {\n relativeParts.protocol = null;\n }\n\n if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {\n return relative.build();\n }\n\n if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {\n return relative.build();\n }\n\n if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {\n relativeParts.hostname = null;\n relativeParts.port = null;\n } else {\n return relative.build();\n }\n\n if (relativePath === basePath) {\n relativeParts.path = '';\n return relative.build();\n }\n\n // determine common sub path\n common = URI.commonPath(relativePath, basePath);\n\n // If the paths have nothing in common, return a relative URL with the absolute path.\n if (!common) {\n return relative.build();\n }\n\n var parents = baseParts.path\n .substring(common.length)\n .replace(/[^\\/]*$/, '')\n .replace(/.*?\\//g, '../');\n\n relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './';\n\n return relative.build();\n };\n\n // comparing URIs\n p.equals = function(uri) {\n var one = this.clone();\n var two = new URI(uri);\n var one_map = {};\n var two_map = {};\n var checked = {};\n var one_query, two_query, key;\n\n one.normalize();\n two.normalize();\n\n // exact match\n if (one.toString() === two.toString()) {\n return true;\n }\n\n // extract query string\n one_query = one.query();\n two_query = two.query();\n one.query('');\n two.query('');\n\n // definitely not equal if not even non-query parts match\n if (one.toString() !== two.toString()) {\n return false;\n }\n\n // query parameters have the same length, even if they're permuted\n if (one_query.length !== two_query.length) {\n return false;\n }\n\n one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace);\n two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace);\n\n for (key in one_map) {\n if (hasOwn.call(one_map, key)) {\n if (!isArray(one_map[key])) {\n if (one_map[key] !== two_map[key]) {\n return false;\n }\n } else if (!arraysEqual(one_map[key], two_map[key])) {\n return false;\n }\n\n checked[key] = true;\n }\n }\n\n for (key in two_map) {\n if (hasOwn.call(two_map, key)) {\n if (!checked[key]) {\n // two contains a parameter not present in one\n return false;\n }\n }\n }\n\n return true;\n };\n\n // state\n p.duplicateQueryParameters = function(v) {\n this._parts.duplicateQueryParameters = !!v;\n return this;\n };\n\n p.escapeQuerySpace = function(v) {\n this._parts.escapeQuerySpace = !!v;\n return this;\n };\n\n return URI;\n}));\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar Spine = require('./spine');\nvar Locations = require('./locations');\nvar Parser = require('./parser');\nvar Navigation = require('./navigation');\nvar Rendition = require('./rendition');\nvar Continuous = require('./continuous');\nvar Paginate = require('./paginate');\nvar Unarchive = require('./unarchive');\nvar request = require('./request');\nvar EpubCFI = require('./epubcfi');\n\nfunction Book(_url, options){\n // Promises\n this.opening = new RSVP.defer();\n this.opened = this.opening.promise;\n this.isOpen = false;\n\n this.url = undefined;\n\n this.loading = {\n manifest: new RSVP.defer(),\n spine: new RSVP.defer(),\n metadata: new RSVP.defer(),\n cover: new RSVP.defer(),\n navigation: new RSVP.defer(),\n pageList: new RSVP.defer()\n };\n\n this.loaded = {\n manifest: this.loading.manifest.promise,\n spine: this.loading.spine.promise,\n metadata: this.loading.metadata.promise,\n cover: this.loading.cover.promise,\n navigation: this.loading.navigation.promise,\n pageList: this.loading.pageList.promise\n };\n\n this.ready = RSVP.hash(this.loaded);\n\n // Queue for methods used before opening\n this.isRendered = false;\n // this._q = core.queue(this);\n\n this.request = this.requestMethod.bind(this);\n\n this.spine = new Spine(this.request);\n this.locations = new Locations(this.spine, this.request);\n\n if(_url) {\n this.open(_url);\n }\n};\n\nBook.prototype.open = function(_url){\n var uri;\n var parse = new Parser();\n var epubPackage;\n var epubContainer;\n var book = this;\n var containerPath = \"META-INF/container.xml\";\n var location;\n\n if(!_url) {\n this.opening.resolve(this);\n return this.opened;\n }\n\n // Reuse parsed url or create a new uri object\n // if(typeof(_url) === \"object\") {\n // uri = _url;\n // } else {\n // uri = core.uri(_url);\n // }\n uri = URI(_url);\n this.url = _url;\n\n // Find path to the Container\n if(uri.suffix() === \"opf\") {\n // Direct link to package, no container\n this.packageUrl = _url;\n this.containerUrl = '';\n\n if(uri.origin()) {\n this.baseUrl = uri.origin() + \"/\" + uri.directory() + \"/\";\n } else if(window){\n this.baseUrl = uri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n this.baseUrl = uri.directory() + \"/\";\n }\n\n epubPackage = this.request(this.packageUrl);\n\n } else if(this.isArchivedUrl(uri)) {\n // Book is archived\n this.url = '/';\n this.containerUrl = URI(containerPath).absoluteTo(this.url).toString();\n\n epubContainer = this.unarchive(_url).\n then(function() {\n return this.request(this.containerUrl);\n }.bind(this));\n\n }\n // Find the path to the Package from the container\n else if (!uri.suffix()) {\n\n this.containerUrl = this.url + containerPath;\n\n epubContainer = this.request(this.containerUrl)\n .catch(function(error) {\n // handle errors in loading container\n book.opening.reject(error);\n });\n }\n\n if (epubContainer) {\n epubPackage = epubContainer.\n then(function(containerXml){\n return parse.container(containerXml); // Container has path to content\n }).\n then(function(paths){\n var packageUri = URI(paths.packagePath);\n var absPackageUri = packageUri.absoluteTo(book.url);\n book.packageUrl = absPackageUri.toString();\n book.encoding = paths.encoding;\n\n // Set Url relative to the content\n if(packageUri.origin()) {\n book.baseUrl = packageUri.origin() + \"/\" + packageUri.directory() + \"/\";\n } else if(window && !book.isArchivedUrl(uri)){\n book.baseUrl = absPackageUri.absoluteTo(window.location.href).directory() + \"/\";\n } else {\n book.baseUrl = \"/\" + packageUri.directory() + \"/\";\n }\n\n return book.request(book.packageUrl);\n }).catch(function(error) {\n // handle errors in either of the two requests\n console.error(\"Could not load book at: \" + (this.packageUrl || this.containerPath));\n book.trigger(\"book:loadFailed\", (this.packageUrl || this.containerPath));\n book.opening.reject(error);\n });\n }\n\n epubPackage.then(function(packageXml) {\n // Get package information from epub opf\n book.unpack(packageXml);\n\n // Resolve promises\n book.loading.manifest.resolve(book.package.manifest);\n book.loading.metadata.resolve(book.package.metadata);\n book.loading.spine.resolve(book.spine);\n book.loading.cover.resolve(book.cover);\n\n book.isOpen = true;\n\n // Clear queue of any waiting book request\n\n // Resolve book opened promise\n book.opening.resolve(book);\n\n }).catch(function(error) {\n // handle errors in parsing the book\n console.error(error.message, error.stack);\n book.opening.reject(error);\n });\n\n return this.opened;\n};\n\nBook.prototype.unpack = function(packageXml){\n var book = this,\n parse = new Parser();\n\n book.package = parse.packageContents(packageXml); // Extract info from contents\n if(!book.package) {\n return;\n }\n\n book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths\n\n this.spine.load(book.package);\n\n book.navigation = new Navigation(book.package, this.request);\n book.navigation.load().then(function(toc){\n book.toc = toc;\n book.loading.navigation.resolve(book.toc);\n });\n\n // //-- Set Global Layout setting based on metadata\n // MOVE TO RENDER\n // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);\n\n book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();\n};\n\n// Alias for book.spine.get\nBook.prototype.section = function(target) {\n return this.spine.get(target);\n};\n\n// Sugar to render a book\nBook.prototype.renderTo = function(element, options) {\n var renderMethod = (options && options.method) ?\n options.method :\n \"rendition\";\n var Renderer = require('./'+renderMethod);\n\n this.rendition = new Renderer(this, options);\n this.rendition.attachTo(element);\n\n return this.rendition;\n};\n\nBook.prototype.requestMethod = function(_url) {\n // Switch request methods\n if(this.archive) {\n return this.archive.request(_url);\n } else {\n return request(_url, null, this.requestCredentials, this.requestHeaders);\n }\n\n};\n\nBook.prototype.setRequestCredentials = function(_credentials) {\n this.requestCredentials = _credentials;\n};\n\nBook.prototype.setRequestHeaders = function(_headers) {\n this.requestHeaders = _headers;\n};\n\nBook.prototype.unarchive = function(bookUrl){\n\tthis.archive = new Unarchive();\n\treturn this.archive.open(bookUrl);\n};\n\n//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)\nBook.prototype.isArchivedUrl = function(bookUrl){\n var uri;\n var extension;\n\n if (bookUrl instanceof ArrayBuffer) {\n\t\treturn true;\n\t}\n\n // Reuse parsed url or create a new uri object\n // if(typeof(bookUrl) === \"object\") {\n // uri = bookUrl;\n // } else {\n // uri = core.uri(bookUrl);\n // }\n uri = URI(bookUrl);\n extension = uri.suffix();\n\n\tif(extension && (extension == \"epub\" || extension == \"zip\")){\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n//-- Returns the cover\nBook.prototype.coverUrl = function(){\n\tvar retrieved = this.loaded.cover.\n\t\tthen(function(url) {\n\t\t\tif(this.archive) {\n\t\t\t\treturn this.archive.createUrl(this.cover);\n\t\t\t}else{\n\t\t\t\treturn this.cover;\n\t\t\t}\n\t\t}.bind(this));\n\n\n\n\treturn retrieved;\n};\n\nBook.prototype.range = function(cfiRange) {\n var cfi = new EpubCFI(cfiRange);\n var item = this.spine.get(cfi.spinePos);\n\n return item.load().then(function (contents) {\n var range = cfi.toRange(item.document);\n return range;\n })\n};\n\nmodule.exports = Book;\n\n//-- Enable binding events to book\nRSVP.EventTarget.mixin(Book.prototype);\n\n//-- Handle RSVP Errors\nRSVP.on('error', function(event) {\n console.error(event);\n});\n\nRSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections\n// RSVP.on('created', listener);\n// RSVP.on('chained', listener);\n// RSVP.on('fulfilled', listener);\nRSVP.on('rejected', function(event){\n console.error(event.detail.message, event.detail.stack);\n});\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Rendition = require('./rendition');\nvar View = require('./view');\n\nfunction Continuous(book, options) {\n\n\tRendition.apply(this, arguments); // call super constructor.\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\toverflow: \"auto\",\n\t\taxis: \"vertical\",\n\t\toffset: 500,\n\t\toffsetDelta: 250\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t}\n\n\n};\n\n// subclass extends superclass\nContinuous.prototype = Object.create(Rendition.prototype);\nContinuous.prototype.constructor = Continuous;\n\nContinuous.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to a percent\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n\n\tif(this.settings.infinite) {\n\t\tthis.start();\n\t}\n\n\n};\n\nContinuous.prototype.parseTarget = function(target){\n\tif(this.epubcfi.isCfiString(target)) {\n cfi = new EpubCFI(target);\n spinePos = cfi.spinePos;\n section = this.book.spine.get(spinePos);\n } else {\n section = this.book.spine.get(target);\n }\n};\n\nContinuous.prototype.moveTo = function(offset){\n // var bounds = this.bounds();\n // var dist = Math.floor(offset.top / bounds.height) * bounds.height;\n return this.check(\n\t\toffset.left+this.settings.offset,\n\t\toffset.top+this.settings.offset)\n\t\t.then(function(){\n\n\t if(this.settings.axis === \"vertical\") {\n\t this.scrollBy(0, offset.top);\n\t } else {\n\t this.scrollBy(offset.left, 0);\n\t }\n\n\t }.bind(this));\n};\n\nContinuous.prototype.afterDisplayed = function(currView){\n\tvar next = currView.section.next();\n\tvar prev = currView.section.prev();\n\tvar index = this.views.indexOf(currView);\n\tvar prevView, nextView;\n\n\tif(index + 1 === this.views.length && next) {\n\t\tnextView = this.createView(next);\n\t\tthis.q.enqueue(this.append, nextView);\n\t}\n\n\tif(index === 0 && prev) {\n\t\tprevView = this.createView(prev, this.viewSettings);\n\t\tthis.q.enqueue(this.prepend, prevView);\n\t}\n\n\t// this.removeShownListeners(currView);\n\t// currView.onShown = this.afterDisplayed.bind(this);\n\tthis.trigger(\"added\", currView.section);\n\n};\n\n\n// Remove Previous Listeners if present\nContinuous.prototype.removeShownListeners = function(view){\n\n\t// view.off(\"shown\", this.afterDisplayed);\n\t// view.off(\"shown\", this.afterDisplayedAbove);\n\tview.onDisplayed = function(){};\n\n};\n\nContinuous.prototype.append = function(view){\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tthis.views.append(view);\n\n //this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.prepend = function(view){\n\t// view.on(\"shown\", this.afterDisplayedAbove.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\tview.on(\"resized\", this.counter.bind(this));\n\n\tthis.views.prepend(view);\n\n // this.q.enqueue(this.check);\n return this.check();\n};\n\nContinuous.prototype.counter = function(bounds){\n\n\tif(this.settings.axis === \"vertical\") {\n\t\tthis.scrollBy(0, bounds.heightDelta, true);\n\t} else {\n\t\tthis.scrollBy(bounds.widthDelta, 0, true);\n\t}\n\n};\n\nContinuous.prototype.check = function(_offset){\n\tvar checking = new RSVP.defer();\n\tvar container = this.bounds();\n var promises = [];\n var offset = _offset || this.settings.offset;\n\n\tthis.views.each(function(view){\n\t\tvar visible = this.isVisible(view, offset, offset, container);\n\n\t\tif(visible) {\n\n\t\t\tif(!view.displayed && !view.rendering) {\n // console.log(\"render\",view.section.index)\n\t\t\t\t\tpromises.push(this.render(view));\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif(view.displayed) {\n // console.log(\"destroy\", view.section.index)\n this.q.enqueue(view.destroy.bind(view));\n // view.destroy();\n // this.q.enqueue(this.trim);\n clearTimeout(this.trimTimeout);\n this.trimTimeout = setTimeout(function(){\n this.q.enqueue(this.trim);\n }.bind(this), 250);\n\t\t\t}\n\n\t\t}\n\n\t}.bind(this));\n\n\n if(promises.length){\n\n return RSVP.all(promises)\n .then(function(posts) {\n // Check to see if anything new is on screen after rendering\n this.q.enqueue(this.check);\n\n }.bind(this));\n\n } else {\n checking.resolve();\n\n return checking.promise;\n }\n\n};\n\nContinuous.prototype.trim = function(){\n var task = new RSVP.defer();\n var displayed = this.views.displayed();\n var first = displayed[0];\n var last = displayed[displayed.length-1];\n var firstIndex = this.views.indexOf(first);\n var lastIndex = this.views.indexOf(last);\n var above = this.views.slice(0, firstIndex);\n var below = this.views.slice(lastIndex+1);\n\n // Erase all but last above\n for (var i = 0; i < above.length-1; i++) {\n this.erase(above[i], above);\n }\n\n // Erase all except first below\n for (var j = 1; j < below.length; j++) {\n this.erase(below[j]);\n }\n\n task.resolve();\n return task.promise;\n};\n\nContinuous.prototype.erase = function(view, above){ //Trim\n\n\tvar prevTop;\n\tvar prevLeft;\n\n\tif(this.settings.height) {\n \tprevTop = this.container.scrollTop;\n\t\tprevLeft = this.container.scrollLeft;\n } else {\n \tprevTop = window.scrollY;\n\t\tprevLeft = window.scrollX;\n }\n\n\tvar bounds = view.bounds();\n\n\tthis.views.remove(view);\n\n\tif(above) {\n\n\t\tif(this.settings.axis === \"vertical\") {\n\t\t\tthis.scrollTo(0, prevTop - bounds.height, true);\n\t\t} else {\n\t\t\tthis.scrollTo(prevLeft - bounds.width, 0, true);\n\t\t}\n\t}\n\n};\n\nContinuous.prototype.start = function() {\n var scroller;\n\n this.tick = core.requestAnimationFrame;\n\n if(this.settings.height) {\n \tthis.prevScrollTop = this.container.scrollTop;\n \tthis.prevScrollLeft = this.container.scrollLeft;\n } else {\n \tthis.prevScrollTop = window.scrollY;\n\t\tthis.prevScrollLeft = window.scrollX;\n }\n\n this.scrollDeltaVert = 0;\n this.scrollDeltaHorz = 0;\n\n if(this.settings.height) {\n \tscroller = this.container;\n } else {\n \tscroller = window;\n }\n\n window.addEventListener(\"scroll\", function(e){\n if(!this.ignore) {\n this.scrolled = true;\n } else {\n this.ignore = false;\n }\n }.bind(this));\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n this.tick.call(window, this.onScroll.bind(this));\n\n this.scrolled = false;\n\n};\n\nContinuous.prototype.onScroll = function(){\n\n if(this.scrolled) {\n\n if(this.settings.height) {\n\t \tscrollTop = this.container.scrollTop;\n\t \tscrollLeft = this.container.scrollLeft;\n\t } else {\n\t \tscrollTop = window.scrollY;\n\t\t\tscrollLeft = window.scrollX;\n\t }\n\n if(!this.ignore) {\n\n\t if((this.scrollDeltaVert === 0 &&\n\t \t this.scrollDeltaHorz === 0) ||\n\t \t this.scrollDeltaVert > this.settings.offsetDelta ||\n\t \t this.scrollDeltaHorz > this.settings.offsetDelta) {\n\n\t\t\t\tthis.q.enqueue(this.check);\n\n\t\t\t\tthis.scrollDeltaVert = 0;\n\t \tthis.scrollDeltaHorz = 0;\n\n\t\t\t\tthis.trigger(\"scroll\", {\n\t\t top: scrollTop,\n\t\t left: scrollLeft\n\t\t });\n\n\t\t\t}\n\n\t\t} else {\n\t this.ignore = false;\n\t\t}\n\n this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);\n this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);\n\n\t\tthis.prevScrollTop = scrollTop;\n\t\tthis.prevScrollLeft = scrollLeft;\n\n \tclearTimeout(this.scrollTimeout);\n\t\tthis.scrollTimeout = setTimeout(function(){\n\t\t\tthis.scrollDeltaVert = 0;\n\t this.scrollDeltaHorz = 0;\n\t\t}.bind(this), 150);\n\n\n this.scrolled = false;\n }\n\n this.tick.call(window, this.onScroll.bind(this));\n\n};\n\n\n Continuous.prototype.resizeView = function(view) {\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tview.lock(\"height\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nContinuous.prototype.currentLocation = function(){\n var visible = this.visible();\n var startPage, endPage;\n\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n return this.map.page(visible[0]);\n }\n\n if(visible.length > 1) {\n\n startPage = this.map.page(visible[0]);\n endPage = this.map.page(visible[visible.length-1]);\n\n return {\n start: startPage.start,\n end: endPage.end\n };\n }\n\n};\n\n/*\nContinuous.prototype.current = function(what){\n var view, top;\n var container = this.container.getBoundingClientRect();\n var length = this.views.length - 1;\n\n if(this.settings.axis === \"horizontal\") {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n left = view.position().left;\n\n if(left < container.right) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n break;\n }\n }\n\n } else {\n\n for (var i = length; i >= 0; i--) {\n view = this.views[i];\n top = view.bounds().top;\n if(top < container.bottom) {\n\n if(this._current == view) {\n break;\n }\n\n this._current = view;\n\n break;\n }\n }\n\n }\n\n return this._current;\n};\n*/\n\nmodule.exports = Continuous;\n","var RSVP = require('rsvp');\n\nvar requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame) : false;\n/*\n//-- Parse the different parts of a url, returning a object\nfunction uri(url){\n var uri = {\n protocol : '',\n host : '',\n path : '',\n origin : '',\n directory : '',\n base : '',\n filename : '',\n extension : '',\n fragment : '',\n href : url\n },\n doubleSlash = url.indexOf('://'),\n search = url.indexOf('?'),\n fragment = url.indexOf(\"#\"),\n withoutProtocol,\n dot,\n firstSlash;\n\n if(fragment != -1) {\n uri.fragment = url.slice(fragment + 1);\n url = url.slice(0, fragment);\n }\n\n if(search != -1) {\n uri.search = url.slice(search + 1);\n url = url.slice(0, search);\n href = url;\n }\n\n if(doubleSlash != -1) {\n uri.protocol = url.slice(0, doubleSlash);\n withoutProtocol = url.slice(doubleSlash+3);\n firstSlash = withoutProtocol.indexOf('/');\n\n if(firstSlash === -1) {\n uri.host = uri.path;\n uri.path = \"\";\n } else {\n uri.host = withoutProtocol.slice(0, firstSlash);\n uri.path = withoutProtocol.slice(firstSlash);\n }\n\n\n uri.origin = uri.protocol + \"://\" + uri.host;\n\n uri.directory = folder(uri.path);\n\n uri.base = uri.origin + uri.directory;\n // return origin;\n } else {\n uri.path = url;\n uri.directory = folder(url);\n uri.base = uri.directory;\n }\n\n //-- Filename\n uri.filename = url.replace(uri.base, '');\n dot = uri.filename.lastIndexOf('.');\n if(dot != -1) {\n uri.extension = uri.filename.slice(dot+1);\n }\n return uri;\n};\n\n//-- Parse out the folder, will return everything before the last slash\nfunction folder(url){\n\n var lastSlash = url.lastIndexOf('/');\n\n if(lastSlash == -1) var folder = '';\n\n folder = url.slice(0, lastSlash + 1);\n\n return folder;\n\n};\n*/\nfunction isElement(obj) {\n return !!(obj && obj.nodeType == 1);\n};\n\n// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\nfunction uuid() {\n var d = new Date().getTime();\n var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (d + Math.random()*16)%16 | 0;\n d = Math.floor(d/16);\n return (c=='x' ? r : (r&0x7|0x8)).toString(16);\n });\n return uuid;\n};\n\n// From Lodash\nfunction values(object) {\n var index = -1,\n props = Object.keys(object),\n length = props.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = object[props[index]];\n }\n return result;\n};\n\nfunction resolveUrl(base, path) {\n var url = [],\n segments = [],\n baseUri = uri(base),\n pathUri = uri(path),\n baseDirectory = baseUri.directory,\n pathDirectory = pathUri.directory,\n directories = [],\n // folders = base.split(\"/\"),\n paths;\n\n // if(uri.host) {\n // return path;\n // }\n\n if(baseDirectory[0] === \"/\") {\n baseDirectory = baseDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n baseDirectory = baseDirectory.substring(0, baseDirectory.length-1);\n }\n\n if(pathDirectory[0] === \"/\") {\n pathDirectory = pathDirectory.substring(1);\n }\n\n if(pathDirectory[pathDirectory.length-1] === \"/\") {\n pathDirectory = pathDirectory.substring(0, pathDirectory.length-1);\n }\n\n if(baseDirectory) {\n directories = baseDirectory.split(\"/\");\n }\n\n paths = pathDirectory.split(\"/\");\n\n paths.reverse().forEach(function(part, index){\n if(part === \"..\"){\n directories.pop();\n } else if(part === directories[directories.length-1]) {\n directories.pop();\n segments.unshift(part);\n } else {\n segments.unshift(part);\n }\n });\n\n url = [baseUri.origin];\n\n if(directories.length) {\n url = url.concat(directories);\n }\n\n if(segments) {\n url = url.concat(segments);\n }\n\n url = url.concat(pathUri.filename);\n\n return url.join(\"/\");\n};\n\nfunction documentHeight() {\n return Math.max(\n document.documentElement.clientHeight,\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight\n );\n};\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n};\n\nfunction prefixed(unprefixed) {\n var vendors = [\"Webkit\", \"Moz\", \"O\", \"ms\" ],\n prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],\n upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),\n length = vendors.length;\n\n if (typeof(document.body.style[unprefixed]) != 'undefined') {\n return unprefixed;\n }\n\n for ( var i=0; i < length; i++ ) {\n if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {\n return vendors[i] + upper;\n }\n }\n\n return unprefixed;\n};\n\nfunction defaults(obj) {\n for (var i = 1, length = arguments.length; i < length; i++) {\n var source = arguments[i];\n for (var prop in source) {\n if (obj[prop] === void 0) obj[prop] = source[prop];\n }\n }\n return obj;\n};\n\nfunction extend(target) {\n var sources = [].slice.call(arguments, 1);\n sources.forEach(function (source) {\n if(!source) return;\n Object.getOwnPropertyNames(source).forEach(function(propName) {\n Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));\n });\n });\n return target;\n};\n\n// Fast quicksort insert for sorted array -- based on:\n// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers\nfunction insert(item, array, compareFunction) {\n var location = locationOf(item, array, compareFunction);\n array.splice(location, 0, item);\n\n return location;\n};\n// Returns where something would fit in\nfunction locationOf(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return pivot;\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared > 0 ? pivot : pivot + 1;\n }\n\n if(compared === 0) {\n return pivot;\n }\n if(compared === -1) {\n return locationOf(item, array, compareFunction, pivot, end);\n } else{\n return locationOf(item, array, compareFunction, start, pivot);\n }\n};\n// Returns -1 of mpt found\nfunction indexOfSorted(item, array, compareFunction, _start, _end) {\n var start = _start || 0;\n var end = _end || array.length;\n var pivot = parseInt(start + (end - start) / 2);\n var compared;\n if(!compareFunction){\n compareFunction = function(a, b) {\n if(a > b) return 1;\n if(a < b) return -1;\n if(a = b) return 0;\n };\n }\n if(end-start <= 0) {\n return -1; // Not found\n }\n\n compared = compareFunction(array[pivot], item);\n if(end-start === 1) {\n return compared === 0 ? pivot : -1;\n }\n if(compared === 0) {\n return pivot; // Found\n }\n if(compared === -1) {\n return indexOfSorted(item, array, compareFunction, pivot, end);\n } else{\n return indexOfSorted(item, array, compareFunction, start, pivot);\n }\n};\n\nfunction bounds(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"width\", \"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"height\", \"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction borders(el) {\n\n var style = window.getComputedStyle(el);\n var widthProps = [\"paddingRight\", \"paddingLeft\", \"marginRight\", \"marginLeft\", \"borderRightWidth\", \"borderLeftWidth\"];\n var heightProps = [\"paddingTop\", \"paddingBottom\", \"marginTop\", \"marginBottom\", \"borderTopWidth\", \"borderBottomWidth\"];\n\n var width = 0;\n var height = 0;\n\n widthProps.forEach(function(prop){\n width += parseFloat(style[prop]) || 0;\n });\n\n heightProps.forEach(function(prop){\n height += parseFloat(style[prop]) || 0;\n });\n\n return {\n height: height,\n width: width\n };\n\n};\n\nfunction windowBounds() {\n\n var width = window.innerWidth;\n var height = window.innerHeight;\n\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width: width,\n height: height\n };\n\n};\n\n//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496\nfunction cleanStringForXpath(str) {\n var parts = str.match(/[^'\"]+|['\"]/g);\n parts = parts.map(function(part){\n if (part === \"'\") {\n return '\\\"\\'\\\"'; // output \"'\"\n }\n\n if (part === '\"') {\n return \"\\'\\\"\\'\"; // output '\"'\n }\n return \"\\'\" + part + \"\\'\";\n });\n return \"concat(\\'\\',\" + parts.join(\",\") + \")\";\n};\n\nfunction indexOfTextNode(textNode){\n var parent = textNode.parentNode;\n var children = parent.childNodes;\n var sib;\n var index = -1;\n for (var i = 0; i < children.length; i++) {\n sib = children[i];\n if(sib.nodeType === Node.TEXT_NODE){\n index++;\n }\n if(sib == textNode) break;\n }\n\n return index;\n};\n\nfunction isXml(ext) {\n return ['xml', 'opf', 'ncx'].indexOf(ext) > -1;\n}\n\nfunction createBlobUrl(content, mime){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob = new Blob([content], {type : mime });\n\n tempUrl = _URL.createObjectURL(blob);\n\n return tempUrl;\n};\n\nfunction type(obj){\n return Object.prototype.toString.call(obj).slice(8, -1);\n}\n\nmodule.exports = {\n // 'uri': uri,\n // 'folder': folder,\n 'isElement': isElement,\n 'uuid': uuid,\n 'values': values,\n 'resolveUrl': resolveUrl,\n 'indexOfSorted': indexOfSorted,\n 'documentHeight': documentHeight,\n 'isNumber': isNumber,\n 'prefixed': prefixed,\n 'defaults': defaults,\n 'extend': extend,\n 'insert': insert,\n 'locationOf': locationOf,\n 'indexOfSorted': indexOfSorted,\n 'requestAnimationFrame': requestAnimationFrame,\n 'bounds': bounds,\n 'borders': borders,\n 'windowBounds': windowBounds,\n 'cleanStringForXpath': cleanStringForXpath,\n 'indexOfTextNode': indexOfTextNode,\n 'isXml': isXml,\n 'createBlobUrl': createBlobUrl,\n 'type': type\n};\n","var URI = require('urijs');\nvar core = require('./core');\n\n/**\n EPUB CFI spec: http://www.idpf.org/epub/linking/cfi/epub-cfi.html\n\n Implements:\n - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)\n - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)\n\n Does Not Implement:\n - Temporal Offset (~)\n - Spatial Offset (@)\n - Temporal-Spatial Offset (~ + @)\n - Text Location Assertion ([)\n*/\n\nfunction EpubCFI(cfiFrom, base, ignoreClass){\n var type;\n\n this.str = '';\n\n this.base = {};\n this.spinePos = 0; // For compatibility\n\n this.range = false; // true || false;\n\n this.path = {};\n this.start = null;\n this.end = null;\n\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof EpubCFI)) {\n return new EpubCFI(cfiFrom, base, ignoreClass);\n }\n\n if(typeof base === 'string') {\n this.base = this.parseComponent(base);\n } else if(typeof base === 'object' && base.steps) {\n this.base = base;\n }\n\n type = this.checkType(cfiFrom);\n\n\n if(type === 'string') {\n this.str = cfiFrom;\n return core.extend(this, this.parse(cfiFrom));\n } else if (type === 'range') {\n return core.extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));\n } else if (type === 'node') {\n return core.extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));\n } else if (type === 'EpubCFI' && cfiFrom.path) {\n return cfiFrom;\n } else if (!cfiFrom) {\n return this;\n } else {\n throw new TypeError('not a valid argument for EpubCFI');\n }\n\n};\n\nEpubCFI.prototype.checkType = function(cfi) {\n\n if (this.isCfiString(cfi)) {\n return 'string';\n // Is a range object\n } else if (typeof cfi === 'object' && core.type(cfi) === \"Range\"){\n return 'range';\n } else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function'\n return 'node';\n } else if (typeof cfi === 'object' && cfi instanceof EpubCFI){\n return 'EpubCFI';\n } else {\n return false;\n }\n};\n\nEpubCFI.prototype.parse = function(cfiStr) {\n var cfi = {\n spinePos: -1,\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n var baseComponent, pathComponent, range;\n\n if(typeof cfiStr !== \"string\") {\n return {spinePos: -1};\n }\n\n if(cfiStr.indexOf(\"epubcfi(\") === 0 && cfiStr[cfiStr.length-1] === \")\") {\n // Remove intial epubcfi( and ending )\n cfiStr = cfiStr.slice(8, cfiStr.length-1);\n }\n\n baseComponent = this.getChapterComponent(cfiStr);\n\n // Make sure this is a valid cfi or return\n if(!baseComponent) {\n return {spinePos: -1};\n }\n\n cfi.base = this.parseComponent(baseComponent);\n\n pathComponent = this.getPathComponent(cfiStr);\n cfi.path = this.parseComponent(pathComponent);\n\n range = this.getRange(cfiStr);\n\n if(range) {\n cfi.range = true;\n cfi.start = this.parseComponent(range[0]);\n cfi.end = this.parseComponent(range[1]);\n }\n\n // Get spine node position\n // cfi.spineSegment = cfi.base.steps[1];\n\n // Chapter segment is always the second step\n cfi.spinePos = cfi.base.steps[1].index;\n\n return cfi;\n};\n\nEpubCFI.prototype.parseComponent = function(componentStr){\n var component = {\n steps: [],\n terminal: {\n offset: null,\n assertion: null\n }\n };\n var parts = componentStr.split(':');\n var steps = parts[0].split('/');\n var terminal;\n\n if(parts.length > 1) {\n terminal = parts[1];\n component.terminal = this.parseTerminal(terminal);\n }\n\n if (steps[0] === '') {\n steps.shift(); // Ignore the first slash\n }\n\n component.steps = steps.map(function(step){\n return this.parseStep(step);\n }.bind(this));\n\n return component;\n};\n\nEpubCFI.prototype.parseStep = function(stepStr){\n var type, num, index, has_brackets, id;\n\n has_brackets = stepStr.match(/\\[(.*)\\]/);\n if(has_brackets && has_brackets[1]){\n id = has_brackets[1];\n }\n\n //-- Check if step is a text node or element\n num = parseInt(stepStr);\n\n if(isNaN(num)) {\n return;\n }\n\n if(num % 2 === 0) { // Even = is an element\n type = \"element\";\n index = num / 2 - 1;\n } else {\n type = \"text\";\n index = (num - 1 ) / 2;\n }\n\n return {\n \"type\" : type,\n 'index' : index,\n 'id' : id || null\n };\n};\n\nEpubCFI.prototype.parseTerminal = function(termialStr){\n var characterOffset, textLocationAssertion;\n var assertion = termialStr.match(/\\[(.*)\\]/);\n\n if(assertion && assertion[1]){\n characterOffset = parseInt(termialStr.split('[')[0]) || null;\n textLocationAssertion = assertion[1];\n } else {\n characterOffset = parseInt(termialStr) || null;\n }\n\n return {\n 'offset': characterOffset,\n 'assertion': textLocationAssertion\n };\n\n};\n\nEpubCFI.prototype.getChapterComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n return indirection[0];\n};\n\nEpubCFI.prototype.getPathComponent = function(cfiStr) {\n\n var indirection = cfiStr.split(\"!\");\n\n if(indirection[1]) {\n ranges = indirection[1].split(',');\n return ranges[0];\n }\n\n};\n\nEpubCFI.prototype.getRange = function(cfiStr) {\n\n var ranges = cfiStr.split(\",\");\n\n if(ranges.length === 3){\n return [\n ranges[1],\n ranges[2]\n ];\n }\n\n return false;\n};\n\nEpubCFI.prototype.getCharecterOffsetComponent = function(cfiStr) {\n var splitStr = cfiStr.split(\":\");\n return splitStr[1] || '';\n};\n\nEpubCFI.prototype.joinSteps = function(steps) {\n return steps.map(function(part){\n var segment = '';\n\n if(part.type === 'element') {\n segment += (part.index + 1) * 2;\n }\n\n if(part.type === 'text') {\n segment += 1 + (2 * part.index); // TODO: double check that this is odd\n }\n\n if(part.id) {\n segment += \"[\" + part.id + \"]\";\n }\n\n return segment;\n\n }).join('/');\n\n};\n\nEpubCFI.prototype.segmentString = function(segment) {\n var segmentString = '/';\n\n segmentString += this.joinSteps(segment.steps);\n\n if(segment.terminal && segment.terminal.offset != null){\n segmentString += ':' + segment.terminal.offset;\n }\n\n if(segment.terminal && segment.terminal.assertion != null){\n segmentString += '[' + segment.terminal.assertion + ']';\n }\n\n return segmentString;\n};\n\nEpubCFI.prototype.toString = function() {\n var cfiString = 'epubcfi(';\n\n cfiString += this.segmentString(this.base);\n\n cfiString += '!';\n cfiString += this.segmentString(this.path);\n\n // Add Range, if present\n if(this.start) {\n cfiString += ',';\n cfiString += this.segmentString(this.start);\n }\n\n if(this.end) {\n cfiString += ',';\n cfiString += this.segmentString(this.end);\n }\n\n cfiString += \")\";\n\n return cfiString;\n};\n\nEpubCFI.prototype.compare = function(cfiOne, cfiTwo) {\n if(typeof cfiOne === 'string') {\n cfiOne = new EpubCFI(cfiOne);\n }\n if(typeof cfiTwo === 'string') {\n cfiTwo = new EpubCFI(cfiTwo);\n }\n // Compare Spine Positions\n if(cfiOne.spinePos > cfiTwo.spinePos) {\n return 1;\n }\n if(cfiOne.spinePos < cfiTwo.spinePos) {\n return -1;\n }\n\n\n // Compare Each Step in the First item\n for (var i = 0; i < cfiOne.path.steps.length; i++) {\n if(!cfiTwo.path.steps[i]) {\n return 1;\n }\n if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {\n return 1;\n }\n if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {\n return -1;\n }\n // Otherwise continue checking\n }\n\n // All steps in First equal to Second and First is Less Specific\n if(cfiOne.path.steps.length < cfiTwo.path.steps.length) {\n return 1;\n }\n\n // Compare the charecter offset of the text node\n if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {\n return 1;\n }\n if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {\n return -1;\n }\n\n // TODO: compare ranges\n\n // CFI's are equal\n return 0;\n};\n\nEpubCFI.prototype.step = function(node) {\n var nodeType = (node.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n return {\n 'id' : node.id,\n 'tagName' : node.tagName,\n 'type' : nodeType,\n 'index' : this.position(node)\n };\n};\n\nEpubCFI.prototype.filteredStep = function(node, ignoreClass) {\n var filteredNode = this.filter(node, ignoreClass);\n var nodeType;\n\n // Node filtered, so ignore\n if (!filteredNode) {\n return;\n }\n\n // Otherwise add the filter node in\n nodeType = (filteredNode.nodeType === Node.TEXT_NODE) ? 'text' : 'element';\n\n return {\n 'id' : filteredNode.id,\n 'tagName' : filteredNode.tagName,\n 'type' : nodeType,\n 'index' : this.filteredPosition(filteredNode, ignoreClass)\n };\n};\n\nEpubCFI.prototype.pathTo = function(node, offset, ignoreClass) {\n var segment = {\n steps: [],\n terminal: {\n offset: null,\n assertion: null\n }\n };\n var currentNode = node;\n var step;\n\n while(currentNode && currentNode.parentNode &&\n currentNode.parentNode.nodeType != Node.DOCUMENT_NODE) {\n\n if (ignoreClass) {\n step = this.filteredStep(currentNode, ignoreClass);\n } else {\n step = this.step(currentNode);\n }\n\n if (step) {\n segment.steps.unshift(step);\n }\n\n currentNode = currentNode.parentNode;\n\n }\n\n if (offset != null && offset >= 0) {\n\n segment.terminal.offset = offset;\n\n // Make sure we are getting to a textNode if there is an offset\n if(segment.steps[segment.steps.length-1].type != \"text\") {\n segment.steps.push({\n 'type' : \"text\",\n 'index' : 0\n });\n }\n\n }\n\n\n return segment;\n}\n\nEpubCFI.prototype.equalStep = function(stepA, stepB) {\n if (!stepA || !stepB) {\n return false;\n }\n\n if(stepA.index === stepB.index &&\n stepA.id === stepB.id &&\n stepA.type === stepB.type) {\n return true;\n }\n\n return false;\n};\nEpubCFI.prototype.fromRange = function(range, base, ignoreClass) {\n var cfi = {\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n\n var start = range.startContainer;\n var end = range.endContainer;\n\n var startOffset = range.startOffset;\n var endOffset = range.endOffset;\n\n var needsIgnoring = false;\n\n if (ignoreClass) {\n // Tell pathTo if / what to ignore\n needsIgnoring = (start.ownerDocument.querySelector('.' + ignoreClass) != null);\n }\n\n\n if (typeof base === 'string') {\n cfi.base = this.parseComponent(base);\n cfi.spinePos = cfi.base.steps[1].index;\n } else if (typeof base === 'object') {\n cfi.base = base;\n }\n\n if (range.collapsed) {\n if (needsIgnoring) {\n startOffset = this.patchOffset(start, startOffset, ignoreClass);\n }\n cfi.path = this.pathTo(start, startOffset, ignoreClass);\n } else {\n cfi.range = true;\n\n if (needsIgnoring) {\n startOffset = this.patchOffset(start, startOffset, ignoreClass);\n }\n\n cfi.start = this.pathTo(start, startOffset, ignoreClass);\n\n if (needsIgnoring) {\n endOffset = this.patchOffset(end, endOffset, ignoreClass);\n }\n\n cfi.end = this.pathTo(end, endOffset, ignoreClass);\n\n // Create a new empty path\n cfi.path = {\n steps: [],\n terminal: null\n };\n\n // Push steps that are shared between start and end to the common path\n var len = cfi.start.steps.length;\n var i;\n\n for (i = 0; i < len; i++) {\n if (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {\n if(i == len-1) {\n // Last step is equal, check terminals\n if(cfi.start.terminal === cfi.end.terminal) {\n // CFI's are equal\n cfi.path.steps.push(cfi.start.steps[i]);\n // Not a range\n cfi.range = false;\n }\n } else {\n cfi.path.steps.push(cfi.start.steps[i]);\n }\n\n } else {\n break;\n }\n };\n\n cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);\n cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length);\n\n // TODO: Add Sanity check to make sure that the end if greater than the start\n }\n\n return cfi;\n}\n\nEpubCFI.prototype.fromNode = function(anchor, base, ignoreClass) {\n var cfi = {\n range: false,\n base: {},\n path: {},\n start: null,\n end: null\n };\n\n var needsIgnoring = false;\n\n if (ignoreClass) {\n // Tell pathTo if / what to ignore\n needsIgnoring = (anchor.ownerDocument.querySelector('.' + ignoreClass) != null);\n }\n\n if (typeof base === 'string') {\n cfi.base = this.parseComponent(base);\n cfi.spinePos = cfi.base.steps[1].index;\n } else if (typeof base === 'object') {\n cfi.base = base;\n }\n\n cfi.path = this.pathTo(anchor, null, ignoreClass);\n\n return cfi;\n};\n\n\nEpubCFI.prototype.filter = function(anchor, ignoreClass) {\n var needsIgnoring;\n var sibling; // to join with\n var parent, prevSibling, nextSibling;\n var isText = false;\n\n if (anchor.nodeType === Node.TEXT_NODE) {\n isText = true;\n parent = anchor.parentNode;\n needsIgnoring = anchor.parentNode.classList.contains(ignoreClass);\n } else {\n isText = false;\n needsIgnoring = anchor.classList.contains(ignoreClass);\n }\n\n if (needsIgnoring && isText) {\n previousSibling = parent.previousSibling;\n nextSibling = parent.nextSibling;\n\n // If the sibling is a text node, join the nodes\n if (previousSibling && previousSibling.nodeType === Node.TEXT_NODE) {\n sibling = previousSibling;\n } else if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n sibling = nextSibling;\n }\n\n if (sibling) {\n return sibling;\n } else {\n // Parent will be ignored on next step\n return anchor;\n }\n\n } else if (needsIgnoring && !isText) {\n // Otherwise just skip the element node\n return false;\n } else {\n // No need to filter\n return anchor;\n }\n\n};\n\nEpubCFI.prototype.patchOffset = function(anchor, offset, ignoreClass) {\n var needsIgnoring;\n var sibling;\n\n if (anchor.nodeType != Node.TEXT_NODE) {\n console.error(\"Anchor must be a text node\");\n return;\n }\n\n var curr = anchor;\n var totalOffset = offset;\n\n // If the parent is a ignored node, get offset from it's start\n if (anchor.parentNode.classList.contains(ignoreClass)) {\n curr = anchor.parentNode;\n }\n\n while (curr.previousSibling) {\n if(curr.previousSibling.nodeType === Node.ELEMENT_NODE) {\n // Originally a text node, so join\n if(curr.previousSibling.classList.contains(ignoreClass)){\n totalOffset += curr.previousSibling.textContent.length;\n } else {\n break; // Normal node, dont join\n }\n } else {\n // If the previous sibling is a text node, join the nodes\n totalOffset += curr.previousSibling.textContent.length;\n }\n\n curr = curr.previousSibling;\n }\n\n return totalOffset;\n\n};\n\nEpubCFI.prototype.normalizedMap = function(children, nodeType, ignoreClass) {\n var output = {};\n var prevIndex = -1;\n var i, len = children.length;\n var currNodeType;\n var prevNodeType;\n\n for (i = 0; i < len; i++) {\n\n currNodeType = children[i].nodeType;\n\n // Check if needs ignoring\n if (currNodeType === Node.ELEMENT_NODE &&\n children[i].classList.contains(ignoreClass)) {\n currNodeType = Node.TEXT_NODE;\n }\n\n if (i > 0 &&\n currNodeType === Node.TEXT_NODE &&\n prevNodeType === Node.TEXT_NODE) {\n // join text nodes\n output[i] = prevIndex;\n } else if (nodeType === currNodeType){\n prevIndex = prevIndex + 1;\n output[i] = prevIndex;\n }\n\n prevNodeType = currNodeType;\n\n }\n\n return output;\n};\n\nEpubCFI.prototype.position = function(anchor) {\n var children, index, map;\n\n if (anchor.nodeType === Node.ELEMENT_NODE) {\n children = anchor.parentNode.children;\n index = Array.prototype.indexOf.call(children, anchor);\n } else {\n children = this.textNodes(anchor.parentNode);\n index = children.indexOf(anchor);\n }\n\n return index;\n};\n\nEpubCFI.prototype.filteredPosition = function(anchor, ignoreClass) {\n var children, index, map;\n\n if (anchor.nodeType === Node.ELEMENT_NODE) {\n children = anchor.parentNode.children;\n map = this.normalizedMap(children, Node.ELEMENT_NODE, ignoreClass);\n } else {\n children = anchor.parentNode.childNodes;\n // Inside an ignored node\n if(anchor.parentNode.classList.contains(ignoreClass)) {\n anchor = anchor.parentNode;\n children = anchor.parentNode.childNodes;\n }\n map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n }\n\n\n index = Array.prototype.indexOf.call(children, anchor);\n\n return map[index];\n};\n\nEpubCFI.prototype.stepsToXpath = function(steps) {\n var xpath = [\".\", \"*\"];\n\n steps.forEach(function(step){\n var position = step.index + 1;\n\n if(step.id){\n xpath.push(\"*[position()=\" + position + \" and @id='\" + step.id + \"']\");\n } else if(step.type === \"text\") {\n xpath.push(\"text()[\" + position + \"]\");\n } else {\n xpath.push(\"*[\" + position + \"]\");\n }\n });\n\n return xpath.join(\"/\");\n};\n\n\n/*\n\nTo get the last step if needed:\n\n// Get the terminal step\nlastStep = steps[steps.length-1];\n// Get the query string\nquery = this.stepsToQuery(steps);\n// Find the containing element\nstartContainerParent = doc.querySelector(query);\n// Find the text node within that element\nif(startContainerParent && lastStep.type == \"text\") {\n container = startContainerParent.childNodes[lastStep.index];\n}\n*/\nEpubCFI.prototype.stepsToQuerySelector = function(steps) {\n var query = [\"html\"];\n\n steps.forEach(function(step){\n var position = step.index + 1;\n\n if(step.id){\n query.push(\"#\" + step.id);\n } else if(step.type === \"text\") {\n // unsupported in querySelector\n // query.push(\"text()[\" + position + \"]\");\n } else {\n query.push(\"*:nth-child(\" + position + \")\");\n }\n });\n\n return query.join(\">\");\n\n};\n\nEpubCFI.prototype.textNodes = function(container, ignoreClass) {\n return Array.prototype.slice.call(container.childNodes).\n filter(function (node) {\n if (node.nodeType === Node.TEXT_NODE) {\n return true;\n } else if (ignoreClass && node.classList.contains(ignoreClass)) {\n return true;\n }\n return false;\n });\n};\n\nEpubCFI.prototype.walkToNode = function(steps, _doc, ignoreClass) {\n var doc = _doc || document;\n var container = doc.documentElement;\n var step;\n var len = steps.length;\n var i;\n\n for (i = 0; i < len; i++) {\n step = steps[i];\n\n if(step.type === \"element\") {\n container = container.children[step.index];\n } else if(step.type === \"text\"){\n container = this.textNodes(container, ignoreClass)[step.index];\n }\n\n };\n\n return container;\n};\n\nEpubCFI.prototype.findNode = function(steps, _doc, ignoreClass) {\n var doc = _doc || document;\n var container;\n var xpath;\n\n if(!ignoreClass && typeof doc.evaluate != 'undefined') {\n xpath = this.stepsToXpath(steps);\n container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n } else if(ignoreClass) {\n container = this.walkToNode(steps, doc, ignoreClass);\n } else {\n container = this.walkToNode(steps, doc);\n }\n\n return container;\n};\n\nEpubCFI.prototype.fixMiss = function(steps, offset, _doc, ignoreClass) {\n var container = this.findNode(steps.slice(0,-1), _doc, ignoreClass);\n var children = container.childNodes;\n var map = this.normalizedMap(children, Node.TEXT_NODE, ignoreClass);\n var i;\n var child;\n var len;\n var childIndex;\n var lastStepIndex = steps[steps.length-1].index;\n\n for (var childIndex in map) {\n if (!map.hasOwnProperty(childIndex)) return;\n\n if(map[childIndex] === lastStepIndex) {\n child = children[childIndex];\n len = child.textContent.length;\n if(offset > len) {\n offset = offset - len;\n } else {\n if (child.nodeType === Node.ELEMENT_NODE) {\n container = child.childNodes[0];\n } else {\n container = child;\n }\n break;\n }\n }\n }\n\n return {\n container: container,\n offset: offset\n };\n\n};\n\nEpubCFI.prototype.toRange = function(_doc, ignoreClass) {\n var doc = _doc || document;\n var range = doc.createRange();\n var start, end, startContainer, endContainer;\n var cfi = this;\n var startSteps, endSteps;\n var needsIgnoring = ignoreClass ? (doc.querySelector('.' + ignoreClass) != null) : false;\n var missed;\n\n if (cfi.range) {\n start = cfi.start;\n startSteps = cfi.path.steps.concat(start.steps);\n startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);\n end = cfi.end;\n endSteps = cfi.path.steps.concat(end.steps);\n endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);\n } else {\n start = cfi.path;\n startSteps = cfi.path.steps;\n startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);\n }\n\n if(startContainer) {\n try {\n\n if(start.terminal.offset != null) {\n range.setStart(startContainer, start.terminal.offset);\n } else {\n range.setStart(startContainer, 0);\n }\n\n } catch (e) {\n missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n range.setStart(missed.container, missed.offset);\n }\n } else {\n // No start found\n return null;\n }\n\n if (endContainer) {\n try {\n\n if(end.terminal.offset != null) {\n range.setEnd(endContainer, end.terminal.offset);\n } else {\n range.setEnd(endContainer, 0);\n }\n\n } catch (e) {\n missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);\n range.setEnd(missed.container, missed.offset);\n }\n }\n\n\n // doc.defaultView.getSelection().addRange(range);\n return range;\n};\n\n// is a cfi string, should be wrapped with \"epubcfi()\"\nEpubCFI.prototype.isCfiString = function(str) {\n if(typeof str === 'string' &&\n str.indexOf(\"epubcfi(\") === 0 &&\n str[str.length-1] === \")\") {\n return true;\n }\n\n return false;\n};\n\nEpubCFI.prototype.generateChapterComponent = function(_spineNodeIndex, _pos, id) {\n var pos = parseInt(_pos),\n spineNodeIndex = _spineNodeIndex + 1,\n cfi = '/'+spineNodeIndex+'/';\n\n cfi += (pos + 1) * 2;\n\n if(id) {\n cfi += \"[\" + id + \"]\";\n }\n\n return cfi;\n};\n\nmodule.exports = EpubCFI;\n","var RSVP = require('rsvp');\n\n//-- Hooks allow for injecting functions that must all complete in order before finishing\n// They will execute in parallel but all must finish before continuing\n// Functions may return a promise if they are asycn.\n\n// this.content = new EPUBJS.Hook();\n// this.content.register(function(){});\n// this.content.trigger(args).then(function(){});\n\nfunction Hook(context){\n this.context = context || this;\n this.hooks = [];\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.register = function(){\n for(var i = 0; i < arguments.length; ++i) {\n if (typeof arguments[i] === \"function\") {\n this.hooks.push(arguments[i]);\n } else {\n // unpack array\n for(var j = 0; j < arguments[i].length; ++j) {\n this.hooks.push(arguments[i][j]);\n }\n }\n }\n};\n\n// Triggers a hook to run all functions\nHook.prototype.trigger = function(){\n var args = arguments;\n var context = this.context;\n var promises = [];\n\n this.hooks.forEach(function(task, i) {\n var executing = task.apply(context, args);\n\n if(executing && typeof executing[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n promises.push(executing);\n }\n // Otherwise Task resolves immediately, continue\n });\n\n\n return RSVP.all(promises);\n};\n\n// Adds a function to be run before a hook completes\nHook.prototype.list = function(){\n return this.hooks;\n};\n\nmodule.exports = Hook;\n","var core = require('./core');\n\nfunction Reflowable(){\n\n};\n\nReflowable.prototype.calculate = function(_width, _height, _gap, _devisor){\n\n var divisor = _devisor || 1;\n\n //-- Check the width and create even width columns\n var fullWidth = Math.floor(_width);\n var width = (fullWidth % 2 === 0) ? fullWidth : fullWidth - 1;\n\n var section = Math.floor(width / 8);\n var gap = (_gap >= 0) ? _gap : ((section % 2 === 0) ? section : section - 1);\n\n var colWidth;\n var spreadWidth;\n var delta;\n\n //-- Double Page\n if(divisor > 1) {\n colWidth = Math.floor((width - gap) / divisor);\n } else {\n colWidth = width;\n }\n\n spreadWidth = colWidth * divisor;\n\n delta = (colWidth + gap) * divisor;\n\n\n\n this.columnAxis = core.prefixed('columnAxis');\n this.columnGap = core.prefixed('columnGap');\n this.columnWidth = core.prefixed('columnWidth');\n this.columnFill = core.prefixed('columnFill');\n\n this.width = width;\n this.height = _height;\n this.spread = spreadWidth;\n this.delta = delta;\n\n this.column = colWidth;\n this.gap = gap;\n this.divisor = divisor;\n\n};\n\nReflowable.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n var $body = view.document.body;//view.document.querySelector(\"body\");\n\n $doc.style.overflow = \"hidden\";\n\n // Must be set to the new calculated width or the columns will be off\n // $body.style.width = this.width + \"px\";\n $doc.style.width = this.width + \"px\";\n\n //-- Adjust height\n $body.style.height = this.height + \"px\";\n\n //-- Add columns\n $body.style[this.columnAxis] = \"horizontal\";\n $body.style[this.columnFill] = \"auto\";\n $body.style[this.columnGap] = this.gap+\"px\";\n $body.style[this.columnWidth] = this.column+\"px\";\n\n // Add extra padding for the gap between this and the next view\n view.iframe.style.marginRight = this.gap+\"px\";\n};\n\nReflowable.prototype.count = function(view) {\n var totalWidth = view.root().scrollWidth;\n var spreads = Math.ceil(totalWidth / this.spread);\n\n return {\n spreads : spreads,\n pages : spreads * this.divisor\n };\n};\n\nfunction Fixed(_width, _height){\n\n};\n\nFixed.prototype.calculate = function(_width, _height){\n\n};\n\nFixed.prototype.format = function(view){\n var width, height;\n\n var $doc = view.document.documentElement;\n var $viewport = documentElement.querySelector(\"[name=viewport\");\n\n /**\n * check for the viewport size\n * \n */\n if($viewport && $viewport.hasAttribute(\"content\")) {\n content = $viewport.getAttribute(\"content\");\n contents = content.split(',');\n if(contents[0]){\n width = contents[0].replace(\"width=\", '');\n }\n if(contents[1]){\n height = contents[1].replace(\"height=\", '');\n }\n }\n\n //-- Adjust width and height\n // $doc.style.width = width + \"px\" || \"auto\";\n // $doc.style.height = height + \"px\" || \"auto\";\n view.resize(width, height);\n\n //-- Scroll\n $doc.style.overflow = \"auto\";\n\n};\n\nFixed.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nfunction Scroll(){\n\n};\n\nScroll.prototype.calculate = function(_width, _height){\n this.spread = _width;\n this.column = _width;\n this.gap = 0;\n};\n\nScroll.prototype.format = function(view){\n\n var $doc = view.document.documentElement;\n\n $doc.style.width = \"auto\";\n $doc.style.height = \"auto\";\n\n};\n\nScroll.prototype.count = function(){\n return {\n spreads : 1,\n pages : 1\n };\n};\n\nmodule.exports = {\n 'Reflowable': Reflowable,\n 'Fixed': Fixed,\n 'Scroll': Scroll\n};\n","var core = require('./core');\nvar Queue = require('./queue');\nvar EpubCFI = require('./epubcfi');\nvar RSVP = require('rsvp');\n\nfunction Locations(spine, request) {\n this.spine = spine;\n this.request = request;\n\n this.q = new Queue(this);\n this.epubcfi = new EpubCFI();\n\n this._locations = [];\n this.total = 0;\n\n this.break = 150;\n\n this._current = 0;\n\n};\n\n// Load all of sections in the book\nLocations.prototype.generate = function(chars) {\n\n if (chars) {\n this.break = chars;\n }\n\n this.q.pause();\n\n this.spine.each(function(section) {\n\n this.q.enqueue(this.process, section);\n\n }.bind(this));\n\n return this.q.run().then(function() {\n this.total = this._locations.length-1;\n\n if (this._currentCfi) {\n this.currentLocation = this._currentCfi;\n }\n\n return this._locations;\n // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));\n }.bind(this));\n\n};\n\nLocations.prototype.process = function(section) {\n\n return section.load(this.request)\n .then(function(contents) {\n\n var range;\n var doc = contents.ownerDocument;\n var counter = 0;\n\n this.sprint(contents, function(node) {\n var len = node.length;\n var dist;\n var pos = 0;\n\n // Start range\n if (counter == 0) {\n range = doc.createRange();\n range.setStart(node, 0);\n }\n\n dist = this.break - counter;\n\n // Node is smaller than a break\n if(dist > len){\n counter += len;\n pos = len;\n }\n\n while (pos < len) {\n counter = this.break;\n pos += this.break;\n\n // Gone over\n if(pos >= len){\n // Continue counter for next node\n counter = len - (pos - this.break);\n\n // At End\n } else {\n // End the previous range\n range.setEnd(node, pos);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi);\n counter = 0;\n\n // Start new range\n pos += 1;\n range = doc.createRange();\n range.setStart(node, pos);\n }\n }\n\n\n\n }.bind(this));\n\n // Close remaining\n if (range) {\n range.setEnd(prev, prev.length);\n cfi = section.cfiFromRange(range);\n this._locations.push(cfi)\n counter = 0;\n }\n\n }.bind(this));\n\n};\n\nLocations.prototype.sprint = function(root, func) {\n\tvar treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);\n\n\twhile ((node = treeWalker.nextNode())) {\n\t\tfunc(node);\n\t}\n\n};\n\nLocations.prototype.locationFromCfi = function(cfi){\n // Check if the location has not been set yet\n\tif(this._locations.length === 0) {\n\t\treturn -1;\n\t}\n\n return core.locationOf(cfi, this._locations, this.epubcfi.compare);\n};\n\nLocations.prototype.precentageFromCfi = function(cfi) {\n // Find closest cfi\n var loc = this.locationFromCfi(cfi);\n // Get percentage in total\n return this.precentageFromLocation(loc);\n};\n\nLocations.prototype.percentageFromLocation = function(loc) {\n if (!loc || !this.total) {\n return 0;\n }\n return (loc / this.total);\n};\n\nLocations.prototype.cfiFromLocation = function(loc){\n\tvar cfi = -1;\n\t// check that pg is an int\n\tif(typeof loc != \"number\"){\n\t\tloc = parseInt(pg);\n\t}\n\n\tif(loc >= 0 && loc < this._locations.length) {\n\t\tcfi = this._locations[loc];\n\t}\n\n\treturn cfi;\n};\n\nLocations.prototype.cfiFromPercentage = function(value){\n var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1\n\tvar loc = Math.ceil(this.total * percentage);\n\n\treturn this.cfiFromLocation(loc);\n};\n\nLocations.prototype.load = function(locations){\n\tthis._locations = JSON.parse(locations);\n this.total = this._locations.length-1;\n return this._locations;\n};\n\nLocations.prototype.save = function(json){\n\treturn JSON.stringify(this._locations);\n};\n\nLocations.prototype.getCurrent = function(json){\n\treturn this._current;\n};\n\nLocations.prototype.setCurrent = function(curr){\n var loc;\n\n if(typeof curr == \"string\"){\n this._currentCfi = curr;\n } else if (typeof curr == \"number\") {\n this._current = curr;\n } else {\n return;\n }\n\n if(this._locations.length === 0) {\n return;\n\t}\n\n if(typeof curr == \"string\"){\n loc = this.locationFromCfi(curr);\n this._current = loc;\n } else {\n loc = curr;\n }\n\n this.trigger(\"changed\", {\n percentage: this.precentageFromLocation(loc)\n });\n};\n\nObject.defineProperty(Locations.prototype, 'currentLocation', {\n get: function () {\n return this._current;\n },\n set: function (curr) {\n this.setCurrent(curr);\n }\n});\n\nRSVP.EventTarget.mixin(Locations.prototype);\n\nmodule.exports = Locations;\n","function Map(layout){\n this.layout = layout;\n};\n\nMap.prototype.section = function(view) {\n var ranges = this.findRanges(view);\n var map = this.rangeListToCfiList(view, ranges);\n\n return map;\n};\n\nMap.prototype.page = function(view, start, end) {\n var root = view.document.body;\n return this.rangePairToCfiPair(view.section, {\n start: this.findStart(root, start, end),\n end: this.findEnd(root, start, end)\n });\n};\n\nMap.prototype.walk = function(root, func) {\n //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);\n var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode: function (node) {\n if ( node.data.trim().length > 0 ) {\n return NodeFilter.FILTER_ACCEPT;\n } else {\n return NodeFilter.FILTER_REJECT;\n }\n }\n }, false);\n var node;\n var result;\n while ((node = treeWalker.nextNode())) {\n result = func(node);\n if(result) break;\n }\n\n return result;\n};\n\nMap.prototype.findRanges = function(view){\n var columns = [];\n var count = this.layout.count(view);\n var column = this.layout.column;\n var gap = this.layout.gap;\n var start, end;\n\n for (var i = 0; i < count.pages; i++) {\n start = (column + gap) * i;\n end = (column * (i+1)) + (gap * i);\n columns.push({\n start: this.findStart(view.document.body, start, end),\n end: this.findEnd(view.document.body, start, end)\n });\n }\n\n return columns;\n};\n\nMap.prototype.findStart = function(root, start, end){\n var stack = [root];\n var $el;\n var found;\n var $prev = root;\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if( left >= start && left <= end ) {\n return node;\n } else if (right > start) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n if(found) {\n return this.findTextStartRange(found, start, end);\n }\n\n }\n\n // Return last element\n return this.findTextStartRange($prev, start, end);\n};\n\nMap.prototype.findEnd = function(root, start, end){\n var stack = [root];\n var $el;\n var $prev = root;\n var found;\n\n while (stack.length) {\n\n $el = stack.shift();\n\n found = this.walk($el, function(node){\n\n var left, right;\n var elPos;\n var elRange;\n\n\n if(node.nodeType == Node.TEXT_NODE){\n elRange = document.createRange();\n elRange.selectNodeContents(node);\n elPos = elRange.getBoundingClientRect();\n } else {\n elPos = node.getBoundingClientRect();\n }\n\n left = elPos.left;\n right = elPos.right;\n\n if(left > end && $prev) {\n return $prev;\n } else if(right > end) {\n return node;\n } else {\n $prev = node;\n stack.push(node);\n }\n\n });\n\n\n if(found){\n return this.findTextEndRange(found, start, end);\n }\n\n }\n\n // end of chapter\n return this.findTextEndRange($prev, start, end);\n};\n\n\nMap.prototype.findTextStartRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if( pos.left >= start ) {\n return range;\n }\n\n prev = range;\n\n }\n\n return ranges[0];\n};\n\nMap.prototype.findTextEndRange = function(node, start, end){\n var ranges = this.splitTextNodeIntoRanges(node);\n var prev;\n var range;\n var pos;\n\n for (var i = 0; i < ranges.length; i++) {\n range = ranges[i];\n\n pos = range.getBoundingClientRect();\n\n if(pos.left > end && prev) {\n return prev;\n } else if(pos.right > end) {\n return range;\n }\n\n prev = range;\n\n }\n\n // Ends before limit\n return ranges[ranges.length-1];\n\n};\n\nMap.prototype.splitTextNodeIntoRanges = function(node, _splitter){\n var ranges = [];\n var textContent = node.textContent || \"\";\n var text = textContent.trim();\n var range;\n var rect;\n var list;\n var doc = node.ownerDocument;\n var splitter = _splitter || \" \";\n\n pos = text.indexOf(splitter);\n\n if(pos === -1 || node.nodeType != Node.TEXT_NODE) {\n range = doc.createRange();\n range.selectNodeContents(node);\n return [range];\n }\n\n range = doc.createRange();\n range.setStart(node, 0);\n range.setEnd(node, pos);\n ranges.push(range);\n range = false;\n\n while ( pos != -1 ) {\n\n pos = text.indexOf(splitter, pos + 1);\n if(pos > 0) {\n\n if(range) {\n range.setEnd(node, pos);\n ranges.push(range);\n }\n\n range = doc.createRange();\n range.setStart(node, pos+1);\n }\n }\n\n if(range) {\n range.setEnd(node, text.length);\n ranges.push(range);\n }\n\n return ranges;\n};\n\n\n\nMap.prototype.rangePairToCfiPair = function(section, rangePair){\n\n var startRange = rangePair.start;\n var endRange = rangePair.end;\n\n startRange.collapse(true);\n endRange.collapse(true);\n\n startCfi = section.cfiFromRange(startRange);\n endCfi = section.cfiFromRange(endRange);\n\n return {\n start: startCfi,\n end: endCfi\n };\n\n};\n\nMap.prototype.rangeListToCfiList = function(view, columns){\n var map = [];\n var rangePair, cifPair;\n\n for (var i = 0; i < columns.length; i++) {\n cifPair = this.rangePairToCfiPair(view.section, columns[i]);\n\n map.push(cifPair);\n\n }\n\n return map;\n};\n\nmodule.exports = Map;\n","var core = require('./core');\nvar Parser = require('./parser');\nvar RSVP = require('rsvp');\nvar URI = require('urijs');\n\nfunction Navigation(_package, _request){\n var navigation = this;\n var parse = new Parser();\n var request = _request || require('./request');\n\n this.package = _package;\n this.toc = [];\n this.tocByHref = {};\n this.tocById = {};\n\n if(_package.navPath) {\n this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();\n this.nav = {};\n\n this.nav.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.navUrl, 'xml').then(function(xml){\n navigation.toc = parse.nav(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n\n if(_package.ncxPath) {\n this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();\n this.ncx = {};\n\n this.ncx.load = function(_request){\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n request(navigation.ncxUrl, 'xml').then(function(xml){\n navigation.toc = parse.ncx(xml);\n navigation.loaded(navigation.toc);\n loading.resolve(navigation.toc);\n });\n\n return loaded;\n };\n\n }\n};\n\n// Load the navigation\nNavigation.prototype.load = function(_request) {\n var request = _request || require('./request');\n var loading, loaded;\n\n if(this.nav) {\n loading = this.nav.load();\n } else if(this.ncx) {\n loading = this.ncx.load();\n } else {\n loaded = new RSVP.defer();\n loaded.resolve([]);\n loading = loaded.promise;\n }\n\n return loading;\n\n};\n\nNavigation.prototype.loaded = function(toc) {\n var item;\n\n for (var i = 0; i < toc.length; i++) {\n item = toc[i];\n this.tocByHref[item.href] = i;\n this.tocById[item.id] = i;\n }\n\n};\n\n// Get an item from the navigation\nNavigation.prototype.get = function(target) {\n var index;\n\n if(!target) {\n return this.toc;\n }\n\n if(target.indexOf(\"#\") === 0) {\n index = this.tocById[target.substring(1)];\n } else if(target in this.tocByHref){\n index = this.tocByHref[target];\n }\n\n return this.toc[index];\n};\n\nmodule.exports = Navigation;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar Continuous = require('./continuous');\nvar Map = require('./map');\nvar Layout = require('./layout');\n\nfunction Paginate(book, options) {\n\n Continuous.apply(this, arguments);\n\n this.settings = core.extend(this.settings || {}, {\n width: 600,\n height: 400,\n axis: \"horizontal\",\n forceSingle: false,\n minSpreadWidth: 800, //-- overridden by spread: none (never) / both (always)\n gap: \"auto\", //-- \"auto\" or int\n overflow: \"hidden\",\n infinite: false\n });\n\n core.extend(this.settings, options);\n\n this.isForcedSingle = this.settings.forceSingle;\n\n this.viewSettings.axis = this.settings.axis;\n\n this.start();\n};\n\nPaginate.prototype = Object.create(Continuous.prototype);\nPaginate.prototype.constructor = Paginate;\n\n\nPaginate.prototype.determineSpreads = function(cutoff){\n if(this.isForcedSingle || !cutoff || this.bounds().width < cutoff) {\n return 1; //-- Single Page\n }else{\n return 2; //-- Double Page\n }\n};\n\nPaginate.prototype.forceSingle = function(bool){\n if(bool === false) {\n this.isForcedSingle = false;\n // this.spreads = false;\n } else {\n this.isForcedSingle = true;\n // this.spreads = this.determineSpreads(this.minSpreadWidth);\n }\n this.applyLayoutMethod();\n};\n\n/**\n* Uses the settings to determine which Layout Method is needed\n* Triggers events based on the method choosen\n* Takes: Layout settings object\n* Returns: String of appropriate for EPUBJS.Layout function\n*/\n// Paginate.prototype.determineLayout = function(settings){\n// // Default is layout: reflowable & spread: auto\n// var spreads = this.determineSpreads(this.settings.minSpreadWidth);\n// console.log(\"spreads\", spreads, this.settings.minSpreadWidth)\n// var layoutMethod = spreads ? \"ReflowableSpreads\" : \"Reflowable\";\n// var scroll = false;\n//\n// if(settings.layout === \"pre-paginated\") {\n// layoutMethod = \"Fixed\";\n// scroll = true;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"none\") {\n// layoutMethod = \"Reflowable\";\n// scroll = false;\n// spreads = false;\n// }\n//\n// if(settings.layout === \"reflowable\" && settings.spread === \"both\") {\n// layoutMethod = \"ReflowableSpreads\";\n// scroll = false;\n// spreads = true;\n// }\n//\n// this.spreads = spreads;\n//\n// return layoutMethod;\n// };\n\nPaginate.prototype.start = function(){\n // On display\n // this.layoutSettings = this.reconcileLayoutSettings(globalLayout, chapter.properties);\n // this.layoutMethod = this.determineLayout(this.layoutSettings);\n // this.layout = new EPUBJS.Layout[this.layoutMethod]();\n //this.hooks.display.register(this.registerLayoutMethod.bind(this));\n // this.hooks.display.register(this.reportLocation);\n this.on('displayed', this.reportLocation.bind(this));\n\n // this.hooks.content.register(this.adjustImages.bind(this));\n\n this.currentPage = 0;\n\n window.addEventListener('unload', function(e){\n this.ignore = true;\n this.destroy();\n }.bind(this));\n\n};\n\n// EPUBJS.Rendition.prototype.createView = function(section) {\n// var view = new EPUBJS.View(section, this.viewSettings);\n\n\n// return view;\n// };\n\nPaginate.prototype.applyLayoutMethod = function() {\n //var task = new RSVP.defer();\n\n // this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout = new Layout.Reflowable();\n\n this.updateLayout();\n\n // Set the look ahead offset for what is visible\n\n this.map = new Map(this.layout);\n\n // this.hooks.layout.register(this.layout.format.bind(this));\n\n //task.resolve();\n //return task.promise;\n // return layout;\n};\n\nPaginate.prototype.updateLayout = function() {\n\n this.spreads = this.determineSpreads(this.settings.minSpreadWidth);\n\n this.layout.calculate(\n this.stage.width,\n this.stage.height,\n this.settings.gap,\n this.spreads\n );\n\n this.settings.offset = this.layout.delta;\n\n};\n\nPaginate.prototype.moveTo = function(offset){\n var dist = Math.floor(offset.left / this.layout.delta) * this.layout.delta;\n return this.check(0, dist+this.settings.offset).then(function(){\n this.scrollBy(dist, 0);\n }.bind(this));\n};\n\nPaginate.prototype.page = function(pg){\n\n // this.currentPage = pg;\n // this.renderer.infinite.scrollTo(this.currentPage * this.formated.pageWidth, 0);\n //-- Return false if page is greater than the total\n // return false;\n};\n\nPaginate.prototype.next = function(){\n\n return this.q.enqueue(function(){\n // console.log(this.container.scrollWidth, this.container.scrollLeft + this.container.offsetWidth + this.layout.delta)\n if(this.container.scrollLeft +\n this.container.offsetWidth +\n this.layout.delta < this.container.scrollWidth) {\n this.scrollBy(this.layout.delta, 0);\n } else {\n this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);\n }\n this.reportLocation();\n return this.check();\n });\n\n // return this.page(this.currentPage + 1);\n};\n\nPaginate.prototype.prev = function(){\n\n return this.q.enqueue(function(){\n this.scrollBy(-this.layout.delta, 0);\n this.reportLocation();\n return this.check();\n });\n // return this.page(this.currentPage - 1);\n};\n\n// Paginate.prototype.reportLocation = function(){\n// return this.q.enqueue(function(){\n// this.location = this.currentLocation();\n// this.trigger(\"locationChanged\", this.location);\n// }.bind(this));\n// };\n\nPaginate.prototype.currentLocation = function(){\n var visible = this.visible();\n var startA, startB, endA, endB;\n var pageLeft, pageRight;\n var container = this.container.getBoundingClientRect();\n\n if(visible.length === 1) {\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.spread;\n\n return this.map.page(visible[0], startA, endA);\n }\n\n if(visible.length > 1) {\n\n // Left Col\n startA = container.left - visible[0].position().left;\n endA = startA + this.layout.column;\n\n // Right Col\n startB = container.left + this.layout.spread - visible[visible.length-1].position().left;\n endB = startB + this.layout.column;\n\n pageLeft = this.map.page(visible[0], startA, endA);\n pageRight = this.map.page(visible[visible.length-1], startB, endB);\n\n return {\n start: pageLeft.start,\n end: pageRight.end\n };\n }\n};\n\nPaginate.prototype.resize = function(width, height){\n // Clear the queue\n this.q.clear();\n\n this.stageSize(width, height);\n\n this.updateLayout();\n\n if(this.location) {\n this.display(this.location.start);\n }\n\n this.trigger(\"resized\", {\n width: this.stage.width,\n height: this.stage.height\n });\n\n};\n\nPaginate.prototype.onResized = function(e) {\n\n this.views.clear();\n\n clearTimeout(this.resizeTimeout);\n this.resizeTimeout = setTimeout(function(){\n this.resize();\n }.bind(this), 150);\n};\n\nPaginate.prototype.adjustImages = function(view) {\n\n view.addStylesheetRules([\n [\"img\",\n [\"max-width\", (this.layout.spread) + \"px\"],\n [\"max-height\", (this.layout.height) + \"px\"]\n ]\n ]);\n return new RSVP.Promise(function(resolve, reject){\n // Wait to apply\n setTimeout(function() {\n resolve();\n }, 1);\n });\n};\n\n// Paginate.prototype.display = function(what){\n// return this.display(what);\n// };\n\nmodule.exports = Paginate;\n","var URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction Parser(){};\n\nParser.prototype.container = function(containerXml){\n //-- \n var rootfile, fullpath, folder, encoding;\n\n if(!containerXml) {\n console.error(\"Container File Not Found\");\n return;\n }\n\n rootfile = containerXml.querySelector(\"rootfile\");\n\n if(!rootfile) {\n console.error(\"No RootFile Found\");\n return;\n }\n\n fullpath = rootfile.getAttribute('full-path');\n folder = URI(fullpath).directory();\n encoding = containerXml.xmlEncoding;\n\n //-- Now that we have the path we can parse the contents\n return {\n 'packagePath' : fullpath,\n 'basePath' : folder,\n 'encoding' : encoding\n };\n};\n\nParser.prototype.identifier = function(packageXml){\n var metadataNode;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n return this.getElementText(metadataNode, \"identifier\");\n};\n\nParser.prototype.packageContents = function(packageXml){\n var parse = this;\n var metadataNode, manifestNode, spineNode;\n var manifest, navPath, ncxPath, coverPath;\n var spineNodeIndex;\n var spine;\n var spineIndexByURL;\n var metadata;\n\n if(!packageXml) {\n console.error(\"Package File Not Found\");\n return;\n }\n\n metadataNode = packageXml.querySelector(\"metadata\");\n if(!metadataNode) {\n console.error(\"No Metadata Found\");\n return;\n }\n\n manifestNode = packageXml.querySelector(\"manifest\");\n if(!manifestNode) {\n console.error(\"No Manifest Found\");\n return;\n }\n\n spineNode = packageXml.querySelector(\"spine\");\n if(!spineNode) {\n console.error(\"No Spine Found\");\n return;\n }\n\n manifest = parse.manifest(manifestNode);\n navPath = parse.findNavPath(manifestNode);\n ncxPath = parse.findNcxPath(manifestNode, spineNode);\n coverPath = parse.findCoverPath(packageXml);\n\n spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);\n\n spine = parse.spine(spineNode, manifest);\n\n metadata = parse.metadata(metadataNode);\n\n\tmetadata.direction = spineNode.getAttribute(\"page-progression-direction\");\n\n return {\n 'metadata' : metadata,\n 'spine' : spine,\n 'manifest' : manifest,\n 'navPath' : navPath,\n 'ncxPath' : ncxPath,\n 'coverPath': coverPath,\n 'spineNodeIndex' : spineNodeIndex\n };\n};\n\n//-- Find TOC NAV\nParser.prototype.findNavPath = function(manifestNode){\n\t// Find item with property 'nav'\n\t// Should catch nav irregardless of order\n var node = manifestNode.querySelector(\"item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']\");\n return node ? node.getAttribute('href') : false;\n};\n\n//-- Find TOC NCX: media-type=\"application/x-dtbncx+xml\" href=\"toc.ncx\"\nParser.prototype.findNcxPath = function(manifestNode, spineNode){\n\tvar node = manifestNode.querySelector(\"item[media-type='application/x-dtbncx+xml']\");\n\tvar tocId;\n\n\t// If we can't find the toc by media-type then try to look for id of the item in the spine attributes as\n\t// according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2,\n\t// \"The item that describes the NCX must be referenced by the spine toc attribute.\"\n\tif (!node) {\n\t\ttocId = spineNode.getAttribute(\"toc\");\n\t\tif(tocId) {\n\t\t\tnode = manifestNode.querySelector(\"item[id='\" + tocId + \"']\");\n\t\t}\n\t}\n\n\treturn node ? node.getAttribute('href') : false;\n};\n\n//-- Expanded to match Readium web components\nParser.prototype.metadata = function(xml){\n var metadata = {},\n p = this;\n\n metadata.title = p.getElementText(xml, 'title');\n metadata.creator = p.getElementText(xml, 'creator');\n metadata.description = p.getElementText(xml, 'description');\n\n metadata.pubdate = p.getElementText(xml, 'date');\n\n metadata.publisher = p.getElementText(xml, 'publisher');\n\n metadata.identifier = p.getElementText(xml, \"identifier\");\n metadata.language = p.getElementText(xml, \"language\");\n metadata.rights = p.getElementText(xml, \"rights\");\n\n metadata.modified_date = p.querySelectorText(xml, \"meta[property='dcterms:modified']\");\n metadata.layout = p.querySelectorText(xml, \"meta[property='rendition:layout']\");\n metadata.orientation = p.querySelectorText(xml, \"meta[property='rendition:orientation']\");\n metadata.spread = p.querySelectorText(xml, \"meta[property='rendition:spread']\");\n // metadata.page_prog_dir = packageXml.querySelector(\"spine\").getAttribute(\"page-progression-direction\");\n\n return metadata;\n};\n\n//-- Find Cover: \n//-- Fallback for Epub 2.0\nParser.prototype.findCoverPath = function(packageXml){\n\n\tvar epubVersion = packageXml.querySelector('package').getAttribute('version');\n\n\tif (epubVersion === '2.0') {\n\t\tvar metaCover = packageXml.querySelector('meta[name=\"cover\"]');\n\t\tif (metaCover) {\n\t\t\tvar coverId = metaCover.getAttribute('content');\n\t\t\tvar cover = packageXml.querySelector(\"item[id='\" + coverId + \"']\");\n\t\t\treturn cover ? cover.getAttribute('href') : false;\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\telse {\n\t\tvar node = packageXml.querySelector(\"item[properties='cover-image']\");\n\t\treturn node ? node.getAttribute('href') : false;\n\t}\n};\n\nParser.prototype.getElementText = function(xml, tag){\n var found = xml.getElementsByTagNameNS(\"http://purl.org/dc/elements/1.1/\", tag),\n el;\n\n if(!found || found.length === 0) return '';\n\n el = found[0];\n\n if(el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n\n};\n\nParser.prototype.querySelectorText = function(xml, q){\n var el = xml.querySelector(q);\n\n if(el && el.childNodes.length){\n return el.childNodes[0].nodeValue;\n }\n\n return '';\n};\n\nParser.prototype.manifest = function(manifestXml){\n var manifest = {};\n\n //-- Turn items into an array\n var selected = manifestXml.querySelectorAll(\"item\"),\n items = Array.prototype.slice.call(selected);\n\n //-- Create an object with the id as key\n items.forEach(function(item){\n var id = item.getAttribute('id'),\n href = item.getAttribute('href') || '',\n type = item.getAttribute('media-type') || '',\n properties = item.getAttribute('properties') || '';\n\n manifest[id] = {\n 'href' : href,\n // 'url' : href,\n 'type' : type,\n 'properties' : properties.length ? properties.split(' ') : []\n };\n\n });\n\n return manifest;\n\n};\n\nParser.prototype.spine = function(spineXml, manifest){\n var spine = [];\n\n var selected = spineXml.getElementsByTagName(\"itemref\"),\n items = Array.prototype.slice.call(selected);\n\n var epubcfi = new EpubCFI();\n\n //-- Add to array to mantain ordering and cross reference with manifest\n items.forEach(function(item, index){\n var idref = item.getAttribute('idref');\n // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);\n var props = item.getAttribute('properties') || '';\n var propArray = props.length ? props.split(' ') : [];\n // var manifestProps = manifest[Id].properties;\n // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];\n\n var itemref = {\n 'idref' : idref,\n 'linear' : item.getAttribute('linear') || '',\n 'properties' : propArray,\n // 'href' : manifest[Id].href,\n // 'url' : manifest[Id].url,\n 'index' : index\n // 'cfiBase' : cfiBase\n };\n spine.push(itemref);\n });\n\n return spine;\n};\n\nParser.prototype.querySelectorByType = function(html, element, type){\n\tvar query = html.querySelector(element+'[*|type=\"'+type+'\"]');\n\t// Handle IE not supporting namespaced epub:type in querySelector\n\tif(query === null || query.length === 0) {\n\t\tquery = html.querySelectorAll(element);\n\t\tfor (var i = 0; i < query.length; i++) {\n\t\t\tif(query[i].getAttributeNS(\"http://www.idpf.org/2007/ops\", \"type\") === type) {\n\t\t\t\treturn query[i];\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn query;\n\t}\n};\n\nParser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"toc\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.navItem(navItems[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.navItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"a, span\"),\n\t\t\tsrc = content.getAttribute('href') || '',\n\t\t\ttext = content.textContent || \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.toc = function(tocXml, spineIndexByURL, bookSpine){\n\tvar navPoints = tocXml.querySelectorAll(\"navMap navPoint\");\n\tvar length = navPoints.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item, parent;\n\n\tif(!navPoints || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.tocItem(navPoints[i], spineIndexByURL, bookSpine);\n\t\ttoc[item.id] = item;\n\t\tif(!item.parent) {\n\t\t\tlist.push(item);\n\t\t} else {\n\t\t\tparent = toc[item.parent];\n\t\t\tparent.subitems.push(item);\n\t\t}\n\t}\n\n\treturn list;\n};\n\nParser.prototype.tocItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\t\tcontent = item.querySelector(\"content\"),\n\t\t\tsrc = content.getAttribute('src'),\n\t\t\tnavLabel = item.querySelector(\"navLabel\"),\n\t\t\ttext = navLabel.textContent ? navLabel.textContent : \"\",\n\t\t\t// split = src.split(\"#\"),\n\t\t\t// baseUrl = split[0],\n\t\t\t// spinePos = spineIndexByURL[baseUrl],\n\t\t\t// spineItem = bookSpine[spinePos],\n\t\t\tsubitems = [],\n\t\t\tparentNode = item.parentNode,\n\t\t\tparent;\n\t\t\t// cfi = spineItem ? spineItem.cfi : '';\n\n\tif(parentNode && parentNode.nodeName === \"navPoint\") {\n\t\tparent = parentNode.getAttribute('id');\n\t}\n\n /*\n\tif(!id) {\n\t\tif(spinePos) {\n\t\t\tspineItem = bookSpine[spinePos];\n\t\t\tid = spineItem.id;\n\t\t\tcfi = spineItem.cfi;\n\t\t} else {\n\t\t\tid = 'epubjs-autogen-toc-id-' + EPUBJS.core.uuid();\n\t\t\titem.setAttribute('id', id);\n\t\t}\n\t}\n */\n\n\treturn {\n\t\t\"id\": id,\n\t\t\"href\": src,\n\t\t\"label\": text,\n\t\t\"subitems\" : subitems,\n\t\t\"parent\" : parent\n\t};\n};\n\nParser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){\n\tvar navElement = this.querySelectorByType(navHtml, \"nav\", \"page-list\");\n\tvar navItems = navElement ? navElement.querySelectorAll(\"ol li\") : [];\n\tvar length = navItems.length;\n\tvar i;\n\tvar toc = {};\n\tvar list = [];\n\tvar item;\n\n\tif(!navItems || length === 0) return list;\n\n\tfor (i = 0; i < length; ++i) {\n\t\titem = this.pageListItem(navItems[i], spineIndexByURL, bookSpine);\n\t\tlist.push(item);\n\t}\n\n\treturn list;\n};\n\nParser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){\n\tvar id = item.getAttribute('id') || false,\n\t\tcontent = item.querySelector(\"a\"),\n\t\thref = content.getAttribute('href') || '',\n\t\ttext = content.textContent || \"\",\n\t\tpage = parseInt(text),\n\t\tisCfi = href.indexOf(\"epubcfi\"),\n\t\tsplit,\n\t\tpackageUrl,\n\t\tcfi;\n\n\tif(isCfi != -1) {\n\t\tsplit = href.split(\"#\");\n\t\tpackageUrl = split[0];\n\t\tcfi = split.length > 1 ? split[1] : false;\n\t\treturn {\n\t\t\t\"cfi\" : cfi,\n\t\t\t\"href\" : href,\n\t\t\t\"packageUrl\" : packageUrl,\n\t\t\t\"page\" : page\n\t\t};\n\t} else {\n\t\treturn {\n\t\t\t\"href\" : href,\n\t\t\t\"page\" : page\n\t\t};\n\t}\n};\n\nmodule.exports = Parser;\n","var RSVP = require('rsvp');\nvar core = require('./core');\n\nfunction Queue(_context){\n this._q = [];\n this.context = _context;\n this.tick = core.requestAnimationFrame;\n this.running = false;\n this.paused = false;\n};\n\n// Add an item to the queue\nQueue.prototype.enqueue = function() {\n var deferred, promise;\n var queued;\n var task = [].shift.call(arguments);\n var args = arguments;\n\n // Handle single args without context\n // if(args && !Array.isArray(args)) {\n // args = [args];\n // }\n if(!task) {\n return console.error(\"No Task Provided\");\n }\n\n if(typeof task === \"function\"){\n\n deferred = new RSVP.defer();\n promise = deferred.promise;\n\n queued = {\n \"task\" : task,\n \"args\" : args,\n //\"context\" : context,\n \"deferred\" : deferred,\n \"promise\" : promise\n };\n\n } else {\n // Task is a promise\n queued = {\n \"promise\" : task\n };\n\n }\n\n this._q.push(queued);\n\n // Wait to start queue flush\n if (this.paused == false && !this.running) {\n // setTimeout(this.flush.bind(this), 0);\n // this.tick.call(window, this.run.bind(this));\n this.run();\n }\n\n return queued.promise;\n};\n\n// Run one item\nQueue.prototype.dequeue = function(){\n var inwait, task, result;\n\n if(this._q.length) {\n inwait = this._q.shift();\n task = inwait.task;\n if(task){\n // console.log(task)\n\n result = task.apply(this.context, inwait.args);\n\n if(result && typeof result[\"then\"] === \"function\") {\n // Task is a function that returns a promise\n return result.then(function(){\n inwait.deferred.resolve.apply(this.context, arguments);\n }.bind(this));\n } else {\n // Task resolves immediately\n inwait.deferred.resolve.apply(this.context, result);\n return inwait.promise;\n }\n\n\n\n } else if(inwait.promise) {\n // Task is a promise\n return inwait.promise;\n }\n\n } else {\n inwait = new RSVP.defer();\n inwait.deferred.resolve();\n return inwait.promise;\n }\n\n};\n\n// Run All Immediately\nQueue.prototype.dump = function(){\n while(this._q.length) {\n this.dequeue();\n }\n};\n\n// Run all sequentially, at convince\n\nQueue.prototype.run = function(){\n\n if(!this.running){\n this.running = true;\n this.defered = new RSVP.defer();\n }\n\n this.tick.call(window, function() {\n\n if(this._q.length) {\n\n this.dequeue()\n .then(function(){\n this.run();\n }.bind(this));\n\n } else {\n this.defered.resolve();\n this.running = undefined;\n }\n\n }.bind(this));\n\n // Unpause\n if(this.paused == true) {\n this.paused = false;\n }\n\n return this.defered.promise;\n};\n\n// Flush all, as quickly as possible\nQueue.prototype.flush = function(){\n\n if(this.running){\n return this.running;\n }\n\n if(this._q.length) {\n this.running = this.dequeue()\n .then(function(){\n this.running = undefined;\n return this.flush();\n }.bind(this));\n\n return this.running;\n }\n\n};\n\n// Clear all items in wait\nQueue.prototype.clear = function(){\n this._q = [];\n this.running = false;\n};\n\nQueue.prototype.length = function(){\n return this._q.length;\n};\n\nQueue.prototype.pause = function(){\n this.paused = true;\n};\n\n// Create a new task from a callback\nfunction Task(task, args, context){\n\n return function(){\n var toApply = arguments || [];\n\n return new RSVP.Promise(function(resolve, reject) {\n var callback = function(value){\n resolve(value);\n };\n // Add the callback to the arguments list\n toApply.push(callback);\n\n // Apply all arguments to the functions\n task.apply(this, toApply);\n\n }.bind(this));\n\n };\n\n};\n\nmodule.exports = Queue;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar replace = require('./replacements');\nvar Hook = require('./hook');\nvar EpubCFI = require('./epubcfi');\nvar Queue = require('./queue');\nvar View = require('./view');\nvar Views = require('./views');\nvar Layout = require('./layout');\nvar Map = require('./map');\n\nfunction Rendition(book, options) {\n\n\tthis.settings = core.extend(this.settings || {}, {\n\t\tinfinite: true,\n\t\thidden: false,\n\t\twidth: false,\n\t\theight: null,\n\t\tlayoutOveride : null, // Default: { spread: 'reflowable', layout: 'auto', orientation: 'auto'},\n\t\taxis: \"vertical\",\n\t\tignoreClass: ''\n\t});\n\n\tcore.extend(this.settings, options);\n\n\tthis.viewSettings = {\n\t\tignoreClass: this.settings.ignoreClass\n\t};\n\n\tthis.book = book;\n\n\tthis.views = null;\n\n\t//-- Adds Hook methods to the Rendition prototype\n\tthis.hooks = {};\n\tthis.hooks.display = new Hook(this);\n\tthis.hooks.serialize = new Hook(this);\n\tthis.hooks.content = new Hook(this);\n\tthis.hooks.layout = new Hook(this);\n\tthis.hooks.render = new Hook(this);\n\tthis.hooks.show = new Hook(this);\n\n\tthis.hooks.content.register(replace.links.bind(this));\n\tthis.hooks.content.register(this.passViewEvents.bind(this));\n\n\t// this.hooks.display.register(this.afterDisplay.bind(this));\n\n this.epubcfi = new EpubCFI();\n\n\tthis.q = new Queue(this);\n\n\tthis.q.enqueue(this.book.opened);\n\n\tthis.q.enqueue(this.parseLayoutProperties);\n\n\tif(this.book.archive) {\n\t\tthis.replacements();\n\t}\n};\n\n/**\n* Creates an element to render to.\n* Resizes to passed width and height or to the elements size\n*/\nRendition.prototype.initialize = function(_options){\n\tvar options = _options || {};\n\tvar height = options.height;// !== false ? options.height : \"100%\";\n\tvar width = options.width;// !== false ? options.width : \"100%\";\n\tvar hidden = options.hidden || false;\n\tvar container;\n\tvar wrapper;\n\n\tif(options.height && core.isNumber(options.height)) {\n\t\theight = options.height + \"px\";\n\t}\n\n\tif(options.width && core.isNumber(options.width)) {\n\t\twidth = options.width + \"px\";\n\t}\n\n\t// Create new container element\n\tcontainer = document.createElement(\"div\");\n\n\tcontainer.id = \"epubjs-container:\" + core.uuid();\n\tcontainer.classList.add(\"epub-container\");\n\n\t// Style Element\n\tcontainer.style.fontSize = \"0\";\n\tcontainer.style.wordSpacing = \"0\";\n\tcontainer.style.lineHeight = \"0\";\n\tcontainer.style.verticalAlign = \"top\";\n\n\tif(this.settings.axis === \"horizontal\") {\n\t\tcontainer.style.whiteSpace = \"nowrap\";\n\t}\n\n\tif(width){\n\t\tcontainer.style.width = width;\n\t}\n\n\tif(height){\n\t\tcontainer.style.height = height;\n\t}\n\n\tcontainer.style.overflow = this.settings.overflow;\n\n\treturn container;\n};\n\nRendition.wrap = function(container) {\n\tvar wrapper = document.createElement(\"div\");\n\n\twrapper.style.visibility = \"hidden\";\n\twrapper.style.overflow = \"hidden\";\n\twrapper.style.width = \"0\";\n\twrapper.style.height = \"0\";\n\n\twrapper.appendChild(container);\n\treturn wrapper;\n};\n\n// Call to attach the container to an element in the dom\n// Container must be attached before rendering can begin\nRendition.prototype.attachTo = function(_element){\n\tvar bounds;\n\n\tthis.container = this.initialize({\n\t\t\"width\" : this.settings.width,\n\t\t\"height\" : this.settings.height\n\t});\n\n\tif(core.isElement(_element)) {\n\t\tthis.element = _element;\n\t} else if (typeof _element === \"string\") {\n\t\tthis.element = document.getElementById(_element);\n\t}\n\n\tif(!this.element){\n\t\tconsole.error(\"Not an Element\");\n\t\treturn;\n\t}\n\n\tif(this.settings.hidden) {\n\t\tthis.wrapper = this.wrap(this.container);\n\t\tthis.element.appendChild(this.wrapper);\n\t} else {\n\t\tthis.element.appendChild(this.container);\n\t}\n\n\tthis.views = new Views(this.container);\n\n\t// Attach Listeners\n\tthis.attachListeners();\n\n\t// Calculate Stage Size\n\tthis.stageSize();\n\n\t// Add Layout method\n\tthis.applyLayoutMethod();\n\n\t// Trigger Attached\n\tthis.trigger(\"attached\");\n\n\t// Start processing queue\n\t// this.q.run();\n\n};\n\nRendition.prototype.attachListeners = function(){\n\n\t// Listen to window for resize event if width or height is set to 100%\n\tif(!core.isNumber(this.settings.width) ||\n\t\t !core.isNumber(this.settings.height) ) {\n\t\twindow.addEventListener(\"resize\", this.onResized.bind(this), false);\n\t}\n\n};\n\nRendition.prototype.bounds = function() {\n\treturn this.container.getBoundingClientRect();\n};\n\nRendition.prototype.display = function(target){\n\n\treturn this.q.enqueue(this._display, target);\n\n};\n\nRendition.prototype._display = function(target){\n\n\tvar displaying = new RSVP.defer();\n\tvar displayed = displaying.promise;\n\n\tvar section;\n var view;\n var offset;\n\tvar fragment;\n\tvar cfi = this.epubcfi.isCfiString(target);\n\n\tvar visible;\n\n\tsection = this.book.spine.get(target);\n\n\tif(!section){\n\t\tdisplaying.reject(new Error(\"No Section Found\"));\n\t\treturn displayed;\n\t}\n\n\t// Check to make sure the section we want isn't already shown\n\tvisible = this.views.find(section);\n\n\tif(visible) {\n\t\toffset = visible.locationOf(target);\n\t\tthis.moveTo(offset);\n\t\tdisplaying.resolve();\n\n\t} else {\n\n\t\t// Hide all current views\n\t\tthis.views.hide();\n\n\t\t// Create a new view\n\t\t// view = new View(section, this.viewSettings);\n\t\tview = this.createView(section);\n\n\t\t// This will clear all previous views\n\t\tdisplayed = this.fill(view)\n\t\t\t.then(function(){\n\n\t\t\t\t// Parse the target fragment\n\t\t\t\tif(typeof target === \"string\" &&\n\t\t\t\t\ttarget.indexOf(\"#\") > -1) {\n\t\t\t\t\t\tfragment = target.substring(target.indexOf(\"#\")+1);\n\t\t\t\t}\n\n\t\t\t\t// Move to correct place within the section, if needed\n\t\t\t\tif(cfi || fragment) {\n\t\t\t\t\toffset = view.locationOf(target);\n\t\t\t\t\treturn this.moveTo(offset);\n\t\t\t\t}\n\n\t\t\t\tif(typeof this.check === 'function') {\n\t\t\t\t\treturn this.check();\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\treturn this.hooks.display.trigger(view);\n\t\t\t}.bind(this))\n\t\t\t.then(function(){\n\t\t\t\tthis.views.show();\n\t\t\t}.bind(this));\n\t}\n\n\tdisplayed.then(function(){\n\n\t\tthis.trigger(\"displayed\", section);\n\n\t}.bind(this));\n\n\n\treturn displayed;\n};\n\n// Takes a cfi, fragment or page?\nRendition.prototype.moveTo = function(offset){\n\tthis.scrollTo(offset.left, offset.top);\n};\n\nRendition.prototype.render = function(view, show) {\n\n\tview.create();\n\n\tview.onLayout = this.layout.format.bind(this.layout);\n\n\t// Fit to size of the container, apply padding\n\tthis.resizeView(view);\n\n\t// Render Chain\n\treturn view.render(this.book.request)\n\t\t.then(function(){\n\t\t\treturn this.hooks.content.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.layout.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn view.display();\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\treturn this.hooks.render.trigger(view, this);\n\t\t}.bind(this))\n\t\t.then(function(){\n\t\t\tif(show !== false && this.views.hidden === false) {\n\t\t\t\tthis.q.enqueue(function(view){\n\t\t\t\t\tview.show();\n\t\t\t\t}, view);\n\t\t\t}\n\n\n\t\t\t// this.map = new Map(view, this.layout);\n\t\t\tthis.hooks.show.trigger(view, this);\n\t\t\tthis.trigger(\"rendered\", view.section);\n\n\t\t}.bind(this))\n\t\t.catch(function(e){\n\t\t\tthis.trigger(\"loaderror\", e);\n\t\t}.bind(this));\n\n};\n\n\nRendition.prototype.afterDisplayed = function(view){\n\tthis.trigger(\"added\", view.section);\n\tthis.reportLocation();\n};\n\nRendition.prototype.fill = function(view){\n\n\tthis.views.clear();\n\n\tthis.views.append(view);\n\n\t// view.on(\"shown\", this.afterDisplayed.bind(this));\n\tview.onDisplayed = this.afterDisplayed.bind(this);\n\n\treturn this.render(view);\n};\n\nRendition.prototype.resizeView = function(view) {\n\n\tif(this.globalLayoutProperties.layout === \"pre-paginated\") {\n\t\tview.lock(\"both\", this.stage.width, this.stage.height);\n\t} else {\n\t\tview.lock(\"width\", this.stage.width, this.stage.height);\n\t}\n\n};\n\nRendition.prototype.stageSize = function(_width, _height){\n\tvar bounds;\n\tvar width = _width || this.settings.width;\n\tvar height = _height || this.settings.height;\n\n\t// If width or height are set to false, inherit them from containing element\n\tif(width === false) {\n\t\tbounds = this.element.getBoundingClientRect();\n\n\t\tif(bounds.width) {\n\t\t\twidth = bounds.width;\n\t\t\tthis.container.style.width = bounds.width + \"px\";\n\t\t}\n\t}\n\n\tif(height === false) {\n\t\tbounds = bounds || this.element.getBoundingClientRect();\n\n\t\tif(bounds.height) {\n\t\t\theight = bounds.height;\n\t\t\tthis.container.style.height = bounds.height + \"px\";\n\t\t}\n\n\t}\n\n\tif(width && !core.isNumber(width)) {\n\t\tbounds = this.container.getBoundingClientRect();\n\t\twidth = bounds.width;\n\t\t//height = bounds.height;\n\t}\n\n\tif(height && !core.isNumber(height)) {\n\t\tbounds = bounds || this.container.getBoundingClientRect();\n\t\t//width = bounds.width;\n\t\theight = bounds.height;\n\t}\n\n\n\tthis.containerStyles = window.getComputedStyle(this.container);\n\tthis.containerPadding = {\n\t\tleft: parseFloat(this.containerStyles[\"padding-left\"]) || 0,\n\t\tright: parseFloat(this.containerStyles[\"padding-right\"]) || 0,\n\t\ttop: parseFloat(this.containerStyles[\"padding-top\"]) || 0,\n\t\tbottom: parseFloat(this.containerStyles[\"padding-bottom\"]) || 0\n\t};\n\n\tthis.stage = {\n\t\twidth: width -\n\t\t\t\t\t\tthis.containerPadding.left -\n\t\t\t\t\t\tthis.containerPadding.right,\n\t\theight: height -\n\t\t\t\t\t\tthis.containerPadding.top -\n\t\t\t\t\t\tthis.containerPadding.bottom\n\t};\n\n\treturn this.stage;\n\n};\n\nRendition.prototype.applyLayoutMethod = function() {\n\n\tthis.layout = new Layout.Scroll();\n\tthis.updateLayout();\n\n\tthis.map = new Map(this.layout);\n};\n\nRendition.prototype.updateLayout = function() {\n\n\tthis.layout.calculate(this.stage.width, this.stage.height);\n\n};\n\nRendition.prototype.resize = function(width, height){\n\n\tthis.stageSize(width, height);\n\n\tthis.updateLayout();\n\n\tthis.views.each(this.resizeView.bind(this));\n\n\tthis.trigger(\"resized\", {\n\t\twidth: this.stage.width,\n\t\theight: this.stage.height\n\t});\n\n};\n\nRendition.prototype.onResized = function(e) {\n\tthis.resize();\n};\n\nRendition.prototype.createView = function(section) {\n\t// Transfer the existing hooks\n\tsection.hooks.serialize.register(this.hooks.serialize.list());\n\n\treturn new View(section, this.viewSettings);\n};\n\nRendition.prototype.next = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar next;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tnext = this.views.last().section.next();\n\n\t\tif(next) {\n\t\t\tview = this.createView(next);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\nRendition.prototype.prev = function(){\n\n\treturn this.q.enqueue(function(){\n\n\t\tvar prev;\n\t\tvar view;\n\n\t\tif(!this.views.length) return;\n\n\t\tprev = this.views.first().section.prev();\n\t\tif(prev) {\n\t\t\tview = this.createView(prev);\n\t\t\treturn this.fill(view);\n\t\t}\n\n\t});\n\n};\n\n//-- http://www.idpf.org/epub/fxl/\nRendition.prototype.parseLayoutProperties = function(_metadata){\n\tvar metadata = _metadata || this.book.package.metadata;\n\tvar layout = (this.layoutOveride && this.layoutOveride.layout) || metadata.layout || \"reflowable\";\n\tvar spread = (this.layoutOveride && this.layoutOveride.spread) || metadata.spread || \"auto\";\n\tvar orientation = (this.layoutOveride && this.layoutOveride.orientation) || metadata.orientation || \"auto\";\n\tthis.globalLayoutProperties = {\n\t\tlayout : layout,\n\t\tspread : spread,\n\t\torientation : orientation\n\t};\n\treturn this.globalLayoutProperties;\n};\n\n\nRendition.prototype.current = function(){\n\tvar visible = this.visible();\n\tif(visible.length){\n\t\t// Current is the last visible view\n\t\treturn visible[visible.length-1];\n\t}\n return null;\n};\n\nRendition.prototype.isVisible = function(view, offsetPrev, offsetNext, _container){\n\tvar position = view.position();\n\tvar container = _container || this.container.getBoundingClientRect();\n\n\tif(this.settings.axis === \"horizontal\" &&\n\t\tposition.right > container.left - offsetPrev &&\n\t\tposition.left < container.right + offsetNext) {\n\n\t\treturn true;\n\n } else if(this.settings.axis === \"vertical\" &&\n \tposition.bottom > container.top - offsetPrev &&\n\t\tposition.top < container.bottom + offsetNext) {\n\n\t\treturn true;\n }\n\n\treturn false;\n\n};\n\nRendition.prototype.visible = function(){\n\tvar container = this.bounds();\n\tvar displayedViews = this.views.displayed();\n var visible = [];\n var isVisible;\n var view;\n\n for (var i = 0; i < displayedViews.length; i++) {\n view = displayedViews[i];\n isVisible = this.isVisible(view, 0, 0, container);\n\n if(isVisible === true) {\n visible.push(view);\n }\n\n }\n return visible;\n\n};\n\nRendition.prototype.bounds = function(func) {\n var bounds;\n\n if(!this.settings.height) {\n bounds = core.windowBounds();\n } else {\n bounds = this.container.getBoundingClientRect();\n }\n\n return bounds;\n};\n\nRendition.prototype.destroy = function(){\n // Clear the queue\n\tthis.q.clear();\n\n\tthis.views.clear();\n\n\tclearTimeout(this.trimTimeout);\n\tif(this.settings.hidden) {\n\t\tthis.element.removeChild(this.wrapper);\n\t} else {\n\t\tthis.element.removeChild(this.container);\n\t}\n\n};\n\nRendition.prototype.reportLocation = function(){\n return this.q.enqueue(function(){\n this.location = this.currentLocation();\n this.trigger(\"locationChanged\", this.location);\n }.bind(this));\n};\n\nRendition.prototype.currentLocation = function(){\n var view;\n var start, end;\n\n if(this.views.length) {\n \tview = this.views.first();\n // start = container.left - view.position().left;\n // end = start + this.layout.spread;\n\n return this.map.page(view);\n }\n\n};\n\nRendition.prototype.scrollBy = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n\n if(x) this.container.scrollLeft += x;\n \tif(y) this.container.scrollTop += y;\n\n } else {\n \twindow.scrollBy(x,y);\n }\n // console.log(\"scrollBy\", x, y);\n this.scrolled = true;\n};\n\nRendition.prototype.scrollTo = function(x, y, silent){\n if(silent) {\n this.ignore = true;\n }\n\n if(this.settings.height) {\n \tthis.container.scrollLeft = x;\n \tthis.container.scrollTop = y;\n } else {\n \twindow.scrollTo(x,y);\n }\n // console.log(\"scrollTo\", x, y);\n this.scrolled = true;\n // if(this.container.scrollLeft != x){\n // setTimeout(function() {\n // this.scrollTo(x, y, silent);\n // }.bind(this), 10);\n // return;\n // };\n };\n\nRendition.prototype.passViewEvents = function(view){\n view.listenedEvents.forEach(function(e){\n\t\tview.on(e, this.triggerViewEvent.bind(this));\n\t}.bind(this));\n\n\tview.on(\"selected\", this.triggerSelectedEvent.bind(this));\n};\n\nRendition.prototype.triggerViewEvent = function(e){\n this.trigger(e.type, e);\n};\n\nRendition.prototype.triggerSelectedEvent = function(cfirange){\n this.trigger(\"selected\", cfirange);\n};\n\nRendition.prototype.replacements = function(){\n\t// Wait for loading\n\treturn this.q.enqueue(function () {\n\t\t// Get thes books manifest\n\t\tvar manifest = this.book.package.manifest;\n\t var manifestArray = Object.keys(manifest).\n\t map(function (key){\n\t return manifest[key];\n\t });\n\n\t // Exclude HTML\n\t var items = manifestArray.\n\t filter(function (item){\n\t if (item.type != \"application/xhtml+xml\" &&\n\t item.type != \"text/html\") {\n\t return true;\n\t }\n\t });\n\n\t // Only CSS\n\t var css = items.\n\t filter(function (item){\n\t if (item.type === \"text/css\") {\n\t return true;\n\t }\n\t });\n\n\t\t// Css Urls\n\t\tvar cssUrls = css.map(function(item) {\n\t\t\treturn item.href;\n\t\t});\n\n\t\t// All Assets Urls\n\t var urls = items.\n\t map(function(item) {\n\t return item.href;\n\t }.bind(this));\n\n\t\t// Create blob urls for all the assets\n\t var processing = urls.\n\t map(function(url) {\n\t\t\t\tvar absolute = URI(url).absoluteTo(this.book.baseUrl).toString();\n\t\t\t\t// Full url from archive base\n\t return this.book.archive.createUrl(absolute);\n\t }.bind(this));\n\n\t\t// After all the urls are created\n\t return RSVP.all(processing).\n\t then(function(replacementUrls) {\n\n\t\t\t\t// Replace Asset Urls in the text of all css files\n\t\t\t\tcssUrls.forEach(function(href) {\n\t\t\t\t\tthis.replaceCss(href, urls, replacementUrls);\n\t\t }.bind(this));\n\n\t\t\t\t// Replace Asset Urls in chapters\n\t\t\t\t// by registering a hook after the sections contents has been serialized\n\t this.hooks.serialize.register(function(output, section) {\n\t\t\t\t\tthis.replaceAssets(section, urls, replacementUrls);\n\t }.bind(this));\n\n\t }.bind(this)).catch(function(reason){\n\t console.error(reason);\n\t });\n\t}.bind(this));\n};\n\nRendition.prototype.replaceCss = function(href, urls, replacementUrls){\n\t\tvar newUrl;\n\t\tvar indexInUrls;\n\n\t\t// Find the absolute url of the css file\n\t\tvar fileUri = URI(href);\n\t\tvar absolute = fileUri.absoluteTo(this.book.baseUrl).toString();\n\t\t// Get the text of the css file from the archive\n\t\tvar text = this.book.archive.getText(absolute);\n\t\t// Get asset links relative to css file\n\t\tvar relUrls = urls.\n\t\t\tmap(function(assetHref) {\n\t\t\t\tvar assetUri = URI(assetHref).absoluteTo(this.book.baseUrl);\n\t\t\t\tvar relative = assetUri.relativeTo(absolute).toString();\n\t\t\t\treturn relative;\n\t\t\t}.bind(this));\n\n\t\t// Replacements in the css text\n\t\ttext = replace.substitute(text, relUrls, replacementUrls);\n\n\t\t// Get the new url\n\t\tnewUrl = core.createBlobUrl(text, 'text/css');\n\n\t\t// switch the url in the replacementUrls\n\t\tindexInUrls = urls.indexOf(href);\n\t\tif (indexInUrls > -1) {\n\t\t\treplacementUrls[indexInUrls] = newUrl;\n\t\t}\n};\n\nRendition.prototype.replaceAssets = function(section, urls, replacementUrls){\n\tvar fileUri = URI(section.url);\n\t// Get Urls relative to current sections\n\tvar relUrls = urls.\n\t\tmap(function(href) {\n\t\t\tvar assetUri = URI(href).absoluteTo(this.book.baseUrl);\n\t\t\tvar relative = assetUri.relativeTo(fileUri).toString();\n\t\t\treturn relative;\n\t\t}.bind(this));\n\n\n\tsection.output = replace.substitute(section.output, relUrls, replacementUrls);\n};\n\nRendition.prototype.range = function(_cfi, ignoreClass){\n var cfi = new EpubCFI(_cfi);\n var found = this.visible().filter(function (view) {\n\t\tif(cfi.spinePos === view.index) return true;\n\t});\n\n\t// Should only every return 1 item\n if (found.length) {\n return found[0].range(cfi, ignoreClass);\n }\n};\n\n//-- Enable binding events to Renderer\nRSVP.EventTarget.mixin(Rendition.prototype);\n\nmodule.exports = Rendition;\n","var URI = require('urijs');\nvar core = require('./core');\n\nfunction base(doc, section){\n var base;\n var head;\n\n if(!doc){\n return;\n }\n\n head = doc.querySelector(\"head\");\n base = head.querySelector(\"base\");\n\n if(!base) {\n base = doc.createElement(\"base\");\n }\n\n base.setAttribute(\"href\", section.url);\n head.insertBefore(base, head.firstChild);\n\n}\n\nfunction links(view, renderer) {\n\n var links = view.document.querySelectorAll(\"a[href]\");\n var replaceLinks = function(link){\n var href = link.getAttribute(\"href\");\n var linkUri = URI(href);\n var absolute = linkUri.absoluteTo(view.section.url);\n var relative = absolute.relativeTo(this.book.baseUrl).toString();\n\n if(linkUri.protocol()){\n\n link.setAttribute(\"target\", \"_blank\");\n\n }else{\n /*\n if(baseDirectory) {\n\t\t\t\t// We must ensure that the file:// protocol is preserved for\n\t\t\t\t// local file links, as in certain contexts (such as under\n\t\t\t\t// Titanium), file links without the file:// protocol will not\n\t\t\t\t// work\n\t\t\t\tif (baseUri.protocol === \"file\") {\n\t\t\t\t\trelative = core.resolveUrl(baseUri.base, href);\n\t\t\t\t} else {\n\t\t\t\t\trelative = core.resolveUrl(baseDirectory, href);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trelative = href;\n\t\t\t}\n */\n\n if(linkUri.fragment()) {\n // do nothing with fragment yet\n } else {\n link.onclick = function(){\n renderer.display(relative);\n return false;\n };\n }\n\n }\n };\n\n for (var i = 0; i < links.length; i++) {\n replaceLinks(links[i]);\n }\n\n\n};\n\nfunction substitute(content, urls, replacements) {\n urls.forEach(function(url, i){\n if (url && replacements[i]) {\n content = content.replace(new RegExp(url, 'g'), replacements[i]);\n }\n });\n return content;\n}\nmodule.exports = {\n 'base': base,\n 'links': links,\n 'substitute': substitute\n};\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\n\nfunction request(url, type, withCredentials, headers) {\n var supportsURL = (typeof window != \"undefined\") ? window.URL : false; // TODO: fallback for url if window isn't defined\n var BLOB_RESPONSE = supportsURL ? \"blob\" : \"arraybuffer\";\n var uri;\n\n var deferred = new RSVP.defer();\n\n var xhr = new XMLHttpRequest();\n\n //-- Check from PDF.js:\n // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js\n var xhrPrototype = XMLHttpRequest.prototype;\n\n var header;\n\n if (!('overrideMimeType' in xhrPrototype)) {\n // IE10 might have response, but not overrideMimeType\n Object.defineProperty(xhrPrototype, 'overrideMimeType', {\n value: function xmlHttpRequestOverrideMimeType(mimeType) {}\n });\n }\n if(withCredentials) {\n xhr.withCredentials = true;\n }\n\n xhr.onreadystatechange = handler;\n xhr.onerror = err;\n\n xhr.open(\"GET\", url, true);\n\n for(header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n\n if(type == \"json\") {\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n }\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n xhr.responseType = BLOB_RESPONSE;\n }\n\n\n if(core.isXml(type)) {\n\t\txhr.responseType = \"document\";\n\t\txhr.overrideMimeType('text/xml'); // for OPF parsing\n\t}\n\n\tif(type == 'xhtml') {\n\t\txhr.responseType = \"document\";\n\t}\n\n\tif(type == 'html' || type == 'htm') {\n\t\txhr.responseType = \"document\";\n \t}\n\n if(type == \"binary\") {\n xhr.responseType = \"arraybuffer\";\n }\n\n xhr.send();\n\n function err(e) {\n console.error(e);\n deferred.reject(e);\n }\n\n function handler() {\n if (this.readyState === XMLHttpRequest.DONE) {\n\n if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls\n var r;\n\n if (!this.response && !this.responseXML) {\n deferred.reject({\n status: this.status,\n message : \"Empty Response\",\n stack : new Error().stack\n });\n return deferred.promise;\n }\n\n if((this.responseType == '' || this.responseType == 'document')\n && this.responseXML){\n r = this.responseXML;\n } else\n if(core.isXml(type)){\n // xhr.overrideMimeType('text/xml'); // for OPF parsing\n // If this.responseXML wasn't set, try to parse using a DOMParser from text\n r = new DOMParser().parseFromString(this.response, \"text/xml\");\n }else\n if(type == 'xhtml'){\n console.log(this.response);\n r = new DOMParser().parseFromString(this.response, \"application/xhtml+xml\");\n }else\n if(type == 'html' || type == 'htm'){\n r = new DOMParser().parseFromString(this.response, \"text/html\");\n }else\n if(type == 'json'){\n r = JSON.parse(this.response);\n }else\n if(type == 'blob'){\n\n if(supportsURL) {\n r = this.response;\n } else {\n //-- Safari doesn't support responseType blob, so create a blob from arraybuffer\n r = new Blob([this.response]);\n }\n\n }else{\n r = this.response;\n }\n\n deferred.resolve(r);\n } else {\n\n deferred.reject({\n status: this.status,\n message : this.response,\n stack : new Error().stack\n });\n\n }\n }\n }\n\n return deferred.promise;\n};\n\nmodule.exports = request;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Hook = require('./hook');\nvar replacements = require('./replacements');\n\nfunction Section(item, hooks){\n this.idref = item.idref;\n this.linear = item.linear;\n this.properties = item.properties;\n this.index = item.index;\n this.href = item.href;\n this.url = item.url;\n this.next = item.next;\n this.prev = item.prev;\n\n this.cfiBase = item.cfiBase;\n\n this.hooks = {};\n this.hooks.serialize = new Hook(this);\n this.hooks.content = new Hook(this);\n\n // Register replacements\n this.hooks.content.register(replacements.base);\n};\n\n\nSection.prototype.load = function(_request){\n var request = _request || this.request || require('./request');\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(this.contents) {\n loading.resolve(this.contents);\n } else {\n request(this.url)\n .then(function(xml){\n var base;\n var directory = URI(this.url).directory();\n\n this.document = xml;\n this.contents = xml.documentElement;\n\n return this.hooks.content.trigger(this.document, this);\n }.bind(this))\n .then(function(){\n loading.resolve(this.contents);\n }.bind(this))\n .catch(function(error){\n loading.reject(error);\n });\n }\n\n return loaded;\n};\n\nSection.prototype.base = function(_document){\n var task = new RSVP.defer();\n var base = _document.createElement(\"base\"); // TODO: check if exists\n var head;\n\n base.setAttribute(\"href\", this.url);\n\n if(_document) {\n head = _document.querySelector(\"head\");\n }\n if(head) {\n head.insertBefore(base, head.firstChild);\n task.resolve();\n } else {\n task.reject(new Error(\"No head to insert into\"));\n }\n\n\n return task.promise;\n};\n\nSection.prototype.beforeSectionLoad = function(){\n // Stub for a hook - replace me for now\n};\n\nSection.prototype.render = function(_request){\n var rendering = new RSVP.defer();\n var rendered = rendering.promise;\n this.output; // TODO: better way to return this from hooks?\n\n this.load(_request).\n then(function(contents){\n var serializer = new XMLSerializer();\n this.output = serializer.serializeToString(contents);\n return this.output;\n }.bind(this)).\n then(function(){\n return this.hooks.serialize.trigger(this.output, this);\n }.bind(this)).\n then(function(){\n rendering.resolve(this.output);\n }.bind(this))\n .catch(function(error){\n rendering.reject(error);\n });\n\n return rendered;\n};\n\nSection.prototype.find = function(_query){\n\n};\n\n/**\n* Reconciles the current chapters layout properies with\n* the global layout properities.\n* Takes: global layout settings object, chapter properties string\n* Returns: Object with layout properties\n*/\nSection.prototype.reconcileLayoutSettings = function(global){\n //-- Get the global defaults\n var settings = {\n layout : global.layout,\n spread : global.spread,\n orientation : global.orientation\n };\n\n //-- Get the chapter's display type\n this.properties.forEach(function(prop){\n var rendition = prop.replace(\"rendition:\", '');\n var split = rendition.indexOf(\"-\");\n var property, value;\n\n if(split != -1){\n property = rendition.slice(0, split);\n value = rendition.slice(split+1);\n\n settings[property] = value;\n }\n });\n return settings;\n};\n\nSection.prototype.cfiFromRange = function(_range) {\n return new EpubCFI(_range, this.cfiBase).toString();\n};\n\nSection.prototype.cfiFromElement = function(el) {\n return new EpubCFI(el, this.cfiBase).toString();\n};\n\nmodule.exports = Section;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\nvar Section = require('./section');\n\nfunction Spine(_request){\n this.request = _request;\n this.spineItems = [];\n this.spineByHref = {};\n this.spineById = {};\n\n};\n\nSpine.prototype.load = function(_package) {\n\n this.items = _package.spine;\n this.manifest = _package.manifest;\n this.spineNodeIndex = _package.spineNodeIndex;\n this.baseUrl = _package.baseUrl || '';\n this.length = this.items.length;\n this.epubcfi = new EpubCFI();\n\n this.items.forEach(function(item, index){\n var href, url;\n var manifestItem = this.manifest[item.idref];\n var spineItem;\n\n item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);\n\n if(manifestItem) {\n item.href = manifestItem.href;\n item.url = this.baseUrl + item.href;\n\n if(manifestItem.properties.length){\n item.properties.push.apply(item.properties, manifestItem.properties);\n }\n }\n\n // if(index > 0) {\n item.prev = function(){ return this.get(index-1); }.bind(this);\n // }\n\n // if(index+1 < this.items.length) {\n item.next = function(){ return this.get(index+1); }.bind(this);\n // }\n\n spineItem = new Section(item);\n this.append(spineItem);\n\n\n }.bind(this));\n\n};\n\n// book.spine.get();\n// book.spine.get(1);\n// book.spine.get(\"chap1.html\");\n// book.spine.get(\"#id1234\");\nSpine.prototype.get = function(target) {\n var index = 0;\n\n if(this.epubcfi.isCfiString(target)) {\n cfi = new EpubCFI(target);\n index = cfi.spinePos;\n } else if(target && (typeof target === \"number\" || isNaN(target) === false)){\n index = target;\n } else if(target && target.indexOf(\"#\") === 0) {\n index = this.spineById[target.substring(1)];\n } else if(target) {\n // Remove fragments\n target = target.split(\"#\")[0];\n index = this.spineByHref[target];\n }\n\n return this.spineItems[index] || null;\n};\n\nSpine.prototype.append = function(section) {\n var index = this.spineItems.length;\n section.index = index;\n\n this.spineItems.push(section);\n\n this.spineByHref[section.href] = index;\n this.spineById[section.idref] = index;\n\n return index;\n};\n\nSpine.prototype.prepend = function(section) {\n var index = this.spineItems.unshift(section);\n this.spineByHref[section.href] = 0;\n this.spineById[section.idref] = 0;\n\n // Re-index\n this.spineItems.forEach(function(item, index){\n item.index = index;\n });\n\n return 0;\n};\n\nSpine.prototype.insert = function(section, index) {\n\n};\n\nSpine.prototype.remove = function(section) {\n var index = this.spineItems.indexOf(section);\n\n if(index > -1) {\n delete this.spineByHref[section.href];\n delete this.spineById[section.idref];\n\n return this.spineItems.splice(index, 1);\n }\n};\n\nSpine.prototype.each = function() {\n\treturn this.spineItems.forEach.apply(this.spineItems, arguments);\n};\n\nmodule.exports = Spine;\n","var RSVP = require('rsvp');\nvar URI = require('urijs');\nvar core = require('./core');\nvar request = require('./request');\nvar mime = require('../libs/mime/mime');\n\nfunction Unarchive() {\n\n this.checkRequirements();\n this.urlCache = {};\n\n}\n\nUnarchive.prototype.checkRequirements = function(callback){\n try {\n if (typeof JSZip !== 'undefined') {\n this.zip = new JSZip();\n } else {\n JSZip = require('jszip');\n this.zip = new JSZip();\n }\n } catch (e) {\n console.error(\"JSZip lib not loaded\");\n }\n};\n\nUnarchive.prototype.open = function(zipUrl){\n\tif (zipUrl instanceof ArrayBuffer) {\n return new RSVP.Promise(function(resolve, reject) {\n this.zip = new JSZip(zipUrl);\n resolve(this.zip);\n });\n\t} else {\n\t\treturn request(zipUrl, \"binary\")\n .then(function(data){\n\t\t\t this.zip = new JSZip(data);\n return this.zip;\n\t\t }.bind(this));\n\t}\n};\n\nUnarchive.prototype.request = function(url, type){\n var deferred = new RSVP.defer();\n var response;\n var r;\n\n // If type isn't set, determine it from the file extension\n\tif(!type) {\n\t\turi = URI(url);\n\t\ttype = uri.suffix();\n\t}\n\n if(type == 'blob'){\n response = this.getBlob(url);\n } else {\n response = this.getText(url);\n }\n\n if (response) {\n r = this.handleResponse(response, type);\n deferred.resolve(r);\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n return deferred.promise;\n};\n\nUnarchive.prototype.handleResponse = function(response, type){\n var r;\n\n if(type == \"json\") {\n r = JSON.parse(response);\n }\n else\n if(core.isXml(type)) {\n r = new DOMParser().parseFromString(response, \"text/xml\");\n\t}\n else\n\tif(type == 'xhtml') {\n r = new DOMParser().parseFromString(response, \"application/xhtml+xml\");\n\t}\n else\n\tif(type == 'html' || type == 'htm') {\n r = new DOMParser().parseFromString(response, \"text/html\");\n \t} else {\n \t r = response;\n \t}\n\n return r;\n};\n\nUnarchive.prototype.getBlob = function(url, _mimeType){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n var mimeType;\n\n\tif(entry) {\n mimeType = _mimeType || mime.lookup(entry.name);\n return new Blob([entry.asUint8Array()], {type : mimeType});\n\t}\n};\n\nUnarchive.prototype.getText = function(url, encoding){\n\tvar decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash\n\tvar entry = this.zip.file(decodededUrl);\n\n\tif(entry) {\n return entry.asText();\n\t}\n};\n\nUnarchive.prototype.createUrl = function(url, mime){\n\tvar deferred = new RSVP.defer();\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar tempUrl;\n\tvar blob;\n\n\tif(url in this.urlCache) {\n\t\tdeferred.resolve(this.urlCache[url]);\n\t\treturn deferred.promise;\n\t}\n\n\tblob = this.getBlob(url);\n\n if (blob) {\n tempUrl = _URL.createObjectURL(blob);\n deferred.resolve(tempUrl);\n this.urlCache[url] = tempUrl;\n } else {\n deferred.reject({\n message : \"File not found in the epub: \" + url,\n stack : new Error().stack\n });\n }\n\n\treturn deferred.promise;\n};\n\nUnarchive.prototype.revokeUrl = function(url){\n\tvar _URL = window.URL || window.webkitURL || window.mozURL;\n\tvar fromCache = this.urlCache[url];\n\tif(fromCache) _URL.revokeObjectURL(fromCache);\n};\n\nmodule.exports = Unarchive;\n","var RSVP = require('rsvp');\nvar core = require('./core');\nvar EpubCFI = require('./epubcfi');\n\nfunction View(section, options) {\n this.settings = core.extend({\n ignoreClass : ''\n }, options || {});\n\n this.id = \"epubjs-view:\" + core.uuid();\n this.section = section;\n this.index = section.index;\n\n this.element = document.createElement('div');\n this.element.classList.add(\"epub-view\");\n\n\n // this.element.style.minHeight = \"100px\";\n this.element.style.height = \"0px\";\n this.element.style.width = \"0px\";\n this.element.style.overflow = \"hidden\";\n\n this.added = false;\n this.displayed = false;\n this.rendered = false;\n\n //this.width = 0;\n //this.height = 0;\n\n // Blank Cfi for Parsing\n this.epubcfi = new EpubCFI();\n\n if(this.settings.axis && this.settings.axis == \"horizontal\"){\n this.element.style.display = \"inline-block\";\n } else {\n this.element.style.display = \"block\";\n }\n\n // Dom events to listen for\n this.listenedEvents = [\"keydown\", \"keyup\", \"keypressed\", \"mouseup\", \"mousedown\", \"click\", \"touchend\", \"touchstart\"];\n\n};\n\nView.prototype.create = function() {\n\n if(this.iframe) {\n return this.iframe;\n }\n\n this.iframe = document.createElement('iframe');\n this.iframe.id = this.id;\n this.iframe.scrolling = \"no\"; // Might need to be removed: breaks ios width calculations\n this.iframe.style.overflow = \"hidden\";\n this.iframe.seamless = \"seamless\";\n // Back up if seamless isn't supported\n this.iframe.style.border = \"none\";\n\n this.resizing = true;\n\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.iframe.style.width = \"0\";\n this.iframe.style.height = \"0\";\n this._width = 0;\n this._height = 0;\n\n this.element.appendChild(this.iframe);\n this.added = true;\n\n this.elementBounds = core.bounds(this.element);\n\n // if(width || height){\n // this.resize(width, height);\n // } else if(this.width && this.height){\n // this.resize(this.width, this.height);\n // } else {\n // this.iframeBounds = core.bounds(this.iframe);\n // }\n\n // Firefox has trouble with baseURI and srcdoc\n // Disabled for now\n /*\n if(!!(\"srcdoc\" in this.iframe)) {\n this.supportsSrcdoc = true;\n } else {\n this.supportsSrcdoc = false;\n }\n */\n this.supportsSrcdoc = false;\n\n return this.iframe;\n};\n\n\nView.prototype.lock = function(what, width, height) {\n\n var elBorders = core.borders(this.element);\n var iframeBorders;\n\n if(this.iframe) {\n iframeBorders = core.borders(this.iframe);\n } else {\n iframeBorders = {width: 0, height: 0};\n }\n\n if(what == \"width\" && core.isNumber(width)){\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.resize(this.lockedWidth, width); // width keeps ratio correct\n }\n\n if(what == \"height\" && core.isNumber(height)){\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n this.resize(width, this.lockedHeight);\n }\n\n if(what === \"both\" &&\n core.isNumber(width) &&\n core.isNumber(height)){\n\n this.lockedWidth = width - elBorders.width - iframeBorders.width;\n this.lockedHeight = height - elBorders.height - iframeBorders.height;\n\n this.resize(this.lockedWidth, this.lockedHeight);\n }\n\n if(this.displayed && this.iframe) {\n\n this.layout();\n this.expand();\n\n }\n\n\n\n};\n\nView.prototype.expand = function(force) {\n var width = this.lockedWidth;\n var height = this.lockedHeight;\n\n var textWidth, textHeight;\n // console.log(\"expanding a\")\n if(!this.iframe || this._expanding) return;\n\n this._expanding = true;\n\n // Expand Horizontally\n if(height && !width) {\n // Get the width of the text\n textWidth = this.textWidth();\n // Check if the textWidth has changed\n if(textWidth != this._textWidth){\n // Get the contentWidth by resizing the iframe\n // Check with a min reset of the textWidth\n width = this.contentWidth(textWidth);\n // Save the textWdith\n this._textWidth = textWidth;\n // Save the contentWidth\n this._contentWidth = width;\n } else {\n // Otherwise assume content height hasn't changed\n width = this._contentWidth;\n }\n }\n\n // Expand Vertically\n if(width && !height) {\n textHeight = this.textHeight();\n if(textHeight != this._textHeight){\n height = this.contentHeight(textHeight);\n this._textHeight = textHeight;\n this._contentHeight = height;\n } else {\n height = this._contentHeight;\n }\n }\n\n // Only Resize if dimensions have changed or\n // if Frame is still hidden, so needs reframing\n if(this._needsReframe || width != this._width || height != this._height){\n this.resize(width, height);\n }\n\n this._expanding = false;\n};\n\nView.prototype.contentWidth = function(min) {\n var prev;\n var width;\n\n // Save previous width\n prev = this.iframe.style.width;\n // Set the iframe size to min, width will only ever be greater\n // Will preserve the aspect ratio\n this.iframe.style.width = (min || 0) + \"px\";\n // Get the scroll overflow width\n width = this.document.body.scrollWidth;\n // Reset iframe size back\n this.iframe.style.width = prev;\n return width;\n};\n\nView.prototype.contentHeight = function(min) {\n var prev;\n var height;\n\n prev = this.iframe.style.height;\n this.iframe.style.height = (min || 0) + \"px\";\n height = this.document.body.scrollHeight;\n this.iframe.style.height = prev;\n return height;\n};\n\nView.prototype.textWidth = function() {\n var width;\n var range = this.document.createRange();\n\n // Select the contents of frame\n range.selectNodeContents(this.document.body);\n\n // get the width of the text content\n width = range.getBoundingClientRect().width;\n return width;\n\n};\n\nView.prototype.textHeight = function() {\n var height;\n var range = this.document.createRange();\n\n range.selectNodeContents(this.document.body);\n\n height = range.getBoundingClientRect().height;\n return height;\n};\n\nView.prototype.resize = function(width, height) {\n\n if(!this.iframe) return;\n\n if(core.isNumber(width)){\n this.iframe.style.width = width + \"px\";\n this._width = width;\n }\n\n if(core.isNumber(height)){\n this.iframe.style.height = height + \"px\";\n this._height = height;\n }\n\n this.iframeBounds = core.bounds(this.iframe);\n\n this.reframe(this.iframeBounds.width, this.iframeBounds.height);\n\n};\n\nView.prototype.reframe = function(width, height) {\n //var prevBounds;\n\n if(!this.displayed) {\n this._needsReframe = true;\n return;\n }\n\n if(core.isNumber(width)){\n this.element.style.width = width + \"px\";\n }\n\n if(core.isNumber(height)){\n this.element.style.height = height + \"px\";\n }\n\n this.prevBounds = this.elementBounds;\n\n this.elementBounds = core.bounds(this.element);\n\n this.trigger(\"resized\", {\n width: this.elementBounds.width,\n height: this.elementBounds.height,\n widthDelta: this.elementBounds.width - this.prevBounds.width,\n heightDelta: this.elementBounds.height - this.prevBounds.height,\n });\n\n};\n\nView.prototype.resized = function(e) {\n /*\n if (!this.resizing) {\n if(this.iframe) {\n // this.expand();\n }\n } else {\n this.resizing = false;\n }*/\n\n};\n\nView.prototype.render = function(_request) {\n\n // if(this.rendering){\n // return this.displayed;\n // }\n\n this.rendering = true;\n // this.displayingDefer = new RSVP.defer();\n // this.displayedPromise = this.displaying.promise;\n\n return this.section.render(_request)\n .then(function(contents){\n return this.load(contents);\n }.bind(this));\n};\n\nView.prototype.load = function(contents) {\n var loading = new RSVP.defer();\n var loaded = loading.promise;\n\n if(!this.iframe) {\n loading.reject(new Error(\"No Iframe Available\"));\n return loaded;\n }\n\n this.iframe.onload = function(event) {\n\n this.window = this.iframe.contentWindow;\n this.document = this.iframe.contentDocument;\n this.rendering = false;\n loading.resolve(this);\n\n }.bind(this);\n\n if(this.supportsSrcdoc){\n this.iframe.srcdoc = contents;\n } else {\n\n this.document = this.iframe.contentDocument;\n\n if(!this.document) {\n loading.reject(new Error(\"No Document Available\"));\n return loaded;\n }\n\n this.document.open();\n this.document.write(contents);\n this.document.close();\n\n }\n\n return loaded;\n};\n\n\nView.prototype.layout = function(layoutFunc) {\n\n this.iframe.style.display = \"inline-block\";\n\n // Reset Body Styles\n this.document.body.style.margin = \"0\";\n //this.document.body.style.display = \"inline-block\";\n //this.document.documentElement.style.width = \"auto\";\n\n if(layoutFunc){\n layoutFunc(this);\n }\n\n this.onLayout(this);\n\n};\n\nView.prototype.onLayout = function(view) {\n // stub\n};\n\nView.prototype.listeners = function() {\n /*\n setTimeout(function(){\n this.window.addEventListener(\"resize\", this.resized.bind(this), false);\n }.bind(this), 10); // Wait to listen for resize events\n */\n\n // Wait for fonts to load to finish\n // http://dev.w3.org/csswg/css-font-loading/\n // Not implemented fully except in chrome\n\n if(this.document.fonts && this.document.fonts.status === \"loading\") {\n // console.log(\"fonts unloaded\");\n this.document.fonts.onloadingdone = function(){\n // console.log(\"loaded fonts\");\n this.expand();\n }.bind(this);\n }\n\n if(this.section.properties.indexOf(\"scripted\") > -1){\n this.observer = this.observe(this.document.body);\n }\n\n this.imageLoadListeners();\n\n this.mediaQueryListeners();\n\n // this.resizeListenters();\n\n this.addEventListeners();\n\n this.addSelectionListeners();\n};\n\nView.prototype.removeListeners = function() {\n\n this.removeEventListeners();\n\n this.removeSelectionListeners();\n};\n\nView.prototype.resizeListenters = function() {\n // Test size again\n clearTimeout(this.expanding);\n this.expanding = setTimeout(this.expand.bind(this), 350);\n};\n\n//https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js\nView.prototype.mediaQueryListeners = function() {\n var sheets = this.document.styleSheets;\n var mediaChangeHandler = function(m){\n if(m.matches && !this._expanding) {\n setTimeout(this.expand.bind(this), 1);\n // this.expand();\n }\n }.bind(this);\n\n for (var i = 0; i < sheets.length; i += 1) {\n var rules = sheets[i].cssRules;\n if(!rules) return; // Stylesheets changed\n for (var j = 0; j < rules.length; j += 1) {\n //if (rules[j].constructor === CSSMediaRule) {\n if(rules[j].media){\n var mql = this.window.matchMedia(rules[j].media.mediaText);\n mql.addListener(mediaChangeHandler);\n //mql.onchange = mediaChangeHandler;\n }\n }\n }\n};\n\nView.prototype.observe = function(target) {\n var renderer = this;\n\n // create an observer instance\n var observer = new MutationObserver(function(mutations) {\n if(renderer._expanding) {\n renderer.expand();\n }\n // mutations.forEach(function(mutation) {\n // console.log(mutation);\n // });\n });\n\n // configuration of the observer:\n var config = { attributes: true, childList: true, characterData: true, subtree: true };\n\n // pass in the target node, as well as the observer options\n observer.observe(target, config);\n\n return observer;\n};\n\n// View.prototype.appendTo = function(element) {\n// this.element = element;\n// this.element.appendChild(this.iframe);\n// };\n//\n// View.prototype.prependTo = function(element) {\n// this.element = element;\n// element.insertBefore(this.iframe, element.firstChild);\n// };\n\nView.prototype.imageLoadListeners = function(target) {\n var images = this.document.body.querySelectorAll(\"img\");\n var img;\n for (var i = 0; i < images.length; i++) {\n img = images[i];\n\n if (typeof img.naturalWidth !== \"undefined\" &&\n img.naturalWidth === 0) {\n img.onload = this.expand.bind(this);\n }\n }\n};\n\nView.prototype.display = function() {\n var displayed = new RSVP.defer();\n\n this.displayed = true;\n\n this.layout();\n\n this.listeners();\n\n this.expand();\n\n this.trigger(\"displayed\", this);\n this.onDisplayed(this);\n\n displayed.resolve(this);\n\n return displayed.promise;\n};\n\nView.prototype.show = function() {\n\n this.element.style.visibility = \"visible\";\n\n if(this.iframe){\n this.iframe.style.visibility = \"visible\";\n }\n\n this.trigger(\"shown\", this);\n};\n\nView.prototype.hide = function() {\n // this.iframe.style.display = \"none\";\n this.element.style.visibility = \"hidden\";\n this.iframe.style.visibility = \"hidden\";\n\n this.stopExpanding = true;\n this.trigger(\"hidden\", this);\n};\n\nView.prototype.position = function() {\n return this.element.getBoundingClientRect();\n};\n\nView.prototype.onDisplayed = function(view) {\n // Stub, override with a custom functions\n};\n\nView.prototype.bounds = function() {\n if(!this.elementBounds) {\n this.elementBounds = core.bounds(this.element);\n }\n return this.elementBounds;\n};\n\nView.prototype.destroy = function() {\n // Stop observing\n if(this.observer) {\n this.observer.disconnect();\n }\n\n if(this.displayed){\n this.removeListeners();\n\n this.stopExpanding = true;\n this.element.removeChild(this.iframe);\n this.displayed = false;\n this.iframe = null;\n\n this._textWidth = null;\n this._textHeight = null;\n this._width = null;\n this._height = null;\n }\n // this.element.style.height = \"0px\";\n // this.element.style.width = \"0px\";\n};\n\nView.prototype.root = function() {\n if(!this.document) return null;\n return this.document.documentElement;\n};\n\nView.prototype.locationOf = function(target) {\n var parentPos = this.iframe.getBoundingClientRect();\n var targetPos = {\"left\": 0, \"top\": 0};\n\n if(!this.document) return;\n\n if(this.epubcfi.isCfiString(target)) {\n range = new EpubCFI(cfi).toRange(this.document, this.settings.ignoreClass);\n if(range) {\n targetPos = range.getBoundingClientRect();\n }\n\n } else if(typeof target === \"string\" &&\n target.indexOf(\"#\") > -1) {\n\n id = target.substring(target.indexOf(\"#\")+1);\n el = this.document.getElementById(id);\n\n if(el) {\n targetPos = el.getBoundingClientRect();\n }\n }\n\n return {\n \"left\": window.scrollX + parentPos.left + targetPos.left,\n \"top\": window.scrollY + parentPos.top + targetPos.top\n };\n};\n\nView.prototype.addCss = function(src) {\n return new RSVP.Promise(function(resolve, reject){\n var $stylesheet;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $stylesheet = this.document.createElement('link');\n $stylesheet.type = 'text/css';\n $stylesheet.rel = \"stylesheet\";\n $stylesheet.href = src;\n $stylesheet.onload = $stylesheet.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n // Let apply\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($stylesheet);\n\n }.bind(this));\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule\nView.prototype.addStylesheetRules = function(rules) {\n var styleEl;\n var styleSheet;\n\n if(!this.document) return;\n\n styleEl = this.document.createElement('style');\n\n // Append style element to head\n this.document.head.appendChild(styleEl);\n\n // Grab style sheet\n styleSheet = styleEl.sheet;\n\n for (var i = 0, rl = rules.length; i < rl; i++) {\n var j = 1, rule = rules[i], selector = rules[i][0], propStr = '';\n // If the second argument of a rule is an array of arrays, correct our variables.\n if (Object.prototype.toString.call(rule[1][0]) === '[object Array]') {\n rule = rule[1];\n j = 0;\n }\n\n for (var pl = rule.length; j < pl; j++) {\n var prop = rule[j];\n propStr += prop[0] + ':' + prop[1] + (prop[2] ? ' !important' : '') + ';\\n';\n }\n\n // Insert CSS Rule\n styleSheet.insertRule(selector + '{' + propStr + '}', styleSheet.cssRules.length);\n }\n};\n\nView.prototype.addScript = function(src) {\n\n return new RSVP.Promise(function(resolve, reject){\n var $script;\n var ready = false;\n\n if(!this.document) {\n resolve(false);\n return;\n }\n\n $script = this.document.createElement('script');\n $script.type = 'text/javascript';\n $script.async = true;\n $script.src = src;\n $script.onload = $script.onreadystatechange = function() {\n if ( !ready && (!this.readyState || this.readyState == 'complete') ) {\n ready = true;\n setTimeout(function(){\n resolve(true);\n }, 1);\n }\n };\n\n this.document.head.appendChild($script);\n\n }.bind(this));\n};\n\nView.prototype.addEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);\n }, this);\n\n};\n\nView.prototype.removeEventListeners = function(){\n if(!this.document) {\n return;\n }\n this.listenedEvents.forEach(function(eventName){\n this.document.removeEventListener(eventName, this.triggerEvent, false);\n }, this);\n\n};\n\n// Pass browser events\nView.prototype.triggerEvent = function(e){\n this.trigger(e.type, e);\n};\n\nView.prototype.addSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.addEventListener(\"selectionchange\", this.onSelectionChange.bind(this), false);\n};\n\nView.prototype.removeSelectionListeners = function(){\n if(!this.document) {\n return;\n }\n this.document.removeEventListener(\"selectionchange\", this.onSelectionChange, false);\n};\n\nView.prototype.onSelectionChange = function(e){\n if (this.selectionEndTimeout) {\n clearTimeout(this.selectionEndTimeout);\n }\n this.selectionEndTimeout = setTimeout(function() {\n var selection = this.window.getSelection();\n this.triggerSelectedEvent(selection);\n }.bind(this), 500);\n};\n\nView.prototype.triggerSelectedEvent = function(selection){\n\tvar range, cfirange;\n\n if (selection && selection.rangeCount > 0) {\n range = selection.getRangeAt(0);\n if(!range.collapsed) {\n cfirange = this.section.cfiFromRange(range);\n this.trigger(\"selected\", cfirange);\n this.trigger(\"selectedRange\", range);\n }\n }\n};\n\nView.prototype.range = function(_cfi, ignoreClass){\n var cfi = new EpubCFI(_cfi);\n return cfi.toRange(this.document, ignoreClass || this.settings.ignoreClass);\n};\n\nRSVP.EventTarget.mixin(View.prototype);\n\nmodule.exports = View;\n","function Views(container) {\n this.container = container;\n this._views = [];\n this.length = 0;\n this.hidden = false;\n};\n\nViews.prototype.first = function() {\n\treturn this._views[0];\n};\n\nViews.prototype.last = function() {\n\treturn this._views[this._views.length-1];\n};\n\nViews.prototype.each = function() {\n\treturn this._views.forEach.apply(this._views, arguments);\n};\n\nViews.prototype.indexOf = function(view) {\n\treturn this._views.indexOf(view);\n};\n\nViews.prototype.slice = function() {\n\treturn this._views.slice.apply(this._views, arguments);\n};\n\nViews.prototype.get = function(i) {\n\treturn this._views[i];\n};\n\nViews.prototype.append = function(view){\n\tthis._views.push(view);\n\tthis.container.appendChild(view.element);\n this.length++;\n return view;\n};\n\nViews.prototype.prepend = function(view){\n\tthis._views.unshift(view);\n\tthis.container.insertBefore(view.element, this.container.firstChild);\n this.length++;\n return view;\n};\n\nViews.prototype.insert = function(view, index) {\n\tthis._views.splice(index, 0, view);\n\n\tif(index < this.container.children.length){\n\t\tthis.container.insertBefore(view.element, this.container.children[index]);\n\t} else {\n\t\tthis.container.appendChild(view.element);\n\t}\n this.length++;\n return view;\n};\n\nViews.prototype.remove = function(view) {\n\tvar index = this._views.indexOf(view);\n\n\tif(index > -1) {\n\t\tthis._views.splice(index, 1);\n\t}\n\n\n\tthis.destroy(view);\n\n this.length--;\n};\n\nViews.prototype.destroy = function(view) {\n\tview.off(\"resized\");\n\n\tif(view.displayed){\n\t\tview.destroy();\n\t}\n\n\tthis.container.removeChild(view.element);\n\tview = null;\n};\n\n// Iterators\n\nViews.prototype.clear = function(){\n\t// Remove all views\n var view;\n var len = this.length;\n\n if(!this.length) return;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tthis.destroy(view);\n }\n\n this._views = [];\n this.length = 0;\n};\n\nViews.prototype.find = function(section){\n\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n\t\tif(view.displayed && view.section.index == section.index) {\n\t\t\treturn view;\n\t\t}\n }\n\n};\n\nViews.prototype.displayed = function(){\n var displayed = [];\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n displayed.push(view);\n }\n }\n return displayed;\n};\n\nViews.prototype.show = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.show();\n }\n }\n this.hidden = false;\n};\n\nViews.prototype.hide = function(){\n var view;\n var len = this.length;\n\n for (var i = 0; i < len; i++) {\n view = this._views[i];\n if(view.displayed){\n view.hide();\n }\n }\n this.hidden = true;\n};\n\nmodule.exports = Views;\n","var Book = require('./book');\nvar EpubCFI = require('./epubcfi');\n\nfunction ePub(_url) {\n\treturn new Book(_url);\n};\n\nePub.VERSION = \"0.3.0\";\n\nePub.CFI = EpubCFI;\n\nmodule.exports = ePub;\n"]} \ No newline at end of file diff --git a/examples/highlights.html b/examples/highlights.html index b45cc82..3bca094 100644 --- a/examples/highlights.html +++ b/examples/highlights.html @@ -5,12 +5,12 @@ EPUB.js Pagination Example - + + - -
- - +
+
+ + +
+
+
    +
    + +