mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-04 15:09:16 +02:00
Added locations generator to get reading percentages
This commit is contained in:
parent
89a9ade8df
commit
d0725af232
18 changed files with 1206 additions and 66 deletions
2
books
2
books
|
@ -1 +1 @@
|
||||||
Subproject commit ab9755a74714b647290c861f666515de220935d8
|
Subproject commit e9790315c2510315e270a7a4c4921825e9918039
|
270
build/epub.js
270
build/epub.js
|
@ -2485,11 +2485,11 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
|
|
||||||
//-- Set Globbal Layout setting based on metadata
|
//-- Set Globbal Layout setting based on metadata
|
||||||
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
||||||
|
|
||||||
if(book.contents.coverPath) {
|
if(book.contents.coverPath) {
|
||||||
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
book.spineNodeIndex = book.contents.spineNodeIndex;
|
book.spineNodeIndex = book.contents.spineNodeIndex;
|
||||||
|
|
||||||
book.ready.manifest.resolve(book.contents.manifest);
|
book.ready.manifest.resolve(book.contents.manifest);
|
||||||
|
@ -2497,6 +2497,7 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
book.ready.metadata.resolve(book.contents.metadata);
|
book.ready.metadata.resolve(book.contents.metadata);
|
||||||
book.ready.cover.resolve(book.contents.cover);
|
book.ready.cover.resolve(book.contents.cover);
|
||||||
|
|
||||||
|
book.locations = new EPUBJS.Locations(book.spine);
|
||||||
|
|
||||||
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
||||||
if(book.contents.navPath) {
|
if(book.contents.navPath) {
|
||||||
|
@ -2763,11 +2764,11 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
|
||||||
EPUBJS.Book.prototype.loadChange = function(url){
|
EPUBJS.Book.prototype.loadChange = function(url){
|
||||||
var uri = EPUBJS.core.uri(url);
|
var uri = EPUBJS.core.uri(url);
|
||||||
var chapter;
|
var chapter;
|
||||||
|
|
||||||
if(this.currentChapter) {
|
if(this.currentChapter) {
|
||||||
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
||||||
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
||||||
this.goto(uri.filename);
|
this.goto(uri.filename);
|
||||||
|
@ -3328,13 +3329,13 @@ EPUBJS.Book.prototype.fromStorage = function(stored) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
||||||
var noreflow = ["color", "background", "background-color"];
|
var noreflow = ["color", "background", "background-color"];
|
||||||
|
|
||||||
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
||||||
|
|
||||||
this.settings.styles[style] = val;
|
this.settings.styles[style] = val;
|
||||||
|
|
||||||
this.renderer.setStyle(style, val, prefixed);
|
this.renderer.setStyle(style, val, prefixed);
|
||||||
|
|
||||||
if(noreflow.indexOf(style) === -1) {
|
if(noreflow.indexOf(style) === -1) {
|
||||||
// clearTimeout(this.reformatTimeout);
|
// clearTimeout(this.reformatTimeout);
|
||||||
// this.reformatTimeout = setTimeout(function(){
|
// this.reformatTimeout = setTimeout(function(){
|
||||||
|
@ -3366,7 +3367,7 @@ EPUBJS.Book.prototype.useSpreads = function(use) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
||||||
var force = typeof _use === "undefined" ? true : _use;
|
var force = typeof _use === "undefined" ? true : _use;
|
||||||
|
|
||||||
this.renderer.forceSingle(force);
|
this.renderer.forceSingle(force);
|
||||||
this.settings.forceSingle = force;
|
this.settings.forceSingle = force;
|
||||||
if(this.isRendered) {
|
if(this.isRendered) {
|
||||||
|
@ -3422,7 +3423,7 @@ EPUBJS.Book.prototype.destroy = function() {
|
||||||
|
|
||||||
this.unload();
|
this.unload();
|
||||||
|
|
||||||
if(this.render) this.render.remove();
|
if(this.renderer) this.renderer.remove();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5168,6 +5169,233 @@ EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations = function(spine, store) {
|
||||||
|
this.spine = spine;
|
||||||
|
this.store = store;
|
||||||
|
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this._locations = [];
|
||||||
|
this.total = 0;
|
||||||
|
|
||||||
|
this.break = 150;
|
||||||
|
|
||||||
|
this._current = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.generate = function(chars) {
|
||||||
|
var deferred = new RSVP.defer();
|
||||||
|
var spinePos = -1;
|
||||||
|
var spineLength = this.spine.length;
|
||||||
|
var nextChapter = function(deferred){
|
||||||
|
var chapter;
|
||||||
|
var next = spinePos + 1;
|
||||||
|
var done = deferred || new RSVP.defer();
|
||||||
|
var loaded;
|
||||||
|
if(next >= spineLength) {
|
||||||
|
done.resolve();
|
||||||
|
} else {
|
||||||
|
spinePos = next;
|
||||||
|
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
|
||||||
|
|
||||||
|
this.process(chapter).then(function() {
|
||||||
|
// Load up the next chapter
|
||||||
|
setTimeout(function(){
|
||||||
|
nextChapter(done);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done.promise;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var finished = nextChapter().then(function(){
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
|
||||||
|
if (this._currentCfi) {
|
||||||
|
this.currentLocation = this._currentCfi;
|
||||||
|
}
|
||||||
|
deferred.resolve(this._locations);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.process = function(chapter) {
|
||||||
|
return chapter.load(this.request)
|
||||||
|
.then(function(_doc) {
|
||||||
|
|
||||||
|
var range;
|
||||||
|
var doc = _doc;
|
||||||
|
var contents = doc.documentElement;
|
||||||
|
var counter = 0;
|
||||||
|
var prev;
|
||||||
|
|
||||||
|
this.sprint(contents, function(node) {
|
||||||
|
var len = node.length;
|
||||||
|
var dist;
|
||||||
|
var pos = 0;
|
||||||
|
|
||||||
|
// Start range
|
||||||
|
if (counter === 0) {
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dist = this.break - counter;
|
||||||
|
|
||||||
|
// Node is smaller than a break
|
||||||
|
if(dist > len){
|
||||||
|
counter += len;
|
||||||
|
pos = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < len) {
|
||||||
|
counter = this.break;
|
||||||
|
pos += this.break;
|
||||||
|
|
||||||
|
// Gone over
|
||||||
|
if(pos >= len){
|
||||||
|
// Continue counter for next node
|
||||||
|
counter = len - (pos - this.break);
|
||||||
|
|
||||||
|
// At End
|
||||||
|
} else {
|
||||||
|
// End the previous range
|
||||||
|
range.setEnd(node, pos);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// Start new range
|
||||||
|
pos += 1;
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = node;
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Close remaining
|
||||||
|
if (range) {
|
||||||
|
range.setEnd(prev, prev.length);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.sprint = function(root, func) {
|
||||||
|
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
|
||||||
|
|
||||||
|
while ((node = treeWalker.nextNode())) {
|
||||||
|
func(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.locationFromCfi = function(cfi){
|
||||||
|
// Check if the location has not been set yet
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EPUBJS.core.locationOf(cfi, this._locations, this.epubcfi.compare);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromCfi = function(cfi) {
|
||||||
|
// Find closest cfi
|
||||||
|
var loc = this.locationFromCfi(cfi);
|
||||||
|
// Get percentage in total
|
||||||
|
return this.percentageFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromLocation = function(loc) {
|
||||||
|
if (!loc || !this.total) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Math.floor((loc / this.total ) * 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromLocation = function(loc){
|
||||||
|
var cfi = -1;
|
||||||
|
// check that pg is an int
|
||||||
|
if(typeof loc != "number"){
|
||||||
|
loc = parseInt(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loc >= 0 && loc < this._locations.length) {
|
||||||
|
cfi = this._locations[loc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfi;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromPercentage = function(percent){
|
||||||
|
var loc = Math.ceil(this.total * (percent/100));
|
||||||
|
|
||||||
|
return this.cfiFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.load = function(locations){
|
||||||
|
this._locations = JSON.parse(locations);
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
return this._locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.save = function(json){
|
||||||
|
return JSON.stringify(this._locations);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.getCurrent = function(json){
|
||||||
|
return this._current;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.setCurrent = function(curr){
|
||||||
|
var loc;
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
this._currentCfi = curr;
|
||||||
|
} else if (typeof curr == "number") {
|
||||||
|
this._current = curr;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
loc = this.locationFromCfi(curr);
|
||||||
|
this._current = loc;
|
||||||
|
} else {
|
||||||
|
loc = curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("changed", {
|
||||||
|
percentage: this.percentageFromLocation(loc)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(EPUBJS.Locations.prototype, 'currentLocation', {
|
||||||
|
get: function () {
|
||||||
|
return this._current;
|
||||||
|
},
|
||||||
|
set: function (curr) {
|
||||||
|
this.setCurrent(curr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(EPUBJS.Locations.prototype);
|
||||||
|
|
||||||
EPUBJS.Pagination = function(pageList) {
|
EPUBJS.Pagination = function(pageList) {
|
||||||
this.pages = [];
|
this.pages = [];
|
||||||
this.locations = [];
|
this.locations = [];
|
||||||
|
@ -7305,13 +7533,24 @@ EPUBJS.replace.hrefs = function(callback, renderer){
|
||||||
link.setAttribute("target", "_blank");
|
link.setAttribute("target", "_blank");
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// Links may need to be resolved, such as ../chp1.xhtml
|
// Links may need to be resolved, such as ../chp1.xhtml
|
||||||
directory = EPUBJS.core.uri(renderer.render.window.location.href).directory;
|
var uri = EPUBJS.core.uri(renderer.render.window.location.href);
|
||||||
if(directory) {
|
|
||||||
relative = EPUBJS.core.resolveUrl(directory, href);
|
directory = uri.directory;
|
||||||
} else {
|
|
||||||
relative = href;
|
if(directory) {
|
||||||
}
|
// We must ensure that the file:// protocol is preserved for
|
||||||
|
// local file links, as in certain contexts (such as under
|
||||||
|
// Titanium), file links without the file:// protocol will not
|
||||||
|
// work
|
||||||
|
if (uri.protocol === "file") {
|
||||||
|
relative = EPUBJS.core.resolveUrl(uri.base, href);
|
||||||
|
} else {
|
||||||
|
relative = EPUBJS.core.resolveUrl(directory, href);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
relative = href;
|
||||||
|
}
|
||||||
|
|
||||||
link.onclick = function(){
|
link.onclick = function(){
|
||||||
book.goto(relative);
|
book.goto(relative);
|
||||||
|
@ -7435,6 +7674,7 @@ EPUBJS.replace.cssUrls = function(_store, base, text){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Unarchiver = function(url){
|
EPUBJS.Unarchiver = function(url){
|
||||||
|
|
||||||
this.loadLib();
|
this.loadLib();
|
||||||
|
|
File diff suppressed because one or more lines are too long
7
build/epub.min.js
vendored
7
build/epub.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2484,11 +2484,11 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
|
|
||||||
//-- Set Globbal Layout setting based on metadata
|
//-- Set Globbal Layout setting based on metadata
|
||||||
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
||||||
|
|
||||||
if(book.contents.coverPath) {
|
if(book.contents.coverPath) {
|
||||||
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
book.spineNodeIndex = book.contents.spineNodeIndex;
|
book.spineNodeIndex = book.contents.spineNodeIndex;
|
||||||
|
|
||||||
book.ready.manifest.resolve(book.contents.manifest);
|
book.ready.manifest.resolve(book.contents.manifest);
|
||||||
|
@ -2496,6 +2496,7 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
book.ready.metadata.resolve(book.contents.metadata);
|
book.ready.metadata.resolve(book.contents.metadata);
|
||||||
book.ready.cover.resolve(book.contents.cover);
|
book.ready.cover.resolve(book.contents.cover);
|
||||||
|
|
||||||
|
book.locations = new EPUBJS.Locations(book.spine);
|
||||||
|
|
||||||
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
||||||
if(book.contents.navPath) {
|
if(book.contents.navPath) {
|
||||||
|
@ -2762,11 +2763,11 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
|
||||||
EPUBJS.Book.prototype.loadChange = function(url){
|
EPUBJS.Book.prototype.loadChange = function(url){
|
||||||
var uri = EPUBJS.core.uri(url);
|
var uri = EPUBJS.core.uri(url);
|
||||||
var chapter;
|
var chapter;
|
||||||
|
|
||||||
if(this.currentChapter) {
|
if(this.currentChapter) {
|
||||||
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
||||||
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
||||||
this.goto(uri.filename);
|
this.goto(uri.filename);
|
||||||
|
@ -3327,13 +3328,13 @@ EPUBJS.Book.prototype.fromStorage = function(stored) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
||||||
var noreflow = ["color", "background", "background-color"];
|
var noreflow = ["color", "background", "background-color"];
|
||||||
|
|
||||||
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
||||||
|
|
||||||
this.settings.styles[style] = val;
|
this.settings.styles[style] = val;
|
||||||
|
|
||||||
this.renderer.setStyle(style, val, prefixed);
|
this.renderer.setStyle(style, val, prefixed);
|
||||||
|
|
||||||
if(noreflow.indexOf(style) === -1) {
|
if(noreflow.indexOf(style) === -1) {
|
||||||
// clearTimeout(this.reformatTimeout);
|
// clearTimeout(this.reformatTimeout);
|
||||||
// this.reformatTimeout = setTimeout(function(){
|
// this.reformatTimeout = setTimeout(function(){
|
||||||
|
@ -3365,7 +3366,7 @@ EPUBJS.Book.prototype.useSpreads = function(use) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
||||||
var force = typeof _use === "undefined" ? true : _use;
|
var force = typeof _use === "undefined" ? true : _use;
|
||||||
|
|
||||||
this.renderer.forceSingle(force);
|
this.renderer.forceSingle(force);
|
||||||
this.settings.forceSingle = force;
|
this.settings.forceSingle = force;
|
||||||
if(this.isRendered) {
|
if(this.isRendered) {
|
||||||
|
@ -3421,7 +3422,7 @@ EPUBJS.Book.prototype.destroy = function() {
|
||||||
|
|
||||||
this.unload();
|
this.unload();
|
||||||
|
|
||||||
if(this.render) this.render.remove();
|
if(this.renderer) this.renderer.remove();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5167,6 +5168,233 @@ EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations = function(spine, store) {
|
||||||
|
this.spine = spine;
|
||||||
|
this.store = store;
|
||||||
|
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this._locations = [];
|
||||||
|
this.total = 0;
|
||||||
|
|
||||||
|
this.break = 150;
|
||||||
|
|
||||||
|
this._current = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.generate = function(chars) {
|
||||||
|
var deferred = new RSVP.defer();
|
||||||
|
var spinePos = -1;
|
||||||
|
var spineLength = this.spine.length;
|
||||||
|
var nextChapter = function(deferred){
|
||||||
|
var chapter;
|
||||||
|
var next = spinePos + 1;
|
||||||
|
var done = deferred || new RSVP.defer();
|
||||||
|
var loaded;
|
||||||
|
if(next >= spineLength) {
|
||||||
|
done.resolve();
|
||||||
|
} else {
|
||||||
|
spinePos = next;
|
||||||
|
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
|
||||||
|
|
||||||
|
this.process(chapter).then(function() {
|
||||||
|
// Load up the next chapter
|
||||||
|
setTimeout(function(){
|
||||||
|
nextChapter(done);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done.promise;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var finished = nextChapter().then(function(){
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
|
||||||
|
if (this._currentCfi) {
|
||||||
|
this.currentLocation = this._currentCfi;
|
||||||
|
}
|
||||||
|
deferred.resolve(this._locations);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.process = function(chapter) {
|
||||||
|
return chapter.load(this.request)
|
||||||
|
.then(function(_doc) {
|
||||||
|
|
||||||
|
var range;
|
||||||
|
var doc = _doc;
|
||||||
|
var contents = doc.documentElement;
|
||||||
|
var counter = 0;
|
||||||
|
var prev;
|
||||||
|
|
||||||
|
this.sprint(contents, function(node) {
|
||||||
|
var len = node.length;
|
||||||
|
var dist;
|
||||||
|
var pos = 0;
|
||||||
|
|
||||||
|
// Start range
|
||||||
|
if (counter === 0) {
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dist = this.break - counter;
|
||||||
|
|
||||||
|
// Node is smaller than a break
|
||||||
|
if(dist > len){
|
||||||
|
counter += len;
|
||||||
|
pos = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < len) {
|
||||||
|
counter = this.break;
|
||||||
|
pos += this.break;
|
||||||
|
|
||||||
|
// Gone over
|
||||||
|
if(pos >= len){
|
||||||
|
// Continue counter for next node
|
||||||
|
counter = len - (pos - this.break);
|
||||||
|
|
||||||
|
// At End
|
||||||
|
} else {
|
||||||
|
// End the previous range
|
||||||
|
range.setEnd(node, pos);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// Start new range
|
||||||
|
pos += 1;
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = node;
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Close remaining
|
||||||
|
if (range) {
|
||||||
|
range.setEnd(prev, prev.length);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.sprint = function(root, func) {
|
||||||
|
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
|
||||||
|
|
||||||
|
while ((node = treeWalker.nextNode())) {
|
||||||
|
func(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.locationFromCfi = function(cfi){
|
||||||
|
// Check if the location has not been set yet
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EPUBJS.core.locationOf(cfi, this._locations, this.epubcfi.compare);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromCfi = function(cfi) {
|
||||||
|
// Find closest cfi
|
||||||
|
var loc = this.locationFromCfi(cfi);
|
||||||
|
// Get percentage in total
|
||||||
|
return this.percentageFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromLocation = function(loc) {
|
||||||
|
if (!loc || !this.total) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Math.floor((loc / this.total ) * 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromLocation = function(loc){
|
||||||
|
var cfi = -1;
|
||||||
|
// check that pg is an int
|
||||||
|
if(typeof loc != "number"){
|
||||||
|
loc = parseInt(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loc >= 0 && loc < this._locations.length) {
|
||||||
|
cfi = this._locations[loc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfi;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromPercentage = function(percent){
|
||||||
|
var loc = Math.ceil(this.total * (percent/100));
|
||||||
|
|
||||||
|
return this.cfiFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.load = function(locations){
|
||||||
|
this._locations = JSON.parse(locations);
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
return this._locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.save = function(json){
|
||||||
|
return JSON.stringify(this._locations);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.getCurrent = function(json){
|
||||||
|
return this._current;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.setCurrent = function(curr){
|
||||||
|
var loc;
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
this._currentCfi = curr;
|
||||||
|
} else if (typeof curr == "number") {
|
||||||
|
this._current = curr;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
loc = this.locationFromCfi(curr);
|
||||||
|
this._current = loc;
|
||||||
|
} else {
|
||||||
|
loc = curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("changed", {
|
||||||
|
percentage: this.percentageFromLocation(loc)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(EPUBJS.Locations.prototype, 'currentLocation', {
|
||||||
|
get: function () {
|
||||||
|
return this._current;
|
||||||
|
},
|
||||||
|
set: function (curr) {
|
||||||
|
this.setCurrent(curr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(EPUBJS.Locations.prototype);
|
||||||
|
|
||||||
EPUBJS.Pagination = function(pageList) {
|
EPUBJS.Pagination = function(pageList) {
|
||||||
this.pages = [];
|
this.pages = [];
|
||||||
this.locations = [];
|
this.locations = [];
|
||||||
|
@ -7304,13 +7532,24 @@ EPUBJS.replace.hrefs = function(callback, renderer){
|
||||||
link.setAttribute("target", "_blank");
|
link.setAttribute("target", "_blank");
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// Links may need to be resolved, such as ../chp1.xhtml
|
// Links may need to be resolved, such as ../chp1.xhtml
|
||||||
directory = EPUBJS.core.uri(renderer.render.window.location.href).directory;
|
var uri = EPUBJS.core.uri(renderer.render.window.location.href);
|
||||||
if(directory) {
|
|
||||||
relative = EPUBJS.core.resolveUrl(directory, href);
|
directory = uri.directory;
|
||||||
} else {
|
|
||||||
relative = href;
|
if(directory) {
|
||||||
}
|
// We must ensure that the file:// protocol is preserved for
|
||||||
|
// local file links, as in certain contexts (such as under
|
||||||
|
// Titanium), file links without the file:// protocol will not
|
||||||
|
// work
|
||||||
|
if (uri.protocol === "file") {
|
||||||
|
relative = EPUBJS.core.resolveUrl(uri.base, href);
|
||||||
|
} else {
|
||||||
|
relative = EPUBJS.core.resolveUrl(directory, href);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
relative = href;
|
||||||
|
}
|
||||||
|
|
||||||
link.onclick = function(){
|
link.onclick = function(){
|
||||||
book.goto(relative);
|
book.goto(relative);
|
||||||
|
@ -7434,6 +7673,7 @@ EPUBJS.replace.cssUrls = function(_store, base, text){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Unarchiver = function(url){
|
EPUBJS.Unarchiver = function(url){
|
||||||
|
|
||||||
this.loadLib();
|
this.loadLib();
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,5 +8,5 @@
|
||||||
"hooks/default/transculsions.js"
|
"hooks/default/transculsions.js"
|
||||||
],
|
],
|
||||||
"names": [],
|
"names": [],
|
||||||
"mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A"
|
"mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
2
build/reader.min.js
vendored
2
build/reader.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
190
examples/locations.html
Normal file
190
examples/locations.html
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<title>Basic ePubJS Example</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
|
||||||
|
<script src="../build/epub.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Hooks -->
|
||||||
|
<!-- <script src="../hooks/default/transculsions.js"></script> -->
|
||||||
|
<!-- <script src="../hooks/default/endnotes.js"></script> -->
|
||||||
|
<script src="../hooks/default/smartimages.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
EPUBJS.filePath = "../reader/js/libs/";
|
||||||
|
EPUBJS.cssPath = "../reader/css/";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
body {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* overflow: hidden; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#area {
|
||||||
|
width: 80%;
|
||||||
|
height: 80%;
|
||||||
|
margin: 5% auto;
|
||||||
|
max-width: 1250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#area iframe {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#prev {
|
||||||
|
left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -32px;
|
||||||
|
font-size: 64px;
|
||||||
|
color: #E2E2E2;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow:hover {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow:active {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 16px;
|
||||||
|
left: 50%;
|
||||||
|
width: 400px;
|
||||||
|
margin-left: -200px;
|
||||||
|
text-align: center;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls > input[type=range] {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var book = ePub("../books/moby-dick/", { width: 1076, height: 588 });
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="main">
|
||||||
|
<div id="prev" onclick="book.prevPage();" class="arrow">‹</div>
|
||||||
|
<div id="area"></div>
|
||||||
|
<div id="next" onclick="book.nextPage();"class="arrow">›</div>
|
||||||
|
<div id="controls">
|
||||||
|
<input id="current-percent" size="3" value="0" /> %
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var controls = document.getElementById("controls");
|
||||||
|
var currentPage = document.getElementById("current-percent");
|
||||||
|
var slider = document.createElement("input");
|
||||||
|
var slide = function(){
|
||||||
|
var cfi = book.locations.cfiFromPercentage(slider.value);
|
||||||
|
book.gotoCfi(cfi);
|
||||||
|
};
|
||||||
|
var throttledSlide = _.throttle(slide, 200);
|
||||||
|
var mouseDown = false;
|
||||||
|
|
||||||
|
var rendered = book.renderTo("area");
|
||||||
|
|
||||||
|
|
||||||
|
book.ready.all.then(function(){
|
||||||
|
// Load in stored locations from json or local storage
|
||||||
|
var key = book.generateBookKey()+'-locations';
|
||||||
|
var stored = false;//localStorage.getItem(key);
|
||||||
|
if (stored) {
|
||||||
|
return book.locations.load(stored);
|
||||||
|
} else {
|
||||||
|
// Or generate the locations on the fly
|
||||||
|
// Can pass an option number of chars to break sections by
|
||||||
|
// default is 150 chars
|
||||||
|
return book.locations.generate(1600);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function(locations){
|
||||||
|
|
||||||
|
controls.style.display = "block";
|
||||||
|
slider.setAttribute("type", "range");
|
||||||
|
slider.setAttribute("min", 0);
|
||||||
|
slider.setAttribute("max", 100);
|
||||||
|
// slider.setAttribute("max", book.locations.total+1);
|
||||||
|
slider.setAttribute("step", 1);
|
||||||
|
slider.setAttribute("value", 0);
|
||||||
|
|
||||||
|
slider.addEventListener("change", throttledSlide, false);
|
||||||
|
slider.addEventListener("mousedown", function(){
|
||||||
|
mouseDown = true;
|
||||||
|
}, false);
|
||||||
|
slider.addEventListener("mouseup", function(){
|
||||||
|
mouseDown = false;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Wait for book to be rendered to get current page
|
||||||
|
rendered.then(function(){
|
||||||
|
// Get the current CFI
|
||||||
|
var currentLocation = book.getCurrentLocationCfi();
|
||||||
|
// Get the Percentage (or location) from that CFI
|
||||||
|
var currentPage = book.locations.percentageFromCfi(currentLocation);
|
||||||
|
slider.value = currentPage;
|
||||||
|
currentPage.value = currentPage;
|
||||||
|
});
|
||||||
|
|
||||||
|
controls.appendChild(slider);
|
||||||
|
|
||||||
|
currentPage.addEventListener("change", function(){
|
||||||
|
var cfi = book.locations.cfiFromPercentage(currentPage.value);
|
||||||
|
book.gotoCfi(cfi);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Listen for location changed event, get percentage from CFI
|
||||||
|
book.on('renderer:locationChanged', function(location){
|
||||||
|
var percent = book.locations.percentageFromCfi(location);
|
||||||
|
if(!mouseDown) {
|
||||||
|
slider.value = percent;
|
||||||
|
}
|
||||||
|
currentPage.value = percent;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save out the generated locations to JSON
|
||||||
|
localStorage.setItem(book.generateBookKey()+'-locations', book.locations.save());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
File diff suppressed because one or more lines are too long
270
reader/js/epub.min.js
vendored
270
reader/js/epub.min.js
vendored
|
@ -2485,11 +2485,11 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
|
|
||||||
//-- Set Globbal Layout setting based on metadata
|
//-- Set Globbal Layout setting based on metadata
|
||||||
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
||||||
|
|
||||||
if(book.contents.coverPath) {
|
if(book.contents.coverPath) {
|
||||||
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
book.spineNodeIndex = book.contents.spineNodeIndex;
|
book.spineNodeIndex = book.contents.spineNodeIndex;
|
||||||
|
|
||||||
book.ready.manifest.resolve(book.contents.manifest);
|
book.ready.manifest.resolve(book.contents.manifest);
|
||||||
|
@ -2497,6 +2497,7 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
book.ready.metadata.resolve(book.contents.metadata);
|
book.ready.metadata.resolve(book.contents.metadata);
|
||||||
book.ready.cover.resolve(book.contents.cover);
|
book.ready.cover.resolve(book.contents.cover);
|
||||||
|
|
||||||
|
book.locations = new EPUBJS.Locations(book.spine);
|
||||||
|
|
||||||
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
||||||
if(book.contents.navPath) {
|
if(book.contents.navPath) {
|
||||||
|
@ -2763,11 +2764,11 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
|
||||||
EPUBJS.Book.prototype.loadChange = function(url){
|
EPUBJS.Book.prototype.loadChange = function(url){
|
||||||
var uri = EPUBJS.core.uri(url);
|
var uri = EPUBJS.core.uri(url);
|
||||||
var chapter;
|
var chapter;
|
||||||
|
|
||||||
if(this.currentChapter) {
|
if(this.currentChapter) {
|
||||||
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
||||||
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
||||||
this.goto(uri.filename);
|
this.goto(uri.filename);
|
||||||
|
@ -3328,13 +3329,13 @@ EPUBJS.Book.prototype.fromStorage = function(stored) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
||||||
var noreflow = ["color", "background", "background-color"];
|
var noreflow = ["color", "background", "background-color"];
|
||||||
|
|
||||||
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
||||||
|
|
||||||
this.settings.styles[style] = val;
|
this.settings.styles[style] = val;
|
||||||
|
|
||||||
this.renderer.setStyle(style, val, prefixed);
|
this.renderer.setStyle(style, val, prefixed);
|
||||||
|
|
||||||
if(noreflow.indexOf(style) === -1) {
|
if(noreflow.indexOf(style) === -1) {
|
||||||
// clearTimeout(this.reformatTimeout);
|
// clearTimeout(this.reformatTimeout);
|
||||||
// this.reformatTimeout = setTimeout(function(){
|
// this.reformatTimeout = setTimeout(function(){
|
||||||
|
@ -3366,7 +3367,7 @@ EPUBJS.Book.prototype.useSpreads = function(use) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
||||||
var force = typeof _use === "undefined" ? true : _use;
|
var force = typeof _use === "undefined" ? true : _use;
|
||||||
|
|
||||||
this.renderer.forceSingle(force);
|
this.renderer.forceSingle(force);
|
||||||
this.settings.forceSingle = force;
|
this.settings.forceSingle = force;
|
||||||
if(this.isRendered) {
|
if(this.isRendered) {
|
||||||
|
@ -3422,7 +3423,7 @@ EPUBJS.Book.prototype.destroy = function() {
|
||||||
|
|
||||||
this.unload();
|
this.unload();
|
||||||
|
|
||||||
if(this.render) this.render.remove();
|
if(this.renderer) this.renderer.remove();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5168,6 +5169,233 @@ EPUBJS.Layout.Fixed.prototype.calculatePages = function(){
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations = function(spine, store) {
|
||||||
|
this.spine = spine;
|
||||||
|
this.store = store;
|
||||||
|
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this._locations = [];
|
||||||
|
this.total = 0;
|
||||||
|
|
||||||
|
this.break = 150;
|
||||||
|
|
||||||
|
this._current = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.generate = function(chars) {
|
||||||
|
var deferred = new RSVP.defer();
|
||||||
|
var spinePos = -1;
|
||||||
|
var spineLength = this.spine.length;
|
||||||
|
var nextChapter = function(deferred){
|
||||||
|
var chapter;
|
||||||
|
var next = spinePos + 1;
|
||||||
|
var done = deferred || new RSVP.defer();
|
||||||
|
var loaded;
|
||||||
|
if(next >= spineLength) {
|
||||||
|
done.resolve();
|
||||||
|
} else {
|
||||||
|
spinePos = next;
|
||||||
|
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
|
||||||
|
|
||||||
|
this.process(chapter).then(function() {
|
||||||
|
// Load up the next chapter
|
||||||
|
setTimeout(function(){
|
||||||
|
nextChapter(done);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done.promise;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var finished = nextChapter().then(function(){
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
|
||||||
|
if (this._currentCfi) {
|
||||||
|
this.currentLocation = this._currentCfi;
|
||||||
|
}
|
||||||
|
deferred.resolve(this._locations);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.process = function(chapter) {
|
||||||
|
return chapter.load(this.request)
|
||||||
|
.then(function(_doc) {
|
||||||
|
|
||||||
|
var range;
|
||||||
|
var doc = _doc;
|
||||||
|
var contents = doc.documentElement;
|
||||||
|
var counter = 0;
|
||||||
|
var prev;
|
||||||
|
|
||||||
|
this.sprint(contents, function(node) {
|
||||||
|
var len = node.length;
|
||||||
|
var dist;
|
||||||
|
var pos = 0;
|
||||||
|
|
||||||
|
// Start range
|
||||||
|
if (counter === 0) {
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dist = this.break - counter;
|
||||||
|
|
||||||
|
// Node is smaller than a break
|
||||||
|
if(dist > len){
|
||||||
|
counter += len;
|
||||||
|
pos = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < len) {
|
||||||
|
counter = this.break;
|
||||||
|
pos += this.break;
|
||||||
|
|
||||||
|
// Gone over
|
||||||
|
if(pos >= len){
|
||||||
|
// Continue counter for next node
|
||||||
|
counter = len - (pos - this.break);
|
||||||
|
|
||||||
|
// At End
|
||||||
|
} else {
|
||||||
|
// End the previous range
|
||||||
|
range.setEnd(node, pos);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// Start new range
|
||||||
|
pos += 1;
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = node;
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Close remaining
|
||||||
|
if (range) {
|
||||||
|
range.setEnd(prev, prev.length);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.sprint = function(root, func) {
|
||||||
|
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
|
||||||
|
|
||||||
|
while ((node = treeWalker.nextNode())) {
|
||||||
|
func(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.locationFromCfi = function(cfi){
|
||||||
|
// Check if the location has not been set yet
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EPUBJS.core.locationOf(cfi, this._locations, this.epubcfi.compare);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromCfi = function(cfi) {
|
||||||
|
// Find closest cfi
|
||||||
|
var loc = this.locationFromCfi(cfi);
|
||||||
|
// Get percentage in total
|
||||||
|
return this.percentageFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromLocation = function(loc) {
|
||||||
|
if (!loc || !this.total) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Math.floor((loc / this.total ) * 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromLocation = function(loc){
|
||||||
|
var cfi = -1;
|
||||||
|
// check that pg is an int
|
||||||
|
if(typeof loc != "number"){
|
||||||
|
loc = parseInt(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loc >= 0 && loc < this._locations.length) {
|
||||||
|
cfi = this._locations[loc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfi;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromPercentage = function(percent){
|
||||||
|
var loc = Math.ceil(this.total * (percent/100));
|
||||||
|
|
||||||
|
return this.cfiFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.load = function(locations){
|
||||||
|
this._locations = JSON.parse(locations);
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
return this._locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.save = function(json){
|
||||||
|
return JSON.stringify(this._locations);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.getCurrent = function(json){
|
||||||
|
return this._current;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.setCurrent = function(curr){
|
||||||
|
var loc;
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
this._currentCfi = curr;
|
||||||
|
} else if (typeof curr == "number") {
|
||||||
|
this._current = curr;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
loc = this.locationFromCfi(curr);
|
||||||
|
this._current = loc;
|
||||||
|
} else {
|
||||||
|
loc = curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("changed", {
|
||||||
|
percentage: this.percentageFromLocation(loc)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(EPUBJS.Locations.prototype, 'currentLocation', {
|
||||||
|
get: function () {
|
||||||
|
return this._current;
|
||||||
|
},
|
||||||
|
set: function (curr) {
|
||||||
|
this.setCurrent(curr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(EPUBJS.Locations.prototype);
|
||||||
|
|
||||||
EPUBJS.Pagination = function(pageList) {
|
EPUBJS.Pagination = function(pageList) {
|
||||||
this.pages = [];
|
this.pages = [];
|
||||||
this.locations = [];
|
this.locations = [];
|
||||||
|
@ -7305,13 +7533,24 @@ EPUBJS.replace.hrefs = function(callback, renderer){
|
||||||
link.setAttribute("target", "_blank");
|
link.setAttribute("target", "_blank");
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// Links may need to be resolved, such as ../chp1.xhtml
|
// Links may need to be resolved, such as ../chp1.xhtml
|
||||||
directory = EPUBJS.core.uri(renderer.render.window.location.href).directory;
|
var uri = EPUBJS.core.uri(renderer.render.window.location.href);
|
||||||
if(directory) {
|
|
||||||
relative = EPUBJS.core.resolveUrl(directory, href);
|
directory = uri.directory;
|
||||||
} else {
|
|
||||||
relative = href;
|
if(directory) {
|
||||||
}
|
// We must ensure that the file:// protocol is preserved for
|
||||||
|
// local file links, as in certain contexts (such as under
|
||||||
|
// Titanium), file links without the file:// protocol will not
|
||||||
|
// work
|
||||||
|
if (uri.protocol === "file") {
|
||||||
|
relative = EPUBJS.core.resolveUrl(uri.base, href);
|
||||||
|
} else {
|
||||||
|
relative = EPUBJS.core.resolveUrl(directory, href);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
relative = href;
|
||||||
|
}
|
||||||
|
|
||||||
link.onclick = function(){
|
link.onclick = function(){
|
||||||
book.goto(relative);
|
book.goto(relative);
|
||||||
|
@ -7435,6 +7674,7 @@ EPUBJS.replace.cssUrls = function(_store, base, text){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EPUBJS.Unarchiver = function(url){
|
EPUBJS.Unarchiver = function(url){
|
||||||
|
|
||||||
this.loadLib();
|
this.loadLib();
|
||||||
|
|
File diff suppressed because one or more lines are too long
2
reader/js/reader.min.js
vendored
2
reader/js/reader.min.js
vendored
File diff suppressed because one or more lines are too long
15
src/book.js
15
src/book.js
|
@ -234,11 +234,11 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
|
|
||||||
//-- Set Globbal Layout setting based on metadata
|
//-- Set Globbal Layout setting based on metadata
|
||||||
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
book.globalLayoutProperties = book.parseLayoutProperties(book.metadata);
|
||||||
|
|
||||||
if(book.contents.coverPath) {
|
if(book.contents.coverPath) {
|
||||||
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
book.cover = book.contents.cover = book.settings.contentsPath + book.contents.coverPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
book.spineNodeIndex = book.contents.spineNodeIndex;
|
book.spineNodeIndex = book.contents.spineNodeIndex;
|
||||||
|
|
||||||
book.ready.manifest.resolve(book.contents.manifest);
|
book.ready.manifest.resolve(book.contents.manifest);
|
||||||
|
@ -246,6 +246,7 @@ EPUBJS.Book.prototype.unpack = function(packageXml){
|
||||||
book.ready.metadata.resolve(book.contents.metadata);
|
book.ready.metadata.resolve(book.contents.metadata);
|
||||||
book.ready.cover.resolve(book.contents.cover);
|
book.ready.cover.resolve(book.contents.cover);
|
||||||
|
|
||||||
|
book.locations = new EPUBJS.Locations(book.spine);
|
||||||
|
|
||||||
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
//-- Load the TOC, optional; either the EPUB3 XHTML Navigation file or the EPUB2 NCX file
|
||||||
if(book.contents.navPath) {
|
if(book.contents.navPath) {
|
||||||
|
@ -512,11 +513,11 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
|
||||||
EPUBJS.Book.prototype.loadChange = function(url){
|
EPUBJS.Book.prototype.loadChange = function(url){
|
||||||
var uri = EPUBJS.core.uri(url);
|
var uri = EPUBJS.core.uri(url);
|
||||||
var chapter;
|
var chapter;
|
||||||
|
|
||||||
if(this.currentChapter) {
|
if(this.currentChapter) {
|
||||||
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
chapter = EPUBJS.core.uri(this.currentChapter.absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
if(!this._rendering && this.currentChapter && uri.path != chapter.path){
|
||||||
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
console.warn("Miss Match", uri.path, this.currentChapter.absolute);
|
||||||
this.goto(uri.filename);
|
this.goto(uri.filename);
|
||||||
|
@ -1077,13 +1078,13 @@ EPUBJS.Book.prototype.fromStorage = function(stored) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
EPUBJS.Book.prototype.setStyle = function(style, val, prefixed) {
|
||||||
var noreflow = ["color", "background", "background-color"];
|
var noreflow = ["color", "background", "background-color"];
|
||||||
|
|
||||||
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
if(!this.isRendered) return this._q.enqueue("setStyle", arguments);
|
||||||
|
|
||||||
this.settings.styles[style] = val;
|
this.settings.styles[style] = val;
|
||||||
|
|
||||||
this.renderer.setStyle(style, val, prefixed);
|
this.renderer.setStyle(style, val, prefixed);
|
||||||
|
|
||||||
if(noreflow.indexOf(style) === -1) {
|
if(noreflow.indexOf(style) === -1) {
|
||||||
// clearTimeout(this.reformatTimeout);
|
// clearTimeout(this.reformatTimeout);
|
||||||
// this.reformatTimeout = setTimeout(function(){
|
// this.reformatTimeout = setTimeout(function(){
|
||||||
|
@ -1115,7 +1116,7 @@ EPUBJS.Book.prototype.useSpreads = function(use) {
|
||||||
|
|
||||||
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
EPUBJS.Book.prototype.forceSingle = function(_use) {
|
||||||
var force = typeof _use === "undefined" ? true : _use;
|
var force = typeof _use === "undefined" ? true : _use;
|
||||||
|
|
||||||
this.renderer.forceSingle(force);
|
this.renderer.forceSingle(force);
|
||||||
this.settings.forceSingle = force;
|
this.settings.forceSingle = force;
|
||||||
if(this.isRendered) {
|
if(this.isRendered) {
|
||||||
|
|
226
src/locations.js
Normal file
226
src/locations.js
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
EPUBJS.Locations = function(spine, store) {
|
||||||
|
this.spine = spine;
|
||||||
|
this.store = store;
|
||||||
|
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this._locations = [];
|
||||||
|
this.total = 0;
|
||||||
|
|
||||||
|
this.break = 150;
|
||||||
|
|
||||||
|
this._current = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.generate = function(chars) {
|
||||||
|
var deferred = new RSVP.defer();
|
||||||
|
var spinePos = -1;
|
||||||
|
var spineLength = this.spine.length;
|
||||||
|
var nextChapter = function(deferred){
|
||||||
|
var chapter;
|
||||||
|
var next = spinePos + 1;
|
||||||
|
var done = deferred || new RSVP.defer();
|
||||||
|
var loaded;
|
||||||
|
if(next >= spineLength) {
|
||||||
|
done.resolve();
|
||||||
|
} else {
|
||||||
|
spinePos = next;
|
||||||
|
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
|
||||||
|
|
||||||
|
this.process(chapter).then(function() {
|
||||||
|
// Load up the next chapter
|
||||||
|
setTimeout(function(){
|
||||||
|
nextChapter(done);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done.promise;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var finished = nextChapter().then(function(){
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
|
||||||
|
if (this._currentCfi) {
|
||||||
|
this.currentLocation = this._currentCfi;
|
||||||
|
}
|
||||||
|
deferred.resolve(this._locations);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.process = function(chapter) {
|
||||||
|
return chapter.load(this.request)
|
||||||
|
.then(function(_doc) {
|
||||||
|
|
||||||
|
var range;
|
||||||
|
var doc = _doc;
|
||||||
|
var contents = doc.documentElement;
|
||||||
|
var counter = 0;
|
||||||
|
var prev;
|
||||||
|
|
||||||
|
this.sprint(contents, function(node) {
|
||||||
|
var len = node.length;
|
||||||
|
var dist;
|
||||||
|
var pos = 0;
|
||||||
|
|
||||||
|
// Start range
|
||||||
|
if (counter === 0) {
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dist = this.break - counter;
|
||||||
|
|
||||||
|
// Node is smaller than a break
|
||||||
|
if(dist > len){
|
||||||
|
counter += len;
|
||||||
|
pos = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < len) {
|
||||||
|
counter = this.break;
|
||||||
|
pos += this.break;
|
||||||
|
|
||||||
|
// Gone over
|
||||||
|
if(pos >= len){
|
||||||
|
// Continue counter for next node
|
||||||
|
counter = len - (pos - this.break);
|
||||||
|
|
||||||
|
// At End
|
||||||
|
} else {
|
||||||
|
// End the previous range
|
||||||
|
range.setEnd(node, pos);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// Start new range
|
||||||
|
pos += 1;
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = node;
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Close remaining
|
||||||
|
if (range) {
|
||||||
|
range.setEnd(prev, prev.length);
|
||||||
|
cfi = chapter.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.sprint = function(root, func) {
|
||||||
|
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
|
||||||
|
|
||||||
|
while ((node = treeWalker.nextNode())) {
|
||||||
|
func(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.locationFromCfi = function(cfi){
|
||||||
|
// Check if the location has not been set yet
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EPUBJS.core.locationOf(cfi, this._locations, this.epubcfi.compare);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromCfi = function(cfi) {
|
||||||
|
// Find closest cfi
|
||||||
|
var loc = this.locationFromCfi(cfi);
|
||||||
|
// Get percentage in total
|
||||||
|
return this.percentageFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.percentageFromLocation = function(loc) {
|
||||||
|
if (!loc || !this.total) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Math.floor((loc / this.total ) * 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromLocation = function(loc){
|
||||||
|
var cfi = -1;
|
||||||
|
// check that pg is an int
|
||||||
|
if(typeof loc != "number"){
|
||||||
|
loc = parseInt(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loc >= 0 && loc < this._locations.length) {
|
||||||
|
cfi = this._locations[loc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfi;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromPercentage = function(percent){
|
||||||
|
var loc = Math.ceil(this.total * (percent/100));
|
||||||
|
|
||||||
|
return this.cfiFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.load = function(locations){
|
||||||
|
this._locations = JSON.parse(locations);
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
return this._locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.save = function(json){
|
||||||
|
return JSON.stringify(this._locations);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.getCurrent = function(json){
|
||||||
|
return this._current;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.setCurrent = function(curr){
|
||||||
|
var loc;
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
this._currentCfi = curr;
|
||||||
|
} else if (typeof curr == "number") {
|
||||||
|
this._current = curr;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._locations.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof curr == "string"){
|
||||||
|
loc = this.locationFromCfi(curr);
|
||||||
|
this._current = loc;
|
||||||
|
} else {
|
||||||
|
loc = curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("changed", {
|
||||||
|
percentage: this.percentageFromLocation(loc)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(EPUBJS.Locations.prototype, 'currentLocation', {
|
||||||
|
get: function () {
|
||||||
|
return this._current;
|
||||||
|
},
|
||||||
|
set: function (curr) {
|
||||||
|
this.setCurrent(curr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(EPUBJS.Locations.prototype);
|
Loading…
Add table
Add a link
Reference in a new issue