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:
commit
8dd67cc167
31 changed files with 7759 additions and 7758 deletions
7025
dist/epub.js
vendored
7025
dist/epub.js
vendored
File diff suppressed because it is too large
Load diff
2
dist/epub.js.map
vendored
2
dist/epub.js.map
vendored
File diff suppressed because one or more lines are too long
162
gulpfile.js
162
gulpfile.js
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
416
src/book.js
416
src/book.js
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
776
src/contents.js
776
src/contents.js
File diff suppressed because it is too large
Load diff
740
src/core.js
740
src/core.js
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
1300
src/epubcfi.js
1300
src/epubcfi.js
File diff suppressed because it is too large
Load diff
52
src/hook.js
52
src/hook.js
|
@ -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;
|
||||||
|
|
150
src/layout.js
150
src/layout.js
|
@ -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;
|
||||||
|
|
222
src/locations.js
222
src/locations.js
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
390
src/mapping.js
390
src/mapping.js
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
350
src/parser.js
350
src/parser.js
|
@ -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),
|
||||||
|
|
232
src/queue.js
232
src/queue.js
|
@ -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));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
120
src/rendition.js
120
src/rendition.js
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
202
src/request.js
202
src/request.js
|
@ -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;
|
||||||
|
|
192
src/section.js
192
src/section.js
|
@ -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;
|
||||||
|
|
146
src/spine.js
146
src/spine.js
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
182
src/unarchive.js
182
src/unarchive.js
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
136
src/views.js
136
src/views.js
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
50
test/epub.js
50
test/epub.js
|
@ -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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
402
test/epubcfi.js
402
test/epubcfi.js
|
@ -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);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -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. Ahab’s Boat and Crew. Fedallah.</h1>", "Chapter text rendered as string" );
|
equal( content.substring(377, 429), "<h1>Chapter 50. Ahab’s 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));
|
||||||
|
|
||||||
});
|
});
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue