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

Merge pull request #485 from futurepress/tabify

Tabify epub.js src and tests
This commit is contained in:
Fred Chasen 2016-10-24 16:18:44 +02:00 committed by GitHub
commit 8dd67cc167
31 changed files with 7759 additions and 7758 deletions

7025
dist/epub.js vendored

File diff suppressed because it is too large Load diff

2
dist/epub.js.map vendored

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@ var uglify = require('gulp-uglify');
var gutil = require('gulp-util'); var gutil = require('gulp-util');
var plumber = require('gulp-plumber'); var plumber = require('gulp-plumber');
var onError = function (err) { var onError = function (err) {
gutil.log(gutil.colors.green(err)); gutil.log(gutil.colors.green(err));
}; };
var server = require("./tools/serve.js"); var server = require("./tools/serve.js");
@ -24,73 +24,73 @@ var mochify = require('mochify');
// Lint JS // Lint JS
gulp.task('lint', function() { gulp.task('lint', function() {
return gulp.src('src/*.js') return gulp.src('src/*.js')
.pipe(jshint()) .pipe(jshint())
.pipe(jshint.reporter('default')); .pipe(jshint.reporter('default'));
}); });
// set up the browserify instance on a task basis // set up the browserify instance on a task basis
gulp.task('bundle', function () { gulp.task('bundle', function () {
return bundle('epub.js'); return bundle('epub.js');
}); });
// Minify JS // Minify JS
gulp.task('minify', ['bundle'], function(){ gulp.task('minify', ['bundle'], function(){
var uglifyOptions = { var uglifyOptions = {
mangle: true, mangle: true,
preserveComments : "license" preserveComments : "license"
}; };
return gulp.src('dist/epub.js') return gulp.src('dist/epub.js')
.pipe(plumber({ errorHandler: onError })) .pipe(plumber({ errorHandler: onError }))
.pipe(rename('epub.min.js')) .pipe(rename('epub.min.js'))
// .pipe(sourcemaps.init({loadMaps: true})) // .pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify(uglifyOptions)) .pipe(uglify(uglifyOptions))
// .pipe(sourcemaps.write('./')) // .pipe(sourcemaps.write('./'))
.pipe(size({ showFiles: true })) .pipe(size({ showFiles: true }))
.pipe(gulp.dest('dist')); .pipe(gulp.dest('dist'));
}); });
// Watch Our Files // Watch Our Files
gulp.task('watch', function(cb) { gulp.task('watch', function(cb) {
bundle('epub.js', cb); bundle('epub.js', cb);
}); });
gulp.task('serve', function(cb) { gulp.task('serve', function(cb) {
server(); server();
bundle('epub.js', cb); bundle('epub.js', cb);
}); });
gulp.task('serve:no-watch', function(cb) { gulp.task('serve:no-watch', function(cb) {
server(); server();
}); });
gulp.task('test', function(cb) { gulp.task('test', function(cb) {
mochify('./test/*.js', { mochify('./test/*.js', {
reporter: 'spec', reporter: 'spec',
transform: 'brfs', transform: 'brfs',
"web-security": false, "web-security": false,
"webSecurityEnabled": false, "webSecurityEnabled": false,
// "localUrlAccess": true, // "localUrlAccess": true,
watch: true, watch: true,
wd: false, wd: false,
debug: false debug: false
}) })
.bundle(); .bundle();
}); });
gulp.task('test:once', function(cb) { gulp.task('test:once', function(cb) {
mochify('./test/*.js', { mochify('./test/*.js', {
reporter: 'spec', reporter: 'spec',
transform: 'brfs', transform: 'brfs',
"web-security": false, "web-security": false,
"webSecurityEnabled": false, "webSecurityEnabled": false,
// "localUrlAccess": true, // "localUrlAccess": true,
watch: false, watch: false,
wd: false, wd: false,
debug: false debug: false
}) })
.bundle(); .bundle();
}); });
// Default // Default
@ -98,51 +98,51 @@ gulp.task('default', ['lint', 'bundle']);
function bundle(file, watch) { function bundle(file, watch) {
var opt = { var opt = {
entries: ['src/'+file], entries: ['src/'+file],
standalone: 'ePub', standalone: 'ePub',
debug : true debug : true
}; };
var b = browserify(opt); var b = browserify(opt);
// Expose epub module for require // Expose epub module for require
b.require('./src/'+file, {expose: 'epub'}); b.require('./src/'+file, {expose: 'epub'});
// Keep JSZip library seperate, // Keep JSZip library seperate,
// must be loaded to use Unarchive or `require` will throw an error // must be loaded to use Unarchive or `require` will throw an error
b.external('jszip'); b.external('jszip');
b.external('xmldom'); b.external('xmldom');
// Ignore optional URI libraries // Ignore optional URI libraries
var urijsPath = URI(require.resolve('urijs')); var urijsPath = URI(require.resolve('urijs'));
['./punycode.js', './IPv6.js'].forEach(function(lib) { ['./punycode.js', './IPv6.js'].forEach(function(lib) {
var libPath = URI(lib).absoluteTo(urijsPath).toString(); var libPath = URI(lib).absoluteTo(urijsPath).toString();
b.ignore(libPath); b.ignore(libPath);
}); });
// watchify() if watch requested, otherwise run browserify() once // watchify() if watch requested, otherwise run browserify() once
var bundler = watch ? watchify(b) : b; var bundler = watch ? watchify(b) : b;
function rebundle() { function rebundle() {
var stream = bundler.bundle(); var stream = bundler.bundle();
return stream return stream
.on('error', gutil.log) .on('error', gutil.log)
.pipe(source(file)) .pipe(source(file))
.pipe(buffer()) .pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true})) .pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('./')) .pipe(sourcemaps.write('./'))
.pipe(size({ showFiles: true })) .pipe(size({ showFiles: true }))
.pipe(gulp.dest('./dist/')); .pipe(gulp.dest('./dist/'));
} }
// listen for an update and run rebundle // listen for an update and run rebundle
bundler.on('update', function() { bundler.on('update', function() {
rebundle(); rebundle();
gutil.log('Rebundle...'); gutil.log('Rebundle...');
}); });
// run it once the first time buildScript is called // run it once the first time buildScript is called
return rebundle(); return rebundle();
} }

View file

@ -12,264 +12,264 @@ var EpubCFI = require('./epubcfi');
function Book(_url, options){ function Book(_url, options){
this.settings = core.extend(this.settings || {}, { this.settings = core.extend(this.settings || {}, {
requestMethod: this.requestMethod requestMethod: this.requestMethod
}); });
core.extend(this.settings, options); core.extend(this.settings, options);
// Promises // Promises
this.opening = new RSVP.defer(); this.opening = new RSVP.defer();
this.opened = this.opening.promise; this.opened = this.opening.promise;
this.isOpen = false; this.isOpen = false;
this.url = undefined; this.url = undefined;
this.loading = { this.loading = {
manifest: new RSVP.defer(), manifest: new RSVP.defer(),
spine: new RSVP.defer(), spine: new RSVP.defer(),
metadata: new RSVP.defer(), metadata: new RSVP.defer(),
cover: new RSVP.defer(), cover: new RSVP.defer(),
navigation: new RSVP.defer(), navigation: new RSVP.defer(),
pageList: new RSVP.defer() pageList: new RSVP.defer()
}; };
this.loaded = { this.loaded = {
manifest: this.loading.manifest.promise, manifest: this.loading.manifest.promise,
spine: this.loading.spine.promise, spine: this.loading.spine.promise,
metadata: this.loading.metadata.promise, metadata: this.loading.metadata.promise,
cover: this.loading.cover.promise, cover: this.loading.cover.promise,
navigation: this.loading.navigation.promise, navigation: this.loading.navigation.promise,
pageList: this.loading.pageList.promise pageList: this.loading.pageList.promise
}; };
this.ready = RSVP.hash(this.loaded); this.ready = RSVP.hash(this.loaded);
// Queue for methods used before opening // Queue for methods used before opening
this.isRendered = false; this.isRendered = false;
// this._q = core.queue(this); // this._q = core.queue(this);
this.request = this.settings.requestMethod.bind(this); this.request = this.settings.requestMethod.bind(this);
this.spine = new Spine(this.request); this.spine = new Spine(this.request);
this.locations = new Locations(this.spine, this.request); this.locations = new Locations(this.spine, this.request);
if(_url) { if(_url) {
this.open(_url).catch(function (error) { this.open(_url).catch(function (error) {
var err = new Error("Cannot load book at "+ _url ); var err = new Error("Cannot load book at "+ _url );
console.error(err); console.error(err);
this.trigger("loadFailed", error); this.trigger("loadFailed", error);
}.bind(this)); }.bind(this));
} }
}; };
Book.prototype.open = function(_url, options){ Book.prototype.open = function(_url, options){
var uri; var uri;
var parse = new Parser(); var parse = new Parser();
var epubPackage; var epubPackage;
var epubContainer; var epubContainer;
var book = this; var book = this;
var containerPath = "META-INF/container.xml"; var containerPath = "META-INF/container.xml";
var location; var location;
var absoluteUri; var absoluteUri;
var isArrayBuffer = false; var isArrayBuffer = false;
var isBase64 = options && options.base64; var isBase64 = options && options.base64;
if(!_url) { if(!_url) {
this.opening.resolve(this); this.opening.resolve(this);
return this.opened; return this.opened;
}
// Reuse parsed url or create a new uri object
// if(typeof(_url) === "object") {
// uri = _url;
// } else {
// uri = core.uri(_url);
// }
if (_url instanceof ArrayBuffer || isBase64) {
isArrayBuffer = true;
this.url = '/';
} else {
uri = URI(_url);
} }
if (window && window.location && uri) { // Reuse parsed url or create a new uri object
absoluteUri = uri.absoluteTo(window.location.href); // if(typeof(_url) === "object") {
this.url = absoluteUri.toString(); // uri = _url;
} else if (window && window.location) { // } else {
this.url = window.location.href; // uri = core.uri(_url);
} else { // }
this.url = _url; if (_url instanceof ArrayBuffer || isBase64) {
} isArrayBuffer = true;
this.url = '/';
} else {
uri = URI(_url);
}
// Find path to the Container if (window && window.location && uri) {
if(uri && uri.suffix() === "opf") { absoluteUri = uri.absoluteTo(window.location.href);
// Direct link to package, no container this.url = absoluteUri.toString();
this.packageUrl = _url; } else if (window && window.location) {
this.containerUrl = ''; this.url = window.location.href;
} else {
this.url = _url;
}
if(uri.origin()) { // Find path to the Container
this.baseUrl = uri.origin() + "/" + uri.directory() + "/"; if(uri && uri.suffix() === "opf") {
} else if(absoluteUri){ // Direct link to package, no container
this.baseUrl = absoluteUri.origin(); this.packageUrl = _url;
this.baseUrl += absoluteUri.directory() + "/"; this.containerUrl = '';
} else {
this.baseUrl = uri.directory() + "/";
}
epubPackage = this.request(this.packageUrl) if(uri.origin()) {
.catch(function(error) { this.baseUrl = uri.origin() + "/" + uri.directory() + "/";
book.opening.reject(error); } else if(absoluteUri){
}); this.baseUrl = absoluteUri.origin();
this.baseUrl += absoluteUri.directory() + "/";
} else {
this.baseUrl = uri.directory() + "/";
}
} else if(isArrayBuffer || isBase64 || this.isArchivedUrl(uri)) { epubPackage = this.request(this.packageUrl)
// Book is archived .catch(function(error) {
this.url = '/'; book.opening.reject(error);
this.containerUrl = URI(containerPath).absoluteTo(this.url).toString(); });
epubContainer = this.unarchive(_url, isBase64). } else if(isArrayBuffer || isBase64 || this.isArchivedUrl(uri)) {
then(function() { // Book is archived
return this.request(this.containerUrl); this.url = '/';
}.bind(this)) this.containerUrl = URI(containerPath).absoluteTo(this.url).toString();
.catch(function(error) {
book.opening.reject(error);
});
}
// Find the path to the Package from the container
else if (!uri.suffix()) {
this.containerUrl = this.url + containerPath; epubContainer = this.unarchive(_url, isBase64).
then(function() {
return this.request(this.containerUrl);
}.bind(this))
.catch(function(error) {
book.opening.reject(error);
});
}
// Find the path to the Package from the container
else if (!uri.suffix()) {
epubContainer = this.request(this.containerUrl) this.containerUrl = this.url + containerPath;
.catch(function(error) {
// handle errors in loading container
book.opening.reject(error);
});
}
if (epubContainer) { epubContainer = this.request(this.containerUrl)
epubPackage = epubContainer. .catch(function(error) {
then(function(containerXml){ // handle errors in loading container
return parse.container(containerXml); // Container has path to content book.opening.reject(error);
}). });
then(function(paths){ }
var packageUri = URI(paths.packagePath);
var absPackageUri = packageUri.absoluteTo(book.url);
var absWindowUri;
book.packageUrl = absPackageUri.toString(); if (epubContainer) {
book.encoding = paths.encoding; epubPackage = epubContainer.
then(function(containerXml){
return parse.container(containerXml); // Container has path to content
}).
then(function(paths){
var packageUri = URI(paths.packagePath);
var absPackageUri = packageUri.absoluteTo(book.url);
var absWindowUri;
// Set Url relative to the content book.packageUrl = absPackageUri.toString();
if(absPackageUri.origin()) { book.encoding = paths.encoding;
book.baseUrl = absPackageUri.origin() + absPackageUri.directory() + "/";
} else {
if(packageUri.directory()) {
book.baseUrl = "/" + packageUri.directory() + "/";
} else {
book.baseUrl = "/"
}
}
return book.request(book.packageUrl); // Set Url relative to the content
}).catch(function(error) { if(absPackageUri.origin()) {
// handle errors in either of the two requests book.baseUrl = absPackageUri.origin() + absPackageUri.directory() + "/";
book.opening.reject(error); } else {
}); if(packageUri.directory()) {
} book.baseUrl = "/" + packageUri.directory() + "/";
} else {
book.baseUrl = "/"
}
}
epubPackage.then(function(packageXml) { return book.request(book.packageUrl);
}).catch(function(error) {
// handle errors in either of the two requests
book.opening.reject(error);
});
}
if (!packageXml) { epubPackage.then(function(packageXml) {
return;
}
// Get package information from epub opf if (!packageXml) {
book.unpack(packageXml); return;
}
// Resolve promises // Get package information from epub opf
book.loading.manifest.resolve(book.package.manifest); book.unpack(packageXml);
book.loading.metadata.resolve(book.package.metadata);
book.loading.spine.resolve(book.spine);
book.loading.cover.resolve(book.cover);
book.isOpen = true; // 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);
// Clear queue of any waiting book request book.isOpen = true;
// Resolve book opened promise // Clear queue of any waiting book request
book.opening.resolve(book);
}).catch(function(error) { // Resolve book opened promise
// handle errors in parsing the book book.opening.resolve(book);
// console.error(error.message, error.stack);
book.opening.reject(error);
});
return this.opened; }).catch(function(error) {
// handle errors in parsing the book
// console.error(error.message, error.stack);
book.opening.reject(error);
});
return this.opened;
}; };
Book.prototype.unpack = function(packageXml){ Book.prototype.unpack = function(packageXml){
var book = this, var book = this,
parse = new Parser(); parse = new Parser();
book.package = parse.packageContents(packageXml); // Extract info from contents book.package = parse.packageContents(packageXml); // Extract info from contents
if(!book.package) { if(!book.package) {
return; return;
} }
book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths book.package.baseUrl = book.baseUrl; // Provides a url base for resolving paths
this.spine.load(book.package); this.spine.load(book.package);
book.navigation = new Navigation(book.package, this.request); book.navigation = new Navigation(book.package, this.request);
book.navigation.load().then(function(toc){ book.navigation.load().then(function(toc){
book.toc = toc; book.toc = toc;
book.loading.navigation.resolve(book.toc); book.loading.navigation.resolve(book.toc);
}); });
// //-- Set Global Layout setting based on metadata // //-- Set Global Layout setting based on metadata
// MOVE TO RENDER // MOVE TO RENDER
// book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata); // book.globalLayoutProperties = book.parseLayoutProperties(book.package.metadata);
book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString(); book.cover = URI(book.package.coverPath).absoluteTo(book.baseUrl).toString();
}; };
// Alias for book.spine.get // Alias for book.spine.get
Book.prototype.section = function(target) { Book.prototype.section = function(target) {
return this.spine.get(target); return this.spine.get(target);
}; };
// Sugar to render a book // Sugar to render a book
Book.prototype.renderTo = function(element, options) { Book.prototype.renderTo = function(element, options) {
// var renderMethod = (options && options.method) ? // var renderMethod = (options && options.method) ?
// options.method : // options.method :
// "single"; // "single";
this.rendition = new Rendition(this, options); this.rendition = new Rendition(this, options);
this.rendition.attachTo(element); this.rendition.attachTo(element);
return this.rendition; return this.rendition;
}; };
Book.prototype.requestMethod = function(_url) { Book.prototype.requestMethod = function(_url) {
// Switch request methods // Switch request methods
if(this.unarchived) { if(this.unarchived) {
return this.unarchived.request(_url); return this.unarchived.request(_url);
} else { } else {
return request(_url, null, this.requestCredentials, this.requestHeaders); return request(_url, null, this.requestCredentials, this.requestHeaders);
} }
}; };
Book.prototype.setRequestCredentials = function(_credentials) { Book.prototype.setRequestCredentials = function(_credentials) {
this.requestCredentials = _credentials; this.requestCredentials = _credentials;
}; };
Book.prototype.setRequestHeaders = function(_headers) { Book.prototype.setRequestHeaders = function(_headers) {
this.requestHeaders = _headers; this.requestHeaders = _headers;
}; };
Book.prototype.unarchive = function(bookUrl, isBase64){ Book.prototype.unarchive = function(bookUrl, isBase64){
@ -279,21 +279,21 @@ Book.prototype.unarchive = function(bookUrl, isBase64){
//-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub) //-- Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)
Book.prototype.isArchivedUrl = function(bookUrl){ Book.prototype.isArchivedUrl = function(bookUrl){
var uri; var uri;
var extension; var extension;
if (bookUrl instanceof ArrayBuffer) { if (bookUrl instanceof ArrayBuffer) {
return true; return true;
} }
// Reuse parsed url or create a new uri object // Reuse parsed url or create a new uri object
// if(typeof(bookUrl) === "object") { // if(typeof(bookUrl) === "object") {
// uri = bookUrl; // uri = bookUrl;
// } else { // } else {
// uri = core.uri(bookUrl); // uri = core.uri(bookUrl);
// } // }
uri = URI(bookUrl); uri = URI(bookUrl);
extension = uri.suffix(); extension = uri.suffix();
if(extension && (extension == "epub" || extension == "zip")){ if(extension && (extension == "epub" || extension == "zip")){
return true; return true;
@ -319,13 +319,13 @@ Book.prototype.coverUrl = function(){
}; };
Book.prototype.range = function(cfiRange) { Book.prototype.range = function(cfiRange) {
var cfi = new EpubCFI(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) { return item.load().then(function (contents) {
var range = cfi.toRange(item.document); var range = cfi.toRange(item.document);
return range; return range;
}) })
}; };
module.exports = Book; module.exports = Book;
@ -335,7 +335,7 @@ RSVP.EventTarget.mixin(Book.prototype);
//-- Handle RSVP Errors //-- Handle RSVP Errors
RSVP.on('error', function(event) { RSVP.on('error', function(event) {
console.error(event); console.error(event);
}); });
RSVP.configure('instrument', false); //-- true | will logging out all RSVP rejections RSVP.configure('instrument', false); //-- true | will logging out all RSVP rejections
@ -343,5 +343,5 @@ RSVP.configure('instrument', false); //-- true | will logging out all RSVP rejec
// RSVP.on('chained', listener); // RSVP.on('chained', listener);
// RSVP.on('fulfilled', listener); // RSVP.on('fulfilled', listener);
RSVP.on('rejected', function(event){ RSVP.on('rejected', function(event){
console.error(event.detail.message, event.detail.stack); console.error(event.detail.message, event.detail.stack);
}); });

File diff suppressed because it is too large Load diff

View file

@ -5,536 +5,536 @@ var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnim
/* /*
//-- Parse the different parts of a url, returning a object //-- Parse the different parts of a url, returning a object
function uri(url){ function uri(url){
var uri = { var uri = {
protocol : '', protocol : '',
host : '', host : '',
path : '', path : '',
origin : '', origin : '',
directory : '', directory : '',
base : '', base : '',
filename : '', filename : '',
extension : '', extension : '',
fragment : '', fragment : '',
href : url href : url
}, },
doubleSlash = url.indexOf('://'), doubleSlash = url.indexOf('://'),
search = url.indexOf('?'), search = url.indexOf('?'),
fragment = url.indexOf("#"), fragment = url.indexOf("#"),
withoutProtocol, withoutProtocol,
dot, dot,
firstSlash; firstSlash;
if(fragment != -1) { if(fragment != -1) {
uri.fragment = url.slice(fragment + 1); uri.fragment = url.slice(fragment + 1);
url = url.slice(0, fragment); url = url.slice(0, fragment);
} }
if(search != -1) { if(search != -1) {
uri.search = url.slice(search + 1); uri.search = url.slice(search + 1);
url = url.slice(0, search); url = url.slice(0, search);
href = url; href = url;
} }
if(doubleSlash != -1) { if(doubleSlash != -1) {
uri.protocol = url.slice(0, doubleSlash); uri.protocol = url.slice(0, doubleSlash);
withoutProtocol = url.slice(doubleSlash+3); withoutProtocol = url.slice(doubleSlash+3);
firstSlash = withoutProtocol.indexOf('/'); firstSlash = withoutProtocol.indexOf('/');
if(firstSlash === -1) { if(firstSlash === -1) {
uri.host = uri.path; uri.host = uri.path;
uri.path = ""; uri.path = "";
} else { } else {
uri.host = withoutProtocol.slice(0, firstSlash); uri.host = withoutProtocol.slice(0, firstSlash);
uri.path = withoutProtocol.slice(firstSlash); uri.path = withoutProtocol.slice(firstSlash);
} }
uri.origin = uri.protocol + "://" + uri.host; uri.origin = uri.protocol + "://" + uri.host;
uri.directory = folder(uri.path); uri.directory = folder(uri.path);
uri.base = uri.origin + uri.directory; uri.base = uri.origin + uri.directory;
// return origin; // return origin;
} else { } else {
uri.path = url; uri.path = url;
uri.directory = folder(url); uri.directory = folder(url);
uri.base = uri.directory; uri.base = uri.directory;
} }
//-- Filename //-- Filename
uri.filename = url.replace(uri.base, ''); uri.filename = url.replace(uri.base, '');
dot = uri.filename.lastIndexOf('.'); dot = uri.filename.lastIndexOf('.');
if(dot != -1) { if(dot != -1) {
uri.extension = uri.filename.slice(dot+1); uri.extension = uri.filename.slice(dot+1);
} }
return uri; return uri;
}; };
//-- Parse out the folder, will return everything before the last slash //-- Parse out the folder, will return everything before the last slash
function folder(url){ function folder(url){
var lastSlash = url.lastIndexOf('/'); var lastSlash = url.lastIndexOf('/');
if(lastSlash == -1) var folder = ''; if(lastSlash == -1) var folder = '';
folder = url.slice(0, lastSlash + 1); folder = url.slice(0, lastSlash + 1);
return folder; return folder;
}; };
*/ */
function isElement(obj) { function isElement(obj) {
return !!(obj && obj.nodeType == 1); return !!(obj && obj.nodeType == 1);
}; };
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
function uuid() { function uuid() {
var d = new Date().getTime(); var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random()*16)%16 | 0; var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16); d = Math.floor(d/16);
return (c=='x' ? r : (r&0x7|0x8)).toString(16); return (c=='x' ? r : (r&0x7|0x8)).toString(16);
}); });
return uuid; return uuid;
}; };
// From Lodash // From Lodash
function values(object) { function values(object) {
var index = -1, var index = -1,
props = Object.keys(object), props = Object.keys(object),
length = props.length, length = props.length,
result = Array(length); result = Array(length);
while (++index < length) { while (++index < length) {
result[index] = object[props[index]]; result[index] = object[props[index]];
} }
return result; return result;
}; };
function resolveUrl(base, path) { function resolveUrl(base, path) {
var url = [], var url = [],
segments = [], segments = [],
baseUri = uri(base), baseUri = uri(base),
pathUri = uri(path), pathUri = uri(path),
baseDirectory = baseUri.directory, baseDirectory = baseUri.directory,
pathDirectory = pathUri.directory, pathDirectory = pathUri.directory,
directories = [], directories = [],
// folders = base.split("/"), // folders = base.split("/"),
paths; paths;
// if(uri.host) { // if(uri.host) {
// return path; // return path;
// } // }
if(baseDirectory[0] === "/") { if(baseDirectory[0] === "/") {
baseDirectory = baseDirectory.substring(1); baseDirectory = baseDirectory.substring(1);
} }
if(pathDirectory[pathDirectory.length-1] === "/") { if(pathDirectory[pathDirectory.length-1] === "/") {
baseDirectory = baseDirectory.substring(0, baseDirectory.length-1); baseDirectory = baseDirectory.substring(0, baseDirectory.length-1);
} }
if(pathDirectory[0] === "/") { if(pathDirectory[0] === "/") {
pathDirectory = pathDirectory.substring(1); pathDirectory = pathDirectory.substring(1);
} }
if(pathDirectory[pathDirectory.length-1] === "/") { if(pathDirectory[pathDirectory.length-1] === "/") {
pathDirectory = pathDirectory.substring(0, pathDirectory.length-1); pathDirectory = pathDirectory.substring(0, pathDirectory.length-1);
} }
if(baseDirectory) { if(baseDirectory) {
directories = baseDirectory.split("/"); directories = baseDirectory.split("/");
} }
paths = pathDirectory.split("/"); paths = pathDirectory.split("/");
paths.reverse().forEach(function(part, index){ paths.reverse().forEach(function(part, index){
if(part === ".."){ if(part === ".."){
directories.pop(); directories.pop();
} else if(part === directories[directories.length-1]) { } else if(part === directories[directories.length-1]) {
directories.pop(); directories.pop();
segments.unshift(part); segments.unshift(part);
} else { } else {
segments.unshift(part); segments.unshift(part);
} }
}); });
url = [baseUri.origin]; url = [baseUri.origin];
if(directories.length) { if(directories.length) {
url = url.concat(directories); url = url.concat(directories);
} }
if(segments) { if(segments) {
url = url.concat(segments); url = url.concat(segments);
} }
url = url.concat(pathUri.filename); url = url.concat(pathUri.filename);
return url.join("/"); return url.join("/");
}; };
function documentHeight() { function documentHeight() {
return Math.max( return Math.max(
document.documentElement.clientHeight, document.documentElement.clientHeight,
document.body.scrollHeight, document.body.scrollHeight,
document.documentElement.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.body.offsetHeight,
document.documentElement.offsetHeight document.documentElement.offsetHeight
); );
}; };
function isNumber(n) { function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n); return !isNaN(parseFloat(n)) && isFinite(n);
}; };
function prefixed(unprefixed) { function prefixed(unprefixed) {
var vendors = ["Webkit", "Moz", "O", "ms" ], var vendors = ["Webkit", "Moz", "O", "ms" ],
prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'], prefixes = ['-Webkit-', '-moz-', '-o-', '-ms-'],
upper = unprefixed[0].toUpperCase() + unprefixed.slice(1), upper = unprefixed[0].toUpperCase() + unprefixed.slice(1),
length = vendors.length; length = vendors.length;
if (typeof(document) === 'undefined' || typeof(document.body.style[unprefixed]) != 'undefined') { if (typeof(document) === 'undefined' || typeof(document.body.style[unprefixed]) != 'undefined') {
return unprefixed; return unprefixed;
} }
for ( var i=0; i < length; i++ ) { for ( var i=0; i < length; i++ ) {
if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') { if (typeof(document.body.style[vendors[i] + upper]) != 'undefined') {
return vendors[i] + upper; return vendors[i] + upper;
} }
} }
return unprefixed; return unprefixed;
}; };
function defaults(obj) { function defaults(obj) {
for (var i = 1, length = arguments.length; i < length; i++) { for (var i = 1, length = arguments.length; i < length; i++) {
var source = arguments[i]; var source = arguments[i];
for (var prop in source) { for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop]; if (obj[prop] === void 0) obj[prop] = source[prop];
} }
} }
return obj; return obj;
}; };
function extend(target) { function extend(target) {
var sources = [].slice.call(arguments, 1); var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) { sources.forEach(function (source) {
if(!source) return; if(!source) return;
Object.getOwnPropertyNames(source).forEach(function(propName) { Object.getOwnPropertyNames(source).forEach(function(propName) {
Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName)); Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));
}); });
}); });
return target; return target;
}; };
// Fast quicksort insert for sorted array -- based on: // Fast quicksort insert for sorted array -- based on:
// http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers // http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers
function insert(item, array, compareFunction) { function insert(item, array, compareFunction) {
var location = locationOf(item, array, compareFunction); var location = locationOf(item, array, compareFunction);
array.splice(location, 0, item); array.splice(location, 0, item);
return location; return location;
}; };
// Returns where something would fit in // Returns where something would fit in
function locationOf(item, array, compareFunction, _start, _end) { function locationOf(item, array, compareFunction, _start, _end) {
var start = _start || 0; var start = _start || 0;
var end = _end || array.length; var end = _end || array.length;
var pivot = parseInt(start + (end - start) / 2); var pivot = parseInt(start + (end - start) / 2);
var compared; var compared;
if(!compareFunction){ if(!compareFunction){
compareFunction = function(a, b) { compareFunction = function(a, b) {
if(a > b) return 1; if(a > b) return 1;
if(a < b) return -1; if(a < b) return -1;
if(a = b) return 0; if(a = b) return 0;
}; };
} }
if(end-start <= 0) { if(end-start <= 0) {
return pivot; return pivot;
} }
compared = compareFunction(array[pivot], item); compared = compareFunction(array[pivot], item);
if(end-start === 1) { if(end-start === 1) {
return compared > 0 ? pivot : pivot + 1; return compared > 0 ? pivot : pivot + 1;
} }
if(compared === 0) { if(compared === 0) {
return pivot; return pivot;
} }
if(compared === -1) { if(compared === -1) {
return locationOf(item, array, compareFunction, pivot, end); return locationOf(item, array, compareFunction, pivot, end);
} else{ } else{
return locationOf(item, array, compareFunction, start, pivot); return locationOf(item, array, compareFunction, start, pivot);
} }
}; };
// Returns -1 of mpt found // Returns -1 of mpt found
function indexOfSorted(item, array, compareFunction, _start, _end) { function indexOfSorted(item, array, compareFunction, _start, _end) {
var start = _start || 0; var start = _start || 0;
var end = _end || array.length; var end = _end || array.length;
var pivot = parseInt(start + (end - start) / 2); var pivot = parseInt(start + (end - start) / 2);
var compared; var compared;
if(!compareFunction){ if(!compareFunction){
compareFunction = function(a, b) { compareFunction = function(a, b) {
if(a > b) return 1; if(a > b) return 1;
if(a < b) return -1; if(a < b) return -1;
if(a = b) return 0; if(a = b) return 0;
}; };
} }
if(end-start <= 0) { if(end-start <= 0) {
return -1; // Not found return -1; // Not found
} }
compared = compareFunction(array[pivot], item); compared = compareFunction(array[pivot], item);
if(end-start === 1) { if(end-start === 1) {
return compared === 0 ? pivot : -1; return compared === 0 ? pivot : -1;
} }
if(compared === 0) { if(compared === 0) {
return pivot; // Found return pivot; // Found
} }
if(compared === -1) { if(compared === -1) {
return indexOfSorted(item, array, compareFunction, pivot, end); return indexOfSorted(item, array, compareFunction, pivot, end);
} else{ } else{
return indexOfSorted(item, array, compareFunction, start, pivot); return indexOfSorted(item, array, compareFunction, start, pivot);
} }
}; };
function bounds(el) { function bounds(el) {
var style = window.getComputedStyle(el); var style = window.getComputedStyle(el);
var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"];
var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"];
var width = 0; var width = 0;
var height = 0; var height = 0;
widthProps.forEach(function(prop){ widthProps.forEach(function(prop){
width += parseFloat(style[prop]) || 0; width += parseFloat(style[prop]) || 0;
}); });
heightProps.forEach(function(prop){ heightProps.forEach(function(prop){
height += parseFloat(style[prop]) || 0; height += parseFloat(style[prop]) || 0;
}); });
return { return {
height: height, height: height,
width: width width: width
}; };
}; };
function borders(el) { function borders(el) {
var style = window.getComputedStyle(el); var style = window.getComputedStyle(el);
var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"];
var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"];
var width = 0; var width = 0;
var height = 0; var height = 0;
widthProps.forEach(function(prop){ widthProps.forEach(function(prop){
width += parseFloat(style[prop]) || 0; width += parseFloat(style[prop]) || 0;
}); });
heightProps.forEach(function(prop){ heightProps.forEach(function(prop){
height += parseFloat(style[prop]) || 0; height += parseFloat(style[prop]) || 0;
}); });
return { return {
height: height, height: height,
width: width width: width
}; };
}; };
function windowBounds() { function windowBounds() {
var width = window.innerWidth; var width = window.innerWidth;
var height = window.innerHeight; var height = window.innerHeight;
return { return {
top: 0, top: 0,
left: 0, left: 0,
right: width, right: width,
bottom: height, bottom: height,
width: width, width: width,
height: height height: height
}; };
}; };
//https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496 //https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496
function cleanStringForXpath(str) { function cleanStringForXpath(str) {
var parts = str.match(/[^'"]+|['"]/g); var parts = str.match(/[^'"]+|['"]/g);
parts = parts.map(function(part){ parts = parts.map(function(part){
if (part === "'") { if (part === "'") {
return '\"\'\"'; // output "'" return '\"\'\"'; // output "'"
} }
if (part === '"') { if (part === '"') {
return "\'\"\'"; // output '"' return "\'\"\'"; // output '"'
} }
return "\'" + part + "\'"; return "\'" + part + "\'";
}); });
return "concat(\'\'," + parts.join(",") + ")"; return "concat(\'\'," + parts.join(",") + ")";
}; };
function indexOfTextNode(textNode){ function indexOfTextNode(textNode){
var parent = textNode.parentNode; var parent = textNode.parentNode;
var children = parent.childNodes; var children = parent.childNodes;
var sib; var sib;
var index = -1; var index = -1;
for (var i = 0; i < children.length; i++) { for (var i = 0; i < children.length; i++) {
sib = children[i]; sib = children[i];
if(sib.nodeType === Node.TEXT_NODE){ if(sib.nodeType === Node.TEXT_NODE){
index++; index++;
} }
if(sib == textNode) break; if(sib == textNode) break;
} }
return index; return index;
}; };
function isXml(ext) { function isXml(ext) {
return ['xml', 'opf', 'ncx'].indexOf(ext) > -1; return ['xml', 'opf', 'ncx'].indexOf(ext) > -1;
} }
function createBlob(content, mime){ function createBlob(content, mime){
var blob = new Blob([content], {type : mime }); var blob = new Blob([content], {type : mime });
return blob; return blob;
}; };
function createBlobUrl(content, mime){ function createBlobUrl(content, mime){
var _URL = window.URL || window.webkitURL || window.mozURL; var _URL = window.URL || window.webkitURL || window.mozURL;
var tempUrl; var tempUrl;
var blob = this.createBlob(content, mime); var blob = this.createBlob(content, mime);
tempUrl = _URL.createObjectURL(blob); tempUrl = _URL.createObjectURL(blob);
return tempUrl; return tempUrl;
}; };
function createBase64Url(content, mime){ function createBase64Url(content, mime){
var string; var string;
var data; var data;
var datauri; var datauri;
if (typeof(content) !== "string") { if (typeof(content) !== "string") {
// Only handles strings // Only handles strings
return; return;
} }
data = btoa(content); data = btoa(content);
datauri = "data:" + mime + ";base64," + data; datauri = "data:" + mime + ";base64," + data;
return datauri; return datauri;
}; };
function type(obj){ function type(obj){
return Object.prototype.toString.call(obj).slice(8, -1); return Object.prototype.toString.call(obj).slice(8, -1);
} }
function parse(markup, mime) { function parse(markup, mime) {
var doc; var doc;
// console.log("parse", markup); // console.log("parse", markup);
if (typeof DOMParser === "undefined") { if (typeof DOMParser === "undefined") {
DOMParser = require('xmldom').DOMParser; DOMParser = require('xmldom').DOMParser;
} }
doc = new DOMParser().parseFromString(markup, mime); doc = new DOMParser().parseFromString(markup, mime);
return doc; return doc;
} }
function qs(el, sel) { function qs(el, sel) {
var elements; var elements;
if (typeof el.querySelector != "undefined") { if (typeof el.querySelector != "undefined") {
return el.querySelector(sel); return el.querySelector(sel);
} else { } else {
elements = el.getElementsByTagName(sel); elements = el.getElementsByTagName(sel);
if (elements.length) { if (elements.length) {
return elements[0]; return elements[0];
} }
} }
} }
function qsa(el, sel) { function qsa(el, sel) {
if (typeof el.querySelector != "undefined") { if (typeof el.querySelector != "undefined") {
return el.querySelectorAll(sel); return el.querySelectorAll(sel);
} else { } else {
return el.getElementsByTagName(sel); return el.getElementsByTagName(sel);
} }
} }
function qsp(el, sel, props) { function qsp(el, sel, props) {
var q, filtered; var q, filtered;
if (typeof el.querySelector != "undefined") { if (typeof el.querySelector != "undefined") {
sel += '['; sel += '[';
for (var prop in props) { for (var prop in props) {
sel += prop + "='" + props[prop] + "'"; sel += prop + "='" + props[prop] + "'";
} }
sel += ']'; sel += ']';
return el.querySelector(sel); return el.querySelector(sel);
} else { } else {
q = el.getElementsByTagName(sel); q = el.getElementsByTagName(sel);
filtered = Array.prototype.slice.call(q, 0).filter(function(el) { filtered = Array.prototype.slice.call(q, 0).filter(function(el) {
for (var prop in props) { for (var prop in props) {
if(el.getAttribute(prop) === props[prop]){ if(el.getAttribute(prop) === props[prop]){
return true; return true;
} }
} }
return false; return false;
}); });
if (filtered) { if (filtered) {
return filtered[0]; return filtered[0];
} }
} }
} }
function blob2base64(blob, cb) { function blob2base64(blob, cb) {
var reader = new FileReader(); var reader = new FileReader();
reader.readAsDataURL(blob); reader.readAsDataURL(blob);
reader.onloadend = function() { reader.onloadend = function() {
cb(reader.result); cb(reader.result);
} }
} }
module.exports = { module.exports = {
// 'uri': uri, // 'uri': uri,
// 'folder': folder, // 'folder': folder,
'isElement': isElement, 'isElement': isElement,
'uuid': uuid, 'uuid': uuid,
'values': values, 'values': values,
'resolveUrl': resolveUrl, 'resolveUrl': resolveUrl,
'indexOfSorted': indexOfSorted, 'indexOfSorted': indexOfSorted,
'documentHeight': documentHeight, 'documentHeight': documentHeight,
'isNumber': isNumber, 'isNumber': isNumber,
'prefixed': prefixed, 'prefixed': prefixed,
'defaults': defaults, 'defaults': defaults,
'extend': extend, 'extend': extend,
'insert': insert, 'insert': insert,
'locationOf': locationOf, 'locationOf': locationOf,
'indexOfSorted': indexOfSorted, 'indexOfSorted': indexOfSorted,
'requestAnimationFrame': requestAnimationFrame, 'requestAnimationFrame': requestAnimationFrame,
'bounds': bounds, 'bounds': bounds,
'borders': borders, 'borders': borders,
'windowBounds': windowBounds, 'windowBounds': windowBounds,
'cleanStringForXpath': cleanStringForXpath, 'cleanStringForXpath': cleanStringForXpath,
'indexOfTextNode': indexOfTextNode, 'indexOfTextNode': indexOfTextNode,
'isXml': isXml, 'isXml': isXml,
'createBlob': createBlob, 'createBlob': createBlob,
'createBlobUrl': createBlobUrl, 'createBlobUrl': createBlobUrl,
'type': type, 'type': type,
'parse' : parse, 'parse' : parse,
'qs' : qs, 'qs' : qs,
'qsa' : qsa, 'qsa' : qsa,
'qsp' : qsp, 'qsp' : qsp,
'blob2base64' : blob2base64, 'blob2base64' : blob2base64,
'createBase64Url': createBase64Url 'createBase64Url': createBase64Url
}; };

View file

@ -19,7 +19,7 @@ ePub.ViewManagers = {};
ePub.Views = {}; ePub.Views = {};
ePub.register = { ePub.register = {
manager : function(name, manager){ manager : function(name, manager){
return ePub.ViewManagers[name] = manager; return ePub.ViewManagers[name] = manager;
}, },
view : function(name, view){ view : function(name, view){
return ePub.Views[name] = view; return ePub.Views[name] = view;

File diff suppressed because it is too large Load diff

View file

@ -9,51 +9,51 @@ var RSVP = require('rsvp');
// this.content.trigger(args).then(function(){}); // this.content.trigger(args).then(function(){});
function Hook(context){ function Hook(context){
this.context = context || this; this.context = context || this;
this.hooks = []; this.hooks = [];
}; };
// Adds a function to be run before a hook completes // Adds a function to be run before a hook completes
Hook.prototype.register = function(){ Hook.prototype.register = function(){
for(var i = 0; i < arguments.length; ++i) { for(var i = 0; i < arguments.length; ++i) {
if (typeof arguments[i] === "function") { if (typeof arguments[i] === "function") {
this.hooks.push(arguments[i]); this.hooks.push(arguments[i]);
} else { } else {
// unpack array // unpack array
for(var j = 0; j < arguments[i].length; ++j) { for(var j = 0; j < arguments[i].length; ++j) {
this.hooks.push(arguments[i][j]); this.hooks.push(arguments[i][j]);
} }
} }
} }
}; };
// Triggers a hook to run all functions // Triggers a hook to run all functions
Hook.prototype.trigger = function(){ Hook.prototype.trigger = function(){
var args = arguments; var args = arguments;
var context = this.context; var context = this.context;
var promises = []; var promises = [];
this.hooks.forEach(function(task, i) { this.hooks.forEach(function(task, i) {
var executing = task.apply(context, args); var executing = task.apply(context, args);
if(executing && typeof executing["then"] === "function") { if(executing && typeof executing["then"] === "function") {
// Task is a function that returns a promise // Task is a function that returns a promise
promises.push(executing); promises.push(executing);
} }
// Otherwise Task resolves immediately, continue // Otherwise Task resolves immediately, continue
}); });
return RSVP.all(promises); return RSVP.all(promises);
}; };
// Adds a function to be run before a hook completes // Adds a function to be run before a hook completes
Hook.prototype.list = function(){ Hook.prototype.list = function(){
return this.hooks; return this.hooks;
}; };
Hook.prototype.clear = function(){ Hook.prototype.clear = function(){
return this.hooks = []; return this.hooks = [];
}; };
module.exports = Hook; module.exports = Hook;

View file

@ -2,120 +2,120 @@ var core = require('./core');
var RSVP = require('rsvp'); var RSVP = require('rsvp');
function Layout(settings){ function Layout(settings){
this.name = settings.layout || "reflowable"; this.name = settings.layout || "reflowable";
this._spread = (settings.spread === "none") ? false : true; this._spread = (settings.spread === "none") ? false : true;
this._minSpreadWidth = settings.spread || 800; this._minSpreadWidth = settings.spread || 800;
this._evenSpreads = settings.evenSpreads || false; this._evenSpreads = settings.evenSpreads || false;
if (settings.flow === "scrolled-continuous" || if (settings.flow === "scrolled-continuous" ||
settings.flow === "scrolled-doc") { settings.flow === "scrolled-doc") {
this._flow = "scrolled"; this._flow = "scrolled";
} else { } else {
this._flow = "paginated"; this._flow = "paginated";
} }
this.width = 0; this.width = 0;
this.height = 0; this.height = 0;
this.spreadWidth = 0; this.spreadWidth = 0;
this.delta = 0; this.delta = 0;
this.columnWidth = 0; this.columnWidth = 0;
this.gap = 0; this.gap = 0;
this.divisor = 1; this.divisor = 1;
}; };
// paginated | scrolled // paginated | scrolled
Layout.prototype.flow = function(flow) { Layout.prototype.flow = function(flow) {
this._flow = (flow === "paginated") ? "paginated" : "scrolled"; this._flow = (flow === "paginated") ? "paginated" : "scrolled";
} }
// true | false // true | false
Layout.prototype.spread = function(spread, min) { Layout.prototype.spread = function(spread, min) {
this._spread = (spread === "none") ? false : true; this._spread = (spread === "none") ? false : true;
if (min >= 0) { if (min >= 0) {
this._minSpreadWidth = min; this._minSpreadWidth = min;
} }
} }
Layout.prototype.calculate = function(_width, _height, _gap){ Layout.prototype.calculate = function(_width, _height, _gap){
var divisor = 1; var divisor = 1;
var gap = _gap || 0; var gap = _gap || 0;
//-- Check the width and create even width columns //-- Check the width and create even width columns
var fullWidth = Math.floor(_width); var fullWidth = Math.floor(_width);
var width = _width; var width = _width;
var section = Math.floor(width / 8); var section = Math.floor(width / 8);
var colWidth; var colWidth;
var spreadWidth; var spreadWidth;
var delta; var delta;
if (this._spread && width >= this._minSpreadWidth) { if (this._spread && width >= this._minSpreadWidth) {
divisor = 2; divisor = 2;
} else { } else {
divisor = 1; divisor = 1;
} }
if (this.name === "reflowable" && this._flow === "paginated" && !(_gap >= 0)) { if (this.name === "reflowable" && this._flow === "paginated" && !(_gap >= 0)) {
gap = ((section % 2 === 0) ? section : section - 1); gap = ((section % 2 === 0) ? section : section - 1);
} }
if (this.name === "pre-paginated" ) { if (this.name === "pre-paginated" ) {
gap = 0; gap = 0;
} }
//-- Double Page //-- Double Page
if(divisor > 1) { if(divisor > 1) {
colWidth = Math.floor((width - gap) / divisor); colWidth = Math.floor((width - gap) / divisor);
} else { } else {
colWidth = width; colWidth = width;
} }
if (this.name === "pre-paginated" && divisor > 1) { if (this.name === "pre-paginated" && divisor > 1) {
width = colWidth; width = colWidth;
} }
spreadWidth = colWidth * divisor; spreadWidth = colWidth * divisor;
delta = (colWidth + gap) * divisor; delta = (colWidth + gap) * divisor;
this.width = width; this.width = width;
this.height = _height; this.height = _height;
this.spreadWidth = spreadWidth; this.spreadWidth = spreadWidth;
this.delta = delta; this.delta = delta;
this.columnWidth = colWidth; this.columnWidth = colWidth;
this.gap = gap; this.gap = gap;
this.divisor = divisor; this.divisor = divisor;
}; };
Layout.prototype.format = function(contents){ Layout.prototype.format = function(contents){
var formating; var formating;
if (this.name === "pre-paginated") { if (this.name === "pre-paginated") {
formating = contents.fit(this.columnWidth, this.height); formating = contents.fit(this.columnWidth, this.height);
} else if (this._flow === "paginated") { } else if (this._flow === "paginated") {
formating = contents.columns(this.width, this.height, this.columnWidth, this.gap); formating = contents.columns(this.width, this.height, this.columnWidth, this.gap);
} else { // scrolled } else { // scrolled
formating = contents.size(this.width, null); formating = contents.size(this.width, null);
} }
return formating; // might be a promise in some View Managers return formating; // might be a promise in some View Managers
}; };
Layout.prototype.count = function(totalWidth) { Layout.prototype.count = function(totalWidth) {
// var totalWidth = contents.scrollWidth(); // var totalWidth = contents.scrollWidth();
var spreads = Math.ceil( totalWidth / this.spreadWidth); var spreads = Math.ceil( totalWidth / this.spreadWidth);
return { return {
spreads : spreads, spreads : spreads,
pages : spreads * this.divisor pages : spreads * this.divisor
}; };
}; };
module.exports = Layout; module.exports = Layout;

View file

@ -4,114 +4,114 @@ var EpubCFI = require('./epubcfi');
var RSVP = require('rsvp'); var RSVP = require('rsvp');
function Locations(spine, request) { function Locations(spine, request) {
this.spine = spine; this.spine = spine;
this.request = request; this.request = request;
this.q = new Queue(this); this.q = new Queue(this);
this.epubcfi = new EpubCFI(); this.epubcfi = new EpubCFI();
this._locations = []; this._locations = [];
this.total = 0; this.total = 0;
this.break = 150; this.break = 150;
this._current = 0; this._current = 0;
}; };
// Load all of sections in the book // Load all of sections in the book
Locations.prototype.generate = function(chars) { Locations.prototype.generate = function(chars) {
if (chars) { if (chars) {
this.break = chars; this.break = chars;
} }
this.q.pause(); this.q.pause();
this.spine.each(function(section) { this.spine.each(function(section) {
this.q.enqueue(this.process, section); this.q.enqueue(this.process, section);
}.bind(this)); }.bind(this));
return this.q.run().then(function() { return this.q.run().then(function() {
this.total = this._locations.length-1; this.total = this._locations.length-1;
if (this._currentCfi) { if (this._currentCfi) {
this.currentLocation = this._currentCfi; this.currentLocation = this._currentCfi;
} }
return this._locations; return this._locations;
// console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end)); // console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));
}.bind(this)); }.bind(this));
}; };
Locations.prototype.process = function(section) { Locations.prototype.process = function(section) {
return section.load(this.request) return section.load(this.request)
.then(function(contents) { .then(function(contents) {
var range; var range;
var doc = contents.ownerDocument; var doc = contents.ownerDocument;
var counter = 0; var counter = 0;
this.sprint(contents, function(node) { this.sprint(contents, function(node) {
var len = node.length; var len = node.length;
var dist; var dist;
var pos = 0; var pos = 0;
// Start range // Start range
if (counter == 0) { if (counter == 0) {
range = doc.createRange(); range = doc.createRange();
range.setStart(node, 0); range.setStart(node, 0);
} }
dist = this.break - counter; dist = this.break - counter;
// Node is smaller than a break // Node is smaller than a break
if(dist > len){ if(dist > len){
counter += len; counter += len;
pos = len; pos = len;
} }
while (pos < len) { while (pos < len) {
counter = this.break; counter = this.break;
pos += this.break; pos += this.break;
// Gone over // Gone over
if(pos >= len){ if(pos >= len){
// Continue counter for next node // Continue counter for next node
counter = len - (pos - this.break); counter = len - (pos - this.break);
// At End // At End
} else { } else {
// End the previous range // End the previous range
range.setEnd(node, pos); range.setEnd(node, pos);
cfi = section.cfiFromRange(range); cfi = section.cfiFromRange(range);
this._locations.push(cfi); this._locations.push(cfi);
counter = 0; counter = 0;
// Start new range // Start new range
pos += 1; pos += 1;
range = doc.createRange(); range = doc.createRange();
range.setStart(node, pos); range.setStart(node, pos);
} }
} }
}.bind(this)); }.bind(this));
// Close remaining // Close remaining
if (range) { if (range) {
range.setEnd(prev, prev.length); range.setEnd(prev, prev.length);
cfi = section.cfiFromRange(range); cfi = section.cfiFromRange(range);
this._locations.push(cfi) this._locations.push(cfi)
counter = 0; counter = 0;
} }
}.bind(this)); }.bind(this));
}; };
@ -125,26 +125,26 @@ Locations.prototype.sprint = function(root, func) {
}; };
Locations.prototype.locationFromCfi = function(cfi){ Locations.prototype.locationFromCfi = function(cfi){
// Check if the location has not been set yet // Check if the location has not been set yet
if(this._locations.length === 0) { if(this._locations.length === 0) {
return -1; return -1;
} }
return core.locationOf(cfi, this._locations, this.epubcfi.compare); return core.locationOf(cfi, this._locations, this.epubcfi.compare);
}; };
Locations.prototype.precentageFromCfi = function(cfi) { Locations.prototype.precentageFromCfi = function(cfi) {
// Find closest cfi // Find closest cfi
var loc = this.locationFromCfi(cfi); var loc = this.locationFromCfi(cfi);
// Get percentage in total // Get percentage in total
return this.precentageFromLocation(loc); return this.precentageFromLocation(loc);
}; };
Locations.prototype.percentageFromLocation = function(loc) { Locations.prototype.percentageFromLocation = function(loc) {
if (!loc || !this.total) { if (!loc || !this.total) {
return 0; return 0;
} }
return (loc / this.total); return (loc / this.total);
}; };
Locations.prototype.cfiFromLocation = function(loc){ Locations.prototype.cfiFromLocation = function(loc){
@ -162,7 +162,7 @@ Locations.prototype.cfiFromLocation = function(loc){
}; };
Locations.prototype.cfiFromPercentage = function(value){ Locations.prototype.cfiFromPercentage = function(value){
var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1 var percentage = (value > 1) ? value / 100 : value; // Normalize value to 0-1
var loc = Math.ceil(this.total * percentage); var loc = Math.ceil(this.total * percentage);
return this.cfiFromLocation(loc); return this.cfiFromLocation(loc);
@ -170,8 +170,8 @@ Locations.prototype.cfiFromPercentage = function(value){
Locations.prototype.load = function(locations){ Locations.prototype.load = function(locations){
this._locations = JSON.parse(locations); this._locations = JSON.parse(locations);
this.total = this._locations.length-1; this.total = this._locations.length-1;
return this._locations; return this._locations;
}; };
Locations.prototype.save = function(json){ Locations.prototype.save = function(json){
@ -183,39 +183,39 @@ Locations.prototype.getCurrent = function(json){
}; };
Locations.prototype.setCurrent = function(curr){ Locations.prototype.setCurrent = function(curr){
var loc; var loc;
if(typeof curr == "string"){ if(typeof curr == "string"){
this._currentCfi = curr; this._currentCfi = curr;
} else if (typeof curr == "number") { } else if (typeof curr == "number") {
this._current = curr; this._current = curr;
} else { } else {
return; return;
}
if(this._locations.length === 0) {
return;
} }
if(typeof curr == "string"){ if(this._locations.length === 0) {
loc = this.locationFromCfi(curr); return;
this._current = loc; }
} else {
loc = curr;
}
this.trigger("changed", { if(typeof curr == "string"){
percentage: this.precentageFromLocation(loc) loc = this.locationFromCfi(curr);
}); this._current = loc;
} else {
loc = curr;
}
this.trigger("changed", {
percentage: this.precentageFromLocation(loc)
});
}; };
Object.defineProperty(Locations.prototype, 'currentLocation', { Object.defineProperty(Locations.prototype, 'currentLocation', {
get: function () { get: function () {
return this._current; return this._current;
}, },
set: function (curr) { set: function (curr) {
this.setCurrent(curr); this.setCurrent(curr);
} }
}); });
RSVP.EventTarget.mixin(Locations.prototype); RSVP.EventTarget.mixin(Locations.prototype);

View file

@ -21,9 +21,9 @@ function ContinuousViewManager(options) {
core.extend(this.settings, options.settings || {}); core.extend(this.settings, options.settings || {});
// Gap can be 0, byt defaults doesn't handle that // Gap can be 0, byt defaults doesn't handle that
if (options.settings.gap != "undefined" && options.settings.gap === 0) { if (options.settings.gap != "undefined" && options.settings.gap === 0) {
this.settings.gap = options.settings.gap; this.settings.gap = options.settings.gap;
} }
// this.viewSettings.axis = this.settings.axis; // this.viewSettings.axis = this.settings.axis;
this.viewSettings = { this.viewSettings = {
@ -43,7 +43,7 @@ ContinuousViewManager.prototype = Object.create(SingleViewManager.prototype);
ContinuousViewManager.prototype.constructor = ContinuousViewManager; ContinuousViewManager.prototype.constructor = ContinuousViewManager;
ContinuousViewManager.prototype.display = function(section, target){ ContinuousViewManager.prototype.display = function(section, target){
return SingleViewManager.prototype.display.call(this, section, target) return SingleViewManager.prototype.display.call(this, section, target)
.then(function () { .then(function () {
return this.fill(); return this.fill();
}.bind(this)); }.bind(this));
@ -64,8 +64,8 @@ ContinuousViewManager.prototype.fill = function(_full){
} }
ContinuousViewManager.prototype.moveTo = function(offset){ ContinuousViewManager.prototype.moveTo = function(offset){
// var bounds = this.stage.bounds(); // var bounds = this.stage.bounds();
// var dist = Math.floor(offset.top / bounds.height) * bounds.height; // var dist = Math.floor(offset.top / bounds.height) * bounds.height;
var distX = 0, var distX = 0,
distY = 0; distY = 0;
@ -80,10 +80,10 @@ ContinuousViewManager.prototype.moveTo = function(offset){
offsetX = distX+this.settings.offset; offsetX = distX+this.settings.offset;
} }
return this.check(offsetX, offsetY) return this.check(offsetX, offsetY)
.then(function(){ .then(function(){
this.scrollBy(distX, distY); this.scrollBy(distX, distY);
}.bind(this)); }.bind(this));
}; };
/* /*
@ -113,7 +113,7 @@ ContinuousViewManager.prototype.afterDisplayed = function(currView){
ContinuousViewManager.prototype.resize = function(width, height){ ContinuousViewManager.prototype.resize = function(width, height){
// Clear the queue // Clear the queue
this.q.clear(); this.q.clear();
this._stageSize = this.stage.size(width, height); this._stageSize = this.stage.size(width, height);
this._bounds = this.bounds(); this._bounds = this.bounds();
@ -127,27 +127,27 @@ ContinuousViewManager.prototype.resize = function(width, height){
view.size(this._stageSize.width, this._stageSize.height); view.size(this._stageSize.width, this._stageSize.height);
}.bind(this)); }.bind(this));
this.updateLayout(); this.updateLayout();
// if(this.location) { // if(this.location) {
// this.rendition.display(this.location.start); // this.rendition.display(this.location.start);
// } // }
this.trigger("resized", { this.trigger("resized", {
width: this.stage.width, width: this.stage.width,
height: this.stage.height height: this.stage.height
}); });
}; };
ContinuousViewManager.prototype.onResized = function(e) { ContinuousViewManager.prototype.onResized = function(e) {
// this.views.clear(); // this.views.clear();
clearTimeout(this.resizeTimeout); clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(function(){ this.resizeTimeout = setTimeout(function(){
this.resize(); this.resize();
}.bind(this), 150); }.bind(this), 150);
}; };
ContinuousViewManager.prototype.afterResized = function(view){ ContinuousViewManager.prototype.afterResized = function(view){
@ -220,34 +220,34 @@ ContinuousViewManager.prototype.update = function(_offset){
var promises = []; var promises = [];
for (var i = 0; i < viewsLength; i++) { for (var i = 0; i < viewsLength; i++) {
view = views[i]; view = views[i];
isVisible = this.isVisible(view, offset, offset, container); isVisible = this.isVisible(view, offset, offset, container);
if(isVisible === true) { if(isVisible === true) {
if (!view.displayed) { if (!view.displayed) {
promises.push(view.display(this.request).then(function (view) { promises.push(view.display(this.request).then(function (view) {
view.show(); view.show();
})); }));
} }
visible.push(view); visible.push(view);
} else { } else {
this.q.enqueue(view.destroy.bind(view)); this.q.enqueue(view.destroy.bind(view));
clearTimeout(this.trimTimeout); clearTimeout(this.trimTimeout);
this.trimTimeout = setTimeout(function(){ this.trimTimeout = setTimeout(function(){
this.q.enqueue(this.trim.bind(this)); this.q.enqueue(this.trim.bind(this));
}.bind(this), 250); }.bind(this), 250);
} }
} }
if(promises.length){ if(promises.length){
return RSVP.all(promises); return RSVP.all(promises);
} else { } else {
updating.resolve(); updating.resolve();
return updating.promise; return updating.promise;
} }
}; };
@ -276,61 +276,61 @@ ContinuousViewManager.prototype.check = function(_offsetLeft, _offsetTop){
if (offset + visibleLength + delta >= contentLength) { if (offset + visibleLength + delta >= contentLength) {
last = this.views.last(); last = this.views.last();
next = last && last.section.next(); next = last && last.section.next();
if(next) { if(next) {
newViews.push(this.append(next)); newViews.push(this.append(next));
} }
} }
if (offset - delta < 0 ) { if (offset - delta < 0 ) {
first = this.views.first(); first = this.views.first();
prev = first && first.section.prev(); prev = first && first.section.prev();
if(prev) { if(prev) {
newViews.push(this.prepend(prev)); newViews.push(this.prepend(prev));
} }
} }
if(newViews.length){ if(newViews.length){
// RSVP.all(promises) // RSVP.all(promises)
// .then(function() { // .then(function() {
// Check to see if anything new is on screen after rendering // Check to see if anything new is on screen after rendering
return this.q.enqueue(function(){ return this.q.enqueue(function(){
return this.update(delta); return this.update(delta);
}.bind(this)); }.bind(this));
// }.bind(this)); // }.bind(this));
} else { } else {
checking.resolve(false); checking.resolve(false);
return checking.promise; return checking.promise;
} }
}; };
ContinuousViewManager.prototype.trim = function(){ ContinuousViewManager.prototype.trim = function(){
var task = new RSVP.defer(); var task = new RSVP.defer();
var displayed = this.views.displayed(); var displayed = this.views.displayed();
var first = displayed[0]; var first = displayed[0];
var last = displayed[displayed.length-1]; var last = displayed[displayed.length-1];
var firstIndex = this.views.indexOf(first); var firstIndex = this.views.indexOf(first);
var lastIndex = this.views.indexOf(last); var lastIndex = this.views.indexOf(last);
var above = this.views.slice(0, firstIndex); var above = this.views.slice(0, firstIndex);
var below = this.views.slice(lastIndex+1); var below = this.views.slice(lastIndex+1);
// Erase all but last above // Erase all but last above
for (var i = 0; i < above.length-1; i++) { for (var i = 0; i < above.length-1; i++) {
this.erase(above[i], above); this.erase(above[i], above);
} }
// Erase all except first below // Erase all except first below
for (var j = 1; j < below.length; j++) { for (var j = 1; j < below.length; j++) {
this.erase(below[j]); this.erase(below[j]);
} }
task.resolve(); task.resolve();
return task.promise; return task.promise;
}; };
ContinuousViewManager.prototype.erase = function(view, above){ //Trim ContinuousViewManager.prototype.erase = function(view, above){ //Trim
@ -339,12 +339,12 @@ ContinuousViewManager.prototype.erase = function(view, above){ //Trim
var prevLeft; var prevLeft;
if(this.settings.height) { if(this.settings.height) {
prevTop = this.container.scrollTop; prevTop = this.container.scrollTop;
prevLeft = this.container.scrollLeft; prevLeft = this.container.scrollLeft;
} else { } else {
prevTop = window.scrollY; prevTop = window.scrollY;
prevLeft = window.scrollX; prevLeft = window.scrollX;
} }
var bounds = view.bounds(); var bounds = view.bounds();
@ -373,60 +373,60 @@ ContinuousViewManager.prototype.addEventListeners = function(stage){
}; };
ContinuousViewManager.prototype.addScrollListeners = function() { ContinuousViewManager.prototype.addScrollListeners = function() {
var scroller; var scroller;
this.tick = core.requestAnimationFrame; this.tick = core.requestAnimationFrame;
if(this.settings.height) { if(this.settings.height) {
this.prevScrollTop = this.container.scrollTop; this.prevScrollTop = this.container.scrollTop;
this.prevScrollLeft = this.container.scrollLeft; this.prevScrollLeft = this.container.scrollLeft;
} else { } else {
this.prevScrollTop = window.scrollY; this.prevScrollTop = window.scrollY;
this.prevScrollLeft = window.scrollX; this.prevScrollLeft = window.scrollX;
} }
this.scrollDeltaVert = 0; this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0; this.scrollDeltaHorz = 0;
if(this.settings.height) { if(this.settings.height) {
scroller = this.container; scroller = this.container;
this.scrollTop = this.container.scrollTop; this.scrollTop = this.container.scrollTop;
this.scrollLeft = this.container.scrollLeft; this.scrollLeft = this.container.scrollLeft;
} else { } else {
scroller = window; scroller = window;
this.scrollTop = window.scrollY; this.scrollTop = window.scrollY;
this.scrollLeft = window.scrollX; this.scrollLeft = window.scrollX;
} }
scroller.addEventListener("scroll", this.onScroll.bind(this)); scroller.addEventListener("scroll", this.onScroll.bind(this));
// this.tick.call(window, this.onScroll.bind(this)); // this.tick.call(window, this.onScroll.bind(this));
this.scrolled = false; this.scrolled = false;
}; };
ContinuousViewManager.prototype.onScroll = function(){ ContinuousViewManager.prototype.onScroll = function(){
// if(!this.ignore) { // if(!this.ignore) {
if(this.settings.height) { if(this.settings.height) {
scrollTop = this.container.scrollTop; scrollTop = this.container.scrollTop;
scrollLeft = this.container.scrollLeft; scrollLeft = this.container.scrollLeft;
} else { } else {
scrollTop = window.scrollY; scrollTop = window.scrollY;
scrollLeft = window.scrollX; scrollLeft = window.scrollX;
} }
this.scrollTop = scrollTop; this.scrollTop = scrollTop;
this.scrollLeft = scrollLeft; this.scrollLeft = scrollLeft;
if(!this.ignore) { if(!this.ignore) {
if((this.scrollDeltaVert === 0 && if((this.scrollDeltaVert === 0 &&
this.scrollDeltaHorz === 0) || this.scrollDeltaHorz === 0) ||
this.scrollDeltaVert > this.settings.offsetDelta || this.scrollDeltaVert > this.settings.offsetDelta ||
this.scrollDeltaHorz > this.settings.offsetDelta) { this.scrollDeltaHorz > this.settings.offsetDelta) {
this.q.enqueue(function() { this.q.enqueue(function() {
this.check(); this.check();
@ -434,44 +434,44 @@ ContinuousViewManager.prototype.onScroll = function(){
// this.check(); // this.check();
this.scrollDeltaVert = 0; this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0; this.scrollDeltaHorz = 0;
this.trigger("scroll", { this.trigger("scroll", {
top: scrollTop, top: scrollTop,
left: scrollLeft left: scrollLeft
}); });
clearTimeout(this.afterScrolled); clearTimeout(this.afterScrolled);
this.afterScrolled = setTimeout(function () { this.afterScrolled = setTimeout(function () {
this.trigger("scrolled", { this.trigger("scrolled", {
top: this.scrollTop, top: this.scrollTop,
left: this.scrollLeft left: this.scrollLeft
}); });
}.bind(this)); }.bind(this));
} }
} else { } else {
this.ignore = false; this.ignore = false;
} }
this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop); this.scrollDeltaVert += Math.abs(scrollTop-this.prevScrollTop);
this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft); this.scrollDeltaHorz += Math.abs(scrollLeft-this.prevScrollLeft);
this.prevScrollTop = scrollTop; this.prevScrollTop = scrollTop;
this.prevScrollLeft = scrollLeft; this.prevScrollLeft = scrollLeft;
clearTimeout(this.scrollTimeout); clearTimeout(this.scrollTimeout);
this.scrollTimeout = setTimeout(function(){ this.scrollTimeout = setTimeout(function(){
this.scrollDeltaVert = 0; this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0; this.scrollDeltaHorz = 0;
}.bind(this), 150); }.bind(this), 150);
this.scrolled = false; this.scrolled = false;
// } // }
// this.tick.call(window, this.onScroll.bind(this)); // this.tick.call(window, this.onScroll.bind(this));
}; };
@ -488,9 +488,9 @@ ContinuousViewManager.prototype.onScroll = function(){
ContinuousViewManager.prototype.currentLocation = function(){ ContinuousViewManager.prototype.currentLocation = function(){
if (this.settings.axis === "vertical") { if (this.settings.axis === "vertical") {
this.location = this.scrolledLocation(); this.location = this.scrolledLocation();
} else { } else {
this.location = this.paginatedLocation(); this.location = this.paginatedLocation();
} }
@ -499,104 +499,104 @@ ContinuousViewManager.prototype.currentLocation = function(){
ContinuousViewManager.prototype.scrolledLocation = function(){ ContinuousViewManager.prototype.scrolledLocation = function(){
var visible = this.visible(); var visible = this.visible();
var startPage, endPage; var startPage, endPage;
var container = this.container.getBoundingClientRect(); var container = this.container.getBoundingClientRect();
if(visible.length === 1) { if(visible.length === 1) {
return this.mapping.page(visible[0].contents, visible[0].section.cfiBase); return this.mapping.page(visible[0].contents, visible[0].section.cfiBase);
} }
if(visible.length > 1) { if(visible.length > 1) {
startPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase); startPage = this.mapping.page(visible[0].contents, visible[0].section.cfiBase);
endPage = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase); endPage = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase);
return { return {
start: startPage.start, start: startPage.start,
end: endPage.end end: endPage.end
}; };
} }
}; };
ContinuousViewManager.prototype.paginatedLocation = function(){ ContinuousViewManager.prototype.paginatedLocation = function(){
var visible = this.visible(); var visible = this.visible();
var startA, startB, endA, endB; var startA, startB, endA, endB;
var pageLeft, pageRight; var pageLeft, pageRight;
var container = this.container.getBoundingClientRect(); var container = this.container.getBoundingClientRect();
if(visible.length === 1) { if(visible.length === 1) {
startA = container.left - visible[0].position().left; startA = container.left - visible[0].position().left;
endA = startA + this.layout.spreadWidth; endA = startA + this.layout.spreadWidth;
return this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA); return this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);
} }
if(visible.length > 1) { if(visible.length > 1) {
// Left Col // Left Col
startA = container.left - visible[0].position().left; startA = container.left - visible[0].position().left;
endA = startA + this.layout.columnWidth; endA = startA + this.layout.columnWidth;
// Right Col // Right Col
startB = container.left + this.layout.spreadWidth - visible[visible.length-1].position().left; startB = container.left + this.layout.spreadWidth - visible[visible.length-1].position().left;
endB = startB + this.layout.columnWidth; endB = startB + this.layout.columnWidth;
pageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA); pageLeft = this.mapping.page(visible[0].contents, visible[0].section.cfiBase, startA, endA);
pageRight = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase, startB, endB); pageRight = this.mapping.page(visible[visible.length-1].contents, visible[visible.length-1].section.cfiBase, startB, endB);
return { return {
start: pageLeft.start, start: pageLeft.start,
end: pageRight.end end: pageRight.end
}; };
} }
}; };
/* /*
Continuous.prototype.current = function(what){ Continuous.prototype.current = function(what){
var view, top; var view, top;
var container = this.container.getBoundingClientRect(); var container = this.container.getBoundingClientRect();
var length = this.views.length - 1; var length = this.views.length - 1;
if(this.settings.axis === "horizontal") { if(this.settings.axis === "horizontal") {
for (var i = length; i >= 0; i--) { for (var i = length; i >= 0; i--) {
view = this.views[i]; view = this.views[i];
left = view.position().left; left = view.position().left;
if(left < container.right) { if(left < container.right) {
if(this._current == view) { if(this._current == view) {
break; break;
} }
this._current = view; this._current = view;
break; break;
} }
} }
} else { } else {
for (var i = length; i >= 0; i--) { for (var i = length; i >= 0; i--) {
view = this.views[i]; view = this.views[i];
top = view.bounds().top; top = view.bounds().top;
if(top < container.bottom) { if(top < container.bottom) {
if(this._current == view) { if(this._current == view) {
break; break;
} }
this._current = view; this._current = view;
break; break;
} }
} }
} }
return this._current; return this._current;
}; };
*/ */
@ -626,7 +626,7 @@ ContinuousViewManager.prototype.updateLayout = function() {
this.viewSettings.width = this.layout.width; this.viewSettings.width = this.layout.width;
this.viewSettings.height = this.layout.height; this.viewSettings.height = this.layout.height;
this.setLayout(this.layout); this.setLayout(this.layout);
}; };
@ -634,15 +634,15 @@ ContinuousViewManager.prototype.next = function(){
if(this.settings.axis === "horizontal") { if(this.settings.axis === "horizontal") {
this.scrollLeft = this.container.scrollLeft; this.scrollLeft = this.container.scrollLeft;
if(this.container.scrollLeft + if(this.container.scrollLeft +
this.container.offsetWidth + this.container.offsetWidth +
this.layout.delta < this.container.scrollWidth) { this.layout.delta < this.container.scrollWidth) {
this.scrollBy(this.layout.delta, 0); this.scrollBy(this.layout.delta, 0);
} else { } else {
this.scrollTo(this.container.scrollWidth - this.layout.delta, 0); this.scrollTo(this.container.scrollWidth - this.layout.delta, 0);
} }
} else { } else {
this.scrollBy(0, this.layout.height); this.scrollBy(0, this.layout.height);
@ -651,7 +651,7 @@ ContinuousViewManager.prototype.next = function(){
ContinuousViewManager.prototype.prev = function(){ ContinuousViewManager.prototype.prev = function(){
if(this.settings.axis === "horizontal") { if(this.settings.axis === "horizontal") {
this.scrollBy(-this.layout.delta, 0); this.scrollBy(-this.layout.delta, 0);
} else { } else {
this.scrollBy(0, -this.layout.height); this.scrollBy(0, -this.layout.height);
} }
@ -672,7 +672,7 @@ ContinuousViewManager.prototype.updateFlow = function(flow){
if (this.settings.axis === "vertical") { if (this.settings.axis === "vertical") {
this.settings.infinite = true; this.settings.infinite = true;
} else { } else {
this.settings.infinite = false; this.settings.infinite = false;
} }

View file

@ -93,15 +93,15 @@ SingleViewManager.prototype.destroy = function(){
SingleViewManager.prototype.onResized = function(e) { SingleViewManager.prototype.onResized = function(e) {
clearTimeout(this.resizeTimeout); clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(function(){ this.resizeTimeout = setTimeout(function(){
this.resize(); this.resize();
}.bind(this), 150); }.bind(this), 150);
}; };
SingleViewManager.prototype.resize = function(width, height){ SingleViewManager.prototype.resize = function(width, height){
// Clear the queue // Clear the queue
this.q.clear(); this.q.clear();
this._stageSize = this.stage.size(width, height); this._stageSize = this.stage.size(width, height);
this._bounds = this.bounds(); this._bounds = this.bounds();
@ -115,12 +115,12 @@ SingleViewManager.prototype.resize = function(width, height){
view.size(this._stageSize.width, this._stageSize.height); view.size(this._stageSize.width, this._stageSize.height);
}.bind(this)); }.bind(this));
this.updateLayout(); this.updateLayout();
this.trigger("resized", { this.trigger("resized", {
width: this.stage.width, width: this.stage.width,
height: this.stage.height height: this.stage.height
}); });
}; };
@ -208,7 +208,7 @@ SingleViewManager.prototype.moveTo = function(offset){
} }
} }
this.scrollTo(distX, distY); this.scrollTo(distX, distY);
}; };
SingleViewManager.prototype.add = function(section){ SingleViewManager.prototype.add = function(section){
@ -349,20 +349,20 @@ SingleViewManager.prototype.current = function(){
// Current is the last visible view // Current is the last visible view
return visible[visible.length-1]; return visible[visible.length-1];
} }
return null; return null;
}; };
SingleViewManager.prototype.currentLocation = function(){ SingleViewManager.prototype.currentLocation = function(){
var view; var view;
var start, end; var start, end;
if(this.views.length) { if(this.views.length) {
view = this.views.first(); view = this.views.first();
start = container.left - view.position().left; start = container.left - view.position().left;
end = start + this.layout.spread; end = start + this.layout.spread;
return this.mapping.page(view, view.section.cfiBase); return this.mapping.page(view, view.section.cfiBase);
} }
}; };
@ -376,12 +376,12 @@ SingleViewManager.prototype.isVisible = function(view, offsetPrev, offsetNext, _
return true; return true;
} else if(this.settings.axis === "vertical" && } else if(this.settings.axis === "vertical" &&
position.bottom > container.top - offsetPrev && position.bottom > container.top - offsetPrev &&
position.top < container.bottom + offsetNext) { position.top < container.bottom + offsetNext) {
return true; return true;
} }
return false; return false;
@ -392,60 +392,60 @@ SingleViewManager.prototype.visible = function(){
var container = this.bounds(); var container = this.bounds();
var views = this.views.displayed(); var views = this.views.displayed();
var viewsLength = views.length; var viewsLength = views.length;
var visible = []; var visible = [];
var isVisible; var isVisible;
var view; var view;
for (var i = 0; i < viewsLength; i++) { for (var i = 0; i < viewsLength; i++) {
view = views[i]; view = views[i];
isVisible = this.isVisible(view, 0, 0, container); isVisible = this.isVisible(view, 0, 0, container);
if(isVisible === true) { if(isVisible === true) {
visible.push(view); visible.push(view);
} }
} }
return visible; return visible;
}; };
SingleViewManager.prototype.scrollBy = function(x, y, silent){ SingleViewManager.prototype.scrollBy = function(x, y, silent){
if(silent) { if(silent) {
this.ignore = true; this.ignore = true;
} }
if(this.settings.height) { if(this.settings.height) {
if(x) this.container.scrollLeft += x; if(x) this.container.scrollLeft += x;
if(y) this.container.scrollTop += y; if(y) this.container.scrollTop += y;
} else { } else {
window.scrollBy(x,y); window.scrollBy(x,y);
} }
// console.log("scrollBy", x, y); // console.log("scrollBy", x, y);
this.scrolled = true; this.scrolled = true;
this.onScroll(); this.onScroll();
}; };
SingleViewManager.prototype.scrollTo = function(x, y, silent){ SingleViewManager.prototype.scrollTo = function(x, y, silent){
if(silent) { if(silent) {
this.ignore = true; this.ignore = true;
} }
if(this.settings.height) { if(this.settings.height) {
this.container.scrollLeft = x; this.container.scrollLeft = x;
this.container.scrollTop = y; this.container.scrollTop = y;
} else { } else {
window.scrollTo(x,y); window.scrollTo(x,y);
} }
// console.log("scrollTo", x, y); // console.log("scrollTo", x, y);
this.scrolled = true; this.scrolled = true;
this.onScroll(); this.onScroll();
// if(this.container.scrollLeft != x){ // if(this.container.scrollLeft != x){
// setTimeout(function() { // setTimeout(function() {
// this.scrollTo(x, y, silent); // this.scrollTo(x, y, silent);
// }.bind(this), 10); // }.bind(this), 10);
// return; // return;
// }; // };
}; };
SingleViewManager.prototype.onScroll = function(){ SingleViewManager.prototype.onScroll = function(){
@ -466,7 +466,7 @@ SingleViewManager.prototype.applyLayout = function(layout) {
this.updateLayout(); this.updateLayout();
this.mapping = new Mapping(this.layout); this.mapping = new Mapping(this.layout);
// this.manager.layout(this.layout.format); // this.manager.layout(this.layout.format);
}; };
SingleViewManager.prototype.updateLayout = function() { SingleViewManager.prototype.updateLayout = function() {

View file

@ -1,297 +1,297 @@
var EpubCFI = require('./epubcfi'); var EpubCFI = require('./epubcfi');
function Mapping(layout){ function Mapping(layout){
this.layout = layout; this.layout = layout;
}; };
Mapping.prototype.section = function(view) { Mapping.prototype.section = function(view) {
var ranges = this.findRanges(view); var ranges = this.findRanges(view);
var map = this.rangeListToCfiList(view.section.cfiBase, ranges); var map = this.rangeListToCfiList(view.section.cfiBase, ranges);
return map; return map;
}; };
Mapping.prototype.page = function(contents, cfiBase, start, end) { Mapping.prototype.page = function(contents, cfiBase, start, end) {
var root = contents && contents.document ? contents.document.body : false; var root = contents && contents.document ? contents.document.body : false;
if (!root) { if (!root) {
return; return;
} }
return this.rangePairToCfiPair(cfiBase, { return this.rangePairToCfiPair(cfiBase, {
start: this.findStart(root, start, end), start: this.findStart(root, start, end),
end: this.findEnd(root, start, end) end: this.findEnd(root, start, end)
}); });
}; };
Mapping.prototype.walk = function(root, func) { Mapping.prototype.walk = function(root, func) {
//var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false); //var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, null, false);
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode: function (node) { acceptNode: function (node) {
if ( node.data.trim().length > 0 ) { if ( node.data.trim().length > 0 ) {
return NodeFilter.FILTER_ACCEPT; return NodeFilter.FILTER_ACCEPT;
} else { } else {
return NodeFilter.FILTER_REJECT; return NodeFilter.FILTER_REJECT;
} }
} }
}, false); }, false);
var node; var node;
var result; var result;
while ((node = treeWalker.nextNode())) { while ((node = treeWalker.nextNode())) {
result = func(node); result = func(node);
if(result) break; if(result) break;
} }
return result; return result;
}; };
Mapping.prototype.findRanges = function(view){ Mapping.prototype.findRanges = function(view){
var columns = []; var columns = [];
var scrollWidth = view.contents.scrollWidth(); var scrollWidth = view.contents.scrollWidth();
var count = this.layout.count(scrollWidth); var count = this.layout.count(scrollWidth);
var column = this.layout.column; var column = this.layout.column;
var gap = this.layout.gap; var gap = this.layout.gap;
var start, end; var start, end;
for (var i = 0; i < count.pages; i++) { for (var i = 0; i < count.pages; i++) {
start = (column + gap) * i; start = (column + gap) * i;
end = (column * (i+1)) + (gap * i); end = (column * (i+1)) + (gap * i);
columns.push({ columns.push({
start: this.findStart(view.document.body, start, end), start: this.findStart(view.document.body, start, end),
end: this.findEnd(view.document.body, start, end) end: this.findEnd(view.document.body, start, end)
}); });
} }
return columns; return columns;
}; };
Mapping.prototype.findStart = function(root, start, end){ Mapping.prototype.findStart = function(root, start, end){
var stack = [root]; var stack = [root];
var $el; var $el;
var found; var found;
var $prev = root; var $prev = root;
while (stack.length) { while (stack.length) {
$el = stack.shift(); $el = stack.shift();
found = this.walk($el, function(node){ found = this.walk($el, function(node){
var left, right; var left, right;
var elPos; var elPos;
var elRange; var elRange;
if(node.nodeType == Node.TEXT_NODE){ if(node.nodeType == Node.TEXT_NODE){
elRange = document.createRange(); elRange = document.createRange();
elRange.selectNodeContents(node); elRange.selectNodeContents(node);
elPos = elRange.getBoundingClientRect(); elPos = elRange.getBoundingClientRect();
} else { } else {
elPos = node.getBoundingClientRect(); elPos = node.getBoundingClientRect();
} }
left = elPos.left; left = elPos.left;
right = elPos.right; right = elPos.right;
if( left >= start && left <= end ) { if( left >= start && left <= end ) {
return node; return node;
} else if (right > start) { } else if (right > start) {
return node; return node;
} else { } else {
$prev = node; $prev = node;
stack.push(node); stack.push(node);
} }
}); });
if(found) { if(found) {
return this.findTextStartRange(found, start, end); return this.findTextStartRange(found, start, end);
} }
} }
// Return last element // Return last element
return this.findTextStartRange($prev, start, end); return this.findTextStartRange($prev, start, end);
}; };
Mapping.prototype.findEnd = function(root, start, end){ Mapping.prototype.findEnd = function(root, start, end){
var stack = [root]; var stack = [root];
var $el; var $el;
var $prev = root; var $prev = root;
var found; var found;
while (stack.length) { while (stack.length) {
$el = stack.shift(); $el = stack.shift();
found = this.walk($el, function(node){ found = this.walk($el, function(node){
var left, right; var left, right;
var elPos; var elPos;
var elRange; var elRange;
if(node.nodeType == Node.TEXT_NODE){ if(node.nodeType == Node.TEXT_NODE){
elRange = document.createRange(); elRange = document.createRange();
elRange.selectNodeContents(node); elRange.selectNodeContents(node);
elPos = elRange.getBoundingClientRect(); elPos = elRange.getBoundingClientRect();
} else { } else {
elPos = node.getBoundingClientRect(); elPos = node.getBoundingClientRect();
} }
left = elPos.left; left = elPos.left;
right = elPos.right; right = elPos.right;
if(left > end && $prev) { if(left > end && $prev) {
return $prev; return $prev;
} else if(right > end) { } else if(right > end) {
return node; return node;
} else { } else {
$prev = node; $prev = node;
stack.push(node); stack.push(node);
} }
}); });
if(found){ if(found){
return this.findTextEndRange(found, start, end); return this.findTextEndRange(found, start, end);
} }
} }
// end of chapter // end of chapter
return this.findTextEndRange($prev, start, end); return this.findTextEndRange($prev, start, end);
}; };
Mapping.prototype.findTextStartRange = function(node, start, end){ Mapping.prototype.findTextStartRange = function(node, start, end){
var ranges = this.splitTextNodeIntoRanges(node); var ranges = this.splitTextNodeIntoRanges(node);
var prev; var prev;
var range; var range;
var pos; var pos;
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
range = ranges[i]; range = ranges[i];
pos = range.getBoundingClientRect(); pos = range.getBoundingClientRect();
if( pos.left >= start ) { if( pos.left >= start ) {
return range; return range;
} }
prev = range; prev = range;
} }
return ranges[0]; return ranges[0];
}; };
Mapping.prototype.findTextEndRange = function(node, start, end){ Mapping.prototype.findTextEndRange = function(node, start, end){
var ranges = this.splitTextNodeIntoRanges(node); var ranges = this.splitTextNodeIntoRanges(node);
var prev; var prev;
var range; var range;
var pos; var pos;
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
range = ranges[i]; range = ranges[i];
pos = range.getBoundingClientRect(); pos = range.getBoundingClientRect();
if(pos.left > end && prev) { if(pos.left > end && prev) {
return prev; return prev;
} else if(pos.right > end) { } else if(pos.right > end) {
return range; return range;
} }
prev = range; prev = range;
} }
// Ends before limit // Ends before limit
return ranges[ranges.length-1]; return ranges[ranges.length-1];
}; };
Mapping.prototype.splitTextNodeIntoRanges = function(node, _splitter){ Mapping.prototype.splitTextNodeIntoRanges = function(node, _splitter){
var ranges = []; var ranges = [];
var textContent = node.textContent || ""; var textContent = node.textContent || "";
var text = textContent.trim(); var text = textContent.trim();
var range; var range;
var rect; var rect;
var list; var list;
var doc = node.ownerDocument; var doc = node.ownerDocument;
var splitter = _splitter || " "; var splitter = _splitter || " ";
pos = text.indexOf(splitter); pos = text.indexOf(splitter);
if(pos === -1 || node.nodeType != Node.TEXT_NODE) { if(pos === -1 || node.nodeType != Node.TEXT_NODE) {
range = doc.createRange(); range = doc.createRange();
range.selectNodeContents(node); range.selectNodeContents(node);
return [range]; return [range];
} }
range = doc.createRange(); range = doc.createRange();
range.setStart(node, 0); range.setStart(node, 0);
range.setEnd(node, pos); range.setEnd(node, pos);
ranges.push(range); ranges.push(range);
range = false; range = false;
while ( pos != -1 ) { while ( pos != -1 ) {
pos = text.indexOf(splitter, pos + 1); pos = text.indexOf(splitter, pos + 1);
if(pos > 0) { if(pos > 0) {
if(range) { if(range) {
range.setEnd(node, pos); range.setEnd(node, pos);
ranges.push(range); ranges.push(range);
} }
range = doc.createRange(); range = doc.createRange();
range.setStart(node, pos+1); range.setStart(node, pos+1);
} }
} }
if(range) { if(range) {
range.setEnd(node, text.length); range.setEnd(node, text.length);
ranges.push(range); ranges.push(range);
} }
return ranges; return ranges;
}; };
Mapping.prototype.rangePairToCfiPair = function(cfiBase, rangePair){ Mapping.prototype.rangePairToCfiPair = function(cfiBase, rangePair){
var startRange = rangePair.start; var startRange = rangePair.start;
var endRange = rangePair.end; var endRange = rangePair.end;
startRange.collapse(true); startRange.collapse(true);
endRange.collapse(true); endRange.collapse(true);
// startCfi = section.cfiFromRange(startRange); // startCfi = section.cfiFromRange(startRange);
// endCfi = section.cfiFromRange(endRange); // endCfi = section.cfiFromRange(endRange);
startCfi = new EpubCFI(startRange, cfiBase).toString(); startCfi = new EpubCFI(startRange, cfiBase).toString();
endCfi = new EpubCFI(endRange, cfiBase).toString(); endCfi = new EpubCFI(endRange, cfiBase).toString();
return { return {
start: startCfi, start: startCfi,
end: endCfi end: endCfi
}; };
}; };
Mapping.prototype.rangeListToCfiList = function(cfiBase, columns){ Mapping.prototype.rangeListToCfiList = function(cfiBase, columns){
var map = []; var map = [];
var rangePair, cifPair; var rangePair, cifPair;
for (var i = 0; i < columns.length; i++) { for (var i = 0; i < columns.length; i++) {
cifPair = this.rangePairToCfiPair(cfiBase, columns[i]); cifPair = this.rangePairToCfiPair(cfiBase, columns[i]);
map.push(cifPair); map.push(cifPair);
} }
return map; return map;
}; };
module.exports = Mapping; module.exports = Mapping;

View file

@ -4,99 +4,99 @@ var RSVP = require('rsvp');
var URI = require('urijs'); var URI = require('urijs');
function Navigation(_package, _request){ function Navigation(_package, _request){
var navigation = this; var navigation = this;
var parse = new Parser(); var parse = new Parser();
var request = _request || require('./request'); var request = _request || require('./request');
this.package = _package; this.package = _package;
this.toc = []; this.toc = [];
this.tocByHref = {}; this.tocByHref = {};
this.tocById = {}; this.tocById = {};
if(_package.navPath) { if(_package.navPath) {
this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString(); this.navUrl = URI(_package.navPath).absoluteTo(_package.baseUrl).toString();
this.nav = {}; this.nav = {};
this.nav.load = function(_request){ this.nav.load = function(_request){
var loading = new RSVP.defer(); var loading = new RSVP.defer();
var loaded = loading.promise; var loaded = loading.promise;
request(navigation.navUrl, 'xml').then(function(xml){ request(navigation.navUrl, 'xml').then(function(xml){
navigation.toc = parse.nav(xml); navigation.toc = parse.nav(xml);
navigation.loaded(navigation.toc); navigation.loaded(navigation.toc);
loading.resolve(navigation.toc); loading.resolve(navigation.toc);
}); });
return loaded; return loaded;
}; };
} }
if(_package.ncxPath) { if(_package.ncxPath) {
this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString(); this.ncxUrl = URI(_package.ncxPath).absoluteTo(_package.baseUrl).toString();
this.ncx = {}; this.ncx = {};
this.ncx.load = function(_request){ this.ncx.load = function(_request){
var loading = new RSVP.defer(); var loading = new RSVP.defer();
var loaded = loading.promise; var loaded = loading.promise;
request(navigation.ncxUrl, 'xml').then(function(xml){ request(navigation.ncxUrl, 'xml').then(function(xml){
navigation.toc = parse.toc(xml); navigation.toc = parse.toc(xml);
navigation.loaded(navigation.toc); navigation.loaded(navigation.toc);
loading.resolve(navigation.toc); loading.resolve(navigation.toc);
}); });
return loaded; return loaded;
}; };
} }
}; };
// Load the navigation // Load the navigation
Navigation.prototype.load = function(_request) { Navigation.prototype.load = function(_request) {
var request = _request || require('./request'); var request = _request || require('./request');
var loading, loaded; var loading, loaded;
if(this.nav) { if(this.nav) {
loading = this.nav.load(); loading = this.nav.load();
} else if(this.ncx) { } else if(this.ncx) {
loading = this.ncx.load(); loading = this.ncx.load();
} else { } else {
loaded = new RSVP.defer(); loaded = new RSVP.defer();
loaded.resolve([]); loaded.resolve([]);
loading = loaded.promise; loading = loaded.promise;
} }
return loading; return loading;
}; };
Navigation.prototype.loaded = function(toc) { Navigation.prototype.loaded = function(toc) {
var item; var item;
for (var i = 0; i < toc.length; i++) { for (var i = 0; i < toc.length; i++) {
item = toc[i]; item = toc[i];
this.tocByHref[item.href] = i; this.tocByHref[item.href] = i;
this.tocById[item.id] = i; this.tocById[item.id] = i;
} }
}; };
// Get an item from the navigation // Get an item from the navigation
Navigation.prototype.get = function(target) { Navigation.prototype.get = function(target) {
var index; var index;
if(!target) { if(!target) {
return this.toc; return this.toc;
} }
if(target.indexOf("#") === 0) { if(target.indexOf("#") === 0) {
index = this.tocById[target.substring(1)]; index = this.tocById[target.substring(1)];
} else if(target in this.tocByHref){ } else if(target in this.tocByHref){
index = this.tocByHref[target]; index = this.tocByHref[target];
} }
return this.toc[index]; return this.toc[index];
}; };
module.exports = Navigation; module.exports = Navigation;

View file

@ -6,120 +6,120 @@ var EpubCFI = require('./epubcfi');
function Parser(){}; function Parser(){};
Parser.prototype.container = function(containerXml){ Parser.prototype.container = function(containerXml){
//-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/> //-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/>
var rootfile, fullpath, folder, encoding; var rootfile, fullpath, folder, encoding;
if(!containerXml) { if(!containerXml) {
console.error("Container File Not Found"); console.error("Container File Not Found");
return; return;
} }
rootfile = core.qs(containerXml, "rootfile"); rootfile = core.qs(containerXml, "rootfile");
if(!rootfile) { if(!rootfile) {
console.error("No RootFile Found"); console.error("No RootFile Found");
return; return;
} }
fullpath = rootfile.getAttribute('full-path'); fullpath = rootfile.getAttribute('full-path');
folder = URI(fullpath).directory(); folder = URI(fullpath).directory();
encoding = containerXml.xmlEncoding; encoding = containerXml.xmlEncoding;
//-- Now that we have the path we can parse the contents //-- Now that we have the path we can parse the contents
return { return {
'packagePath' : fullpath, 'packagePath' : fullpath,
'basePath' : folder, 'basePath' : folder,
'encoding' : encoding 'encoding' : encoding
}; };
}; };
Parser.prototype.identifier = function(packageXml){ Parser.prototype.identifier = function(packageXml){
var metadataNode; var metadataNode;
if(!packageXml) { if(!packageXml) {
console.error("Package File Not Found"); console.error("Package File Not Found");
return; return;
} }
metadataNode = core.qs(packageXml, "metadata"); metadataNode = core.qs(packageXml, "metadata");
if(!metadataNode) { if(!metadataNode) {
console.error("No Metadata Found"); console.error("No Metadata Found");
return; return;
} }
return this.getElementText(metadataNode, "identifier"); return this.getElementText(metadataNode, "identifier");
}; };
Parser.prototype.packageContents = function(packageXml){ Parser.prototype.packageContents = function(packageXml){
var parse = this; var parse = this;
var metadataNode, manifestNode, spineNode; var metadataNode, manifestNode, spineNode;
var manifest, navPath, ncxPath, coverPath; var manifest, navPath, ncxPath, coverPath;
var spineNodeIndex; var spineNodeIndex;
var spine; var spine;
var spineIndexByURL; var spineIndexByURL;
var metadata; var metadata;
if(!packageXml) { if(!packageXml) {
console.error("Package File Not Found"); console.error("Package File Not Found");
return; return;
} }
metadataNode = core.qs(packageXml, "metadata"); metadataNode = core.qs(packageXml, "metadata");
if(!metadataNode) { if(!metadataNode) {
console.error("No Metadata Found"); console.error("No Metadata Found");
return; return;
} }
manifestNode = core.qs(packageXml, "manifest"); manifestNode = core.qs(packageXml, "manifest");
if(!manifestNode) { if(!manifestNode) {
console.error("No Manifest Found"); console.error("No Manifest Found");
return; return;
} }
spineNode = core.qs(packageXml, "spine"); spineNode = core.qs(packageXml, "spine");
if(!spineNode) { if(!spineNode) {
console.error("No Spine Found"); console.error("No Spine Found");
return; return;
} }
manifest = parse.manifest(manifestNode); manifest = parse.manifest(manifestNode);
navPath = parse.findNavPath(manifestNode); navPath = parse.findNavPath(manifestNode);
ncxPath = parse.findNcxPath(manifestNode, spineNode); ncxPath = parse.findNcxPath(manifestNode, spineNode);
coverPath = parse.findCoverPath(packageXml); coverPath = parse.findCoverPath(packageXml);
spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode); spineNodeIndex = Array.prototype.indexOf.call(spineNode.parentNode.childNodes, spineNode);
spine = parse.spine(spineNode, manifest); spine = parse.spine(spineNode, manifest);
metadata = parse.metadata(metadataNode); metadata = parse.metadata(metadataNode);
metadata.direction = spineNode.getAttribute("page-progression-direction"); metadata.direction = spineNode.getAttribute("page-progression-direction");
return { return {
'metadata' : metadata, 'metadata' : metadata,
'spine' : spine, 'spine' : spine,
'manifest' : manifest, 'manifest' : manifest,
'navPath' : navPath, 'navPath' : navPath,
'ncxPath' : ncxPath, 'ncxPath' : ncxPath,
'coverPath': coverPath, 'coverPath': coverPath,
'spineNodeIndex' : spineNodeIndex 'spineNodeIndex' : spineNodeIndex
}; };
}; };
//-- Find TOC NAV //-- Find TOC NAV
Parser.prototype.findNavPath = function(manifestNode){ Parser.prototype.findNavPath = function(manifestNode){
// Find item with property 'nav' // Find item with property 'nav'
// Should catch nav irregardless of order // Should catch nav irregardless of order
// var node = manifestNode.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']"); // var node = manifestNode.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']");
var node = core.qsp(manifestNode, "item", {"properties":"nav"}); var node = core.qsp(manifestNode, "item", {"properties":"nav"});
return node ? node.getAttribute('href') : false; return node ? node.getAttribute('href') : false;
}; };
//-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx" //-- Find TOC NCX: media-type="application/x-dtbncx+xml" href="toc.ncx"
Parser.prototype.findNcxPath = function(manifestNode, spineNode){ Parser.prototype.findNcxPath = function(manifestNode, spineNode){
// var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']"); // var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
var node = core.qsp(manifestNode, "item", {"media-type":"application/x-dtbncx+xml"}); var node = core.qsp(manifestNode, "item", {"media-type":"application/x-dtbncx+xml"});
var tocId; var tocId;
// If we can't find the toc by media-type then try to look for id of the item in the spine attributes as // If we can't find the toc by media-type then try to look for id of the item in the spine attributes as
@ -129,7 +129,7 @@ Parser.prototype.findNcxPath = function(manifestNode, spineNode){
tocId = spineNode.getAttribute("toc"); tocId = spineNode.getAttribute("toc");
if(tocId) { if(tocId) {
// node = manifestNode.querySelector("item[id='" + tocId + "']"); // node = manifestNode.querySelector("item[id='" + tocId + "']");
node = manifestNode.getElementById(tocId); node = manifestNode.getElementById(tocId);
} }
} }
@ -138,36 +138,36 @@ Parser.prototype.findNcxPath = function(manifestNode, spineNode){
//-- Expanded to match Readium web components //-- Expanded to match Readium web components
Parser.prototype.metadata = function(xml){ Parser.prototype.metadata = function(xml){
var metadata = {}, var metadata = {},
p = this; p = this;
metadata.title = p.getElementText(xml, 'title'); metadata.title = p.getElementText(xml, 'title');
metadata.creator = p.getElementText(xml, 'creator'); metadata.creator = p.getElementText(xml, 'creator');
metadata.description = p.getElementText(xml, 'description'); metadata.description = p.getElementText(xml, 'description');
metadata.pubdate = p.getElementText(xml, 'date'); metadata.pubdate = p.getElementText(xml, 'date');
metadata.publisher = p.getElementText(xml, 'publisher'); metadata.publisher = p.getElementText(xml, 'publisher');
metadata.identifier = p.getElementText(xml, "identifier"); metadata.identifier = p.getElementText(xml, "identifier");
metadata.language = p.getElementText(xml, "language"); metadata.language = p.getElementText(xml, "language");
metadata.rights = p.getElementText(xml, "rights"); metadata.rights = p.getElementText(xml, "rights");
metadata.modified_date = p.getPropertyText(xml, 'dcterms:modified'); metadata.modified_date = p.getPropertyText(xml, 'dcterms:modified');
metadata.layout = p.getPropertyText(xml, "rendition:layout"); metadata.layout = p.getPropertyText(xml, "rendition:layout");
metadata.orientation = p.getPropertyText(xml, 'rendition:orientation'); metadata.orientation = p.getPropertyText(xml, 'rendition:orientation');
metadata.flow = p.getPropertyText(xml, 'rendition:flow'); metadata.flow = p.getPropertyText(xml, 'rendition:flow');
metadata.viewport = p.getPropertyText(xml, 'rendition:viewport'); metadata.viewport = p.getPropertyText(xml, 'rendition:viewport');
// metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction"); // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
return metadata; return metadata;
}; };
//-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" /> //-- Find Cover: <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
//-- Fallback for Epub 2.0 //-- Fallback for Epub 2.0
Parser.prototype.findCoverPath = function(packageXml){ Parser.prototype.findCoverPath = function(packageXml){
var pkg = core.qs(packageXml, "package"); var pkg = core.qs(packageXml, "package");
var epubVersion = pkg.getAttribute('version'); var epubVersion = pkg.getAttribute('version');
if (epubVersion === '2.0') { if (epubVersion === '2.0') {
@ -175,7 +175,7 @@ Parser.prototype.findCoverPath = function(packageXml){
if (metaCover) { if (metaCover) {
var coverId = metaCover.getAttribute('content'); var coverId = metaCover.getAttribute('content');
// var cover = packageXml.querySelector("item[id='" + coverId + "']"); // var cover = packageXml.querySelector("item[id='" + coverId + "']");
var cover = packageXml.getElementById(coverId); var cover = packageXml.getElementById(coverId);
return cover ? cover.getAttribute('href') : false; return cover ? cover.getAttribute('href') : false;
} }
else { else {
@ -183,113 +183,113 @@ Parser.prototype.findCoverPath = function(packageXml){
} }
} }
else { else {
// var node = packageXml.querySelector("item[properties='cover-image']"); // var node = packageXml.querySelector("item[properties='cover-image']");
var node = core.qsp(packageXml, 'item', {'properties':'cover-image'}); var node = core.qsp(packageXml, 'item', {'properties':'cover-image'});
return node ? node.getAttribute('href') : false; return node ? node.getAttribute('href') : false;
} }
}; };
Parser.prototype.getElementText = function(xml, tag){ Parser.prototype.getElementText = function(xml, tag){
var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag), var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag),
el; el;
if(!found || found.length === 0) return ''; if(!found || found.length === 0) return '';
el = found[0]; el = found[0];
if(el.childNodes.length){ if(el.childNodes.length){
return el.childNodes[0].nodeValue; return el.childNodes[0].nodeValue;
} }
return ''; return '';
}; };
Parser.prototype.getPropertyText = function(xml, property){ Parser.prototype.getPropertyText = function(xml, property){
var el = core.qsp(xml, "meta", {"property":property}); var el = core.qsp(xml, "meta", {"property":property});
if(el && el.childNodes.length){ if(el && el.childNodes.length){
return el.childNodes[0].nodeValue; return el.childNodes[0].nodeValue;
} }
return ''; return '';
}; };
Parser.prototype.querySelectorText = function(xml, q){ Parser.prototype.querySelectorText = function(xml, q){
var el = xml.querySelector(q); var el = xml.querySelector(q);
if(el && el.childNodes.length){ if(el && el.childNodes.length){
return el.childNodes[0].nodeValue; return el.childNodes[0].nodeValue;
} }
return ''; return '';
}; };
Parser.prototype.manifest = function(manifestXml){ Parser.prototype.manifest = function(manifestXml){
var manifest = {}; var manifest = {};
//-- Turn items into an array //-- Turn items into an array
// var selected = manifestXml.querySelectorAll("item"); // var selected = manifestXml.querySelectorAll("item");
var selected = core.qsa(manifestXml, "item"); var selected = core.qsa(manifestXml, "item");
var items = Array.prototype.slice.call(selected); var items = Array.prototype.slice.call(selected);
//-- Create an object with the id as key //-- Create an object with the id as key
items.forEach(function(item){ items.forEach(function(item){
var id = item.getAttribute('id'), var id = item.getAttribute('id'),
href = item.getAttribute('href') || '', href = item.getAttribute('href') || '',
type = item.getAttribute('media-type') || '', type = item.getAttribute('media-type') || '',
properties = item.getAttribute('properties') || ''; properties = item.getAttribute('properties') || '';
manifest[id] = { manifest[id] = {
'href' : href, 'href' : href,
// 'url' : href, // 'url' : href,
'type' : type, 'type' : type,
'properties' : properties.length ? properties.split(' ') : [] 'properties' : properties.length ? properties.split(' ') : []
}; };
}); });
return manifest; return manifest;
}; };
Parser.prototype.spine = function(spineXml, manifest){ Parser.prototype.spine = function(spineXml, manifest){
var spine = []; var spine = [];
var selected = spineXml.getElementsByTagName("itemref"), var selected = spineXml.getElementsByTagName("itemref"),
items = Array.prototype.slice.call(selected); items = Array.prototype.slice.call(selected);
var epubcfi = new EpubCFI(); var epubcfi = new EpubCFI();
//-- Add to array to mantain ordering and cross reference with manifest //-- Add to array to mantain ordering and cross reference with manifest
items.forEach(function(item, index){ items.forEach(function(item, index){
var idref = item.getAttribute('idref'); var idref = item.getAttribute('idref');
// var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id); // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);
var props = item.getAttribute('properties') || ''; var props = item.getAttribute('properties') || '';
var propArray = props.length ? props.split(' ') : []; var propArray = props.length ? props.split(' ') : [];
// var manifestProps = manifest[Id].properties; // var manifestProps = manifest[Id].properties;
// var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : []; // var manifestPropArray = manifestProps.length ? manifestProps.split(' ') : [];
var itemref = { var itemref = {
'idref' : idref, 'idref' : idref,
'linear' : item.getAttribute('linear') || '', 'linear' : item.getAttribute('linear') || '',
'properties' : propArray, 'properties' : propArray,
// 'href' : manifest[Id].href, // 'href' : manifest[Id].href,
// 'url' : manifest[Id].url, // 'url' : manifest[Id].url,
'index' : index 'index' : index
// 'cfiBase' : cfiBase // 'cfiBase' : cfiBase
}; };
spine.push(itemref); spine.push(itemref);
}); });
return spine; return spine;
}; };
Parser.prototype.querySelectorByType = function(html, element, type){ Parser.prototype.querySelectorByType = function(html, element, type){
var query; var query;
if (typeof html.querySelector != "undefined") { if (typeof html.querySelector != "undefined") {
query = html.querySelector(element+'[*|type="'+type+'"]'); query = html.querySelector(element+'[*|type="'+type+'"]');
} }
// Handle IE not supporting namespaced epub:type in querySelector // Handle IE not supporting namespaced epub:type in querySelector
if(!query || query.length === 0) { if(!query || query.length === 0) {
query = core.qsa(html, element); query = core.qsa(html, element);
@ -305,7 +305,7 @@ Parser.prototype.querySelectorByType = function(html, element, type){
Parser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){ Parser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){
var navElement = this.querySelectorByType(navHtml, "nav", "toc"); var navElement = this.querySelectorByType(navHtml, "nav", "toc");
// var navItems = navElement ? navElement.querySelectorAll("ol li") : []; // var navItems = navElement ? navElement.querySelectorAll("ol li") : [];
var navItems = navElement ? core.qsa(navElement, "li") : []; var navItems = navElement ? core.qsa(navElement, "li") : [];
var length = navItems.length; var length = navItems.length;
var i; var i;
@ -332,7 +332,7 @@ Parser.prototype.nav = function(navHtml, spineIndexByURL, bookSpine){
Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){ Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){
var id = item.getAttribute('id') || false, var id = item.getAttribute('id') || false,
// content = item.querySelector("a, span"), // content = item.querySelector("a, span"),
content = core.qs(item, "a"), content = core.qs(item, "a"),
src = content.getAttribute('href') || '', src = content.getAttribute('href') || '',
text = content.textContent || "", text = content.textContent || "",
// split = src.split("#"), // split = src.split("#"),
@ -348,7 +348,7 @@ Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){
parent = parentNode.getAttribute('id'); parent = parentNode.getAttribute('id');
} }
/* /*
if(!id) { if(!id) {
if(spinePos) { if(spinePos) {
spineItem = bookSpine[spinePos]; spineItem = bookSpine[spinePos];
@ -359,7 +359,7 @@ Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){
item.setAttribute('id', id); item.setAttribute('id', id);
} }
} }
*/ */
return { return {
"id": id, "id": id,
@ -372,7 +372,7 @@ Parser.prototype.navItem = function(item, spineIndexByURL, bookSpine){
Parser.prototype.ncx = function(tocXml, spineIndexByURL, bookSpine){ Parser.prototype.ncx = function(tocXml, spineIndexByURL, bookSpine){
// var navPoints = tocXml.querySelectorAll("navMap navPoint"); // var navPoints = tocXml.querySelectorAll("navMap navPoint");
var navPoints = core.qsa(tocXml, "navPoint"); var navPoints = core.qsa(tocXml, "navPoint");
var length = navPoints.length; var length = navPoints.length;
var i; var i;
var toc = {}; var toc = {};
@ -400,8 +400,8 @@ Parser.prototype.ncxItem = function(item, spineIndexByURL, bookSpine){
// content = item.querySelector("content"), // content = item.querySelector("content"),
content = core.qs(item, "content"), content = core.qs(item, "content"),
src = content.getAttribute('src'), src = content.getAttribute('src'),
// navLabel = item.querySelector("navLabel"), // navLabel = item.querySelector("navLabel"),
navLabel = core.qs(item, "navLabel"), navLabel = core.qs(item, "navLabel"),
text = navLabel.textContent ? navLabel.textContent : "", text = navLabel.textContent ? navLabel.textContent : "",
// split = src.split("#"), // split = src.split("#"),
// baseUrl = split[0], // baseUrl = split[0],
@ -416,7 +416,7 @@ Parser.prototype.ncxItem = function(item, spineIndexByURL, bookSpine){
parent = parentNode.getAttribute('id'); parent = parentNode.getAttribute('id');
} }
/* /*
if(!id) { if(!id) {
if(spinePos) { if(spinePos) {
spineItem = bookSpine[spinePos]; spineItem = bookSpine[spinePos];
@ -427,7 +427,7 @@ Parser.prototype.ncxItem = function(item, spineIndexByURL, bookSpine){
item.setAttribute('id', id); item.setAttribute('id', id);
} }
} }
*/ */
return { return {
"id": id, "id": id,
@ -440,7 +440,7 @@ Parser.prototype.ncxItem = function(item, spineIndexByURL, bookSpine){
Parser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){ Parser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){
var navElement = this.querySelectorByType(navHtml, "nav", "page-list"); var navElement = this.querySelectorByType(navHtml, "nav", "page-list");
// var navItems = navElement ? navElement.querySelectorAll("ol li") : []; // var navItems = navElement ? navElement.querySelectorAll("ol li") : [];
var navItems = navElement ? core.qsa(navElement, "li") : []; var navItems = navElement ? core.qsa(navElement, "li") : [];
var length = navItems.length; var length = navItems.length;
var i; var i;
@ -461,7 +461,7 @@ Parser.prototype.pageList = function(navHtml, spineIndexByURL, bookSpine){
Parser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){ Parser.prototype.pageListItem = function(item, spineIndexByURL, bookSpine){
var id = item.getAttribute('id') || false, var id = item.getAttribute('id') || false,
// content = item.querySelector("a"), // content = item.querySelector("a"),
content = core.qs(item, "a"), content = core.qs(item, "a"),
href = content.getAttribute('href') || '', href = content.getAttribute('href') || '',
text = content.textContent || "", text = content.textContent || "",
page = parseInt(text), page = parseInt(text),

View file

@ -2,191 +2,191 @@ var RSVP = require('rsvp');
var core = require('./core'); var core = require('./core');
function Queue(_context){ function Queue(_context){
this._q = []; this._q = [];
this.context = _context; this.context = _context;
this.tick = core.requestAnimationFrame; this.tick = core.requestAnimationFrame;
this.running = false; this.running = false;
this.paused = false; this.paused = false;
}; };
// Add an item to the queue // Add an item to the queue
Queue.prototype.enqueue = function() { Queue.prototype.enqueue = function() {
var deferred, promise; var deferred, promise;
var queued; var queued;
var task = [].shift.call(arguments); var task = [].shift.call(arguments);
var args = arguments; var args = arguments;
// Handle single args without context // Handle single args without context
// if(args && !Array.isArray(args)) { // if(args && !Array.isArray(args)) {
// args = [args]; // args = [args];
// } // }
if(!task) { if(!task) {
return console.error("No Task Provided"); return console.error("No Task Provided");
} }
if(typeof task === "function"){ if(typeof task === "function"){
deferred = new RSVP.defer(); deferred = new RSVP.defer();
promise = deferred.promise; promise = deferred.promise;
queued = { queued = {
"task" : task, "task" : task,
"args" : args, "args" : args,
//"context" : context, //"context" : context,
"deferred" : deferred, "deferred" : deferred,
"promise" : promise "promise" : promise
}; };
} else { } else {
// Task is a promise // Task is a promise
queued = { queued = {
"promise" : task "promise" : task
}; };
} }
this._q.push(queued); this._q.push(queued);
// Wait to start queue flush // Wait to start queue flush
if (this.paused == false && !this.running) { if (this.paused == false && !this.running) {
// setTimeout(this.flush.bind(this), 0); // setTimeout(this.flush.bind(this), 0);
// this.tick.call(window, this.run.bind(this)); // this.tick.call(window, this.run.bind(this));
this.run(); this.run();
} }
return queued.promise; return queued.promise;
}; };
// Run one item // Run one item
Queue.prototype.dequeue = function(){ Queue.prototype.dequeue = function(){
var inwait, task, result; var inwait, task, result;
if(this._q.length) { if(this._q.length) {
inwait = this._q.shift(); inwait = this._q.shift();
task = inwait.task; task = inwait.task;
if(task){ if(task){
// console.log(task) // console.log(task)
result = task.apply(this.context, inwait.args); result = task.apply(this.context, inwait.args);
if(result && typeof result["then"] === "function") { if(result && typeof result["then"] === "function") {
// Task is a function that returns a promise // Task is a function that returns a promise
return result.then(function(){ return result.then(function(){
inwait.deferred.resolve.apply(this.context, arguments); inwait.deferred.resolve.apply(this.context, arguments);
}.bind(this)); }.bind(this));
} else { } else {
// Task resolves immediately // Task resolves immediately
inwait.deferred.resolve.apply(this.context, result); inwait.deferred.resolve.apply(this.context, result);
return inwait.promise; return inwait.promise;
} }
} else if(inwait.promise) { } else if(inwait.promise) {
// Task is a promise // Task is a promise
return inwait.promise; return inwait.promise;
} }
} else { } else {
inwait = new RSVP.defer(); inwait = new RSVP.defer();
inwait.deferred.resolve(); inwait.deferred.resolve();
return inwait.promise; return inwait.promise;
} }
}; };
// Run All Immediately // Run All Immediately
Queue.prototype.dump = function(){ Queue.prototype.dump = function(){
while(this._q.length) { while(this._q.length) {
this.dequeue(); this.dequeue();
} }
}; };
// Run all sequentially, at convince // Run all sequentially, at convince
Queue.prototype.run = function(){ Queue.prototype.run = function(){
if(!this.running){ if(!this.running){
this.running = true; this.running = true;
this.defered = new RSVP.defer(); this.defered = new RSVP.defer();
} }
this.tick.call(window, function() { this.tick.call(window, function() {
if(this._q.length) { if(this._q.length) {
this.dequeue() this.dequeue()
.then(function(){ .then(function(){
this.run(); this.run();
}.bind(this)); }.bind(this));
} else { } else {
this.defered.resolve(); this.defered.resolve();
this.running = undefined; this.running = undefined;
} }
}.bind(this)); }.bind(this));
// Unpause // Unpause
if(this.paused == true) { if(this.paused == true) {
this.paused = false; this.paused = false;
} }
return this.defered.promise; return this.defered.promise;
}; };
// Flush all, as quickly as possible // Flush all, as quickly as possible
Queue.prototype.flush = function(){ Queue.prototype.flush = function(){
if(this.running){ if(this.running){
return this.running; return this.running;
} }
if(this._q.length) { if(this._q.length) {
this.running = this.dequeue() this.running = this.dequeue()
.then(function(){ .then(function(){
this.running = undefined; this.running = undefined;
return this.flush(); return this.flush();
}.bind(this)); }.bind(this));
return this.running; return this.running;
} }
}; };
// Clear all items in wait // Clear all items in wait
Queue.prototype.clear = function(){ Queue.prototype.clear = function(){
this._q = []; this._q = [];
this.running = false; this.running = false;
}; };
Queue.prototype.length = function(){ Queue.prototype.length = function(){
return this._q.length; return this._q.length;
}; };
Queue.prototype.pause = function(){ Queue.prototype.pause = function(){
this.paused = true; this.paused = true;
}; };
// Create a new task from a callback // Create a new task from a callback
function Task(task, args, context){ function Task(task, args, context){
return function(){ return function(){
var toApply = arguments || []; var toApply = arguments || [];
return new RSVP.Promise(function(resolve, reject) { return new RSVP.Promise(function(resolve, reject) {
var callback = function(value){ var callback = function(value){
resolve(value); resolve(value);
}; };
// Add the callback to the arguments list // Add the callback to the arguments list
toApply.push(callback); toApply.push(callback);
// Apply all arguments to the functions // Apply all arguments to the functions
task.apply(this, toApply); task.apply(this, toApply);
}.bind(this)); }.bind(this));
}; };
}; };

View file

@ -49,7 +49,7 @@ function Rendition(book, options) {
// this.hooks.display.register(this.afterDisplay.bind(this)); // this.hooks.display.register(this.afterDisplay.bind(this));
this.epubcfi = new EpubCFI(); this.epubcfi = new EpubCFI();
this.q = new Queue(this); this.q = new Queue(this);
@ -83,7 +83,7 @@ Rendition.prototype.requireManager = function(manager) {
viewManager = manager viewManager = manager
} }
return viewManager; return viewManager;
}; };
Rendition.prototype.requireView = function(view) { Rendition.prototype.requireView = function(view) {
@ -96,7 +96,7 @@ Rendition.prototype.requireView = function(view) {
View = view View = view
} }
return View; return View;
}; };
Rendition.prototype.start = function(){ Rendition.prototype.start = function(){
@ -362,24 +362,24 @@ Rendition.prototype.spread = function(spread, min){
Rendition.prototype.reportLocation = function(){ Rendition.prototype.reportLocation = function(){
return this.q.enqueue(function(){ return this.q.enqueue(function(){
var location = this.manager.currentLocation(); var location = this.manager.currentLocation();
if (location && location.then && typeof location.then === 'function') { if (location && location.then && typeof location.then === 'function') {
location.then(function(result) { location.then(function(result) {
this.location = result; this.location = result;
this.trigger("locationChanged", this.location); this.trigger("locationChanged", this.location);
}.bind(this)); }.bind(this));
} else if (location) { } else if (location) {
this.location = location; this.location = location;
this.trigger("locationChanged", this.location); this.trigger("locationChanged", this.location);
} }
}.bind(this)); }.bind(this));
}; };
Rendition.prototype.destroy = function(){ Rendition.prototype.destroy = function(){
// Clear the queue // Clear the queue
this.q.clear(); this.q.clear();
this.views.clear(); this.views.clear();
@ -394,7 +394,7 @@ Rendition.prototype.destroy = function(){
}; };
Rendition.prototype.passViewEvents = function(view){ Rendition.prototype.passViewEvents = function(view){
view.contents.listenedEvents.forEach(function(e){ view.contents.listenedEvents.forEach(function(e){
view.on(e, this.triggerViewEvent.bind(this)); view.on(e, this.triggerViewEvent.bind(this));
}.bind(this)); }.bind(this));
@ -402,11 +402,11 @@ Rendition.prototype.passViewEvents = function(view){
}; };
Rendition.prototype.triggerViewEvent = function(e){ Rendition.prototype.triggerViewEvent = function(e){
this.trigger(e.type, e); this.trigger(e.type, e);
}; };
Rendition.prototype.triggerSelectedEvent = function(cfirange){ Rendition.prototype.triggerSelectedEvent = function(cfirange){
this.trigger("selected", cfirange); this.trigger("selected", cfirange);
}; };
Rendition.prototype.replacements = function(){ Rendition.prototype.replacements = function(){
@ -414,27 +414,27 @@ Rendition.prototype.replacements = function(){
// return this.q.enqueue(function () { // return this.q.enqueue(function () {
// Get thes books manifest // Get thes books manifest
var manifest = this.book.package.manifest; var manifest = this.book.package.manifest;
var manifestArray = Object.keys(manifest). var manifestArray = Object.keys(manifest).
map(function (key){ map(function (key){
return manifest[key]; return manifest[key];
}); });
// Exclude HTML // Exclude HTML
var items = manifestArray. var items = manifestArray.
filter(function (item){ filter(function (item){
if (item.type != "application/xhtml+xml" && if (item.type != "application/xhtml+xml" &&
item.type != "text/html") { item.type != "text/html") {
return true; return true;
} }
}); });
// Only CSS // Only CSS
var css = items. var css = items.
filter(function (item){ filter(function (item){
if (item.type === "text/css") { if (item.type === "text/css") {
return true; return true;
} }
}); });
// Css Urls // Css Urls
var cssUrls = css.map(function(item) { var cssUrls = css.map(function(item) {
@ -442,18 +442,18 @@ Rendition.prototype.replacements = function(){
}); });
// All Assets Urls // All Assets Urls
var urls = items. var urls = items.
map(function(item) { map(function(item) {
return item.href; return item.href;
}.bind(this)); }.bind(this));
// Create blob urls for all the assets // Create blob urls for all the assets
var processing = urls. var processing = urls.
map(function(url) { map(function(url) {
var absolute = URI(url).absoluteTo(this.book.baseUrl).toString(); var absolute = URI(url).absoluteTo(this.book.baseUrl).toString();
// Full url from archive base // Full url from archive base
return this.book.unarchived.createUrl(absolute, {"base64": this.settings.useBase64}); return this.book.unarchived.createUrl(absolute, {"base64": this.settings.useBase64});
}.bind(this)); }.bind(this));
var replacementUrls; var replacementUrls;
@ -467,11 +467,11 @@ Rendition.prototype.replacements = function(){
// Replace Asset Urls in the text of all css files // Replace Asset Urls in the text of all css files
cssUrls.forEach(function(href) { cssUrls.forEach(function(href) {
replaced.push(this.replaceCss(href, urls, replacementUrls)); replaced.push(this.replaceCss(href, urls, replacementUrls));
}.bind(this)); }.bind(this));
return RSVP.all(replaced); return RSVP.all(replaced);
}.bind(this)) }.bind(this))
.then(function () { .then(function () {
// Replace Asset Urls in chapters // Replace Asset Urls in chapters
// by registering a hook after the sections contents has been serialized // by registering a hook after the sections contents has been serialized
@ -483,8 +483,8 @@ Rendition.prototype.replacements = function(){
}.bind(this)) }.bind(this))
.catch(function(reason){ .catch(function(reason){
console.error(reason); console.error(reason);
}); });
// }.bind(this)); // }.bind(this));
}; };
@ -545,31 +545,31 @@ Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){
}; };
Rendition.prototype.range = function(_cfi, ignoreClass){ Rendition.prototype.range = function(_cfi, ignoreClass){
var cfi = new EpubCFI(_cfi); var cfi = new EpubCFI(_cfi);
var found = this.visible().filter(function (view) { var found = this.visible().filter(function (view) {
if(cfi.spinePos === view.index) return true; if(cfi.spinePos === view.index) return true;
}); });
// Should only every return 1 item // Should only every return 1 item
if (found.length) { if (found.length) {
return found[0].range(cfi, ignoreClass); return found[0].range(cfi, ignoreClass);
} }
}; };
Rendition.prototype.adjustImages = function(view) { Rendition.prototype.adjustImages = function(view) {
view.addStylesheetRules([ view.addStylesheetRules([
["img", ["img",
["max-width", (view.layout.spreadWidth) + "px"], ["max-width", (view.layout.spreadWidth) + "px"],
["max-height", (view.layout.height) + "px"] ["max-height", (view.layout.height) + "px"]
] ]
]); ]);
return new RSVP.Promise(function(resolve, reject){ return new RSVP.Promise(function(resolve, reject){
// Wait to apply // Wait to apply
setTimeout(function() { setTimeout(function() {
resolve(); resolve();
}, 1); }, 1);
}); });
}; };
//-- Enable binding events to Renderer //-- Enable binding events to Renderer

View file

@ -2,69 +2,69 @@ var URI = require('urijs');
var core = require('./core'); var core = require('./core');
function base(doc, section){ function base(doc, section){
var base; var base;
var head; var head;
if(!doc){ if(!doc){
return; return;
} }
// head = doc.querySelector("head"); // head = doc.querySelector("head");
// base = head.querySelector("base"); // base = head.querySelector("base");
head = core.qs(doc, "head"); head = core.qs(doc, "head");
base = core.qs(head, "base"); base = core.qs(head, "base");
if(!base) { if(!base) {
base = doc.createElement("base"); base = doc.createElement("base");
head.insertBefore(base, head.firstChild); head.insertBefore(base, head.firstChild);
} }
base.setAttribute("href", section.url); base.setAttribute("href", section.url);
} }
function canonical(doc, section){ function canonical(doc, section){
var head; var head;
var link; var link;
var url = section.url; // window.location.origin + window.location.pathname + "?loc=" + encodeURIComponent(section.url); var url = section.url; // window.location.origin + window.location.pathname + "?loc=" + encodeURIComponent(section.url);
if(!doc){ if(!doc){
return; return;
} }
head = core.qs(doc, "head"); head = core.qs(doc, "head");
link = core.qs(head, "link[rel='canonical']"); link = core.qs(head, "link[rel='canonical']");
if (link) { if (link) {
link.setAttribute("href", url); link.setAttribute("href", url);
} else { } else {
link = doc.createElement("link"); link = doc.createElement("link");
link.setAttribute("rel", "canonical"); link.setAttribute("rel", "canonical");
link.setAttribute("href", url); link.setAttribute("href", url);
head.appendChild(link); head.appendChild(link);
} }
} }
function links(view, renderer) { function links(view, renderer) {
var links = view.document.querySelectorAll("a[href]"); var links = view.document.querySelectorAll("a[href]");
var replaceLinks = function(link){ var replaceLinks = function(link){
var href = link.getAttribute("href"); var href = link.getAttribute("href");
if(href.indexOf("mailto:") === 0){ if(href.indexOf("mailto:") === 0){
return; return;
} }
var linkUri = URI(href); var linkUri = URI(href);
var absolute = linkUri.absoluteTo(view.section.url); var absolute = linkUri.absoluteTo(view.section.url);
var relative = absolute.relativeTo(this.book.baseUrl).toString(); var relative = absolute.relativeTo(this.book.baseUrl).toString();
if(linkUri.protocol()){ if(linkUri.protocol()){
link.setAttribute("target", "_blank"); link.setAttribute("target", "_blank");
}else{ }else{
/* /*
if(baseDirectory) { if(baseDirectory) {
// We must ensure that the file:// protocol is preserved for // We must ensure that the file:// protocol is preserved for
// local file links, as in certain contexts (such as under // local file links, as in certain contexts (such as under
// Titanium), file links without the file:// protocol will not // Titanium), file links without the file:// protocol will not
@ -77,38 +77,38 @@ function links(view, renderer) {
} else { } else {
relative = href; relative = href;
} }
*/ */
if(linkUri.fragment()) { if(linkUri.fragment()) {
// do nothing with fragment yet // do nothing with fragment yet
} else { } else {
link.onclick = function(){ link.onclick = function(){
renderer.display(relative); renderer.display(relative);
return false; return false;
}; };
} }
} }
}.bind(this); }.bind(this);
for (var i = 0; i < links.length; i++) { for (var i = 0; i < links.length; i++) {
replaceLinks(links[i]); replaceLinks(links[i]);
} }
}; };
function substitute(content, urls, replacements) { function substitute(content, urls, replacements) {
urls.forEach(function(url, i){ urls.forEach(function(url, i){
if (url && replacements[i]) { if (url && replacements[i]) {
content = content.replace(new RegExp(url, 'g'), replacements[i]); content = content.replace(new RegExp(url, 'g'), replacements[i]);
} }
}); });
return content; return content;
} }
module.exports = { module.exports = {
'base': base, 'base': base,
'canonical' : canonical, 'canonical' : canonical,
'links': links, 'links': links,
'substitute': substitute 'substitute': substitute
}; };

View file

@ -3,55 +3,55 @@ var URI = require('urijs');
var core = require('./core'); var core = require('./core');
function request(url, type, withCredentials, headers) { function request(url, type, withCredentials, headers) {
var supportsURL = (typeof window != "undefined") ? window.URL : false; // TODO: fallback for url if window isn't defined var supportsURL = (typeof window != "undefined") ? window.URL : false; // TODO: fallback for url if window isn't defined
var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer"; var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer";
var uri; var uri;
var deferred = new RSVP.defer(); var deferred = new RSVP.defer();
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
//-- Check from PDF.js: //-- Check from PDF.js:
// https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js
var xhrPrototype = XMLHttpRequest.prototype; var xhrPrototype = XMLHttpRequest.prototype;
var header; var header;
if (!('overrideMimeType' in xhrPrototype)) { if (!('overrideMimeType' in xhrPrototype)) {
// IE10 might have response, but not overrideMimeType // IE10 might have response, but not overrideMimeType
Object.defineProperty(xhrPrototype, 'overrideMimeType', { Object.defineProperty(xhrPrototype, 'overrideMimeType', {
value: function xmlHttpRequestOverrideMimeType(mimeType) {} value: function xmlHttpRequestOverrideMimeType(mimeType) {}
}); });
} }
if(withCredentials) { if(withCredentials) {
xhr.withCredentials = true; xhr.withCredentials = true;
} }
xhr.onreadystatechange = handler; xhr.onreadystatechange = handler;
xhr.onerror = err; xhr.onerror = err;
xhr.open("GET", url, true); xhr.open("GET", url, true);
for(header in headers) { for(header in headers) {
xhr.setRequestHeader(header, headers[header]); xhr.setRequestHeader(header, headers[header]);
} }
if(type == "json") { if(type == "json") {
xhr.setRequestHeader("Accept", "application/json"); xhr.setRequestHeader("Accept", "application/json");
} }
// If type isn't set, determine it from the file extension // If type isn't set, determine it from the file extension
if(!type) { if(!type) {
uri = URI(url); uri = URI(url);
type = uri.suffix(); type = uri.suffix();
} }
if(type == 'blob'){ if(type == 'blob'){
xhr.responseType = BLOB_RESPONSE; xhr.responseType = BLOB_RESPONSE;
} }
if(core.isXml(type)) { if(core.isXml(type)) {
// xhr.responseType = "document"; // xhr.responseType = "document";
xhr.overrideMimeType('text/xml'); // for OPF parsing xhr.overrideMimeType('text/xml'); // for OPF parsing
} }
@ -62,89 +62,89 @@ function request(url, type, withCredentials, headers) {
if(type == 'html' || type == 'htm') { if(type == 'html' || type == 'htm') {
// xhr.responseType = "document"; // xhr.responseType = "document";
} }
if(type == "binary") { if(type == "binary") {
xhr.responseType = "arraybuffer"; xhr.responseType = "arraybuffer";
} }
xhr.send(); xhr.send();
function err(e) { function err(e) {
console.error(e); console.error(e);
deferred.reject(e); deferred.reject(e);
} }
function handler() { function handler() {
if (this.readyState === XMLHttpRequest.DONE) { if (this.readyState === XMLHttpRequest.DONE) {
if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls if (this.status === 200 || this.responseXML ) { //-- Firefox is reporting 0 for blob urls
var r; var r;
if (!this.response && !this.responseXML) { if (!this.response && !this.responseXML) {
deferred.reject({ deferred.reject({
status: this.status, status: this.status,
message : "Empty Response", message : "Empty Response",
stack : new Error().stack stack : new Error().stack
}); });
return deferred.promise; return deferred.promise;
} }
if (this.status === 403) { if (this.status === 403) {
deferred.reject({ deferred.reject({
status: this.status, status: this.status,
response: this.response, response: this.response,
message : "Forbidden", message : "Forbidden",
stack : new Error().stack stack : new Error().stack
}); });
return deferred.promise; return deferred.promise;
} }
if((this.responseType == '' || this.responseType == 'document') if((this.responseType == '' || this.responseType == 'document')
&& this.responseXML){ && this.responseXML){
r = this.responseXML; r = this.responseXML;
} else } else
if(core.isXml(type)){ if(core.isXml(type)){
// xhr.overrideMimeType('text/xml'); // for OPF parsing // xhr.overrideMimeType('text/xml'); // for OPF parsing
// If this.responseXML wasn't set, try to parse using a DOMParser from text // If this.responseXML wasn't set, try to parse using a DOMParser from text
r = core.parse(this.response, "text/xml"); r = core.parse(this.response, "text/xml");
}else }else
if(type == 'xhtml'){ if(type == 'xhtml'){
r = core.parse(this.response, "application/xhtml+xml"); r = core.parse(this.response, "application/xhtml+xml");
}else }else
if(type == 'html' || type == 'htm'){ if(type == 'html' || type == 'htm'){
r = core.parse(this.response, "text/html"); r = core.parse(this.response, "text/html");
}else }else
if(type == 'json'){ if(type == 'json'){
r = JSON.parse(this.response); r = JSON.parse(this.response);
}else }else
if(type == 'blob'){ if(type == 'blob'){
if(supportsURL) { if(supportsURL) {
r = this.response; r = this.response;
} else { } else {
//-- Safari doesn't support responseType blob, so create a blob from arraybuffer //-- Safari doesn't support responseType blob, so create a blob from arraybuffer
r = new Blob([this.response]); r = new Blob([this.response]);
} }
}else{ }else{
r = this.response; r = this.response;
} }
deferred.resolve(r); deferred.resolve(r);
} else { } else {
deferred.reject({ deferred.reject({
status: this.status, status: this.status,
message : this.response, message : this.response,
stack : new Error().stack stack : new Error().stack
}); });
} }
} }
} }
return deferred.promise; return deferred.promise;
}; };
module.exports = request; module.exports = request;

View file

@ -5,110 +5,110 @@ var EpubCFI = require('./epubcfi');
var Hook = require('./hook'); var Hook = require('./hook');
function Section(item, hooks){ function Section(item, hooks){
this.idref = item.idref; this.idref = item.idref;
this.linear = item.linear; this.linear = item.linear;
this.properties = item.properties; this.properties = item.properties;
this.index = item.index; this.index = item.index;
this.href = item.href; this.href = item.href;
this.url = item.url; this.url = item.url;
this.next = item.next; this.next = item.next;
this.prev = item.prev; this.prev = item.prev;
this.cfiBase = item.cfiBase; this.cfiBase = item.cfiBase;
if (hooks) { if (hooks) {
this.hooks = hooks; this.hooks = hooks;
} else { } else {
this.hooks = {}; this.hooks = {};
this.hooks.serialize = new Hook(this); this.hooks.serialize = new Hook(this);
this.hooks.content = new Hook(this); this.hooks.content = new Hook(this);
} }
}; };
Section.prototype.load = function(_request){ Section.prototype.load = function(_request){
var request = _request || this.request || require('./request'); var request = _request || this.request || require('./request');
var loading = new RSVP.defer(); var loading = new RSVP.defer();
var loaded = loading.promise; var loaded = loading.promise;
if(this.contents) { if(this.contents) {
loading.resolve(this.contents); loading.resolve(this.contents);
} else { } else {
request(this.url) request(this.url)
.then(function(xml){ .then(function(xml){
var base; var base;
var directory = URI(this.url).directory(); var directory = URI(this.url).directory();
this.document = xml; this.document = xml;
this.contents = xml.documentElement; this.contents = xml.documentElement;
return this.hooks.content.trigger(this.document, this); return this.hooks.content.trigger(this.document, this);
}.bind(this)) }.bind(this))
.then(function(){ .then(function(){
loading.resolve(this.contents); loading.resolve(this.contents);
}.bind(this)) }.bind(this))
.catch(function(error){ .catch(function(error){
loading.reject(error); loading.reject(error);
}); });
} }
return loaded; return loaded;
}; };
Section.prototype.base = function(_document){ Section.prototype.base = function(_document){
var task = new RSVP.defer(); var task = new RSVP.defer();
var base = _document.createElement("base"); // TODO: check if exists var base = _document.createElement("base"); // TODO: check if exists
var head; var head;
console.log(window.location.origin + "/" +this.url); console.log(window.location.origin + "/" +this.url);
base.setAttribute("href", window.location.origin + "/" +this.url); base.setAttribute("href", window.location.origin + "/" +this.url);
if(_document) { if(_document) {
head = _document.querySelector("head"); head = _document.querySelector("head");
} }
if(head) { if(head) {
head.insertBefore(base, head.firstChild); head.insertBefore(base, head.firstChild);
task.resolve(); task.resolve();
} else { } else {
task.reject(new Error("No head to insert into")); task.reject(new Error("No head to insert into"));
} }
return task.promise; return task.promise;
}; };
Section.prototype.beforeSectionLoad = function(){ Section.prototype.beforeSectionLoad = function(){
// Stub for a hook - replace me for now // Stub for a hook - replace me for now
}; };
Section.prototype.render = function(_request){ Section.prototype.render = function(_request){
var rendering = new RSVP.defer(); var rendering = new RSVP.defer();
var rendered = rendering.promise; var rendered = rendering.promise;
this.output; // TODO: better way to return this from hooks? this.output; // TODO: better way to return this from hooks?
this.load(_request). this.load(_request).
then(function(contents){ then(function(contents){
var serializer; var serializer;
if (typeof XMLSerializer === "undefined") { if (typeof XMLSerializer === "undefined") {
XMLSerializer = require('xmldom').XMLSerializer; XMLSerializer = require('xmldom').XMLSerializer;
} }
serializer = new XMLSerializer(); serializer = new XMLSerializer();
this.output = serializer.serializeToString(contents); this.output = serializer.serializeToString(contents);
return this.output; return this.output;
}.bind(this)). }.bind(this)).
then(function(){ then(function(){
return this.hooks.serialize.trigger(this.output, this); return this.hooks.serialize.trigger(this.output, this);
}.bind(this)). }.bind(this)).
then(function(){ then(function(){
rendering.resolve(this.output); rendering.resolve(this.output);
}.bind(this)) }.bind(this))
.catch(function(error){ .catch(function(error){
rendering.reject(error); rendering.reject(error);
}); });
return rendered; return rendered;
}; };
Section.prototype.find = function(_query){ Section.prototype.find = function(_query){
@ -122,35 +122,35 @@ Section.prototype.find = function(_query){
* Returns: Object with layout properties * Returns: Object with layout properties
*/ */
Section.prototype.reconcileLayoutSettings = function(global){ Section.prototype.reconcileLayoutSettings = function(global){
//-- Get the global defaults //-- Get the global defaults
var settings = { var settings = {
layout : global.layout, layout : global.layout,
spread : global.spread, spread : global.spread,
orientation : global.orientation orientation : global.orientation
}; };
//-- Get the chapter's display type //-- Get the chapter's display type
this.properties.forEach(function(prop){ this.properties.forEach(function(prop){
var rendition = prop.replace("rendition:", ''); var rendition = prop.replace("rendition:", '');
var split = rendition.indexOf("-"); var split = rendition.indexOf("-");
var property, value; var property, value;
if(split != -1){ if(split != -1){
property = rendition.slice(0, split); property = rendition.slice(0, split);
value = rendition.slice(split+1); value = rendition.slice(split+1);
settings[property] = value; settings[property] = value;
} }
}); });
return settings; return settings;
}; };
Section.prototype.cfiFromRange = function(_range) { Section.prototype.cfiFromRange = function(_range) {
return new EpubCFI(_range, this.cfiBase).toString(); return new EpubCFI(_range, this.cfiBase).toString();
}; };
Section.prototype.cfiFromElement = function(el) { Section.prototype.cfiFromElement = function(el) {
return new EpubCFI(el, this.cfiBase).toString(); return new EpubCFI(el, this.cfiBase).toString();
}; };
module.exports = Section; module.exports = Section;

View file

@ -6,64 +6,64 @@ var Section = require('./section');
var replacements = require('./replacements'); var replacements = require('./replacements');
function Spine(_request){ function Spine(_request){
this.request = _request; this.request = _request;
this.spineItems = []; this.spineItems = [];
this.spineByHref = {}; this.spineByHref = {};
this.spineById = {}; this.spineById = {};
this.hooks = {}; this.hooks = {};
this.hooks.serialize = new Hook(); this.hooks.serialize = new Hook();
this.hooks.content = new Hook(); this.hooks.content = new Hook();
// Register replacements // Register replacements
this.hooks.content.register(replacements.base); this.hooks.content.register(replacements.base);
this.hooks.content.register(replacements.canonical); this.hooks.content.register(replacements.canonical);
this.epubcfi = new EpubCFI(); this.epubcfi = new EpubCFI();
this.loaded = false; this.loaded = false;
}; };
Spine.prototype.load = function(_package) { Spine.prototype.load = function(_package) {
this.items = _package.spine; this.items = _package.spine;
this.manifest = _package.manifest; this.manifest = _package.manifest;
this.spineNodeIndex = _package.spineNodeIndex; this.spineNodeIndex = _package.spineNodeIndex;
this.baseUrl = _package.baseUrl || ''; this.baseUrl = _package.baseUrl || '';
this.length = this.items.length; this.length = this.items.length;
this.items.forEach(function(item, index){ this.items.forEach(function(item, index){
var href, url; var href, url;
var manifestItem = this.manifest[item.idref]; var manifestItem = this.manifest[item.idref];
var spineItem; var spineItem;
item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref); item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.idref);
if(manifestItem) { if(manifestItem) {
item.href = manifestItem.href; item.href = manifestItem.href;
item.url = this.baseUrl + item.href; item.url = this.baseUrl + item.href;
if(manifestItem.properties.length){ if(manifestItem.properties.length){
item.properties.push.apply(item.properties, manifestItem.properties); item.properties.push.apply(item.properties, manifestItem.properties);
} }
} }
// if(index > 0) { // if(index > 0) {
item.prev = function(){ return this.get(index-1); }.bind(this); item.prev = function(){ return this.get(index-1); }.bind(this);
// } // }
// if(index+1 < this.items.length) { // if(index+1 < this.items.length) {
item.next = function(){ return this.get(index+1); }.bind(this); item.next = function(){ return this.get(index+1); }.bind(this);
// } // }
spineItem = new Section(item, this.hooks); spineItem = new Section(item, this.hooks);
this.append(spineItem); this.append(spineItem);
}.bind(this)); }.bind(this));
this.loaded = true; this.loaded = true;
}; };
// book.spine.get(); // book.spine.get();
@ -71,47 +71,47 @@ Spine.prototype.load = function(_package) {
// book.spine.get("chap1.html"); // book.spine.get("chap1.html");
// book.spine.get("#id1234"); // book.spine.get("#id1234");
Spine.prototype.get = function(target) { Spine.prototype.get = function(target) {
var index = 0; var index = 0;
if(this.epubcfi.isCfiString(target)) { if(this.epubcfi.isCfiString(target)) {
cfi = new EpubCFI(target); cfi = new EpubCFI(target);
index = cfi.spinePos; index = cfi.spinePos;
} else if(target && (typeof target === "number" || isNaN(target) === false)){ } else if(target && (typeof target === "number" || isNaN(target) === false)){
index = target; index = target;
} else if(target && target.indexOf("#") === 0) { } else if(target && target.indexOf("#") === 0) {
index = this.spineById[target.substring(1)]; index = this.spineById[target.substring(1)];
} else if(target) { } else if(target) {
// Remove fragments // Remove fragments
target = target.split("#")[0]; target = target.split("#")[0];
index = this.spineByHref[target]; index = this.spineByHref[target];
} }
return this.spineItems[index] || null; return this.spineItems[index] || null;
}; };
Spine.prototype.append = function(section) { Spine.prototype.append = function(section) {
var index = this.spineItems.length; var index = this.spineItems.length;
section.index = index; section.index = index;
this.spineItems.push(section); this.spineItems.push(section);
this.spineByHref[section.href] = index; this.spineByHref[section.href] = index;
this.spineById[section.idref] = index; this.spineById[section.idref] = index;
return index; return index;
}; };
Spine.prototype.prepend = function(section) { Spine.prototype.prepend = function(section) {
var index = this.spineItems.unshift(section); var index = this.spineItems.unshift(section);
this.spineByHref[section.href] = 0; this.spineByHref[section.href] = 0;
this.spineById[section.idref] = 0; this.spineById[section.idref] = 0;
// Re-index // Re-index
this.spineItems.forEach(function(item, index){ this.spineItems.forEach(function(item, index){
item.index = index; item.index = index;
}); });
return 0; return 0;
}; };
Spine.prototype.insert = function(section, index) { Spine.prototype.insert = function(section, index) {
@ -119,14 +119,14 @@ Spine.prototype.insert = function(section, index) {
}; };
Spine.prototype.remove = function(section) { Spine.prototype.remove = function(section) {
var index = this.spineItems.indexOf(section); var index = this.spineItems.indexOf(section);
if(index > -1) { if(index > -1) {
delete this.spineByHref[section.href]; delete this.spineByHref[section.href];
delete this.spineById[section.idref]; delete this.spineById[section.idref];
return this.spineItems.splice(index, 1); return this.spineItems.splice(index, 1);
} }
}; };
Spine.prototype.each = function() { Spine.prototype.each = function() {

View file

@ -20,7 +20,7 @@ Stage.prototype.create = function(options){
var height = options.height;// !== false ? options.height : "100%"; var height = options.height;// !== false ? options.height : "100%";
var width = options.width;// !== false ? options.width : "100%"; var width = options.width;// !== false ? options.width : "100%";
var overflow = options.overflow || false; var overflow = options.overflow || false;
var axis = options.axis || "vertical"; var axis = options.axis || "vertical";
if(options.height && core.isNumber(options.height)) { if(options.height && core.isNumber(options.height)) {
height = options.height + "px"; height = options.height + "px";
@ -223,7 +223,7 @@ Stage.prototype.addStyleRules = function(selector, rulesArray){
} }
}) })
this.sheet.insertRule(scope + selector + " {" + rules + "}", 0); this.sheet.insertRule(scope + selector + " {" + rules + "}", 0);
} }

View file

@ -6,100 +6,100 @@ var mime = require('../libs/mime/mime');
function Unarchive() { function Unarchive() {
this.checkRequirements(); this.checkRequirements();
this.urlCache = {}; this.urlCache = {};
} }
Unarchive.prototype.checkRequirements = function(callback){ Unarchive.prototype.checkRequirements = function(callback){
try { try {
if (typeof JSZip !== 'undefined') { if (typeof JSZip !== 'undefined') {
this.zip = new JSZip(); this.zip = new JSZip();
} else { } else {
JSZip = require('jszip'); JSZip = require('jszip');
this.zip = new JSZip(); this.zip = new JSZip();
} }
} catch (e) { } catch (e) {
console.error("JSZip lib not loaded"); console.error("JSZip lib not loaded");
} }
}; };
Unarchive.prototype.open = function(zipUrl, isBase64){ Unarchive.prototype.open = function(zipUrl, isBase64){
if (zipUrl instanceof ArrayBuffer || isBase64) { if (zipUrl instanceof ArrayBuffer || isBase64) {
return this.zip.loadAsync(zipUrl, {"base64": isBase64}); return this.zip.loadAsync(zipUrl, {"base64": isBase64});
} else { } else {
return request(zipUrl, "binary") return request(zipUrl, "binary")
.then(function(data){ .then(function(data){
return this.zip.loadAsync(data); return this.zip.loadAsync(data);
}.bind(this)); }.bind(this));
} }
}; };
Unarchive.prototype.request = function(url, type){ Unarchive.prototype.request = function(url, type){
var deferred = new RSVP.defer(); var deferred = new RSVP.defer();
var response; var response;
var r; var r;
// If type isn't set, determine it from the file extension // If type isn't set, determine it from the file extension
if(!type) { if(!type) {
uri = URI(url); uri = URI(url);
type = uri.suffix(); type = uri.suffix();
} }
if(type == 'blob'){ if(type == 'blob'){
response = this.getBlob(url); response = this.getBlob(url);
} else { } else {
response = this.getText(url); response = this.getText(url);
} }
if (response) { if (response) {
response.then(function (r) { response.then(function (r) {
result = this.handleResponse(r, type); result = this.handleResponse(r, type);
deferred.resolve(result); deferred.resolve(result);
}.bind(this)); }.bind(this));
} else { } else {
deferred.reject({ deferred.reject({
message : "File not found in the epub: " + url, message : "File not found in the epub: " + url,
stack : new Error().stack stack : new Error().stack
}); });
} }
return deferred.promise; return deferred.promise;
}; };
Unarchive.prototype.handleResponse = function(response, type){ Unarchive.prototype.handleResponse = function(response, type){
var r; var r;
if(type == "json") { if(type == "json") {
r = JSON.parse(response); r = JSON.parse(response);
}
else
if(core.isXml(type)) {
r = core.parse(response, "text/xml");
} }
else else
if(core.isXml(type)) {
r = core.parse(response, "text/xml");
}
else
if(type == 'xhtml') { if(type == 'xhtml') {
r = core.parse(response, "application/xhtml+xml"); r = core.parse(response, "application/xhtml+xml");
} }
else else
if(type == 'html' || type == 'htm') { if(type == 'html' || type == 'htm') {
r = core.parse(response, "text/html"); r = core.parse(response, "text/html");
} else { } else {
r = response; r = response;
} }
return r; return r;
}; };
Unarchive.prototype.getBlob = function(url, _mimeType){ Unarchive.prototype.getBlob = function(url, _mimeType){
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
var entry = this.zip.file(decodededUrl); var entry = this.zip.file(decodededUrl);
var mimeType; var mimeType;
if(entry) { if(entry) {
mimeType = _mimeType || mime.lookup(entry.name); mimeType = _mimeType || mime.lookup(entry.name);
return entry.async("uint8array").then(function(uint8array) { return entry.async("uint8array").then(function(uint8array) {
return new Blob([uint8array], {type : mimeType}); return new Blob([uint8array], {type : mimeType});
}); });
} }
}; };
@ -108,22 +108,22 @@ Unarchive.prototype.getText = function(url, encoding){
var entry = this.zip.file(decodededUrl); var entry = this.zip.file(decodededUrl);
if(entry) { if(entry) {
return entry.async("string").then(function(text) { return entry.async("string").then(function(text) {
return text; return text;
}); });
} }
}; };
Unarchive.prototype.getBase64 = function(url, _mimeType){ Unarchive.prototype.getBase64 = function(url, _mimeType){
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
var entry = this.zip.file(decodededUrl); var entry = this.zip.file(decodededUrl);
var mimeType; var mimeType;
if(entry) { if(entry) {
mimeType = _mimeType || mime.lookup(entry.name); mimeType = _mimeType || mime.lookup(entry.name);
return entry.async("base64").then(function(data) { return entry.async("base64").then(function(data) {
return "data:" + mimeType + ";base64," + data; return "data:" + mimeType + ";base64," + data;
}); });
} }
}; };
@ -131,51 +131,51 @@ Unarchive.prototype.createUrl = function(url, options){
var deferred = new RSVP.defer(); var deferred = new RSVP.defer();
var _URL = window.URL || window.webkitURL || window.mozURL; var _URL = window.URL || window.webkitURL || window.mozURL;
var tempUrl; var tempUrl;
var blob; var blob;
var response; var response;
var useBase64 = options && options.base64; var useBase64 = options && options.base64;
if(url in this.urlCache) { if(url in this.urlCache) {
deferred.resolve(this.urlCache[url]); deferred.resolve(this.urlCache[url]);
return deferred.promise; return deferred.promise;
} }
if (useBase64) { if (useBase64) {
response = this.getBase64(url); response = this.getBase64(url);
if (response) { if (response) {
response.then(function(tempUrl) { response.then(function(tempUrl) {
this.urlCache[url] = tempUrl; this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl); deferred.resolve(tempUrl);
}.bind(this)); }.bind(this));
} }
} else { } else {
response = this.getBlob(url); response = this.getBlob(url);
if (response) { if (response) {
response.then(function(blob) { response.then(function(blob) {
tempUrl = _URL.createObjectURL(blob); tempUrl = _URL.createObjectURL(blob);
this.urlCache[url] = tempUrl; this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl); deferred.resolve(tempUrl);
}.bind(this)); }.bind(this));
} }
} }
if (!response) { if (!response) {
deferred.reject({ deferred.reject({
message : "File not found in the epub: " + url, message : "File not found in the epub: " + url,
stack : new Error().stack stack : new Error().stack
}); });
} }
return deferred.promise; return deferred.promise;
}; };

View file

@ -1,8 +1,8 @@
function Views(container) { function Views(container) {
this.container = container; this.container = container;
this._views = []; this._views = [];
this.length = 0; this.length = 0;
this.hidden = false; this.hidden = false;
}; };
Views.prototype.all = function() { Views.prototype.all = function() {
@ -31,35 +31,35 @@ Views.prototype.get = function(i) {
Views.prototype.append = function(view){ Views.prototype.append = function(view){
this._views.push(view); this._views.push(view);
if(this.container){ if(this.container){
this.container.appendChild(view.element); this.container.appendChild(view.element);
} }
this.length++; this.length++;
return view; return view;
}; };
Views.prototype.prepend = function(view){ Views.prototype.prepend = function(view){
this._views.unshift(view); this._views.unshift(view);
if(this.container){ if(this.container){
this.container.insertBefore(view.element, this.container.firstChild); this.container.insertBefore(view.element, this.container.firstChild);
} }
this.length++; this.length++;
return view; return view;
}; };
Views.prototype.insert = function(view, index) { Views.prototype.insert = function(view, index) {
this._views.splice(index, 0, view); this._views.splice(index, 0, view);
if(this.container){ if(this.container){
if(index < this.container.children.length){ if(index < this.container.children.length){
this.container.insertBefore(view.element, this.container.children[index]); this.container.insertBefore(view.element, this.container.children[index]);
} else { } else {
this.container.appendChild(view.element); this.container.appendChild(view.element);
} }
} }
this.length++; this.length++;
return view; return view;
}; };
Views.prototype.remove = function(view) { Views.prototype.remove = function(view) {
@ -72,7 +72,7 @@ Views.prototype.remove = function(view) {
this.destroy(view); this.destroy(view);
this.length--; this.length--;
}; };
Views.prototype.destroy = function(view) { Views.prototype.destroy = function(view) {
@ -82,9 +82,9 @@ Views.prototype.destroy = function(view) {
view.destroy(); view.destroy();
} }
if(this.container){ if(this.container){
this.container.removeChild(view.element); this.container.removeChild(view.element);
} }
view = null; view = null;
}; };
@ -96,72 +96,72 @@ Views.prototype.each = function() {
Views.prototype.clear = function(){ Views.prototype.clear = function(){
// Remove all views // Remove all views
var view; var view;
var len = this.length; var len = this.length;
if(!this.length) return; if(!this.length) return;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
view = this._views[i]; view = this._views[i];
this.destroy(view); this.destroy(view);
} }
this._views = []; this._views = [];
this.length = 0; this.length = 0;
}; };
Views.prototype.find = function(section){ Views.prototype.find = function(section){
var view; var view;
var len = this.length; var len = this.length;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
view = this._views[i]; view = this._views[i];
if(view.displayed && view.section.index == section.index) { if(view.displayed && view.section.index == section.index) {
return view; return view;
} }
} }
}; };
Views.prototype.displayed = function(){ Views.prototype.displayed = function(){
var displayed = []; var displayed = [];
var view; var view;
var len = this.length; var len = this.length;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
view = this._views[i]; view = this._views[i];
if(view.displayed){ if(view.displayed){
displayed.push(view); displayed.push(view);
} }
} }
return displayed; return displayed;
}; };
Views.prototype.show = function(){ Views.prototype.show = function(){
var view; var view;
var len = this.length; var len = this.length;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
view = this._views[i]; view = this._views[i];
if(view.displayed){ if(view.displayed){
view.show(); view.show();
} }
} }
this.hidden = false; this.hidden = false;
}; };
Views.prototype.hide = function(){ Views.prototype.hide = function(){
var view; var view;
var len = this.length; var len = this.length;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
view = this._views[i]; view = this._views[i];
if(view.displayed){ if(view.displayed){
view.hide(); view.hide();
} }
} }
this.hidden = true; this.hidden = true;
}; };
module.exports = Views; module.exports = Views;

View file

@ -4,110 +4,110 @@ var EpubCFI = require('../epubcfi');
var Contents = require('../contents'); var Contents = require('../contents');
function IframeView(section, options) { function IframeView(section, options) {
this.settings = core.extend({ this.settings = core.extend({
ignoreClass : '', ignoreClass : '',
axis: 'vertical', axis: 'vertical',
width: 0, width: 0,
height: 0, height: 0,
layout: undefined, layout: undefined,
globalLayoutProperties: {}, globalLayoutProperties: {},
}, options || {}); }, options || {});
this.id = "epubjs-view-" + core.uuid(); this.id = "epubjs-view-" + core.uuid();
this.section = section; this.section = section;
this.index = section.index; this.index = section.index;
this.element = this.container(this.settings.axis); this.element = this.container(this.settings.axis);
this.added = false; this.added = false;
this.displayed = false; this.displayed = false;
this.rendered = false; this.rendered = false;
this.width = this.settings.width; this.width = this.settings.width;
this.height = this.settings.height; this.height = this.settings.height;
this.fixedWidth = 0; this.fixedWidth = 0;
this.fixedHeight = 0; this.fixedHeight = 0;
// Blank Cfi for Parsing // Blank Cfi for Parsing
this.epubcfi = new EpubCFI(); this.epubcfi = new EpubCFI();
this.layout = this.settings.layout; this.layout = this.settings.layout;
// Dom events to listen for // Dom events to listen for
// this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"]; // this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
}; };
IframeView.prototype.container = function(axis) { IframeView.prototype.container = function(axis) {
var element = document.createElement('div'); var element = document.createElement('div');
element.classList.add("epub-view"); element.classList.add("epub-view");
// this.element.style.minHeight = "100px"; // this.element.style.minHeight = "100px";
element.style.height = "0px"; element.style.height = "0px";
element.style.width = "0px"; element.style.width = "0px";
element.style.overflow = "hidden"; element.style.overflow = "hidden";
if(axis && axis == "horizontal"){ if(axis && axis == "horizontal"){
element.style.display = "inline-block"; element.style.display = "inline-block";
} else { } else {
element.style.display = "block"; element.style.display = "block";
} }
return element; return element;
}; };
IframeView.prototype.create = function() { IframeView.prototype.create = function() {
if(this.iframe) { if(this.iframe) {
return this.iframe; return this.iframe;
} }
if(!this.element) { if(!this.element) {
this.element = this.createContainer(); this.element = this.createContainer();
} }
this.iframe = document.createElement('iframe'); this.iframe = document.createElement('iframe');
this.iframe.id = this.id; this.iframe.id = this.id;
this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations
this.iframe.style.overflow = "hidden"; this.iframe.style.overflow = "hidden";
this.iframe.seamless = "seamless"; this.iframe.seamless = "seamless";
// Back up if seamless isn't supported // Back up if seamless isn't supported
this.iframe.style.border = "none"; this.iframe.style.border = "none";
this.resizing = true; this.resizing = true;
// this.iframe.style.display = "none"; // this.iframe.style.display = "none";
this.element.style.visibility = "hidden"; this.element.style.visibility = "hidden";
this.iframe.style.visibility = "hidden"; this.iframe.style.visibility = "hidden";
this.iframe.style.width = "0"; this.iframe.style.width = "0";
this.iframe.style.height = "0"; this.iframe.style.height = "0";
this._width = 0; this._width = 0;
this._height = 0; this._height = 0;
this.element.appendChild(this.iframe); this.element.appendChild(this.iframe);
this.added = true; this.added = true;
this.elementBounds = core.bounds(this.element); this.elementBounds = core.bounds(this.element);
// if(width || height){ // if(width || height){
// this.resize(width, height); // this.resize(width, height);
// } else if(this.width && this.height){ // } else if(this.width && this.height){
// this.resize(this.width, this.height); // this.resize(this.width, this.height);
// } else { // } else {
// this.iframeBounds = core.bounds(this.iframe); // this.iframeBounds = core.bounds(this.iframe);
// } // }
// Firefox has trouble with baseURI and srcdoc // Firefox has trouble with baseURI and srcdoc
// TODO: Disable for now in firefox // TODO: Disable for now in firefox
if(!!("srcdoc" in this.iframe)) { if(!!("srcdoc" in this.iframe)) {
this.supportsSrcdoc = true; this.supportsSrcdoc = true;
} else { } else {
this.supportsSrcdoc = false; this.supportsSrcdoc = false;
} }
return this.iframe; return this.iframe;
}; };
IframeView.prototype.render = function(request, show) { IframeView.prototype.render = function(request, show) {
@ -116,11 +116,11 @@ IframeView.prototype.render = function(request, show) {
this.create(); this.create();
// Fit to size of the container, apply padding // Fit to size of the container, apply padding
this.size(); this.size();
if(!this.sectionRender) { if(!this.sectionRender) {
this.sectionRender = this.section.render(request); this.sectionRender = this.section.render(request);
} }
// Render Chain // Render Chain
return this.sectionRender return this.sectionRender
@ -142,14 +142,14 @@ IframeView.prototype.render = function(request, show) {
// }.bind(this)) // }.bind(this))
.then(function(){ .then(function(){
// apply the layout function to the contents // apply the layout function to the contents
this.settings.layout.format(this.contents); this.settings.layout.format(this.contents);
// Expand the iframe to the full size of the content // Expand the iframe to the full size of the content
this.expand(); this.expand();
// Listen for events that require an expansion of the iframe // Listen for events that require an expansion of the iframe
this.addListeners(); this.addListeners();
if(show !== false) { if(show !== false) {
//this.q.enqueue(function(view){ //this.q.enqueue(function(view){
@ -169,12 +169,12 @@ IframeView.prototype.render = function(request, show) {
// Determine locks base on settings // Determine locks base on settings
IframeView.prototype.size = function(_width, _height) { IframeView.prototype.size = function(_width, _height) {
var width = _width || this.settings.width; var width = _width || this.settings.width;
var height = _height || this.settings.height; var height = _height || this.settings.height;
if(this.layout.name === "pre-paginated") { if(this.layout.name === "pre-paginated") {
this.lock("both", width, height); this.lock("both", width, height);
} else if(this.settings.axis === "horizontal") { } else if(this.settings.axis === "horizontal") {
this.lock("height", width, height); this.lock("height", width, height);
} else { } else {
this.lock("width", width, height); this.lock("width", width, height);
@ -184,41 +184,41 @@ IframeView.prototype.size = function(_width, _height) {
// Lock an axis to element dimensions, taking borders into account // Lock an axis to element dimensions, taking borders into account
IframeView.prototype.lock = function(what, width, height) { IframeView.prototype.lock = function(what, width, height) {
var elBorders = core.borders(this.element); var elBorders = core.borders(this.element);
var iframeBorders; var iframeBorders;
if(this.iframe) { if(this.iframe) {
iframeBorders = core.borders(this.iframe); iframeBorders = core.borders(this.iframe);
} else { } else {
iframeBorders = {width: 0, height: 0}; iframeBorders = {width: 0, height: 0};
} }
if(what == "width" && core.isNumber(width)){ if(what == "width" && core.isNumber(width)){
this.lockedWidth = width - elBorders.width - iframeBorders.width; this.lockedWidth = width - elBorders.width - iframeBorders.width;
this.resize(this.lockedWidth, width); // width keeps ratio correct this.resize(this.lockedWidth, width); // width keeps ratio correct
} }
if(what == "height" && core.isNumber(height)){ if(what == "height" && core.isNumber(height)){
this.lockedHeight = height - elBorders.height - iframeBorders.height; this.lockedHeight = height - elBorders.height - iframeBorders.height;
this.resize(width, this.lockedHeight); this.resize(width, this.lockedHeight);
} }
if(what === "both" && if(what === "both" &&
core.isNumber(width) && core.isNumber(width) &&
core.isNumber(height)){ core.isNumber(height)){
this.lockedWidth = width - elBorders.width - iframeBorders.width; this.lockedWidth = width - elBorders.width - iframeBorders.width;
this.lockedHeight = height - elBorders.height - iframeBorders.height; this.lockedHeight = height - elBorders.height - iframeBorders.height;
this.resize(this.lockedWidth, this.lockedHeight); this.resize(this.lockedWidth, this.lockedHeight);
} }
if(this.displayed && this.iframe) { if(this.displayed && this.iframe) {
// this.contents.layout(); // this.contents.layout();
this.expand(); this.expand();
} }
@ -226,209 +226,209 @@ IframeView.prototype.lock = function(what, width, height) {
// Resize a single axis based on content dimensions // Resize a single axis based on content dimensions
IframeView.prototype.expand = function(force) { IframeView.prototype.expand = function(force) {
var width = this.lockedWidth; var width = this.lockedWidth;
var height = this.lockedHeight; var height = this.lockedHeight;
var columns; var columns;
var textWidth, textHeight; var textWidth, textHeight;
if(!this.iframe || this._expanding) return; if(!this.iframe || this._expanding) return;
this._expanding = true; this._expanding = true;
// Expand Horizontally // Expand Horizontally
// if(height && !width) { // if(height && !width) {
if(this.settings.axis === "horizontal") { if(this.settings.axis === "horizontal") {
// Get the width of the text // Get the width of the text
textWidth = this.contents.textWidth(); textWidth = this.contents.textWidth();
// Check if the textWidth has changed // Check if the textWidth has changed
if(textWidth != this._textWidth){ if(textWidth != this._textWidth){
// Get the contentWidth by resizing the iframe // Get the contentWidth by resizing the iframe
// Check with a min reset of the textWidth // Check with a min reset of the textWidth
width = this.contentWidth(textWidth); width = this.contentWidth(textWidth);
columns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap)); columns = Math.ceil(width / (this.settings.layout.columnWidth + this.settings.layout.gap));
if ( this.settings.layout.divisor > 1 && if ( this.settings.layout.divisor > 1 &&
this.settings.layout.name === "reflowable" && this.settings.layout.name === "reflowable" &&
(columns % 2 > 0)) { (columns % 2 > 0)) {
// add a blank page // add a blank page
width += this.settings.layout.gap + this.settings.layout.columnWidth; width += this.settings.layout.gap + this.settings.layout.columnWidth;
} }
// Save the textWdith // Save the textWdith
this._textWidth = textWidth; this._textWidth = textWidth;
// Save the contentWidth // Save the contentWidth
this._contentWidth = width; this._contentWidth = width;
} else { } else {
// Otherwise assume content height hasn't changed // Otherwise assume content height hasn't changed
width = this._contentWidth; width = this._contentWidth;
} }
} // Expand Vertically } // Expand Vertically
else if(this.settings.axis === "vertical") { else if(this.settings.axis === "vertical") {
textHeight = this.contents.textHeight(); textHeight = this.contents.textHeight();
if(textHeight != this._textHeight){ if(textHeight != this._textHeight){
height = this.contentHeight(textHeight); height = this.contentHeight(textHeight);
this._textHeight = textHeight; this._textHeight = textHeight;
this._contentHeight = height; this._contentHeight = height;
} else { } else {
height = this._contentHeight; height = this._contentHeight;
} }
} }
// Only Resize if dimensions have changed or // Only Resize if dimensions have changed or
// if Frame is still hidden, so needs reframing // if Frame is still hidden, so needs reframing
if(this._needsReframe || width != this._width || height != this._height){ if(this._needsReframe || width != this._width || height != this._height){
this.resize(width, height); this.resize(width, height);
} }
this._expanding = false; this._expanding = false;
}; };
IframeView.prototype.contentWidth = function(min) { IframeView.prototype.contentWidth = function(min) {
var prev; var prev;
var width; var width;
// Save previous width // Save previous width
prev = this.iframe.style.width; prev = this.iframe.style.width;
// Set the iframe size to min, width will only ever be greater // Set the iframe size to min, width will only ever be greater
// Will preserve the aspect ratio // Will preserve the aspect ratio
this.iframe.style.width = (min || 0) + "px"; this.iframe.style.width = (min || 0) + "px";
// Get the scroll overflow width // Get the scroll overflow width
width = this.contents.scrollWidth(); width = this.contents.scrollWidth();
// Reset iframe size back // Reset iframe size back
this.iframe.style.width = prev; this.iframe.style.width = prev;
return width; return width;
}; };
IframeView.prototype.contentHeight = function(min) { IframeView.prototype.contentHeight = function(min) {
var prev; var prev;
var height; var height;
prev = this.iframe.style.height; prev = this.iframe.style.height;
this.iframe.style.height = (min || 0) + "px"; this.iframe.style.height = (min || 0) + "px";
height = this.contents.scrollHeight(); height = this.contents.scrollHeight();
this.iframe.style.height = prev; this.iframe.style.height = prev;
return height; return height;
}; };
IframeView.prototype.resize = function(width, height) { IframeView.prototype.resize = function(width, height) {
if(!this.iframe) return; if(!this.iframe) return;
if(core.isNumber(width)){ if(core.isNumber(width)){
this.iframe.style.width = width + "px"; this.iframe.style.width = width + "px";
this._width = width; this._width = width;
} }
if(core.isNumber(height)){ if(core.isNumber(height)){
this.iframe.style.height = height + "px"; this.iframe.style.height = height + "px";
this._height = height; this._height = height;
} }
this.iframeBounds = core.bounds(this.iframe); this.iframeBounds = core.bounds(this.iframe);
this.reframe(this.iframeBounds.width, this.iframeBounds.height); this.reframe(this.iframeBounds.width, this.iframeBounds.height);
}; };
IframeView.prototype.reframe = function(width, height) { IframeView.prototype.reframe = function(width, height) {
var size; var size;
// if(!this.displayed) { // if(!this.displayed) {
// this._needsReframe = true; // this._needsReframe = true;
// return; // return;
// } // }
if(core.isNumber(width)){ if(core.isNumber(width)){
this.element.style.width = width + "px"; this.element.style.width = width + "px";
} }
if(core.isNumber(height)){ if(core.isNumber(height)){
this.element.style.height = height + "px"; this.element.style.height = height + "px";
} }
this.prevBounds = this.elementBounds; this.prevBounds = this.elementBounds;
this.elementBounds = core.bounds(this.element); this.elementBounds = core.bounds(this.element);
size = { size = {
width: this.elementBounds.width, width: this.elementBounds.width,
height: this.elementBounds.height, height: this.elementBounds.height,
widthDelta: this.elementBounds.width - this.prevBounds.width, widthDelta: this.elementBounds.width - this.prevBounds.width,
heightDelta: this.elementBounds.height - this.prevBounds.height, heightDelta: this.elementBounds.height - this.prevBounds.height,
}; };
this.onResize(this, size); this.onResize(this, size);
this.trigger("resized", size); this.trigger("resized", size);
}; };
IframeView.prototype.load = function(contents) { IframeView.prototype.load = function(contents) {
var loading = new RSVP.defer(); var loading = new RSVP.defer();
var loaded = loading.promise; var loaded = loading.promise;
if(!this.iframe) { if(!this.iframe) {
loading.reject(new Error("No Iframe Available")); loading.reject(new Error("No Iframe Available"));
return loaded; return loaded;
} }
this.iframe.onload = function(event) { this.iframe.onload = function(event) {
this.onLoad(event, loading); this.onLoad(event, loading);
}.bind(this); }.bind(this);
if(this.supportsSrcdoc){ if(this.supportsSrcdoc){
this.iframe.srcdoc = contents; this.iframe.srcdoc = contents;
} else { } else {
this.document = this.iframe.contentDocument; this.document = this.iframe.contentDocument;
if(!this.document) { if(!this.document) {
loading.reject(new Error("No Document Available")); loading.reject(new Error("No Document Available"));
return loaded; return loaded;
} }
this.iframe.contentDocument.open(); this.iframe.contentDocument.open();
this.iframe.contentDocument.write(contents); this.iframe.contentDocument.write(contents);
this.iframe.contentDocument.close(); this.iframe.contentDocument.close();
} }
return loaded; return loaded;
}; };
IframeView.prototype.onLoad = function(event, promise) { IframeView.prototype.onLoad = function(event, promise) {
this.window = this.iframe.contentWindow; this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument; this.document = this.iframe.contentDocument;
this.contents = new Contents(this.document, this.document.body, this.section.cfiBase); this.contents = new Contents(this.document, this.document.body, this.section.cfiBase);
this.rendering = false; this.rendering = false;
var link = this.document.querySelector("link[rel='canonical']"); var link = this.document.querySelector("link[rel='canonical']");
if (link) { if (link) {
link.setAttribute("href", this.section.url); link.setAttribute("href", this.section.url);
} else { } else {
link = this.document.createElement("link"); link = this.document.createElement("link");
link.setAttribute("rel", "canonical"); link.setAttribute("rel", "canonical");
link.setAttribute("href", this.section.url); link.setAttribute("href", this.section.url);
this.document.querySelector("head").appendChild(link); this.document.querySelector("head").appendChild(link);
} }
this.contents.on("expand", function () { this.contents.on("expand", function () {
if(this.displayed && this.iframe) { if(this.displayed && this.iframe) {
this.expand(); this.expand();
} }
}); });
promise.resolve(this.contents); promise.resolve(this.contents);
}; };
@ -455,118 +455,118 @@ IframeView.prototype.onLoad = function(event, promise) {
// }; // };
IframeView.prototype.setLayout = function(layout) { IframeView.prototype.setLayout = function(layout) {
this.layout = layout; this.layout = layout;
}; };
IframeView.prototype.setAxis = function(axis) { IframeView.prototype.setAxis = function(axis) {
this.settings.axis = axis; this.settings.axis = axis;
}; };
IframeView.prototype.resizeListenters = function() { IframeView.prototype.resizeListenters = function() {
// Test size again // Test size again
clearTimeout(this.expanding); clearTimeout(this.expanding);
this.expanding = setTimeout(this.expand.bind(this), 350); this.expanding = setTimeout(this.expand.bind(this), 350);
}; };
IframeView.prototype.addListeners = function() { IframeView.prototype.addListeners = function() {
//TODO: Add content listeners for expanding //TODO: Add content listeners for expanding
}; };
IframeView.prototype.removeListeners = function(layoutFunc) { IframeView.prototype.removeListeners = function(layoutFunc) {
//TODO: remove content listeners for expanding //TODO: remove content listeners for expanding
}; };
IframeView.prototype.display = function(request) { IframeView.prototype.display = function(request) {
var displayed = new RSVP.defer(); var displayed = new RSVP.defer();
if (!this.displayed) { if (!this.displayed) {
this.render(request).then(function () { this.render(request).then(function () {
this.trigger("displayed", this); this.trigger("displayed", this);
this.onDisplayed(this); this.onDisplayed(this);
this.displayed = true; this.displayed = true;
displayed.resolve(this); displayed.resolve(this);
}.bind(this)); }.bind(this));
} else { } else {
displayed.resolve(this); displayed.resolve(this);
} }
return displayed.promise; return displayed.promise;
}; };
IframeView.prototype.show = function() { IframeView.prototype.show = function() {
this.element.style.visibility = "visible"; this.element.style.visibility = "visible";
if(this.iframe){ if(this.iframe){
this.iframe.style.visibility = "visible"; this.iframe.style.visibility = "visible";
} }
this.trigger("shown", this); this.trigger("shown", this);
}; };
IframeView.prototype.hide = function() { IframeView.prototype.hide = function() {
// this.iframe.style.display = "none"; // this.iframe.style.display = "none";
this.element.style.visibility = "hidden"; this.element.style.visibility = "hidden";
this.iframe.style.visibility = "hidden"; this.iframe.style.visibility = "hidden";
this.stopExpanding = true; this.stopExpanding = true;
this.trigger("hidden", this); this.trigger("hidden", this);
}; };
IframeView.prototype.position = function() { IframeView.prototype.position = function() {
return this.element.getBoundingClientRect(); return this.element.getBoundingClientRect();
}; };
IframeView.prototype.locationOf = function(target) { IframeView.prototype.locationOf = function(target) {
var parentPos = this.iframe.getBoundingClientRect(); var parentPos = this.iframe.getBoundingClientRect();
var targetPos = this.contents.locationOf(target, this.settings.ignoreClass); var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
return { return {
"left": window.scrollX + parentPos.left + targetPos.left, "left": window.scrollX + parentPos.left + targetPos.left,
"top": window.scrollY + parentPos.top + targetPos.top "top": window.scrollY + parentPos.top + targetPos.top
}; };
}; };
IframeView.prototype.onDisplayed = function(view) { IframeView.prototype.onDisplayed = function(view) {
// Stub, override with a custom functions // Stub, override with a custom functions
}; };
IframeView.prototype.onResize = function(view, e) { IframeView.prototype.onResize = function(view, e) {
// Stub, override with a custom functions // Stub, override with a custom functions
}; };
IframeView.prototype.bounds = function() { IframeView.prototype.bounds = function() {
if(!this.elementBounds) { if(!this.elementBounds) {
this.elementBounds = core.bounds(this.element); this.elementBounds = core.bounds(this.element);
} }
return this.elementBounds; return this.elementBounds;
}; };
IframeView.prototype.destroy = function() { IframeView.prototype.destroy = function() {
if(this.displayed){ if(this.displayed){
this.displayed = false; this.displayed = false;
this.removeListeners(); this.removeListeners();
this.stopExpanding = true; this.stopExpanding = true;
this.element.removeChild(this.iframe); this.element.removeChild(this.iframe);
this.displayed = false; this.displayed = false;
this.iframe = null; this.iframe = null;
this._textWidth = null; this._textWidth = null;
this._textHeight = null; this._textHeight = null;
this._width = null; this._width = null;
this._height = null; this._height = null;
} }
// this.element.style.height = "0px"; // this.element.style.height = "0px";
// this.element.style.width = "0px"; // this.element.style.width = "0px";
}; };
RSVP.EventTarget.mixin(IframeView.prototype); RSVP.EventTarget.mixin(IframeView.prototype);

View file

@ -5,103 +5,103 @@ var Contents = require('../contents');
var URI = require('urijs'); var URI = require('urijs');
function InlineView(section, options) { function InlineView(section, options) {
this.settings = core.extend({ this.settings = core.extend({
ignoreClass : '', ignoreClass : '',
axis: 'vertical', axis: 'vertical',
width: 0, width: 0,
height: 0, height: 0,
layout: undefined, layout: undefined,
globalLayoutProperties: {}, globalLayoutProperties: {},
}, options || {}); }, options || {});
this.id = "epubjs-view:" + core.uuid(); this.id = "epubjs-view:" + core.uuid();
this.section = section; this.section = section;
this.index = section.index; this.index = section.index;
this.element = this.container(this.settings.axis); this.element = this.container(this.settings.axis);
this.added = false; this.added = false;
this.displayed = false; this.displayed = false;
this.rendered = false; this.rendered = false;
this.width = this.settings.width; this.width = this.settings.width;
this.height = this.settings.height; this.height = this.settings.height;
this.fixedWidth = 0; this.fixedWidth = 0;
this.fixedHeight = 0; this.fixedHeight = 0;
// Blank Cfi for Parsing // Blank Cfi for Parsing
this.epubcfi = new EpubCFI(); this.epubcfi = new EpubCFI();
this.layout = this.settings.layout; this.layout = this.settings.layout;
// Dom events to listen for // Dom events to listen for
// this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"]; // this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
}; };
InlineView.prototype.container = function(axis) { InlineView.prototype.container = function(axis) {
var element = document.createElement('div'); var element = document.createElement('div');
element.classList.add("epub-view"); element.classList.add("epub-view");
// if(this.settings.axis === "horizontal") { // if(this.settings.axis === "horizontal") {
// element.style.width = "auto"; // element.style.width = "auto";
// element.style.height = "0"; // element.style.height = "0";
// } else { // } else {
// element.style.width = "0"; // element.style.width = "0";
// element.style.height = "auto"; // element.style.height = "auto";
// } // }
element.style.overflow = "hidden"; element.style.overflow = "hidden";
if(axis && axis == "horizontal"){ if(axis && axis == "horizontal"){
element.style.display = "inline-block"; element.style.display = "inline-block";
} else { } else {
element.style.display = "block"; element.style.display = "block";
} }
return element; return element;
}; };
InlineView.prototype.create = function() { InlineView.prototype.create = function() {
if(this.frame) { if(this.frame) {
return this.frame; return this.frame;
}
if(!this.element) {
this.element = this.createContainer();
}
this.frame = document.createElement('div');
this.frame.id = this.id;
this.frame.style.overflow = "hidden";
this.frame.style.wordSpacing = "initial";
this.frame.style.lineHeight = "initial";
this.resizing = true;
// this.frame.style.display = "none";
this.element.style.visibility = "hidden";
this.frame.style.visibility = "hidden";
if(this.settings.axis === "horizontal") {
this.frame.style.width = "auto";
this.frame.style.height = "0";
} else {
this.frame.style.width = "0";
this.frame.style.height = "auto";
} }
this._width = 0; if(!this.element) {
this._height = 0; this.element = this.createContainer();
}
this.element.appendChild(this.frame); this.frame = document.createElement('div');
this.added = true; this.frame.id = this.id;
this.frame.style.overflow = "hidden";
this.frame.style.wordSpacing = "initial";
this.frame.style.lineHeight = "initial";
this.elementBounds = core.bounds(this.element); this.resizing = true;
return this.frame; // this.frame.style.display = "none";
this.element.style.visibility = "hidden";
this.frame.style.visibility = "hidden";
if(this.settings.axis === "horizontal") {
this.frame.style.width = "auto";
this.frame.style.height = "0";
} else {
this.frame.style.width = "0";
this.frame.style.height = "auto";
}
this._width = 0;
this._height = 0;
this.element.appendChild(this.frame);
this.added = true;
this.elementBounds = core.bounds(this.element);
return this.frame;
}; };
InlineView.prototype.render = function(request, show) { InlineView.prototype.render = function(request, show) {
@ -110,7 +110,7 @@ InlineView.prototype.render = function(request, show) {
this.create(); this.create();
// Fit to size of the container, apply padding // Fit to size of the container, apply padding
this.size(); this.size();
// Render Chain // Render Chain
return this.section.render(request) return this.section.render(request)
@ -132,14 +132,14 @@ InlineView.prototype.render = function(request, show) {
// }.bind(this)) // }.bind(this))
.then(function(){ .then(function(){
// apply the layout function to the contents // apply the layout function to the contents
this.settings.layout.format(this.contents); this.settings.layout.format(this.contents);
// Expand the iframe to the full size of the content // Expand the iframe to the full size of the content
// this.expand(); // this.expand();
// Listen for events that require an expansion of the iframe // Listen for events that require an expansion of the iframe
this.addListeners(); this.addListeners();
if(show !== false) { if(show !== false) {
//this.q.enqueue(function(view){ //this.q.enqueue(function(view){
@ -159,13 +159,13 @@ InlineView.prototype.render = function(request, show) {
// Determine locks base on settings // Determine locks base on settings
InlineView.prototype.size = function(_width, _height) { InlineView.prototype.size = function(_width, _height) {
var width = _width || this.settings.width; var width = _width || this.settings.width;
var height = _height || this.settings.height; var height = _height || this.settings.height;
if(this.layout.name === "pre-paginated") { if(this.layout.name === "pre-paginated") {
// TODO: check if these are different than the size set in chapter // TODO: check if these are different than the size set in chapter
this.lock("both", width, height); this.lock("both", width, height);
} else if(this.settings.axis === "horizontal") { } else if(this.settings.axis === "horizontal") {
this.lock("height", width, height); this.lock("height", width, height);
} else { } else {
this.lock("width", width, height); this.lock("width", width, height);
@ -175,253 +175,253 @@ InlineView.prototype.size = function(_width, _height) {
// Lock an axis to element dimensions, taking borders into account // Lock an axis to element dimensions, taking borders into account
InlineView.prototype.lock = function(what, width, height) { InlineView.prototype.lock = function(what, width, height) {
var elBorders = core.borders(this.element); var elBorders = core.borders(this.element);
var iframeBorders; var iframeBorders;
if(this.frame) { if(this.frame) {
iframeBorders = core.borders(this.frame); iframeBorders = core.borders(this.frame);
} else { } else {
iframeBorders = {width: 0, height: 0}; iframeBorders = {width: 0, height: 0};
} }
if(what == "width" && core.isNumber(width)){ if(what == "width" && core.isNumber(width)){
this.lockedWidth = width - elBorders.width - iframeBorders.width; this.lockedWidth = width - elBorders.width - iframeBorders.width;
this.resize(this.lockedWidth, false); // width keeps ratio correct this.resize(this.lockedWidth, false); // width keeps ratio correct
} }
if(what == "height" && core.isNumber(height)){ if(what == "height" && core.isNumber(height)){
this.lockedHeight = height - elBorders.height - iframeBorders.height; this.lockedHeight = height - elBorders.height - iframeBorders.height;
this.resize(false, this.lockedHeight); this.resize(false, this.lockedHeight);
} }
if(what === "both" && if(what === "both" &&
core.isNumber(width) && core.isNumber(width) &&
core.isNumber(height)){ core.isNumber(height)){
this.lockedWidth = width - elBorders.width - iframeBorders.width; this.lockedWidth = width - elBorders.width - iframeBorders.width;
this.lockedHeight = height - elBorders.height - iframeBorders.height; this.lockedHeight = height - elBorders.height - iframeBorders.height;
this.resize(this.lockedWidth, this.lockedHeight); this.resize(this.lockedWidth, this.lockedHeight);
} }
}; };
// Resize a single axis based on content dimensions // Resize a single axis based on content dimensions
InlineView.prototype.expand = function(force) { InlineView.prototype.expand = function(force) {
var width = this.lockedWidth; var width = this.lockedWidth;
var height = this.lockedHeight; var height = this.lockedHeight;
var textWidth, textHeight; var textWidth, textHeight;
if(!this.frame || this._expanding) return; if(!this.frame || this._expanding) return;
this._expanding = true; this._expanding = true;
// Expand Horizontally // Expand Horizontally
if(this.settings.axis === "horizontal") { if(this.settings.axis === "horizontal") {
width = this.contentWidth(textWidth); width = this.contentWidth(textWidth);
} // Expand Vertically } // Expand Vertically
else if(this.settings.axis === "vertical") { else if(this.settings.axis === "vertical") {
height = this.contentHeight(textHeight); height = this.contentHeight(textHeight);
} }
// Only Resize if dimensions have changed or // Only Resize if dimensions have changed or
// if Frame is still hidden, so needs reframing // if Frame is still hidden, so needs reframing
if(this._needsReframe || width != this._width || height != this._height){ if(this._needsReframe || width != this._width || height != this._height){
this.resize(width, height); this.resize(width, height);
} }
this._expanding = false; this._expanding = false;
}; };
InlineView.prototype.contentWidth = function(min) { InlineView.prototype.contentWidth = function(min) {
return this.frame.scrollWidth; return this.frame.scrollWidth;
}; };
InlineView.prototype.contentHeight = function(min) { InlineView.prototype.contentHeight = function(min) {
console.log(this.frame.scrollHeight); console.log(this.frame.scrollHeight);
return this.frame.scrollHeight; return this.frame.scrollHeight;
}; };
InlineView.prototype.resize = function(width, height) { InlineView.prototype.resize = function(width, height) {
if(!this.frame) return; if(!this.frame) return;
if(core.isNumber(width)){ if(core.isNumber(width)){
this.frame.style.width = width + "px"; this.frame.style.width = width + "px";
this._width = width; this._width = width;
} }
if(core.isNumber(height)){ if(core.isNumber(height)){
this.frame.style.height = height + "px"; this.frame.style.height = height + "px";
this._height = height; this._height = height;
} }
this.prevBounds = this.elementBounds; this.prevBounds = this.elementBounds;
this.elementBounds = core.bounds(this.element); this.elementBounds = core.bounds(this.element);
size = { size = {
width: this.elementBounds.width, width: this.elementBounds.width,
height: this.elementBounds.height, height: this.elementBounds.height,
widthDelta: this.elementBounds.width - this.prevBounds.width, widthDelta: this.elementBounds.width - this.prevBounds.width,
heightDelta: this.elementBounds.height - this.prevBounds.height, heightDelta: this.elementBounds.height - this.prevBounds.height,
}; };
this.onResize(this, size); this.onResize(this, size);
this.trigger("resized", size); this.trigger("resized", size);
}; };
InlineView.prototype.load = function(contents) { InlineView.prototype.load = function(contents) {
var loading = new RSVP.defer(); var loading = new RSVP.defer();
var loaded = loading.promise; var loaded = loading.promise;
var doc = core.parse(contents, "text/html"); var doc = core.parse(contents, "text/html");
var body = core.qs(doc, "body"); var body = core.qs(doc, "body");
var srcs = doc.querySelectorAll("[src]"); var srcs = doc.querySelectorAll("[src]");
Array.prototype.slice.call(srcs) Array.prototype.slice.call(srcs)
.forEach(function(item) { .forEach(function(item) {
var src = item.getAttribute('src'); var src = item.getAttribute('src');
var assetUri = URI(src); var assetUri = URI(src);
var origin = assetUri.origin(); var origin = assetUri.origin();
var absoluteUri; var absoluteUri;
if (!origin) { if (!origin) {
absoluteUri = assetUri.absoluteTo(this.section.url); absoluteUri = assetUri.absoluteTo(this.section.url);
item.src = absoluteUri; item.src = absoluteUri;
} }
}.bind(this)); }.bind(this));
this.frame.innerHTML = body.innerHTML; this.frame.innerHTML = body.innerHTML;
this.document = this.frame.ownerDocument; this.document = this.frame.ownerDocument;
this.window = this.document.defaultView; this.window = this.document.defaultView;
this.contents = new Contents(this.document, this.frame); this.contents = new Contents(this.document, this.frame);
this.rendering = false; this.rendering = false;
loading.resolve(this.contents); loading.resolve(this.contents);
return loaded; return loaded;
}; };
InlineView.prototype.setLayout = function(layout) { InlineView.prototype.setLayout = function(layout) {
this.layout = layout; this.layout = layout;
}; };
InlineView.prototype.resizeListenters = function() { InlineView.prototype.resizeListenters = function() {
// Test size again // Test size again
// clearTimeout(this.expanding); // clearTimeout(this.expanding);
// this.expanding = setTimeout(this.expand.bind(this), 350); // this.expanding = setTimeout(this.expand.bind(this), 350);
}; };
InlineView.prototype.addListeners = function() { InlineView.prototype.addListeners = function() {
//TODO: Add content listeners for expanding //TODO: Add content listeners for expanding
}; };
InlineView.prototype.removeListeners = function(layoutFunc) { InlineView.prototype.removeListeners = function(layoutFunc) {
//TODO: remove content listeners for expanding //TODO: remove content listeners for expanding
}; };
InlineView.prototype.display = function(request) { InlineView.prototype.display = function(request) {
var displayed = new RSVP.defer(); var displayed = new RSVP.defer();
if (!this.displayed) { if (!this.displayed) {
this.render(request).then(function () { this.render(request).then(function () {
this.trigger("displayed", this); this.trigger("displayed", this);
this.onDisplayed(this); this.onDisplayed(this);
this.displayed = true; this.displayed = true;
displayed.resolve(this); displayed.resolve(this);
}.bind(this)); }.bind(this));
} else { } else {
displayed.resolve(this); displayed.resolve(this);
} }
return displayed.promise; return displayed.promise;
}; };
InlineView.prototype.show = function() { InlineView.prototype.show = function() {
this.element.style.visibility = "visible"; this.element.style.visibility = "visible";
if(this.frame){ if(this.frame){
this.frame.style.visibility = "visible"; this.frame.style.visibility = "visible";
} }
this.trigger("shown", this); this.trigger("shown", this);
}; };
InlineView.prototype.hide = function() { InlineView.prototype.hide = function() {
// this.frame.style.display = "none"; // this.frame.style.display = "none";
this.element.style.visibility = "hidden"; this.element.style.visibility = "hidden";
this.frame.style.visibility = "hidden"; this.frame.style.visibility = "hidden";
this.stopExpanding = true; this.stopExpanding = true;
this.trigger("hidden", this); this.trigger("hidden", this);
}; };
InlineView.prototype.position = function() { InlineView.prototype.position = function() {
return this.element.getBoundingClientRect(); return this.element.getBoundingClientRect();
}; };
InlineView.prototype.locationOf = function(target) { InlineView.prototype.locationOf = function(target) {
var parentPos = this.frame.getBoundingClientRect(); var parentPos = this.frame.getBoundingClientRect();
var targetPos = this.contents.locationOf(target, this.settings.ignoreClass); var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
return { return {
"left": window.scrollX + parentPos.left + targetPos.left, "left": window.scrollX + parentPos.left + targetPos.left,
"top": window.scrollY + parentPos.top + targetPos.top "top": window.scrollY + parentPos.top + targetPos.top
}; };
}; };
InlineView.prototype.onDisplayed = function(view) { InlineView.prototype.onDisplayed = function(view) {
// Stub, override with a custom functions // Stub, override with a custom functions
}; };
InlineView.prototype.onResize = function(view, e) { InlineView.prototype.onResize = function(view, e) {
// Stub, override with a custom functions // Stub, override with a custom functions
}; };
InlineView.prototype.bounds = function() { InlineView.prototype.bounds = function() {
if(!this.elementBounds) { if(!this.elementBounds) {
this.elementBounds = core.bounds(this.element); this.elementBounds = core.bounds(this.element);
} }
return this.elementBounds; return this.elementBounds;
}; };
InlineView.prototype.destroy = function() { InlineView.prototype.destroy = function() {
if(this.displayed){ if(this.displayed){
this.displayed = false; this.displayed = false;
this.removeListeners(); this.removeListeners();
this.stopExpanding = true; this.stopExpanding = true;
this.element.removeChild(this.frame); this.element.removeChild(this.frame);
this.displayed = false; this.displayed = false;
this.frame = null; this.frame = null;
this._textWidth = null; this._textWidth = null;
this._textHeight = null; this._textHeight = null;
this._width = null; this._width = null;
this._height = null; this._height = null;
} }
// this.element.style.height = "0px"; // this.element.style.height = "0px";
// this.element.style.width = "0px"; // this.element.style.width = "0px";
}; };
RSVP.EventTarget.mixin(InlineView.prototype); RSVP.EventTarget.mixin(InlineView.prototype);

View file

@ -4,36 +4,36 @@ var fs = require('fs');
describe('ePub', function() { describe('ePub', function() {
var ePub = require('../src/epub'); var ePub = require('../src/epub');
var server; var server;
before(function(){ before(function(){
var packageContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/package.opf', 'utf8'); var packageContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/package.opf', 'utf8');
var tocContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/toc.xhtml', 'utf8'); var tocContents = fs.readFileSync(__dirname + '/../books/moby-dick/OPS/toc.xhtml', 'utf8');
server = sinon.fakeServer.create(); server = sinon.fakeServer.create();
server.autoRespond = true; server.autoRespond = true;
server.respondWith("moby-dick/OPS/package.opf", [200, { server.respondWith("moby-dick/OPS/package.opf", [200, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
}, packageContents]); }, packageContents]);
server.respondWith("moby-dick/OPS/toc.xhtml", [200, { server.respondWith("moby-dick/OPS/toc.xhtml", [200, {
"Content-Type": "application/xhtml+xml" "Content-Type": "application/xhtml+xml"
}, tocContents]); }, tocContents]);
}); });
after(function(){ after(function(){
server.restore(); server.restore();
}); });
it('should open a epub', function(done) { it('should open a epub', function(done) {
var book = ePub("moby-dick/OPS/package.opf"); var book = ePub("moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
assert.equal( book.isOpen, true, "book is opened" ); assert.equal( book.isOpen, true, "book is opened" );
assert.equal( book.url, "moby-dick/OPS/package.opf", "book url is passed to new Book" ); assert.equal( book.url, "moby-dick/OPS/package.opf", "book url is passed to new Book" );
done(); done();
}); });
}); });
}); });

View file

@ -1,11 +1,11 @@
var assert = require('assert'); var assert = require('assert');
var fs = require('fs'); var fs = require('fs');
if (typeof DOMParser === "undefined") { if (typeof DOMParser === "undefined") {
global.DOMParser = require('xmldom').DOMParser; global.DOMParser = require('xmldom').DOMParser;
} }
describe('EpubCFI', function() { describe('EpubCFI', function() {
var EpubCFI = require('../src/epubcfi.js'); var EpubCFI = require('../src/epubcfi.js');
it('parse a cfi on init', function() { it('parse a cfi on init', function() {
var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)"); var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)");
@ -19,58 +19,58 @@ describe('EpubCFI', function() {
assert.equal( cfi.spinePos, 0, "base is ignored and spinePos is parsed as the first item" ); assert.equal( cfi.spinePos, 0, "base is ignored and spinePos is parsed as the first item" );
}); });
describe('#parse()', function() { describe('#parse()', function() {
var cfi = new EpubCFI(); var cfi = new EpubCFI();
it('parse a cfi on init', function() { it('parse a cfi on init', function() {
var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)"); var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)");
assert.equal( parsed.spinePos, 0, "spinePos is parsed as the first item" ); assert.equal( parsed.spinePos, 0, "spinePos is parsed as the first item" );
}); });
it('parse a cfi and ignore the base if present', function() { it('parse a cfi and ignore the base if present', function() {
var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)", "/6/6[end]"); var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)", "/6/6[end]");
assert.equal( parsed.spinePos, 0, "base is ignored and spinePos is parsed as the first item" ); assert.equal( parsed.spinePos, 0, "base is ignored and spinePos is parsed as the first item" );
}); });
it('parse a cfi with a charecter offset', function() { it('parse a cfi with a charecter offset', function() {
var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)"); var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)");
assert.equal( parsed.path.terminal.offset, 3, "Path has a terminal offset of 3" ); assert.equal( parsed.path.terminal.offset, 3, "Path has a terminal offset of 3" );
}); });
it('parse a cfi with a range', function() { it('parse a cfi with a range', function() {
var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)"); var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)");
assert.equal( parsed.range, true, "Range is true" ); assert.equal( parsed.range, true, "Range is true" );
assert.equal( parsed.start.steps.length, 2, "Start steps are present" ); assert.equal( parsed.start.steps.length, 2, "Start steps are present" );
assert.equal( parsed.end.steps.length, 1, "End steps are present" ); assert.equal( parsed.end.steps.length, 1, "End steps are present" );
assert.equal( parsed.start.terminal.offset, 1, "Start has a terminal offset of 1" ); assert.equal( parsed.start.terminal.offset, 1, "Start has a terminal offset of 1" );
assert.equal( parsed.end.terminal.offset, 4, "End has a terminal offset of 4" ); assert.equal( parsed.end.terminal.offset, 4, "End has a terminal offset of 4" );
}); });
}); });
describe('#toString()', function() { describe('#toString()', function() {
it('parse a cfi and write it back', function() { it('parse a cfi and write it back', function() {
assert.equal(EpubCFI("epubcfi(/6/2[cover]!/6)").toString(), "epubcfi(/6/2[cover]!/6)", "output cfi string is same as input" ); assert.equal(EpubCFI("epubcfi(/6/2[cover]!/6)").toString(), "epubcfi(/6/2[cover]!/6)", "output cfi string is same as input" );
assert.equal(EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)").toString(), "epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)", "output cfi string is same as input" ); assert.equal(EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)").toString(), "epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)", "output cfi string is same as input" );
assert.equal(EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)").toString(), "epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)", "output cfi string is same as input" ); assert.equal(EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)").toString(), "epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)", "output cfi string is same as input" );
}); });
}); });
describe('#checkType()', function() { describe('#checkType()', function() {
it('determine the type of a cfi string', function() { it('determine the type of a cfi string', function() {
var cfi = new EpubCFI(); var cfi = new EpubCFI();
assert.equal( cfi.checkType('epubcfi(/6/2[cover]!/6)'), 'string' ); assert.equal( cfi.checkType('epubcfi(/6/2[cover]!/6)'), 'string' );
assert.equal( cfi.checkType('/6/2[cover]!/6'), false ); assert.equal( cfi.checkType('/6/2[cover]!/6'), false );
}); });
it('determine the type of a cfi', function() { it('determine the type of a cfi', function() {
var ogcfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)"); var ogcfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)");
@ -96,10 +96,10 @@ describe('EpubCFI', function() {
}); });
}); });
describe('#compare()', function() { describe('#compare()', function() {
it('compare CFIs', function() { it('compare CFIs', function() {
var epubcfi = new EpubCFI(); var epubcfi = new EpubCFI();
// Spines // Spines
@ -131,272 +131,272 @@ describe('EpubCFI', function() {
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/5:1)", "epubcfi(/6/2[cover]!/4/6/15:2)"), 1, "First Element is greater"); assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/5:1)", "epubcfi(/6/2[cover]!/4/6/15:2)"), 1, "First Element is greater");
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/1:0)", "epubcfi(/6/2[cover]!/4/8/1:0)"), 0, "All Equal"); assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/1:0)", "epubcfi(/6/2[cover]!/4/8/1:0)"), 0, "All Equal");
}); });
}); });
describe('#fromNode()', function() { describe('#fromNode()', function() {
var base = "/6/4[chap01ref]"; var base = "/6/4[chap01ref]";
var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8');
// var serializer = new XMLSerializer(); // var serializer = new XMLSerializer();
// var doc = serializer.serializeToString(contents); // var doc = serializer.serializeToString(contents);
var doc = new DOMParser().parseFromString(contents, "application/xhtml+xml"); var doc = new DOMParser().parseFromString(contents, "application/xhtml+xml");
it('get a cfi from a p node', function() { it('get a cfi from a p node', function() {
var span = doc.getElementById('c001p0004'); var span = doc.getElementById('c001p0004');
var cfi = new EpubCFI(span, base); var cfi = new EpubCFI(span, base);
assert.equal(span.nodeType, Node.ELEMENT_NODE, "provided a element node"); assert.equal(span.nodeType, Node.ELEMENT_NODE, "provided a element node");
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004])" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004])" );
}); });
it('get a cfi from a text node', function() { it('get a cfi from a text node', function() {
var t = doc.getElementById('c001p0004').childNodes[0]; var t = doc.getElementById('c001p0004').childNodes[0];
var cfi = new EpubCFI(t, base); var cfi = new EpubCFI(t, base);
assert.equal(t.nodeType, Node.TEXT_NODE, "provided a text node"); assert.equal(t.nodeType, Node.TEXT_NODE, "provided a text node");
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004]/1)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004]/1)" );
}); });
it('get a cfi from a text node inside a highlight', function() { it('get a cfi from a text node inside a highlight', function() {
var t = doc.getElementById('highlight-1').childNodes[0]; var t = doc.getElementById('highlight-1').childNodes[0];
var cfi = new EpubCFI(t, base, 'annotator-hl'); var cfi = new EpubCFI(t, base, 'annotator-hl');
assert.equal(t.nodeType, Node.TEXT_NODE, "provided a text node"); assert.equal(t.nodeType, Node.TEXT_NODE, "provided a text node");
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1)" );
}); });
it('get a cfi from a highlight node', function() { it('get a cfi from a highlight node', function() {
var t = doc.getElementById('highlight-1'); var t = doc.getElementById('highlight-1');
var cfi = new EpubCFI(t, base, 'annotator-hl'); var cfi = new EpubCFI(t, base, 'annotator-hl');
assert.equal(t.nodeType, Node.ELEMENT_NODE, "provided a highlight node"); assert.equal(t.nodeType, Node.ELEMENT_NODE, "provided a highlight node");
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017])" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017])" );
}); });
}); });
describe('#fromRange()', function() { describe('#fromRange()', function() {
var base = "/6/4[chap01ref]"; var base = "/6/4[chap01ref]";
var contentsClean = fs.readFileSync(__dirname + '/fixtures/chapter1.xhtml', 'utf8'); var contentsClean = fs.readFileSync(__dirname + '/fixtures/chapter1.xhtml', 'utf8');
var doc = new DOMParser().parseFromString(contentsClean, "application/xhtml+xml"); var doc = new DOMParser().parseFromString(contentsClean, "application/xhtml+xml");
var contentsHighlights = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); var contentsHighlights = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8');
var docHighlights = new DOMParser().parseFromString(contentsHighlights, "application/xhtml+xml"); var docHighlights = new DOMParser().parseFromString(contentsHighlights, "application/xhtml+xml");
var highlightContents = fs.readFileSync(__dirname + '/fixtures/highlight.xhtml', 'utf8'); var highlightContents = fs.readFileSync(__dirname + '/fixtures/highlight.xhtml', 'utf8');
var docHighlightsAlice = new DOMParser().parseFromString(highlightContents, "application/xhtml+xml"); var docHighlightsAlice = new DOMParser().parseFromString(highlightContents, "application/xhtml+xml");
it('get a cfi from a collapsed range', function() { it('get a cfi from a collapsed range', function() {
var t1 = doc.getElementById('c001p0004').childNodes[0]; var t1 = doc.getElementById('c001p0004').childNodes[0];
var t2 = doc.getElementById('c001p0007').childNodes[0]; var t2 = doc.getElementById('c001p0007').childNodes[0];
var range = doc.createRange(); var range = doc.createRange();
var cfi; var cfi;
range.setStart(t1, 6); range.setStart(t1, 6);
cfi = new EpubCFI(range, base); cfi = new EpubCFI(range, base);
assert.equal( cfi.range, false); assert.equal( cfi.range, false);
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004]/1:6)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004]/1:6)" );
}); });
it('get a cfi from a range', function() { it('get a cfi from a range', function() {
var t1 = doc.getElementById('c001p0004').childNodes[0]; var t1 = doc.getElementById('c001p0004').childNodes[0];
var t2 = doc.getElementById('c001p0007').childNodes[0]; var t2 = doc.getElementById('c001p0007').childNodes[0];
var range = doc.createRange(); var range = doc.createRange();
var cfi; var cfi;
range.setStart(t1, 6); range.setStart(t1, 6);
range.setEnd(t2, 27); range.setEnd(t2, 27);
cfi = new EpubCFI(range, base); cfi = new EpubCFI(range, base);
assert.equal( cfi.range, true); assert.equal( cfi.range, true);
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2,/10/2[c001p0004]/1:6,/16/2[c001p0007]/1:27)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2,/10/2[c001p0004]/1:6,/16/2[c001p0007]/1:27)" );
}); });
it('get a cfi from a range with offset 0', function() { it('get a cfi from a range with offset 0', function() {
var t1 = doc.getElementById('c001p0004').childNodes[0]; var t1 = doc.getElementById('c001p0004').childNodes[0];
var range = doc.createRange(); var range = doc.createRange();
var cfi; var cfi;
range.setStart(t1, 0); range.setStart(t1, 0);
range.setEnd(t1, 1); range.setEnd(t1, 1);
cfi = new EpubCFI(range, base); cfi = new EpubCFI(range, base);
assert.equal( cfi.range, true); assert.equal( cfi.range, true);
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004],/1:0,/1:1)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004],/1:0,/1:1)" );
}); });
it('get a cfi from a range inside a highlight', function() { it('get a cfi from a range inside a highlight', function() {
var t1 = docHighlights.getElementById('highlight-1').childNodes[0]; var t1 = docHighlights.getElementById('highlight-1').childNodes[0];
var range = docHighlights.createRange(); var range = docHighlights.createRange();
var cfi; var cfi;
range.setStart(t1, 6); range.setStart(t1, 6);
cfi = new EpubCFI(range, base, 'annotator-hl'); cfi = new EpubCFI(range, base, 'annotator-hl');
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" );
}); });
// TODO: might need to have double ranges in front // TODO: might need to have double ranges in front
it('get a cfi from a range past a highlight', function() { it('get a cfi from a range past a highlight', function() {
var t1 = docHighlights.getElementById('c001s0001').childNodes[1]; var t1 = docHighlights.getElementById('c001s0001').childNodes[1];
var range = docHighlights.createRange(); var range = docHighlights.createRange();
var cfi; var cfi;
range.setStart(t1, 25); range.setStart(t1, 25);
cfi = new EpubCFI(range, base, 'annotator-hl'); cfi = new EpubCFI(range, base, 'annotator-hl');
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001]/1:41)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001]/1:41)" );
}); });
it('get a cfi from a range inbetween two highlights', function() { it('get a cfi from a range inbetween two highlights', function() {
var t1 = docHighlightsAlice.getElementById('p2').childNodes[1]; var t1 = docHighlightsAlice.getElementById('p2').childNodes[1];
var range = docHighlightsAlice.createRange(); var range = docHighlightsAlice.createRange();
var cfi; var cfi;
range.setStart(t1, 4); range.setStart(t1, 4);
cfi = new EpubCFI(range, base, 'annotator-hl'); cfi = new EpubCFI(range, base, 'annotator-hl');
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/4[p2]/1:123)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/4[p2]/1:123)" );
}); });
it('correctly count text nodes, independent of any elements present inbetween', function() { it('correctly count text nodes, independent of any elements present inbetween', function() {
var t1 = docHighlightsAlice.getElementById('p3').childNodes[2]; var t1 = docHighlightsAlice.getElementById('p3').childNodes[2];
var range = docHighlightsAlice.createRange(); var range = docHighlightsAlice.createRange();
var cfi; var cfi;
range.setStart(t1, 4); range.setStart(t1, 4);
cfi = new EpubCFI(range, base); cfi = new EpubCFI(range, base);
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/6[p3]/3:4)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/6[p3]/3:4)" );
}); });
}); });
describe('#toRange()', function() { describe('#toRange()', function() {
var base = "/6/4[chap01ref]"; var base = "/6/4[chap01ref]";
var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8'); var contents = fs.readFileSync(__dirname + '/fixtures/chapter1-highlights.xhtml', 'utf8');
var doc = new DOMParser().parseFromString(contents, "application/xhtml+xml"); var doc = new DOMParser().parseFromString(contents, "application/xhtml+xml");
// var serializer = new XMLSerializer(); // var serializer = new XMLSerializer();
// console.log(serializer.serializeToString(doc)); // console.log(serializer.serializeToString(doc));
it('get a range from a cfi', function() { it('get a range from a cfi', function() {
var t1 = doc.getElementById('c001p0004').childNodes[0]; var t1 = doc.getElementById('c001p0004').childNodes[0];
var t2 = doc.getElementById('c001p0007').childNodes[0]; var t2 = doc.getElementById('c001p0007').childNodes[0];
var ogRange = doc.createRange(); var ogRange = doc.createRange();
var cfi; var cfi;
var newRange; var newRange;
ogRange.setStart(t1, 6); ogRange.setStart(t1, 6);
cfi = new EpubCFI(ogRange, base); cfi = new EpubCFI(ogRange, base);
// Check it was parse correctly // Check it was parse correctly
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004]/1:6)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/10/2[c001p0004]/1:6)" );
// Check the range // Check the range
newRange = cfi.toRange(doc); newRange = cfi.toRange(doc);
assert.equal( newRange.startContainer, t1); assert.equal( newRange.startContainer, t1);
assert.equal( newRange.startOffset, 6); assert.equal( newRange.startOffset, 6);
assert.equal( newRange.collapsed, true); assert.equal( newRange.collapsed, true);
}); });
it('get a range from a cfi with a range', function() { it('get a range from a cfi with a range', function() {
var t1 = doc.getElementById('c001p0004').childNodes[0]; var t1 = doc.getElementById('c001p0004').childNodes[0];
var t2 = doc.getElementById('c001p0007').childNodes[0]; var t2 = doc.getElementById('c001p0007').childNodes[0];
var ogRange = doc.createRange(); var ogRange = doc.createRange();
var cfi; var cfi;
var newRange; var newRange;
ogRange.setStart(t1, 6); ogRange.setStart(t1, 6);
ogRange.setEnd(t2, 27); ogRange.setEnd(t2, 27);
cfi = new EpubCFI(ogRange, base); cfi = new EpubCFI(ogRange, base);
// Check it was parse correctly // Check it was parse correctly
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2,/10/2[c001p0004]/1:6,/16/2[c001p0007]/1:27)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2,/10/2[c001p0004]/1:6,/16/2[c001p0007]/1:27)" );
// Check the range // Check the range
newRange = cfi.toRange(doc); newRange = cfi.toRange(doc);
assert.equal( newRange.startContainer, t1); assert.equal( newRange.startContainer, t1);
assert.equal( newRange.startOffset, 6); assert.equal( newRange.startOffset, 6);
assert.equal( newRange.endContainer, t2); assert.equal( newRange.endContainer, t2);
assert.equal( newRange.endOffset, 27); assert.equal( newRange.endOffset, 27);
assert.equal( newRange.collapsed, false); assert.equal( newRange.collapsed, false);
}); });
it('get a cfi from a range inside a highlight', function() { it('get a cfi from a range inside a highlight', function() {
var t1 = doc.getElementById('highlight-1').childNodes[0]; var t1 = doc.getElementById('highlight-1').childNodes[0];
var ogRange = doc.createRange(); var ogRange = doc.createRange();
var cfi; var cfi;
var newRange; var newRange;
ogRange.setStart(t1, 6); ogRange.setStart(t1, 6);
cfi = new EpubCFI(ogRange, base, 'annotator-hl'); cfi = new EpubCFI(ogRange, base, 'annotator-hl');
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/32/2[c001p0017]/1:43)" );
// Check the range // Check the range
newRange = cfi.toRange(doc, 'annotator-hl'); newRange = cfi.toRange(doc, 'annotator-hl');
assert.ok(newRange.startContainer); assert.ok(newRange.startContainer);
assert.equal( newRange.startContainer, t1); assert.equal( newRange.startContainer, t1);
assert.equal( newRange.startOffset, 6); assert.equal( newRange.startOffset, 6);
}); });
it('get a cfi from a range inside a highlight range', function() { it('get a cfi from a range inside a highlight range', function() {
var t1 = doc.getElementById('highlight-2').childNodes[0]; var t1 = doc.getElementById('highlight-2').childNodes[0];
var t2 = doc.getElementById('c001s0001').childNodes[1]; var t2 = doc.getElementById('c001s0001').childNodes[1];
var ogRange = doc.createRange(); var ogRange = doc.createRange();
var cfi; var cfi;
var newRange; var newRange;
ogRange.setStart(t1, 5); ogRange.setStart(t1, 5);
ogRange.setEnd(t2, 25); ogRange.setEnd(t2, 25);
cfi = new EpubCFI(ogRange, base, 'annotator-hl'); cfi = new EpubCFI(ogRange, base, 'annotator-hl');
assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001],/1:5,/1:41)" ); assert.equal( cfi.toString(), "epubcfi(/6/4[chap01ref]!/4/2/4/2[c001s0001],/1:5,/1:41)" );
// Check the range // Check the range
newRange = cfi.toRange(doc, 'annotator-hl'); newRange = cfi.toRange(doc, 'annotator-hl');
assert.strictEqual( newRange.startContainer.textContent, t1.textContent); assert.strictEqual( newRange.startContainer.textContent, t1.textContent);
// assert.strictEqual( newRange.startContainer, t1); // assert.strictEqual( newRange.startContainer, t1);
// assert.equal( newRange.startOffset, 5); // assert.equal( newRange.startOffset, 5);
}); });
}); });
}); });

View file

@ -3,102 +3,102 @@ var domain = window.location.origin;
module('Core'); module('Core');
test("EPUBJS.core.resolveUrl", 1, function() { test("EPUBJS.core.resolveUrl", 1, function() {
var a = "http://example.com/fred/chasen/"; var a = "http://example.com/fred/chasen/";
var b = "/chasen/derf.html"; var b = "/chasen/derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b); var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "http://example.com/fred/chasen/derf.html", "resolved" ); equal( resolved, "http://example.com/fred/chasen/derf.html", "resolved" );
}); });
test("EPUBJS.core.resolveUrl ../", 1, function() { test("EPUBJS.core.resolveUrl ../", 1, function() {
var a = "http://example.com/fred/chasen/"; var a = "http://example.com/fred/chasen/";
var b = "../derf.html"; var b = "../derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b); var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "http://example.com/fred/derf.html", "resolved" ); equal( resolved, "http://example.com/fred/derf.html", "resolved" );
}); });
test("EPUBJS.core.resolveUrl folders", 1, function() { test("EPUBJS.core.resolveUrl folders", 1, function() {
var a = "/fred/chasen/"; var a = "/fred/chasen/";
var b = "/fred/chasen/derf.html"; var b = "/fred/chasen/derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b); var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "/fred/chasen/derf.html", "resolved" ); equal( resolved, "/fred/chasen/derf.html", "resolved" );
}); });
test("EPUBJS.core.resolveUrl ../folders", 1, function() { test("EPUBJS.core.resolveUrl ../folders", 1, function() {
var a = "/fred/chasen/"; var a = "/fred/chasen/";
var b = "../../derf.html"; var b = "../../derf.html";
var resolved = EPUBJS.core.resolveUrl(a, b); var resolved = EPUBJS.core.resolveUrl(a, b);
equal( resolved, "/derf.html", "resolved" ); equal( resolved, "/derf.html", "resolved" );
}); });
module('Create'); module('Create');
asyncTest("Create new ePub(/path/to/epub/)", 1, function() { asyncTest("Create new ePub(/path/to/epub/)", 1, function() {
var book = ePub("../books/moby-dick/"); var book = ePub("../books/moby-dick/");
book.opened.then(function(){ book.opened.then(function(){
equal( book.url, "../books/moby-dick/OPS/", "book url is passed to new EPUBJS.Book" ); equal( book.url, "../books/moby-dick/OPS/", "book url is passed to new EPUBJS.Book" );
start(); start();
}); });
}); });
asyncTest("Create new ePub(/path/to/epub/package.opf)", 1, function() { asyncTest("Create new ePub(/path/to/epub/package.opf)", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.url, domain + "/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(); start();
}); });
}); });
asyncTest("Open using ePub(/path/to/epub/package.opf)", 1, function() { asyncTest("Open using ePub(/path/to/epub/package.opf)", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.packageUrl, "../books/moby-dick/OPS/package.opf", "packageUrl is set" ); equal( book.packageUrl, "../books/moby-dick/OPS/package.opf", "packageUrl is set" );
start(); start();
}); });
}); });
asyncTest("Open Remote ePub", 1, function() { asyncTest("Open Remote ePub", 1, function() {
var book = ePub("https://s3.amazonaws.com/moby-dick/"); var book = ePub("https://s3.amazonaws.com/moby-dick/");
book.opened.then(function(){ book.opened.then(function(){
equal( book.packageUrl, "https://s3.amazonaws.com/moby-dick/OPS/package.opf", "packageUrl is set" ); equal( book.packageUrl, "https://s3.amazonaws.com/moby-dick/OPS/package.opf", "packageUrl is set" );
start(); start();
}); });
}); });
asyncTest("Open Remote ePub from Package", 1, function() { asyncTest("Open Remote ePub from Package", 1, function() {
var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf"); var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.packageUrl, "https://s3.amazonaws.com/moby-dick/OPS/package.opf", "packageUrl is set" ); equal( book.packageUrl, "https://s3.amazonaws.com/moby-dick/OPS/package.opf", "packageUrl is set" );
start(); start();
}); });
}); });
asyncTest("Find Epub Package", 1, function() { asyncTest("Find Epub Package", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.packageUrl, "../books/moby-dick/OPS/package.opf", "packageUrl is set" ); equal( book.packageUrl, "../books/moby-dick/OPS/package.opf", "packageUrl is set" );
start(); start();
}); });
}); });
@ -108,43 +108,43 @@ module('Parse');
asyncTest("Manifest", 1, function() { asyncTest("Manifest", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( Object.keys(book.package.manifest).length, 152, "Manifest is parsed" ); equal( Object.keys(book.package.manifest).length, 152, "Manifest is parsed" );
start(); start();
}); });
}); });
asyncTest("Metadata", 3, function() { asyncTest("Metadata", 3, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.package.metadata.creator, "Herman Melville", "Creator metadata is parsed" ); equal( book.package.metadata.creator, "Herman Melville", "Creator metadata is parsed" );
equal( book.package.metadata.title, "Moby-Dick", "Title metadata is parsed" ); equal( book.package.metadata.title, "Moby-Dick", "Title metadata is parsed" );
equal( book.package.metadata.identifier, "code.google.com.epub-samples.moby-dick-basic", "Identifier metadata is parsed" ); equal( book.package.metadata.identifier, "code.google.com.epub-samples.moby-dick-basic", "Identifier metadata is parsed" );
start(); start();
}); });
}); });
asyncTest("Spine", 1, function() { asyncTest("Spine", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.package.spine.length, 144, "Spine is parsed" ); equal( book.package.spine.length, 144, "Spine is parsed" );
start(); start();
}); });
}); });
asyncTest("Cover", 1, function() { asyncTest("Cover", 1, function() {
var book = ePub("../books/moby-dick/"); var book = ePub("../books/moby-dick/");
book.opened.then(function(){ book.opened.then(function(){
equal( book.cover, "../books/moby-dick/OPS/images/9780316000000.jpg", "Cover is set" ); equal( book.cover, "../books/moby-dick/OPS/images/9780316000000.jpg", "Cover is set" );
start(); start();
}); });
}); });
@ -152,74 +152,74 @@ module('Spine');
asyncTest("Length", 1, function() { asyncTest("Length", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.spine.length, 144, "All spine items present" ); equal( book.spine.length, 144, "All spine items present" );
start(); start();
}); });
}); });
asyncTest("Items", 1, function() { asyncTest("Items", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
equal( book.spine.spineItems.length, 144, "All spine items added" ); equal( book.spine.spineItems.length, 144, "All spine items added" );
start(); start();
}); });
}); });
asyncTest("First Item", 2, function() { asyncTest("First Item", 2, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
var section = book.spine.get(0); var section = book.spine.get(0);
equal( section.href, "cover.xhtml", "First spine item href found" ); equal( section.href, "cover.xhtml", "First spine item href found" );
equal( section.cfiBase, "/6/2[cover]", "First spine item cfi found" ); equal( section.cfiBase, "/6/2[cover]", "First spine item cfi found" );
start(); start();
}); });
}); });
asyncTest("Find Item by Href", 2, function() { asyncTest("Find Item by Href", 2, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
var section = book.spine.get("chapter_001.xhtml"); var section = book.spine.get("chapter_001.xhtml");
equal( section.href, "chapter_001.xhtml", "chap 1 spine item href found" ); equal( section.href, "chapter_001.xhtml", "chap 1 spine item href found" );
equal( section.cfiBase, "/6/14[xchapter_001]", "chap 1 spine item cfi found" ); equal( section.cfiBase, "/6/14[xchapter_001]", "chap 1 spine item cfi found" );
start(); start();
}); });
}); });
asyncTest("Find Item by ID", 2, function() { asyncTest("Find Item by ID", 2, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
var section = book.spine.get("#xchapter_050"); var section = book.spine.get("#xchapter_050");
equal( section.href, "chapter_050.xhtml", "chap 50 spine item href found" ); equal( section.href, "chapter_050.xhtml", "chap 50 spine item href found" );
equal( section.cfiBase, "/6/112[xchapter_050]", "chap 50 spine item cfi found" ); equal( section.cfiBase, "/6/112[xchapter_050]", "chap 50 spine item cfi found" );
start(); start();
}); });
}); });
asyncTest("Render Spine Item", 1, function() { asyncTest("Render Spine Item", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
var section = book.spine.get("#xchapter_050"); var section = book.spine.get("#xchapter_050");
section.render().then(function(content){ section.render().then(function(content){
equal( content.substring(377, 429), "<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(); start();
}); });
}); });
@ -227,84 +227,84 @@ module('Navigation');
asyncTest("NCX & Nav", 2, function() { asyncTest("NCX & Nav", 2, function() {
var book = ePub("../books/moby-dick/"); var book = ePub("../books/moby-dick/");
book.opened.then(function(){ book.opened.then(function(){
equal( book.navigation.navUrl, "../books/moby-dick/OPS/toc.xhtml", "Nav URL found" ); 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" ); equal( book.navigation.ncxUrl, "../books/moby-dick/OPS/toc.ncx", "NCX URL found" );
start(); start();
}); });
}); });
asyncTest("Load TOC Auto Pick", 1, function() { asyncTest("Load TOC Auto Pick", 1, function() {
var book = ePub("../books/moby-dick/"); var book = ePub("../books/moby-dick/");
book.opened.then(function(){ book.opened.then(function(){
book.navigation.load().then(function(toc){ book.navigation.load().then(function(toc){
equal( toc.length, 141, "Full Nav toc parsed" ); equal( toc.length, 141, "Full Nav toc parsed" );
start(); start();
}); });
}); });
}); });
asyncTest("Load TOC from Nav", 1, function() { asyncTest("Load TOC from Nav", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
var nav = book.navigation.nav.load(); var nav = book.navigation.nav.load();
nav.then(function(toc){ nav.then(function(toc){
equal( toc.length, 141, "Full Nav toc parsed" ); equal( toc.length, 141, "Full Nav toc parsed" );
start(); start();
}); });
}); });
}); });
asyncTest("Load TOC from NCX", 1, function() { asyncTest("Load TOC from NCX", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.opened.then(function(){ book.opened.then(function(){
var ncx = book.navigation.ncx.load(); var ncx = book.navigation.ncx.load();
ncx.then(function(toc){ ncx.then(function(toc){
equal( toc.length, 14, "Full NCX toc parsed" ); equal( toc.length, 14, "Full NCX toc parsed" );
start(); start();
}); });
}); });
}); });
asyncTest("Get all TOC", 1, function() { asyncTest("Get all TOC", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.loaded.navigation.then(function(){ book.loaded.navigation.then(function(){
equal( book.navigation.get().length, 141, "Full Nav toc parsed" ); equal( book.navigation.get().length, 141, "Full Nav toc parsed" );
start(); start();
}); });
}); });
asyncTest("Get TOC item by href", 1, function() { asyncTest("Get TOC item by href", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.loaded.navigation.then(function(){ book.loaded.navigation.then(function(){
var item = book.navigation.get("chapter_001.xhtml"); var item = book.navigation.get("chapter_001.xhtml");
equal( item.id, "toc-chapter_001", "Found TOC item" ); equal( item.id, "toc-chapter_001", "Found TOC item" );
start(); start();
}); });
}); });
asyncTest("Get TOC item by ID", 1, function() { asyncTest("Get TOC item by ID", 1, function() {
var book = ePub("../books/moby-dick/OPS/package.opf"); var book = ePub("../books/moby-dick/OPS/package.opf");
book.loaded.navigation.then(function(){ book.loaded.navigation.then(function(){
var item = book.navigation.get("#toc-chapter_001"); var item = book.navigation.get("#toc-chapter_001");
equal( item.href, "chapter_001.xhtml", "Found TOC item" ); equal( item.href, "chapter_001.xhtml", "Found TOC item" );
start(); start();
}); });
}); });
@ -312,15 +312,15 @@ module('Hooks');
asyncTest("Register a new hook", 1, function() { asyncTest("Register a new hook", 1, function() {
var beforeDisplay = new EPUBJS.Hook(); var beforeDisplay = new EPUBJS.Hook();
beforeDisplay.register(function(args){ beforeDisplay.register(function(args){
var defer = new RSVP.defer(); var defer = new RSVP.defer();
console.log("ran", 1); console.log("ran", 1);
defer.resolve(); defer.resolve();
return defer.promise; return defer.promise;
}); });
equal( beforeDisplay.hooks.length, 1, "Registered a hook" ); equal( beforeDisplay.hooks.length, 1, "Registered a hook" );
start(); start();
// this.beforeDisplay.trigger(args).then(function(){}); // this.beforeDisplay.trigger(args).then(function(){});
@ -328,44 +328,44 @@ asyncTest("Register a new hook", 1, function() {
asyncTest("Trigger all new hook", 4, function() { asyncTest("Trigger all new hook", 4, function() {
var beforeDisplay = new EPUBJS.Hook(this); var beforeDisplay = new EPUBJS.Hook(this);
this.testerObject = {tester: 1}; this.testerObject = {tester: 1};
beforeDisplay.register(function(testerObject){ beforeDisplay.register(function(testerObject){
var defer = new RSVP.defer(); var defer = new RSVP.defer();
start(); start();
equal( testerObject.tester, 1, "tester is 1" ); equal( testerObject.tester, 1, "tester is 1" );
stop(); stop();
testerObject.tester += 1; testerObject.tester += 1;
defer.resolve(); defer.resolve();
return defer.promise; return defer.promise;
}); });
beforeDisplay.register(function(testerObject){ beforeDisplay.register(function(testerObject){
var defer = new RSVP.defer(); var defer = new RSVP.defer();
start(); start();
equal(testerObject.tester, 2, "tester is 2" ); equal(testerObject.tester, 2, "tester is 2" );
stop(); stop();
testerObject.tester += 1; testerObject.tester += 1;
defer.resolve(); defer.resolve();
return defer.promise; return defer.promise;
}); });
start(); start();
equal( beforeDisplay.hooks.length, 2, "Added two hooks" ); equal( beforeDisplay.hooks.length, 2, "Added two hooks" );
stop(); stop();
beforeDisplay.trigger(this.testerObject).then(function(){ beforeDisplay.trigger(this.testerObject).then(function(){
start(); start();
equal( this.testerObject.tester, 3, "tester is 3" ); equal( this.testerObject.tester, 3, "tester is 3" );
}.bind(this)); }.bind(this));
}); });

View file

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