EPUBJS.Book = function(_url){ // Promises this.opening = new RSVP.defer(); this.opened = this.opening.promise; this.url = undefined; this.spine = undefined; this.loading = { manifest: new RSVP.defer(), spine: new RSVP.defer(), metadata: new RSVP.defer(), cover: new RSVP.defer(), navigation: new RSVP.defer(), pageList: new RSVP.defer() }; this.loaded = { manifest: this.loading.manifest.promise, spine: this.loading.spine.promise, metadata: this.loading.metadata.promise, cover: this.loading.cover.promise, navigation: this.loading.navigation.promise, pageList: this.loading.pageList.promise }; this.loaders = []; for(var promise in this.loaded){ this.loaders.push(this.loaded[promise]); } this.ready = RSVP.all(this.loaders); // this.pageList = []; // this.ready.all.then(this._ready.bind(this)); if(_url) { this.open(_url); } }; EPUBJS.Book.prototype.open = function(_url){ var uri; var parse = new EPUBJS.Parser(); var epubPackage; var book = this; var containerPath = "META-INF/container.xml"; // Reuse parsed url or create a new uri object if(typeof(_url) === "object") { uri = _url; } else { uri = EPUBJS.core.uri(_url); } // Find path to the Container if(uri.extension === "opf") { // Direct link to package, no container this.packageUrl = uri.href; this.containerUrl = ''; if(uri.origin) { this.url = uri.origin + "/" + uri.directory; } else { this.url = uri.directory; } epubPackage = this.request(this.packageUrl); } else if(uri.extension === "epub" || uri.extension === "zip" ) { // Book is archived this.archived = true; this.url = ''; } // Find the path to the Package from the container else if (!uri.extension) { this.containerUrl = _url + containerPath; epubPackage = this.request(this.containerUrl). then(function(containerXml){ return parse.container(containerXml); // Container has path to content }). then(function(paths){ var packageUri = EPUBJS.core.uri(paths.packagePath); book.packageUrl = _url + paths.packagePath; book.url = _url + packageUri.directory; // Set Url relative to the content book.encoding = paths.encoding; return book.request(book.packageUrl); }).catch(function(error) { // handle errors in either of the two requests console.error("Could not load book at: " + (this.packageUrl || this.containerPath)); book.trigger("book:loadFailed", (this.packageUrl || this.containerPath)); book.opening.reject(error); }); } epubPackage.then(function(packageXml) { // Get package information from epub opf book.unpack(packageXml); // Resolve promises book.loading.manifest.resolve(book.package.manifest); book.loading.metadata.resolve(book.package.metadata); book.loading.spine.resolve(book.spine); book.loading.cover.resolve(book.cover); // Resolve book opened promise book.opening.resolve(book); // Clear queue of any waiting book request }).catch(function(error) { // handle errors in parsing the book console.error(error.message, error.stack); book.opening.reject(error); }); return this.opened; }; EPUBJS.Book.prototype.unpack = function(packageXml){ var book = this, parse = new EPUBJS.Parser(); book.package = parse.packageContents(packageXml); // Extract info from contents book.package.baseUrl = book.url; // Provides a url base for resolving paths book.spine = new EPUBJS.Spine(book.package, this.request); book.navigation = new EPUBJS.Navigation(book.package, this.request); book.navigation.load().then(function(toc){ book.toc = toc; book.loading.navigation.resolve(book.navigation); }); // //-- Set Global Layout setting based on metadata // MOVE TO RENDER // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata); book.cover = book.url + book.package.coverPath; }; // Alias for book.spine.get EPUBJS.Book.prototype.section = function(target) { return this.spine.get(target); }; EPUBJS.Book.prototype.request = function(_url) { // Switch request methods if(this.archived) { // TODO: handle archived } else { return EPUBJS.core.request(_url, 'xml', this.credentials); } }; EPUBJS.Book.prototype.setCredentials = function(_credentials) { this.credentials = _credentials; }; //-- Enable binding events to book RSVP.EventTarget.mixin(EPUBJS.Book.prototype); //-- Handle RSVP Errors RSVP.on('error', function(event) { //console.error(event, event.detail); }); RSVP.configure('instrument', true); //-- true | will logging out all RSVP rejections // RSVP.on('created', listener); // RSVP.on('chained', listener); // RSVP.on('fulfilled', listener); RSVP.on('rejected', function(event){ console.error(event.detail.message, event.detail.stack); });