1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-03 14:59:18 +02:00

Added error handles, sections, updated url resolving, use book.request for requests

This commit is contained in:
Fred Chasen 2014-08-21 17:39:35 -04:00
parent c6465177c5
commit c29e5f84ee
19 changed files with 3049 additions and 683 deletions

View file

@ -26,6 +26,7 @@
"devDependencies": {
"qunit": "~1.14.0",
"jquery": "~2.1.1",
"rsvp": "~3.0.8"
"rsvp": "~3.0.8",
"uri.js": "~1.13.2"
}
}

2778
dist/epub.js vendored

File diff suppressed because it is too large Load diff

5
dist/epub.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -9,19 +9,26 @@
<style type="text/css">
body {
margin: 0;
background: #fafafa;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #333;
}
#viewer {
position: absolute;
left: 10%;
width: 80%;
#viewer {
display: block;
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
/* display: block;
margin: 50px auto;
width: 600px;*/
}
#viewer iframe {
background: white;
box-shadow: 0 0 4px #ccc;
width: 590px;
margin: 10px auto;
}
#prev {
left: 40px;
}
@ -65,7 +72,7 @@
<script>
var currentSectionIndex = 10;
// Load the opf
var book = ePub("../books/moby-dick/OPS/package.opf");
var book = ePub("../books/accessible_epub_3-20121024.epub/package.opf");
var rendition = book.renderTo("viewer");
var displayed = rendition.display(currentSectionIndex);

View file

@ -28,5 +28,6 @@ EPUBJS.Render = {};
} else {
root.ePub = ePub;
}
})(this);
})(this);

View file

@ -6,7 +6,7 @@ EPUBJS.Book = function(_url){
this.url = undefined;
this.spine = undefined;
this.spine = new EPUBJS.Spine(this.request);
this.loading = {
manifest: new RSVP.defer(),
@ -32,6 +32,8 @@ EPUBJS.Book = function(_url){
this.isRendered = false;
this._q = EPUBJS.core.queue(this);
this.request = this.requestMethod.bind(this);
if(_url) {
this.open(_url);
}
@ -45,6 +47,11 @@ EPUBJS.Book.prototype.open = function(_url){
var containerPath = "META-INF/container.xml";
var location;
if(!_url) {
this.opening.resolve(this);
return this.opened;
}
// Reuse parsed url or create a new uri object
if(typeof(_url) === "object") {
uri = _url;
@ -133,7 +140,7 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
book.package = parse.packageContents(packageXml); // Extract info from contents
book.package.baseUrl = book.url; // Provides a url base for resolving paths
book.spine = new EPUBJS.Spine(book.package, this.request);
this.spine.load(book.package);
book.navigation = new EPUBJS.Navigation(book.package, this.request);
book.navigation.load().then(function(toc){
@ -160,20 +167,23 @@ EPUBJS.Book.prototype.renderTo = function(element, options) {
return rendition;
};
EPUBJS.Book.prototype.request = function(_url) {
EPUBJS.Book.prototype.requestMethod = function(_url) {
// Switch request methods
if(this.archived) {
// TODO: handle archived
} else {
return EPUBJS.core.request(_url, 'xml', this.credentials);
return EPUBJS.core.request(_url, 'xml', this.requestCredentials, this.requestHeaders);
}
};
EPUBJS.Book.prototype.setCredentials = function(_credentials) {
this.credentials = _credentials;
EPUBJS.Book.prototype.setRequestCredentials = function(_credentials) {
this.requestCredentials = _credentials;
};
EPUBJS.Book.prototype.setRequestHeaders = function(_headers) {
this.requestHeaders = _headers;
};
//-- Enable binding events to book
RSVP.EventTarget.mixin(EPUBJS.Book.prototype);

View file

@ -1,6 +1,6 @@
EPUBJS.core = {};
EPUBJS.core.request = function(url, type, withCredentials) {
EPUBJS.core.request = function(url, type, withCredentials, headers) {
var supportsURL = window.URL;
var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer";
@ -12,6 +12,8 @@ EPUBJS.core.request = function(url, type, withCredentials) {
// https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js
var xhrPrototype = XMLHttpRequest.prototype;
var header;
if (!('overrideMimeType' in xhrPrototype)) {
// IE10 might have response, but not overrideMimeType
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
@ -21,7 +23,13 @@ EPUBJS.core.request = function(url, type, withCredentials) {
if(withCredentials) {
xhr.withCredentials = true;
}
xhr.open("GET", url, true);
for(header in headers) {
xhr.setRequestHeader(header, headers[header]);
}
xhr.onreadystatechange = handler;
if(type == 'blob'){
@ -65,6 +73,7 @@ EPUBJS.core.request = function(url, type, withCredentials) {
deferred.resolve(r);
} else {
deferred.reject({
status: this.status,
message : this.response,
stack : new Error().stack
});
@ -233,28 +242,52 @@ EPUBJS.core.values = function(object) {
};
EPUBJS.core.resolveUrl = function(base, path) {
var url,
var url = [],
segments = [],
// uri = EPUBJS.core.uri(path),
folders = base.split("/"),
baseUri = EPUBJS.core.uri(base),
pathUri = EPUBJS.core.uri(path),
baseDirectory = baseUri.directory,
pathDirectory = pathUri.directory,
// folders = base.split("/"),
paths;
// if(uri.host) {
// return path;
// }
folders.pop();
paths = path.split("/");
paths.forEach(function(p){
if(p === ".."){
folders.pop();
}else{
segments.push(p);
if(baseDirectory[0] === "/") {
baseDirectory = baseDirectory.substring(1);
}
if(pathDirectory[pathDirectory.length-1] === "/") {
baseDirectory = baseDirectory.substring(0, baseDirectory.length-1);
}
if(pathDirectory[0] === "/") {
pathDirectory = pathDirectory.substring(1);
}
if(pathDirectory[pathDirectory.length-1] === "/") {
pathDirectory = pathDirectory.substring(0, pathDirectory.length-1);
}
directories = baseDirectory.split("/");
paths = pathDirectory.split("/");
paths.reverse().forEach(function(part, index){
if(part === ".."){
directories.pop();
} else if(part === directories[directories.length-1]) {
directories.pop();
segments.unshift(part);
} else {
segments.push(part);
}
});
url = folders.concat(segments);
url = url.concat(baseUri.origin, directories, segments, pathUri.filename);
return url.join("/");
};
@ -267,4 +300,8 @@ EPUBJS.core.documentHeight = function() {
document.body.offsetHeight,
document.documentElement.offsetHeight
);
};
};
EPUBJS.core.isNumber = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}

View file

@ -1,87 +1,42 @@
EPUBJS.hooks = {};
EPUBJS.Hooks = (function(){
function hooks(){}
//-- Get pre-registered hooks
hooks.prototype.getHooks = function(){
var plugs, hooks;
this.hooks = {};
Array.prototype.slice.call(arguments).forEach(function(arg){
this.hooks[arg] = [];
}, this);
EPUBJS.Hook = function(context){
this.context = context || this;
this.hooks = [];
};
for (var plugType in this.hooks) {
hooks = EPUBJS.hooks[plugType];
if(hooks){
plugs = EPUBJS.core.values();
plugs.forEach(function(hook){
this.registerHook(plugType, hook);
}, this);
}
}
};
//-- Hooks allow for injecting async functions that must all complete before continuing
// Functions must have a callback as their first argument.
hooks.prototype.registerHook = function(type, toAdd, toFront){
if(typeof(this.hooks[type]) != "undefined"){
if(typeof(toAdd) === "function"){
if(toFront) {
this.hooks[type].unshift(toAdd);
}else{
this.hooks[type].push(toAdd);
}
}else if(Array.isArray(toAdd)){
toAdd.forEach(function(hook){
if(toFront) {
this.hooks[type].unshift(hook);
}else{
this.hooks[type].push(hook);
}
}, this);
}
}else{
//-- Allows for undefined hooks, but maybe this should error?
this.hooks[type] = [func];
}
};
hooks.prototype.triggerHooks = function(type, callback, passed){
var hooks, count;
if(typeof(this.hooks[type]) == "undefined") return false;
hooks = this.hooks[type];
count = hooks.length;
if(count === 0 && callback) {
callback();
}
//-- Hooks allow for injecting async functions that must all complete in order before finishing
// Functions must return a promise.
function countdown(){
count--;
if(count <= 0 && callback) callback();
}
hooks.forEach(function(hook){
hook(countdown, passed);
});
};
return {
register: function(name) {
if(EPUBJS.hooks[name] === undefined) { EPUBJS.hooks[name] = {}; }
if(typeof EPUBJS.hooks[name] !== 'object') { throw "Already registered: "+name; }
return EPUBJS.hooks[name];
},
mixin: function(object) {
for (var prop in hooks.prototype) {
object[prop] = hooks.prototype[prop];
}
}
};
})();
// this.beforeDisplay = new EPUBJS.Hook();
// this.beforeDisplay.register(function(){});
// this.beforeDisplay.trigger(args).then(function(){});
// Adds a function to be run before a hook completes
EPUBJS.Hook.prototype.register = function(func){
this.hooks.push(func);
};
// Triggers a hook to run all functions
EPUBJS.Hook.prototype.trigger = function(){
var length = this.hooks.length;
var current = 0;
var executing;
var defer = new RSVP.defer();
var args = arguments;
if(length) {
executing = this.hooks[current].apply(this.context, args);
executing.then(function(){
current += 1;
if(current < length) {
return this.hooks[current].apply(this.context, args);
}
}.bind(this));
} else {
executing = defer.promise;
defer.resolve();
}
return executing;
};

View file

@ -5,7 +5,7 @@ EPUBJS.Infinite = function(container, renderer){
this.scrolled = false;
this.ignore = false;
this.displaying = false;
this.offset = 250;
this.offset = 350;
this.views = [];
this.renderer = renderer;
this.prevScrollTop = 0;
@ -21,7 +21,6 @@ EPUBJS.Infinite.prototype.start = function() {
} else {
this.ignore = false;
}
// console.log("scroll", this.container.scrollTop)
}.bind(this));
// Reset to prevent jump
@ -45,44 +44,6 @@ EPUBJS.Infinite.prototype.backwards = function() {
this.trigger("backwards");
};
/*
// Manage Views
EPUBJS.Infinite.prototype.jump = function(view){
this.views.push(view);
};
EPUBJS.Infinite.prototype.append = function(view){
this.views.push(view);
view.appendTo(this.container);
};
EPUBJS.Infinite.prototype.prepend = function(view){
this.views.unshift(view);
view.prependTo(this.container);
};
// Simple Insert
EPUBJS.Infinite.prototype.insert = function(view, index){
var position;
var distanceFront = index - this.positions[0];
var distanceRear = index - this.positions[this.positions.length-1];
if(distanceFront >= 0 || !this.positions.length) {
position = this.append(view);
this.positions.push(index);
} else if(distanceRear <= 0) {
position = this.prepend(view);
this.positions.unshift(index);
}
return position;
};
*/
EPUBJS.Infinite.prototype.check = function(){
@ -99,10 +60,12 @@ EPUBJS.Infinite.prototype.check = function(){
var up = scrollTop + this.offset > scrollHeight-height;
var down = scrollTop < this.offset;
// console.debug("scroll", scrollTop)
// Add to bottom
if(up && direction > 0) {
this.forwards();
}
// Add to top
else if(down && direction < 0) {
this.backwards();
}

View file

@ -50,12 +50,16 @@ EPUBJS.Navigation = function(_package, _request){
// Load the navigation
EPUBJS.Navigation.prototype.load = function(_request) {
var request = _request || EPUBJS.core.request;
var loading;
var loading, loaded;
if(this.nav) {
loading = this.nav.load();
} else if(this.ncx) {
loading = this.ncx.load();
} else {
loaded = new RSVP.defer();
loaded.resolve([]);
loading = loaded.promise;
}
return loading;

View file

@ -187,7 +187,7 @@ EPUBJS.Parser.prototype.manifest = function(manifestXml){
'type' : type,
'properties' : properties
};
});
return manifest;
@ -210,6 +210,7 @@ EPUBJS.Parser.prototype.spine = function(spineXml, manifest){
var propArray = props.length ? props.split(' ') : [];
// var manifestProps = manifest[Id].properties;
// var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];
var itemref = {
'idref' : idref,
'linear' : item.getAttribute('linear') || '',

View file

@ -2,28 +2,18 @@ EPUBJS.Renderer = function(book, _options) {
var options = _options || {};
this.settings = {
hidden: options.hidden || false,
viewsLimit: 4,
viewsLimit: 6,
width: options.width || false,
height: options.height || false,
};
this.book = book;
// Listen for load events
// this.on("render:loaded", this.loaded.bind(this));
// Blank Cfi for Parsing
this.epubcfi = new EPUBJS.EpubCFI();
this.layoutSettings = {};
//-- Adds Hook methods to the Book prototype
// Hooks will all return before triggering the callback.
EPUBJS.Hooks.mixin(this);
//-- Get pre-registered hooks for events
this.getHooks("beforeChapterDisplay");
//-- Queue up page changes if page map isn't ready
this._q = EPUBJS.core.queue(this);
@ -31,14 +21,18 @@ EPUBJS.Renderer = function(book, _options) {
this.initialize({
"width" : this.settings.width,
"height" : this.settings.height,
"hidden" : true
"height" : this.settings.height
});
this.rendering = false;
this.views = [];
this.positions = [];
//-- Adds Hook methods to the Renderer prototype
this.hooks = {};
this.hooks.display = new EPUBJS.Hook(this);
this.hooks.replacements = new EPUBJS.Hook(this);
};
/**
@ -51,7 +45,6 @@ EPUBJS.Renderer.prototype.initialize = function(_options){
var width = options.width ? options.width + "px" : "100%";
var hidden = options.hidden || false;
this.container = document.createElement("div");
this.infinite = new EPUBJS.Infinite(this.container, this);
@ -69,7 +62,7 @@ EPUBJS.Renderer.prototype.initialize = function(_options){
this.wrapper.appendChild(this.container);
return this.wrapper;
}
return this.container;
};
@ -126,15 +119,27 @@ EPUBJS.Renderer.prototype.attachTo = function(_element){
this.infinite.start();
this.infinite.on("forwards", function(){
if(!this.rendering) this.forwards();
var next = this.last().section.index + 1;
if(!this.rendering && next < this.book.spine.length){
this.forwards();
}
}.bind(this));
this.infinite.on("backwards", function(){
if(!this.rendering) this.backwards();
var prev = this.first().section.index - 1;
if(!this.rendering && prev > 0){
this.backwards();
}
}.bind(this));
window.addEventListener("resize", this.onResized.bind(this), false);
this.hooks.replacements.register(this.replacements.bind(this));
};
EPUBJS.Renderer.prototype.clear = function(){
@ -154,14 +159,20 @@ EPUBJS.Renderer.prototype.display = function(what){
this.book.opened.then(function(){
var section = this.book.spine.get(what);
var rendered = this.render(section);
var rendered;
rendered.
then(this.fill.bind(this)).
then(function(){
displaying.resolve(this);
}.bind(this));
if(section){
rendered = this.render(section);
rendered
.then(this.fill.bind(this))
.then(function(){
displaying.resolve(this);
}.bind(this));
} else {
displaying.reject(new Error("No Section Found"));
}
}.bind(this));
return displayed;
@ -169,28 +180,35 @@ EPUBJS.Renderer.prototype.display = function(what){
EPUBJS.Renderer.prototype.render = function(section){
var rendered;
var view = new EPUBJS.View();
var view;
if(!section) {
rendered.reject();
return;
};
rendered = section.render();
view.index = section.index;
rendered = new RSVP.defer();
rendered.reject(new Error("No Section Provided"));
return rendered.promise;
};
view = new EPUBJS.View(section);
// Place view in correct position
this.insert(view, section.index);
return rendered.
then(function(contents){
// Place view in correct position
this.insert(view, section.index);
rendered = view.render(this.book.request);
return view.load(contents);
return rendered
.then(function(){
return this.hooks.display.trigger(view);
}.bind(this))
.then(function(){
return this.hooks.replacements.trigger(view, this);
}.bind(this))
.then(function(){
this.rendering = false;
view.show();
return view;
}.bind(this))
.catch(function(e){
this.trigger("loaderror", e);
}.bind(this));
};
@ -201,14 +219,13 @@ EPUBJS.Renderer.prototype.forwards = function(){
var rendered;
var section;
next = this.last().index + 1;
next = this.last().section.index + 1;
if(this.rendering || next === this.book.spine.length){
rendered = new RSVP.defer();
rendered.reject({message: "reject forwards"});
rendered.reject(new Error("Reject Forwards"));
return rendered.promise;
}
console.log("going forwards")
// console.log("going forwards")
this.rendering = true;
@ -216,11 +233,8 @@ EPUBJS.Renderer.prototype.forwards = function(){
rendered = this.render(section);
rendered.then(function(){
// this.rendering = false;
var first = this.first();
var bounds = first.bounds();
var container = this.container.getBoundingClientRect();
var offset;
var prev = this.container.scrollTop;
if(this.views.length > this.settings.viewsLimit) {
@ -232,6 +246,7 @@ EPUBJS.Renderer.prototype.forwards = function(){
}
}.bind(this));
return rendered;
};
@ -242,13 +257,14 @@ EPUBJS.Renderer.prototype.backwards = function(view){
var section;
prev = this.first().index - 1;
prev = this.first().section.index - 1;
if(this.rendering || prev < 0){
rendered = new RSVP.defer();
rendered.reject({message: "reject backwards"});
rendered.reject(new Error("Reject Backwards"));
return rendered.promise;
}
console.log("going backwards")
// console.log("going backwards")
this.rendering = true;
@ -257,6 +273,7 @@ EPUBJS.Renderer.prototype.backwards = function(view){
rendered.then(function(){
// this.container.scrollTop += this.first().height;
this.infinite.scrollBy(0, this.first().height, true);
if(this.views.length > this.settings.viewsLimit) {
@ -277,21 +294,25 @@ EPUBJS.Renderer.prototype.fill = function() {
var next = function(){
var bottom = this.last().bounds().bottom;
var defer = new RSVP.defer();
var promise = defer.promise;
if (height && bottom && (bottom < height) && (this.last().index + 1 < this.book.spine.length)) {
if (height && bottom && (bottom < height)) { //&& (this.last().section.index + 1 < this.book.spine.length)) {
return this.forwards().then(next);
} else {
this.rendering = false;
defer.resolve();
return promise;
return defer.promise;
}
}.bind(this);
var prev = this.first().section.index - 1;
var filling = next();
if(prev > 0){
filling.then(this.backwards.bind(this));
}
return next().
then(this.backwards.bind(this)).
then(function(){
return filling
.then(function(){
this.rendering = false;
}.bind(this));
@ -319,12 +340,11 @@ EPUBJS.Renderer.prototype.insert = function(view, index){
if(!this.first()) {
this.append(view);
} else if(index - this.first().index >= 0) {
} else if(index - this.first().section.index >= 0) {
this.append(view);
} else if(index - this.last().index <= 0) {
} else if(index - this.last().section.index <= 0) {
this.prepend(view);
}
console.log("insert")
// return position;
};
@ -345,5 +365,38 @@ EPUBJS.Renderer.prototype.last = function() {
return this.views[this.views.length-1];
};
EPUBJS.Renderer.prototype.replacements = function(view, renderer) {
var task = new RSVP.defer();
var links = view.document.querySelectorAll("a[href]");
var replaceLinks = function(link){
var href = link.getAttribute("href");
var isRelative = href.search("://");
// var directory = EPUBJS.core.uri(view.window.location.href).directory;
// var relative;
if(isRelative != -1){
link.setAttribute("target", "_blank");
}else{
// relative = EPUBJS.core.resolveUrl(directory, href);
link.onclick = function(){
renderer.display(href);
return false;
};
}
};
for (var i = 0; i < links.length; i++) {
replaceLinks(links[i]);
};
task.resolve();
return task.promise;
};
//-- Enable binding events to Renderer
RSVP.EventTarget.mixin(EPUBJS.Renderer.prototype);

81
lib/epubjs/section.js Normal file
View file

@ -0,0 +1,81 @@
EPUBJS.Section = function(item){
this.idref = item.idref;
this.linear = item.linear;
this.properties = item.properties;
this.index = item.index;
this.href = item.href;
this.url = item.url;
this.cfiBase = item.cfiBase;
this.hooks = {};
this.hooks.replacements = new EPUBJS.Hook(this);
// Register replacements
this.hooks.replacements.register(this.replacements);
};
EPUBJS.Section.prototype.load = function(_request){
var request = _request || this.request || EPUBJS.core.request;
var loading = new RSVP.defer();
var loaded = loading.promise;
if(this.contents) {
loading.resolve(this.contents);
} else {
request(this.url, 'xml')
.then(function(xml){
var base;
var directory = EPUBJS.core.folder(this.url);
this.document = xml;
this.contents = xml.documentElement;
return this.hooks.replacements.trigger(this.document);
}.bind(this))
.then(function(){
loading.resolve(this.contents);
}.bind(this))
.catch(function(error){
loading.reject(error);
});
}
return loaded;
};
EPUBJS.Section.prototype.replacements = function(_document){
var task = new RSVP.defer();
var base = _document.createElement("base"); // TODO: check if exists
base.setAttribute("href", this.url);
_document.head.insertBefore(base, _document.head.firstChild);
task.resolve();
return task.promise;
};
EPUBJS.Section.prototype.beforeSectionLoad = function(){
// Stub for a hook - replace me for now
}
EPUBJS.Section.prototype.render = function(_request){
var rendering = new RSVP.defer();
var rendered = rendering.promise;
this.load(_request).then(function(contents){
var serializer = new XMLSerializer();
var output = serializer.serializeToString(contents);
rendering.resolve(output);
})
.catch(function(error){
rendering.reject(error);
});
return rendered;
};
EPUBJS.Section.prototype.find = function(_query){
};

View file

@ -1,31 +1,33 @@
EPUBJS.Spine = function(_package, _request){
this.items = _package.spine;
this.manifest = _package.manifest;
this.spineNodeIndex = _package.spineNodeIndex;
this.baseUrl = _package.baseUrl || '';
EPUBJS.Spine = function(_request){
this.request = _request;
this.length = this.items.length;
this.epubcfi = new EPUBJS.EpubCFI();
this.spineItems = [];
this.spineByHref = {};
this.spineById = {};
};
EPUBJS.Spine.prototype.load = function(_package) {
this.items = _package.spine;
this.manifest = _package.manifest;
this.spineNodeIndex = _package.spineNodeIndex;
this.baseUrl = _package.baseUrl || '';
this.length = this.items.length;
this.epubcfi = new EPUBJS.EpubCFI();
this.items.forEach(function(item, index){
var cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);
var href, url;
var manifestItem = this.manifest[item.idref];
var spineItem;
item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);
if(manifestItem) {
href = manifestItem.href;
url = this.baseUrl + href;
item.href = manifestItem.href;
item.url = this.baseUrl + item.href;
}
spineItem = new EPUBJS.SpineItem(item, href, url, cfiBase);
this.spineItems.push(spineItem);
this.spineByHref[spineItem.href] = index;
this.spineById[spineItem.idref] = index;
spineItem = new EPUBJS.Section(item);
this.append(spineItem);
}.bind(this));
@ -50,61 +52,42 @@ EPUBJS.Spine.prototype.get = function(target) {
return this.spineItems[index];
};
EPUBJS.Spine.prototype.append = function(section) {
var index = this.spineItems.length;
section.index = index;
EPUBJS.SpineItem = function(item, href, url, cfiBase){
this.idref = item.idref;
this.linear = item.linear;
this.properties = item.properties;
this.index = item.index;
this.href = href;
this.url = url;
this.cfiBase = cfiBase;
this.spineItems.push(section);
this.spineByHref[section.href] = index;
this.spineById[section.idref] = index;
return index;
};
EPUBJS.Spine.prototype.prepend = function(section) {
var index = this.spineItems.unshift(section);
this.spineByHref[section.href] = 0;
this.spineById[section.idref] = 0;
EPUBJS.SpineItem.prototype.load = function(_request){
var request = _request || this.request || EPUBJS.core.request;
var loading = new RSVP.defer();
var loaded = loading.promise;
if(this.contents) {
loading.resolve(this.contents);
} else {
request(this.url, 'xml').then(function(xml){
var base;
var directory = EPUBJS.core.folder(this.url);
this.document = xml;
this.contents = xml.documentElement;
this.replacements(this.document);
loading.resolve(this.contents);
}.bind(this));
}
return loaded;
};
EPUBJS.SpineItem.prototype.replacements = function(_document){
var base = _document.createElement("base");
base.setAttribute("href", this.url);
_document.head.insertBefore(base, _document.head.firstChild);
};
EPUBJS.SpineItem.prototype.render = function(){
var rendering = new RSVP.defer();
var rendered = rendering.promise;
this.load().then(function(contents){
var serializer = new XMLSerializer();
var output = serializer.serializeToString(contents);
rendering.resolve(output);
// Re-index
this.spineItems.forEach(function(item, index){
item.index = index;
});
return rendered;
return 0;
};
EPUBJS.SpineItem.prototype.find = function(_query){
EPUBJS.Spine.prototype.insert = function(section, index) {
};
EPUBJS.Spine.prototype.remove = function(section) {
var index = this.spineItems.indexOf(section);
if(index > -1) {
delete this.spineByHref[section.href];
delete this.spineById[section.idref];
return this.spineItems.splice(index, 1);
}
};

View file

@ -1,57 +1,9 @@
EPUBJS.View = function(width, height) {
EPUBJS.View = function(section) {
this.id = "epubjs-view:" + EPUBJS.core.uuid();
this.loading = new RSVP.defer();
this.loaded = this.loading.promise;
this.rendering = new RSVP.defer();
this.rendered = this.rendering.promise;
this.iframe = this.create();
this.height;
this.width;
};
EPUBJS.View.prototype.load = function(contents) {
var loading = new RSVP.defer();
var loaded = loading.promise;
this.document = this.iframe.contentDocument;
this.iframe.addEventListener("load", function(event) {
var layout;
this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument;
this.iframe.style.display = "block";
// Reset Body Styles
this.document.body.style.margin = "0";
this.document.body.style.display = "inline-block";
this.layout();
this.iframe.style.visibility = "visible";
setTimeout(function(){
this.window.addEventListener("resize", this.resized.bind(this), false);
}.bind(this), 10); // Wait to listen for resize events
this.document.fonts.onloading = function(){
console.log("loaded fonts");
// this.layout();
}.bind(this);
// this.observer = this.observe(this.document);
loading.resolve(this);
this.loading.resolve(this);
}.bind(this));
// this.iframe.srcdoc = contents;
this.document.open();
this.document.write(contents);
this.document.close();
return loaded;
this.section = section;
};
EPUBJS.View.prototype.create = function() {
@ -83,9 +35,81 @@ EPUBJS.View.prototype.resized = function(e) {
};
EPUBJS.View.prototype.render = function(_request) {
return this.section.render(_request)
.then(function(contents){
return this.load(contents);
}.bind(this))
.then(this.display.bind(this))
.then(function(){
this.rendering.resolve(this);
}.bind(this));
};
EPUBJS.View.prototype.load = function(contents) {
var loading = new RSVP.defer();
var loaded = loading.promise;
this.document = this.iframe.contentDocument;
this.iframe.addEventListener("load", function(event) {
var layout;
this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument;
loading.resolve(this);
}.bind(this));
// this.iframe.srcdoc = contents;
this.document.open();
this.document.write(contents);
this.document.close();
return loaded;
};
EPUBJS.View.prototype.display = function(contents) {
var displaying = new RSVP.defer();
var displayed = displaying.promise;
this.iframe.style.display = "block";
// Reset Body Styles
this.document.body.style.margin = "0";
this.document.body.style.display = "inline-block";
// Set Padding -> TODO: apply these from a function
this.document.body.style.padding = "0 20px 20px 20px";
setTimeout(function(){
this.window.addEventListener("resize", this.resized.bind(this), false);
}.bind(this), 10); // Wait to listen for resize events
if(this.document.fonts.status !== "loading") {
this.layout();
displaying.resolve(this);
} else {
this.document.fonts.onloading = function(){
this.layout();
displaying.resolve(this);
}.bind(this);
}
// this.observer = this.observe(this.document);
return displayed
};
EPUBJS.View.prototype.layout = function() {
var bounds;
console.log("layout")
// Check bounds
bounds = this.document.body.getBoundingClientRect();
@ -93,13 +117,8 @@ EPUBJS.View.prototype.layout = function() {
console.error("View not shown");
}
// Apply Changes
this.resizing = true;
this.iframe.style.height = bounds.height + "px";
// this.iframe.style.width = bounds.width + "px";
// Check again
bounds = this.document.body.getBoundingClientRect();
// Apply Changes
this.resizing = true;
this.iframe.style.height = bounds.height + "px";
// this.iframe.style.width = bounds.width + "px";
@ -142,10 +161,20 @@ EPUBJS.View.prototype.bounds = function() {
return this.iframe.getBoundingClientRect();
};
EPUBJS.View.prototype.show = function() {
this.iframe.style.display = "block";
this.iframe.style.visibility = "visible";
};
EPUBJS.View.prototype.hide = function() {
this.iframe.style.display = "none";
this.iframe.style.visibility = "hidden";
};
EPUBJS.View.prototype.destroy = function() {
// Stop observing
// this.observer.disconnect();
this.element.removeChild(this.iframe);
};

View file

@ -8,7 +8,7 @@
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/qunit/qunit/qunit.js"></script>
<script src="../bower_components/rsvp/rsvp.js"></script>
<!-- <script src="../bower_components/rsvp/rsvp.js"></script>
<script src="../lib/epub.js"></script>
<script src="../lib/epubjs/core.js"></script>
@ -19,13 +19,14 @@
<script src="../lib/epubjs/navigation.js"></script>
<script src="../lib/epubjs/epubcfi.js"></script>
<script src="../lib/epubjs/renderer.js"></script>
<script src="../lib/epubjs/view.js"></script>
<script src="../lib/epubjs/view.js"></script> -->
<script src="../dist/epub.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="tests/epub.js"></script>
<script src="tests/rendering.js"></script>

View file

@ -1,10 +1,52 @@
var domain = window.location.origin;
module('Core');
test("EPUBJS.core.resolveUrl", 1, function() {
var a = "http://example.com/fred/chasen/";
var b = "/chasen/derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "http://example.com/fred/chasen/derf.html", "resolved" );
});
test("EPUBJS.core.resolveUrl ../", 1, function() {
var a = "http://example.com/fred/chasen/";
var b = "../derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "http://example.com/fred/derf.html", "resolved" );
});
test("EPUBJS.core.resolveUrl folders", 1, function() {
var a = "/fred/chasen/";
var b = "/fred/chasen/derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "/fred/chasen/derf.html", "resolved" );
});
test("EPUBJS.core.resolveUrl ../folders", 1, function() {
var a = "/fred/chasen/";
var b = "../../derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "/derf.html", "resolved" );
});
module('Create');
asyncTest("Create new ePub(/path/to/epub/)", 1, function() {
var book = ePub("../books/moby-dick/");
book.opened.then(function(){
equal( book.url, "../books/moby-dick/OPS/", "bookPath is passed to new EPUBJS.Book" );
equal( book.url, "../books/moby-dick/OPS/", "book url is passed to new EPUBJS.Book" );
start();
});
@ -14,7 +56,7 @@ asyncTest("Create new ePub(/path/to/epub/package.opf)", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){
equal( book.url, "../books/moby-dick/OPS/", "bookPath is passed to new EPUBJS.Book" );
equal( book.url, domain + "/books/moby-dick/OPS/", "bookPath is passed to new EPUBJS.Book" );
start();
});
@ -98,7 +140,7 @@ asyncTest("Spine", 1, function() {
asyncTest("Cover", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf");
var book = ePub("../books/moby-dick/");
book.opened.then(function(){
equal( book.cover, "../books/moby-dick/OPS/images/9780316000000.jpg", "Cover is set" );
start();
@ -132,7 +174,7 @@ asyncTest("First Item", 2, function() {
var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){
var section = book.spine.get(1);
var section = book.spine.get(0);
equal( section.href, "cover.xhtml", "First spine item href found" );
equal( section.cfiBase, "/6/2[cover]", "First spine item cfi found" );
@ -173,7 +215,7 @@ asyncTest("Render Spine Item", 1, function() {
book.opened.then(function(){
var section = book.spine.get("#xchapter_050");
section.render().then(function(content){
equal( content.substring(303, 355), "<h1>Chapter 50. Ahabs Boat and Crew. Fedallah.</h1>", "Chapter text rendered as string" );
equal( content.substring(377, 429), "<h1>Chapter 50. Ahabs Boat and Crew. Fedallah.</h1>", "Chapter text rendered as string" );
});
start();
@ -185,7 +227,7 @@ module('Navigation');
asyncTest("NCX & Nav", 2, function() {
var book = ePub("../books/moby-dick/OPS/package.opf");
var book = ePub("../books/moby-dick/");
book.opened.then(function(){
equal( book.navigation.navUrl, "../books/moby-dick/OPS/toc.xhtml", "Nav URL found" );
equal( book.navigation.ncxUrl, "../books/moby-dick/OPS/toc.ncx", "NCX URL found" );
@ -198,7 +240,7 @@ asyncTest("NCX & Nav", 2, function() {
asyncTest("Load TOC Auto Pick", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf");
var book = ePub("../books/moby-dick/");
book.opened.then(function(){
book.navigation.load().then(function(toc){
equal( toc.length, 141, "Full Nav toc parsed" );
@ -264,4 +306,66 @@ asyncTest("Get TOC time by ID", 1, function() {
start();
});
});
module('Hooks');
asyncTest("Register a new hook", 1, function() {
var beforeDisplay = new EPUBJS.Hook();
beforeDisplay.register(function(args){
var defer = new RSVP.defer();
console.log("ran", 1);
defer.resolve();
return defer.promise;
});
equal( beforeDisplay.hooks.length, 1, "Registered a hook" );
start();
// this.beforeDisplay.trigger(args).then(function(){});
});
asyncTest("Trigger all new hook", 4, function() {
var beforeDisplay = new EPUBJS.Hook(this);
this.testerObject = {tester: 1};
beforeDisplay.register(function(testerObject){
var defer = new RSVP.defer();
start();
equal( testerObject.tester, 1, "tester is 1" );
stop();
testerObject.tester += 1;
defer.resolve();
return defer.promise;
});
beforeDisplay.register(function(testerObject){
var defer = new RSVP.defer();
start();
equal(testerObject.tester, 2, "tester is 2" );
stop();
testerObject.tester += 1;
defer.resolve();
return defer.promise;
});
start();
equal( beforeDisplay.hooks.length, 2, "Added two hooks" );
stop();
beforeDisplay.trigger(this.testerObject).then(function(){
start();
equal( this.testerObject.tester, 3, "tester is 3" );
}.bind(this));
});

View file

@ -1,10 +1,10 @@
module('Rendering');
/*
asyncTest("Render To", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf");
var rendition = book.renderTo("qunit-fixture");
var displayed = rendition.display();
var rendition = book.renderTo("qunit-fixture", {width:400, height:600});
var displayed = rendition.display(0);
displayed.then(function(){
equal( $( "iframe", "#qunit-fixture" ).length, 1, "iframe added successfully" );
@ -12,4 +12,5 @@ asyncTest("Render To", 1, function() {
});
});
});
*/

View file

@ -1,6 +1,7 @@
#!/usr/bin/env node
var connect = require('connect');
var express = require('express');
var serveStatic = require('serve-static');
var morgan = require('morgan');
var colors = require('colors');
@ -21,11 +22,20 @@ if (!argv.p) {
listen(port);
}
//CORS middleware
function allowCrossDomain(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
function listen(port) {
var server = connect();
server.use(serveStatic(__dirname + "../../"))
var server = express();
server.use(allowCrossDomain);
server.use(serveStatic(__dirname + "../../"));
if(!logger) server.use(morgan(logger))