mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
Added locations
This commit is contained in:
parent
d7371a619d
commit
80787fc86b
10 changed files with 648 additions and 125 deletions
285
dist/epub.js
vendored
285
dist/epub.js
vendored
|
@ -2174,6 +2174,7 @@ EPUBJS.Queue = function(_context){
|
||||||
this.context = _context;
|
this.context = _context;
|
||||||
this.tick = EPUBJS.core.requestAnimationFrame;
|
this.tick = EPUBJS.core.requestAnimationFrame;
|
||||||
this.running = false;
|
this.running = false;
|
||||||
|
this.paused = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add an item to the queue
|
// Add an item to the queue
|
||||||
|
@ -2215,7 +2216,11 @@ EPUBJS.Queue.prototype.enqueue = function() {
|
||||||
this._q.push(queued);
|
this._q.push(queued);
|
||||||
|
|
||||||
// Wait to start queue flush
|
// Wait to start queue flush
|
||||||
setTimeout(this.flush.bind(this), 0);
|
if (this.paused == false && !this.running) {
|
||||||
|
// setTimeout(this.flush.bind(this), 0);
|
||||||
|
// this.tick.call(window, this.run.bind(this));
|
||||||
|
this.run();
|
||||||
|
}
|
||||||
|
|
||||||
return queued.promise;
|
return queued.promise;
|
||||||
};
|
};
|
||||||
|
@ -2268,25 +2273,46 @@ EPUBJS.Queue.prototype.dump = function(){
|
||||||
// Run all sequentially, at convince
|
// Run all sequentially, at convince
|
||||||
|
|
||||||
EPUBJS.Queue.prototype.run = function(){
|
EPUBJS.Queue.prototype.run = function(){
|
||||||
if(!this.running && this._q.length) {
|
|
||||||
|
if(!this.running){
|
||||||
this.running = true;
|
this.running = true;
|
||||||
this.dequeue().then(function(){
|
this.defered = new RSVP.defer();
|
||||||
this.running = false;
|
|
||||||
}.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tick.call(window, this.run.bind(this));
|
this.tick.call(window, function() {
|
||||||
|
|
||||||
|
if(this._q.length) {
|
||||||
|
|
||||||
|
this.dequeue()
|
||||||
|
.then(function(){
|
||||||
|
this.run();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.defered.resolve();
|
||||||
|
this.running = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Unpause
|
||||||
|
if(this.paused == true) {
|
||||||
|
this.paused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.defered.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flush all, as quickly as possible
|
// Flush all, as quickly as possible
|
||||||
EPUBJS.Queue.prototype.flush = function(){
|
EPUBJS.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));
|
||||||
|
@ -2306,6 +2332,10 @@ EPUBJS.Queue.prototype.length = function(){
|
||||||
return this._q.length;
|
return this._q.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Queue.prototype.pause = function(){
|
||||||
|
this.paused = true;
|
||||||
|
};
|
||||||
|
|
||||||
// Create a new task from a callback
|
// Create a new task from a callback
|
||||||
EPUBJS.Task = function(task, args, context){
|
EPUBJS.Task = function(task, args, context){
|
||||||
|
|
||||||
|
@ -3165,7 +3195,14 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) {
|
||||||
endPath = this.generatePathComponent(endSteps);
|
endPath = this.generatePathComponent(endSteps);
|
||||||
endOffset = range.endOffset;
|
endOffset = range.endOffset;
|
||||||
|
|
||||||
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")";
|
// Remove steps present in startPath
|
||||||
|
endPath = endPath.replace(startPath, '');
|
||||||
|
|
||||||
|
if (endPath.length) {
|
||||||
|
endPath = endPath + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + endIndex + ":" + endOffset + ")";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")";
|
return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")";
|
||||||
|
@ -3245,6 +3282,7 @@ EPUBJS.EpubCFI.prototype.isCfiString = function(target) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
EPUBJS.Navigation = function(_package, _request){
|
EPUBJS.Navigation = function(_package, _request){
|
||||||
var navigation = this;
|
var navigation = this;
|
||||||
var parse = new EPUBJS.Parser();
|
var parse = new EPUBJS.Parser();
|
||||||
|
@ -3468,6 +3506,11 @@ EPUBJS.Section.prototype.reconcileLayoutSettings = function(global){
|
||||||
EPUBJS.Section.prototype.cfiFromRange = function(_range) {
|
EPUBJS.Section.prototype.cfiFromRange = function(_range) {
|
||||||
return this.epubcfi.generateCfiFromRange(_range, this.cfiBase);
|
return this.epubcfi.generateCfiFromRange(_range, this.cfiBase);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Section.prototype.cfiFromElement = function(el) {
|
||||||
|
return this.epubcfi.generateCfiFromElement(el, this.cfiBase);
|
||||||
|
};
|
||||||
|
|
||||||
EPUBJS.Spine = function(_request){
|
EPUBJS.Spine = function(_request){
|
||||||
this.request = _request;
|
this.request = _request;
|
||||||
this.spineItems = [];
|
this.spineItems = [];
|
||||||
|
@ -3580,6 +3623,10 @@ EPUBJS.Spine.prototype.remove = function(section) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Spine.prototype.each = function() {
|
||||||
|
return this.spineItems.forEach.apply(this.spineItems, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
EPUBJS.replace = {};
|
EPUBJS.replace = {};
|
||||||
EPUBJS.replace.links = function(view, renderer) {
|
EPUBJS.replace.links = function(view, renderer) {
|
||||||
|
|
||||||
|
@ -3623,7 +3670,7 @@ EPUBJS.replace.links = function(view, renderer) {
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
EPUBJS.Book = function(_url){
|
EPUBJS.Book = function(_url, options){
|
||||||
// Promises
|
// Promises
|
||||||
this.opening = new RSVP.defer();
|
this.opening = new RSVP.defer();
|
||||||
this.opened = this.opening.promise;
|
this.opened = this.opening.promise;
|
||||||
|
@ -3631,8 +3678,6 @@ EPUBJS.Book = function(_url){
|
||||||
|
|
||||||
this.url = undefined;
|
this.url = undefined;
|
||||||
|
|
||||||
this.spine = new EPUBJS.Spine(this.request);
|
|
||||||
|
|
||||||
this.loading = {
|
this.loading = {
|
||||||
manifest: new RSVP.defer(),
|
manifest: new RSVP.defer(),
|
||||||
spine: new RSVP.defer(),
|
spine: new RSVP.defer(),
|
||||||
|
@ -3659,6 +3704,9 @@ EPUBJS.Book = function(_url){
|
||||||
|
|
||||||
this.request = this.requestMethod.bind(this);
|
this.request = this.requestMethod.bind(this);
|
||||||
|
|
||||||
|
this.spine = new EPUBJS.Spine(this.request);
|
||||||
|
this.locations = new EPUBJS.Locations(this.spine, this.request);
|
||||||
|
|
||||||
if(_url) {
|
if(_url) {
|
||||||
this.open(_url);
|
this.open(_url);
|
||||||
}
|
}
|
||||||
|
@ -3822,6 +3870,7 @@ EPUBJS.Book.prototype.setRequestCredentials = function(_credentials) {
|
||||||
EPUBJS.Book.prototype.setRequestHeaders = function(_headers) {
|
EPUBJS.Book.prototype.setRequestHeaders = function(_headers) {
|
||||||
this.requestHeaders = _headers;
|
this.requestHeaders = _headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-- Enable binding events to book
|
//-- Enable binding events to book
|
||||||
RSVP.EventTarget.mixin(EPUBJS.Book.prototype);
|
RSVP.EventTarget.mixin(EPUBJS.Book.prototype);
|
||||||
|
|
||||||
|
@ -3837,6 +3886,7 @@ RSVP.configure('instrument', true); //-- true | will logging out all RSVP reject
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
EPUBJS.View = function(section, options) {
|
EPUBJS.View = function(section, options) {
|
||||||
this.settings = options || {};
|
this.settings = options || {};
|
||||||
|
|
||||||
|
@ -6495,3 +6545,214 @@ EPUBJS.Map.prototype.rangeListToCfiList = function(view, columns){
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
EPUBJS.Locations = function(spine, request) {
|
||||||
|
this.spine = spine;
|
||||||
|
this.request = request;
|
||||||
|
|
||||||
|
this.q = new EPUBJS.Queue(this);
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this._locations = [];
|
||||||
|
this.total = 0;
|
||||||
|
|
||||||
|
this.break = 150;
|
||||||
|
|
||||||
|
this._current = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load all of sections in the book
|
||||||
|
EPUBJS.Locations.prototype.generate = function(chars) {
|
||||||
|
|
||||||
|
if (chars) {
|
||||||
|
this.break = chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.q.pause();
|
||||||
|
|
||||||
|
this.spine.each(function(section) {
|
||||||
|
|
||||||
|
this.q.enqueue(this.process, section);
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return this.q.run().then(function() {
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
|
||||||
|
if (this._currentCfi) {
|
||||||
|
this.currentLocation = this._currentCfi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._locations;
|
||||||
|
// console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.process = function(section) {
|
||||||
|
|
||||||
|
return section.load(this.request)
|
||||||
|
.then(function(contents) {
|
||||||
|
|
||||||
|
var range;
|
||||||
|
var doc = contents.ownerDocument;
|
||||||
|
var counter = 0;
|
||||||
|
|
||||||
|
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 = section.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// Start new range
|
||||||
|
pos += 1;
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Close remaining
|
||||||
|
if (range) {
|
||||||
|
range.setEnd(prev, prev.length);
|
||||||
|
cfi = section.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.precentageFromCfi = function(cfi) {
|
||||||
|
// Find closest cfi
|
||||||
|
var loc = this.locationFromCfi(cfi);
|
||||||
|
// Get percentage in total
|
||||||
|
return this.precentageFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.precentageFromLocation = function(loc) {
|
||||||
|
return Math.ceil((loc / this.total ) * 1000) / 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromLocation = function(loc){
|
||||||
|
var cfi = -1;
|
||||||
|
// check that pg is an int
|
||||||
|
if(typeof loc != "number"){
|
||||||
|
loc = parseInt(pg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loc >= 0 && loc < this._locations.length) {
|
||||||
|
cfi = this._locations[loc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfi;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromPercentage = function(percent){
|
||||||
|
var loc = Math.round(this.total * percent);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
console.log( this.precentageFromLocation(loc))
|
||||||
|
this.trigger("changed", {
|
||||||
|
percentage: this.precentageFromLocation(loc)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(EPUBJS.Locations.prototype, 'currentLocation', {
|
||||||
|
get: function () {
|
||||||
|
return this._current;
|
||||||
|
},
|
||||||
|
set: function (curr) {
|
||||||
|
this.setCurrent(curr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(EPUBJS.Locations.prototype);
|
||||||
|
|
6
dist/epub.min.js
vendored
6
dist/epub.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -119,7 +119,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Load the opf
|
// Load the opf
|
||||||
// var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
|
// var book = ePub("https://s3.amazonaws.com/moby-dick/OPS/package.opf");
|
||||||
var book = ePub("books/alice/OPS/package.opf");
|
var book = ePub("../books/alice/OPS/package.opf");
|
||||||
var rendition = book.renderTo("viewer", {
|
var rendition = book.renderTo("viewer", {
|
||||||
method: "paginate",
|
method: "paginate",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
|
@ -148,7 +148,7 @@
|
||||||
rendition.prev();
|
rendition.prev();
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
document.addEventListener("keyup", function(e){
|
var keyListener = function(e){
|
||||||
|
|
||||||
// Left Key
|
// Left Key
|
||||||
if ((e.keyCode || e.which) == 37) {
|
if ((e.keyCode || e.which) == 37) {
|
||||||
|
@ -160,7 +160,10 @@
|
||||||
rendition.next();
|
rendition.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, false);
|
};
|
||||||
|
|
||||||
|
rendition.on("keyup", keyListener);
|
||||||
|
document.addEventListener("keyup", keyListener, false);
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -29,7 +29,8 @@ var files = [
|
||||||
'src/rendition.js',
|
'src/rendition.js',
|
||||||
'src/continuous.js',
|
'src/continuous.js',
|
||||||
'src/paginate.js',
|
'src/paginate.js',
|
||||||
'src/map.js'
|
'src/map.js',
|
||||||
|
'src/locations.js'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Lint JS
|
// Lint JS
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
EPUBJS.Book = function(_url){
|
EPUBJS.Book = function(_url, options){
|
||||||
// Promises
|
// Promises
|
||||||
this.opening = new RSVP.defer();
|
this.opening = new RSVP.defer();
|
||||||
this.opened = this.opening.promise;
|
this.opened = this.opening.promise;
|
||||||
|
@ -6,8 +6,6 @@ EPUBJS.Book = function(_url){
|
||||||
|
|
||||||
this.url = undefined;
|
this.url = undefined;
|
||||||
|
|
||||||
this.spine = new EPUBJS.Spine(this.request);
|
|
||||||
|
|
||||||
this.loading = {
|
this.loading = {
|
||||||
manifest: new RSVP.defer(),
|
manifest: new RSVP.defer(),
|
||||||
spine: new RSVP.defer(),
|
spine: new RSVP.defer(),
|
||||||
|
@ -34,6 +32,9 @@ EPUBJS.Book = function(_url){
|
||||||
|
|
||||||
this.request = this.requestMethod.bind(this);
|
this.request = this.requestMethod.bind(this);
|
||||||
|
|
||||||
|
this.spine = new EPUBJS.Spine(this.request);
|
||||||
|
this.locations = new EPUBJS.Locations(this.spine, this.request);
|
||||||
|
|
||||||
if(_url) {
|
if(_url) {
|
||||||
this.open(_url);
|
this.open(_url);
|
||||||
}
|
}
|
||||||
|
@ -197,6 +198,7 @@ EPUBJS.Book.prototype.setRequestCredentials = function(_credentials) {
|
||||||
EPUBJS.Book.prototype.setRequestHeaders = function(_headers) {
|
EPUBJS.Book.prototype.setRequestHeaders = function(_headers) {
|
||||||
this.requestHeaders = _headers;
|
this.requestHeaders = _headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-- Enable binding events to book
|
//-- Enable binding events to book
|
||||||
RSVP.EventTarget.mixin(EPUBJS.Book.prototype);
|
RSVP.EventTarget.mixin(EPUBJS.Book.prototype);
|
||||||
|
|
||||||
|
|
|
@ -430,7 +430,14 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) {
|
||||||
endPath = this.generatePathComponent(endSteps);
|
endPath = this.generatePathComponent(endSteps);
|
||||||
endOffset = range.endOffset;
|
endOffset = range.endOffset;
|
||||||
|
|
||||||
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")";
|
// Remove steps present in startPath
|
||||||
|
endPath = endPath.replace(startPath, '');
|
||||||
|
|
||||||
|
if (endPath.length) {
|
||||||
|
endPath = endPath + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + endIndex + ":" + endOffset + ")";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")";
|
return "epubcfi(" + base + "!" + startPath + "/"+ startIndex +":"+ startOffset +")";
|
||||||
|
|
211
src/locations.js
Normal file
211
src/locations.js
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
EPUBJS.Locations = function(spine, request) {
|
||||||
|
this.spine = spine;
|
||||||
|
this.request = request;
|
||||||
|
|
||||||
|
this.q = new EPUBJS.Queue(this);
|
||||||
|
this.epubcfi = new EPUBJS.EpubCFI();
|
||||||
|
|
||||||
|
this._locations = [];
|
||||||
|
this.total = 0;
|
||||||
|
|
||||||
|
this.break = 150;
|
||||||
|
|
||||||
|
this._current = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load all of sections in the book
|
||||||
|
EPUBJS.Locations.prototype.generate = function(chars) {
|
||||||
|
|
||||||
|
if (chars) {
|
||||||
|
this.break = chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.q.pause();
|
||||||
|
|
||||||
|
this.spine.each(function(section) {
|
||||||
|
|
||||||
|
this.q.enqueue(this.process, section);
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return this.q.run().then(function() {
|
||||||
|
this.total = this._locations.length-1;
|
||||||
|
|
||||||
|
if (this._currentCfi) {
|
||||||
|
this.currentLocation = this._currentCfi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._locations;
|
||||||
|
// console.log(this.precentage(this.book.rendition.location.start), this.precentage(this.book.rendition.location.end));
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.process = function(section) {
|
||||||
|
|
||||||
|
return section.load(this.request)
|
||||||
|
.then(function(contents) {
|
||||||
|
|
||||||
|
var range;
|
||||||
|
var doc = contents.ownerDocument;
|
||||||
|
var counter = 0;
|
||||||
|
|
||||||
|
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 = section.cfiFromRange(range);
|
||||||
|
this._locations.push(cfi);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// Start new range
|
||||||
|
pos += 1;
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(node, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Close remaining
|
||||||
|
if (range) {
|
||||||
|
range.setEnd(prev, prev.length);
|
||||||
|
cfi = section.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.precentageFromCfi = function(cfi) {
|
||||||
|
// Find closest cfi
|
||||||
|
var loc = this.locationFromCfi(cfi);
|
||||||
|
// Get percentage in total
|
||||||
|
return this.precentageFromLocation(loc);
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.precentageFromLocation = function(loc) {
|
||||||
|
return Math.ceil((loc / this.total ) * 1000) / 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromLocation = function(loc){
|
||||||
|
var cfi = -1;
|
||||||
|
// check that pg is an int
|
||||||
|
if(typeof loc != "number"){
|
||||||
|
loc = parseInt(pg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(loc >= 0 && loc < this._locations.length) {
|
||||||
|
cfi = this._locations[loc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfi;
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.Locations.prototype.cfiFromPercentage = function(percent){
|
||||||
|
var loc = Math.round(this.total * percent);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
console.log( this.precentageFromLocation(loc))
|
||||||
|
this.trigger("changed", {
|
||||||
|
percentage: this.precentageFromLocation(loc)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(EPUBJS.Locations.prototype, 'currentLocation', {
|
||||||
|
get: function () {
|
||||||
|
return this._current;
|
||||||
|
},
|
||||||
|
set: function (curr) {
|
||||||
|
this.setCurrent(curr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RSVP.EventTarget.mixin(EPUBJS.Locations.prototype);
|
46
src/queue.js
46
src/queue.js
|
@ -3,6 +3,7 @@ EPUBJS.Queue = function(_context){
|
||||||
this.context = _context;
|
this.context = _context;
|
||||||
this.tick = EPUBJS.core.requestAnimationFrame;
|
this.tick = EPUBJS.core.requestAnimationFrame;
|
||||||
this.running = false;
|
this.running = false;
|
||||||
|
this.paused = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add an item to the queue
|
// Add an item to the queue
|
||||||
|
@ -44,7 +45,11 @@ EPUBJS.Queue.prototype.enqueue = function() {
|
||||||
this._q.push(queued);
|
this._q.push(queued);
|
||||||
|
|
||||||
// Wait to start queue flush
|
// Wait to start queue flush
|
||||||
setTimeout(this.flush.bind(this), 0);
|
if (this.paused == false && !this.running) {
|
||||||
|
// setTimeout(this.flush.bind(this), 0);
|
||||||
|
// this.tick.call(window, this.run.bind(this));
|
||||||
|
this.run();
|
||||||
|
}
|
||||||
|
|
||||||
return queued.promise;
|
return queued.promise;
|
||||||
};
|
};
|
||||||
|
@ -97,25 +102,46 @@ EPUBJS.Queue.prototype.dump = function(){
|
||||||
// Run all sequentially, at convince
|
// Run all sequentially, at convince
|
||||||
|
|
||||||
EPUBJS.Queue.prototype.run = function(){
|
EPUBJS.Queue.prototype.run = function(){
|
||||||
if(!this.running && this._q.length) {
|
|
||||||
|
if(!this.running){
|
||||||
this.running = true;
|
this.running = true;
|
||||||
this.dequeue().then(function(){
|
this.defered = new RSVP.defer();
|
||||||
this.running = false;
|
|
||||||
}.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tick.call(window, this.run.bind(this));
|
this.tick.call(window, function() {
|
||||||
|
|
||||||
|
if(this._q.length) {
|
||||||
|
|
||||||
|
this.dequeue()
|
||||||
|
.then(function(){
|
||||||
|
this.run();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.defered.resolve();
|
||||||
|
this.running = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Unpause
|
||||||
|
if(this.paused == true) {
|
||||||
|
this.paused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.defered.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flush all, as quickly as possible
|
// Flush all, as quickly as possible
|
||||||
EPUBJS.Queue.prototype.flush = function(){
|
EPUBJS.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));
|
||||||
|
@ -135,6 +161,10 @@ EPUBJS.Queue.prototype.length = function(){
|
||||||
return this._q.length;
|
return this._q.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Queue.prototype.pause = function(){
|
||||||
|
this.paused = true;
|
||||||
|
};
|
||||||
|
|
||||||
// Create a new task from a callback
|
// Create a new task from a callback
|
||||||
EPUBJS.Task = function(task, args, context){
|
EPUBJS.Task = function(task, args, context){
|
||||||
|
|
||||||
|
|
|
@ -126,3 +126,7 @@ EPUBJS.Section.prototype.reconcileLayoutSettings = function(global){
|
||||||
EPUBJS.Section.prototype.cfiFromRange = function(_range) {
|
EPUBJS.Section.prototype.cfiFromRange = function(_range) {
|
||||||
return this.epubcfi.generateCfiFromRange(_range, this.cfiBase);
|
return this.epubcfi.generateCfiFromRange(_range, this.cfiBase);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Section.prototype.cfiFromElement = function(el) {
|
||||||
|
return this.epubcfi.generateCfiFromElement(el, this.cfiBase);
|
||||||
|
};
|
||||||
|
|
|
@ -109,3 +109,7 @@ EPUBJS.Spine.prototype.remove = function(section) {
|
||||||
return this.spineItems.splice(index, 1);
|
return this.spineItems.splice(index, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EPUBJS.Spine.prototype.each = function() {
|
||||||
|
return this.spineItems.forEach.apply(this.spineItems, arguments);
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue