1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-04 15:09:16 +02:00

Removed use of finding element by position, added pageMaps to find locations by word

This commit is contained in:
fchasen 2014-04-29 21:55:35 -07:00
parent 1fb81952c1
commit 4f93358b09
15 changed files with 1158 additions and 329 deletions

View file

@ -2570,30 +2570,37 @@ EPUBJS.Book.prototype.createHiddenRender = function(renderer, _width, _height) {
var box = this.element.getBoundingClientRect();
var width = _width || this.settings.width || box.width;
var height = _height || this.settings.height || box.height;
var hiddenContainer;
var hiddenEl;
renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
this._registerReplacements(renderer);
if(this.settings.forceSingle) {
renderer.forceSingle(true);
}
hiddenContainer = document.createElement("div");
hiddenContainer.style.visibility = "hidden";
hiddenContainer.style.overflow = "hidden";
hiddenContainer.style.width = "0";
hiddenContainer.style.height = "0";
this.element.appendChild(hiddenContainer);
hiddenEl = document.createElement("div");
hiddenEl.style.visibility = "hidden";
hiddenEl.style.overflow = "hidden";
hiddenEl.style.width = "0";
hiddenEl.style.height = "0";
this.element.appendChild(hiddenEl);
hiddenEl.style.width = width + "px";//"0";
hiddenEl.style.height = height +"px"; //"0";
hiddenContainer.appendChild(hiddenEl);
renderer.initialize(hiddenEl, width, height);
return hiddenEl;
renderer.initialize(hiddenEl);
return hiddenContainer;
};
// Generates the pageList array by loading every chapter and paging through them
EPUBJS.Book.prototype.generatePageList = function(width, height){
var pageList = [];
var pager = new EPUBJS.Renderer(this.settings.render_method);
var hiddenElement = this.createHiddenRender(pager, width, height);
var pager = new EPUBJS.Renderer(this.settings.render_method, false); //hidden
var hiddenContainer = this.createHiddenRender(pager, width, height);
var deferred = new RSVP.defer();
var spinePos = -1;
var spineLength = this.spine.length;
@ -2609,14 +2616,26 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
} else {
spinePos = next;
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
pager.displayChapter(chapter, this.globalLayoutProperties).then(function(chap){
var nextPage = true;
pager.pageMap.forEach(function(item){
currentPage += 1;
pageList.push({
"cfi" : item.start,
"page" : currentPage
});
// Page though the entire chapter
while (nextPage) {
nextPage = pager.nextPage();
});
if(pager.pageMap.length % 2 > 0 &&
pager.layoutMethod == "ReflowableSpreads") {
currentPage += 1; // Handle Spreads
pageList.push({
"cfi" : pager.pageMap[pager.pageMap.length - 1].end,
"page" : currentPage
});
}
// Load up the next chapter
nextChapter(done);
});
@ -2626,37 +2645,10 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
var finished = nextChapter().then(function(){
pager.remove();
this.element.removeChild(hiddenElement);
this.element.removeChild(hiddenContainer);
deferred.resolve(pageList);
}.bind(this));
pager.on("renderer:visibleRangeChanged", function(range){
var endX, endY;
var endRange, endCfi;
currentPage += 1;
pageList.push({
"cfi" : range.start,
"page" : currentPage
});
if (pager.layoutMethod == "ReflowableSpreads") {
endX = pager.layout.colWidth + pager.layout.gap + 1;
endY = 1;
endRange = pager.getRange(endX, endY);
if(endRange) {
endCfi = pager.currentChapter.cfiFromRange(endRange);
currentPage += 1;
pageList.push({
"cfi" : endCfi,
"page" : currentPage
});
}
}
});
return deferred.promise;
};
@ -2740,9 +2732,9 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
if(range.end) {
endPage = this.pagination.pageFromCfi(range.end);
if(startPage != endPage) {
//if(startPage != endPage) {
pageRange.push(endPage);
}
//}
}
this.trigger("book:pageChanged", {
"anchorPage": startPage,
@ -3387,21 +3379,21 @@ EPUBJS.Book.prototype._rendered = function(err) {
};
EPUBJS.Book.prototype.applyStyles = function(callback){
if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
this.renderer.applyStyles(this.settings.styles);
EPUBJS.Book.prototype.applyStyles = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
renderer.applyStyles(this.settings.styles);
callback();
};
EPUBJS.Book.prototype.applyHeadTags = function(callback){
if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
this.renderer.applyHeadTags(this.settings.headTags);
EPUBJS.Book.prototype.applyHeadTags = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
renderer.applyHeadTags(this.settings.headTags);
callback();
};
EPUBJS.Book.prototype._registerReplacements = function(renderer){
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs.bind(this), true);
if(this._needsAssetReplacement()) {
@ -3565,7 +3557,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
range.setEnd(endContainer, _range.endOffset);
}
} catch (e) {
console.log("missed");
// console.log("missed");
startContainer = false;
}
@ -3573,13 +3565,14 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
// Fuzzy Match
if(!startContainer) {
console.log("not found, try fuzzy match");
// console.log("not found, try fuzzy match");
startXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
endXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
startContainer = this.contents.evaluate(startXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(startContainer){
// console.log("Found with Fuzzy");
range.setStart(startContainer, _range.startOffset);
if(!_range.collapsed) {
@ -4485,25 +4478,25 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) {
} else if(range.collapsed) {
return this.generateCfiFromElement(start, base); // single element
} else {
startSteps = this.pathTo(startElement);
startSteps = this.pathTo(start);
}
startPath = this.generatePathComponent(startSteps);
startOffset = range.startOffset;
if(!range.collapsed) {
end = range.startContainer;
end = range.endContainer;
if(end.nodeType === 3) { // text node
endElement = end.parentElement;
startIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endSteps = this.pathTo(endElement);
} else {
endSteps = this.pathTo(end);
}
endPath = this.generatePathComponent(endSteps);
endOffset = range.endOffset;
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")";
@ -4764,6 +4757,8 @@ EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _h
documentElement.style[columnAxis] = "horizontal";
documentElement.style[columnWidth] = width+"px";
documentElement.style[columnGap] = gap+"px";
this.colWidth = width;
this.gap = gap;
return {
pageWidth : this.spreadWidth,
@ -4878,6 +4873,8 @@ EPUBJS.Layout.Fixed = function(documentElement, _width, _height){
//-- Scroll
documentElement.style.overflow = "auto";
this.colWidth = width;
this.gap = 0;
return {
pageWidth : width,
@ -4931,12 +4928,14 @@ EPUBJS.Pagination.prototype.pageFromCfi = function(cfi){
} else {
// Otherwise add it to the list of locations
// Insert it in the correct position in the locations page
index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
//index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
index = EPUBJS.core.locationOf(cfi, this.locations, this.epubcfi.compare);
// Get the page at the location just before the new one, or return the first
pg = index-1 >= 0 ? this.pages[index-1] : this.pages[0];
pg = this.pages[index];
if(pg !== undefined) {
// Add the new page in so that the locations and page array match up
this.pages.splice(index, 0, pg);
//this.pages.splice(index, 0, pg);
} else {
pg = -1;
}
@ -5652,7 +5651,7 @@ EPUBJS.Render.Iframe.prototype.unload = function(){
//-- Enable binding events to Render
RSVP.EventTarget.mixin(EPUBJS.Render.Iframe.prototype);
EPUBJS.Renderer = function(renderMethod) {
EPUBJS.Renderer = function(renderMethod, hidden) {
// Dom events to listen for
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
this.upEvent = "mouseup";
@ -5687,6 +5686,7 @@ EPUBJS.Renderer = function(renderMethod) {
this.layoutSettings = {};
this.hidden = hidden || false;
//-- Adds Hook methods to the Book prototype
// Hooks will all return before triggering the callback.
EPUBJS.Hooks.mixin(this);
@ -5911,6 +5911,7 @@ EPUBJS.Renderer.prototype.beforeDisplay = function(callback, renderer){
// Update the renderer with the information passed by the layout
EPUBJS.Renderer.prototype.updatePages = function(layout){
this.pageMap = this.mapPage();
this.displayedPages = layout.displayedPages;
this.currentChapter.pages = layout.pageCount;
};
@ -5945,13 +5946,13 @@ EPUBJS.Renderer.prototype.reformat = function(){
// Hide and show the render's container .
EPUBJS.Renderer.prototype.visible = function(bool){
if(typeof(bool) === "undefined") {
return this.container.style.visibility;
return this.element.style.visibility;
}
if(bool === true){
this.container.style.visibility = "visible";
if(bool === true && !this.hidden){
this.element.style.visibility = "visible";
}else if(bool === false){
this.container.style.visibility = "hidden";
this.element.style.visibility = "hidden";
}
};
@ -6073,7 +6074,7 @@ EPUBJS.Renderer.prototype.firstElementisTextNode = function(node) {
};
// Walk the node tree from a start element to next visible element
EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.walk = function(node, x, y) {
var r, children, leng,
startNode = node,
prevNode,
@ -6082,9 +6083,8 @@ EPUBJS.Renderer.prototype.walk = function(node) {
var STOP = 10000, ITER=0;
while(!r && stack.length) {
node = stack.shift();
if( this.render.isElementVisible(node) && this.firstElementisTextNode(node)) {
if( this.containsPoint(node, x, y) && this.firstElementisTextNode(node)) {
r = node;
}
@ -6118,6 +6118,164 @@ EPUBJS.Renderer.prototype.walk = function(node) {
return r;
};
// Checks if an element is on the screen
EPUBJS.Renderer.prototype.containsPoint = function(el, x, y){
var rect;
var left;
if(el && typeof el.getBoundingClientRect === 'function'){
rect = el.getBoundingClientRect();
// console.log(el, rect, x, y);
if( rect.width !== 0 &&
rect.height !== 0 && // Element not visible
rect.left >= x &&
x <= rect.left + rect.width) {
return true;
}
}
return false;
};
EPUBJS.Renderer.prototype.sprint = function(root, func) {
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode: function (node) {
if ( ! /^\s*$/.test(node.data) ) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_REJECT;
}
}
}, false);
while ((node = treeWalker.nextNode())) {
func(node);
}
};
EPUBJS.Renderer.prototype.mapPage = function(){
var renderer = this;
var map = [{ start: null, end: null }];
var root = this.render.getBaseElement();
var page = 1;
var width = this.layout.colWidth + this.layout.gap;
var offset = this.formated.pageWidth * (this.chapterPos-1);
var limit = (width * page) - offset;
var prevRange;
var cfi;
var check = function(node) {
var ranges = renderer.splitTextNodeIntoWordsRanges(node);
ranges.forEach(function(range){
var pos = renderer.rangePosition(range);
// console.log(pos.left, pos.top, node);
if(!pos || (pos.width === 0 && pos.height === 0)) {
return;
}
if(pos.left + pos.width < limit) {
if(!map[page-1].start){
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[page-1].start = cfi;
}
} else {
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map.push({
start: cfi,
end: null
});
page += 1;
limit = (width * page) - offset;
}
prevRange = range;
});
};
this.sprint(root, check);
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
// Handle empty map
if(map.length === 1 && !map[0].start) {
range = this.doc.createRange();
range.selectNodeContents(root);
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[0].start = cfi;
map[0].end = cfi;
}
return map;
};
EPUBJS.Renderer.prototype.splitTextNodeIntoWordsRanges = function(node){
var ranges = [];
var text = node.textContent;
var range;
var rect;
var list;
pos = text.indexOf(" ");
if(pos === -1) {
range = this.doc.createRange();
range.selectNodeContents(node);
return [range];
}
range = this.doc.createRange();
range.setStart(node, pos+1);
while ( pos != -1 ) {
pos = text.indexOf(" ", pos + 1);
if(pos > 0) {
range.setEnd(node, pos);
ranges.push(range);
range = this.doc.createRange();
range.setStart(node, pos+1);
}
}
range.setEnd(node, text.length);
ranges.push(range);
return ranges;
};
EPUBJS.Renderer.prototype.rangePosition = function(range){
var rect;
var list;
list = range.getClientRects();
if(list.length) {
rect = list[0];
return rect;
}
return null;
};
/*
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
var range = this.doc.createRange();
@ -6137,19 +6295,32 @@ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
return this.currentChapter.cfiFromRange(range);
};
*/
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(){
var pg;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
}
return this.pageMap[(this.chapterPos * 2) -1].start;
};
EPUBJS.Renderer.prototype.getRange = function(x, y){
EPUBJS.Renderer.prototype.getRange = function(x, y, forceElement){
var range = this.doc.createRange();
var position;
if(typeof document.caretPositionFromPoint !== "undefined"){
forceElement = true; // temp override
if(typeof document.caretPositionFromPoint !== "undefined" && !forceElement){
position = this.doc.caretPositionFromPoint(x, y);
range.setStart(position.offsetNode, position.offset);
} else if(typeof document.caretRangeFromPoint !== "undefined"){
} else if(typeof document.caretRangeFromPoint !== "undefined" && !forceElement){
range = this.doc.caretRangeFromPoint(x, y);
} else {
this.visibileEl = this.findFirstVisible(prevEl);
this.visibileEl = this.findElementAfter(x, y);
range.setStart(this.visibileEl, 1);
}
@ -6162,9 +6333,10 @@ EPUBJS.Renderer.prototype.getRange = function(x, y){
return range;
};
/*
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var startX = 1;
var startY = 1;
var startX = 0;
var startY = 0;
var endX = this.width-1;
var endY = this.height-1;
var startRange = this.getRange(startX, startY);
@ -6180,6 +6352,29 @@ EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
end: endCfi || false
};
};
*/
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var pg;
var startRange, endRange;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
endRange = startRange;
if(this.layout.pageCount > 1) {
endRange = this.pageMap[pg-1];
}
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
endRange = startRange;
}
return {
start: startRange.start,
end: endRange.end
};
};
// Goto a cfi position in the current chapter
EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
@ -6220,6 +6415,18 @@ EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
return startEl;
}
};
// TODO: remove me - unsused
EPUBJS.Renderer.prototype.findElementAfter = function(x, y, startEl){
var el = startEl || this.render.getBaseElement();
var found;
found = this.walk(el, x, y);
if(found) {
return found;
}else{
return el;
}
};
/*

File diff suppressed because one or more lines are too long

6
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

View file

@ -2569,30 +2569,37 @@ EPUBJS.Book.prototype.createHiddenRender = function(renderer, _width, _height) {
var box = this.element.getBoundingClientRect();
var width = _width || this.settings.width || box.width;
var height = _height || this.settings.height || box.height;
var hiddenContainer;
var hiddenEl;
renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
this._registerReplacements(renderer);
if(this.settings.forceSingle) {
renderer.forceSingle(true);
}
hiddenContainer = document.createElement("div");
hiddenContainer.style.visibility = "hidden";
hiddenContainer.style.overflow = "hidden";
hiddenContainer.style.width = "0";
hiddenContainer.style.height = "0";
this.element.appendChild(hiddenContainer);
hiddenEl = document.createElement("div");
hiddenEl.style.visibility = "hidden";
hiddenEl.style.overflow = "hidden";
hiddenEl.style.width = "0";
hiddenEl.style.height = "0";
this.element.appendChild(hiddenEl);
hiddenEl.style.width = width + "px";//"0";
hiddenEl.style.height = height +"px"; //"0";
hiddenContainer.appendChild(hiddenEl);
renderer.initialize(hiddenEl, width, height);
return hiddenEl;
renderer.initialize(hiddenEl);
return hiddenContainer;
};
// Generates the pageList array by loading every chapter and paging through them
EPUBJS.Book.prototype.generatePageList = function(width, height){
var pageList = [];
var pager = new EPUBJS.Renderer(this.settings.render_method);
var hiddenElement = this.createHiddenRender(pager, width, height);
var pager = new EPUBJS.Renderer(this.settings.render_method, false); //hidden
var hiddenContainer = this.createHiddenRender(pager, width, height);
var deferred = new RSVP.defer();
var spinePos = -1;
var spineLength = this.spine.length;
@ -2608,14 +2615,26 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
} else {
spinePos = next;
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
pager.displayChapter(chapter, this.globalLayoutProperties).then(function(chap){
var nextPage = true;
pager.pageMap.forEach(function(item){
currentPage += 1;
pageList.push({
"cfi" : item.start,
"page" : currentPage
});
// Page though the entire chapter
while (nextPage) {
nextPage = pager.nextPage();
});
if(pager.pageMap.length % 2 > 0 &&
pager.layoutMethod == "ReflowableSpreads") {
currentPage += 1; // Handle Spreads
pageList.push({
"cfi" : pager.pageMap[pager.pageMap.length - 1].end,
"page" : currentPage
});
}
// Load up the next chapter
nextChapter(done);
});
@ -2625,37 +2644,10 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
var finished = nextChapter().then(function(){
pager.remove();
this.element.removeChild(hiddenElement);
this.element.removeChild(hiddenContainer);
deferred.resolve(pageList);
}.bind(this));
pager.on("renderer:visibleRangeChanged", function(range){
var endX, endY;
var endRange, endCfi;
currentPage += 1;
pageList.push({
"cfi" : range.start,
"page" : currentPage
});
if (pager.layoutMethod == "ReflowableSpreads") {
endX = pager.layout.colWidth + pager.layout.gap + 1;
endY = 1;
endRange = pager.getRange(endX, endY);
if(endRange) {
endCfi = pager.currentChapter.cfiFromRange(endRange);
currentPage += 1;
pageList.push({
"cfi" : endCfi,
"page" : currentPage
});
}
}
});
return deferred.promise;
};
@ -2739,9 +2731,9 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
if(range.end) {
endPage = this.pagination.pageFromCfi(range.end);
if(startPage != endPage) {
//if(startPage != endPage) {
pageRange.push(endPage);
}
//}
}
this.trigger("book:pageChanged", {
"anchorPage": startPage,
@ -3386,21 +3378,21 @@ EPUBJS.Book.prototype._rendered = function(err) {
};
EPUBJS.Book.prototype.applyStyles = function(callback){
if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
this.renderer.applyStyles(this.settings.styles);
EPUBJS.Book.prototype.applyStyles = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
renderer.applyStyles(this.settings.styles);
callback();
};
EPUBJS.Book.prototype.applyHeadTags = function(callback){
if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
this.renderer.applyHeadTags(this.settings.headTags);
EPUBJS.Book.prototype.applyHeadTags = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
renderer.applyHeadTags(this.settings.headTags);
callback();
};
EPUBJS.Book.prototype._registerReplacements = function(renderer){
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs.bind(this), true);
if(this._needsAssetReplacement()) {
@ -3564,7 +3556,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
range.setEnd(endContainer, _range.endOffset);
}
} catch (e) {
console.log("missed");
// console.log("missed");
startContainer = false;
}
@ -3572,13 +3564,14 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
// Fuzzy Match
if(!startContainer) {
console.log("not found, try fuzzy match");
// console.log("not found, try fuzzy match");
startXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
endXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
startContainer = this.contents.evaluate(startXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(startContainer){
// console.log("Found with Fuzzy");
range.setStart(startContainer, _range.startOffset);
if(!_range.collapsed) {
@ -4484,25 +4477,25 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) {
} else if(range.collapsed) {
return this.generateCfiFromElement(start, base); // single element
} else {
startSteps = this.pathTo(startElement);
startSteps = this.pathTo(start);
}
startPath = this.generatePathComponent(startSteps);
startOffset = range.startOffset;
if(!range.collapsed) {
end = range.startContainer;
end = range.endContainer;
if(end.nodeType === 3) { // text node
endElement = end.parentElement;
startIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endSteps = this.pathTo(endElement);
} else {
endSteps = this.pathTo(end);
}
endPath = this.generatePathComponent(endSteps);
endOffset = range.endOffset;
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")";
@ -4763,6 +4756,8 @@ EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _h
documentElement.style[columnAxis] = "horizontal";
documentElement.style[columnWidth] = width+"px";
documentElement.style[columnGap] = gap+"px";
this.colWidth = width;
this.gap = gap;
return {
pageWidth : this.spreadWidth,
@ -4877,6 +4872,8 @@ EPUBJS.Layout.Fixed = function(documentElement, _width, _height){
//-- Scroll
documentElement.style.overflow = "auto";
this.colWidth = width;
this.gap = 0;
return {
pageWidth : width,
@ -4930,12 +4927,14 @@ EPUBJS.Pagination.prototype.pageFromCfi = function(cfi){
} else {
// Otherwise add it to the list of locations
// Insert it in the correct position in the locations page
index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
//index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
index = EPUBJS.core.locationOf(cfi, this.locations, this.epubcfi.compare);
// Get the page at the location just before the new one, or return the first
pg = index-1 >= 0 ? this.pages[index-1] : this.pages[0];
pg = this.pages[index];
if(pg !== undefined) {
// Add the new page in so that the locations and page array match up
this.pages.splice(index, 0, pg);
//this.pages.splice(index, 0, pg);
} else {
pg = -1;
}
@ -5651,7 +5650,7 @@ EPUBJS.Render.Iframe.prototype.unload = function(){
//-- Enable binding events to Render
RSVP.EventTarget.mixin(EPUBJS.Render.Iframe.prototype);
EPUBJS.Renderer = function(renderMethod) {
EPUBJS.Renderer = function(renderMethod, hidden) {
// Dom events to listen for
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
this.upEvent = "mouseup";
@ -5686,6 +5685,7 @@ EPUBJS.Renderer = function(renderMethod) {
this.layoutSettings = {};
this.hidden = hidden || false;
//-- Adds Hook methods to the Book prototype
// Hooks will all return before triggering the callback.
EPUBJS.Hooks.mixin(this);
@ -5910,6 +5910,7 @@ EPUBJS.Renderer.prototype.beforeDisplay = function(callback, renderer){
// Update the renderer with the information passed by the layout
EPUBJS.Renderer.prototype.updatePages = function(layout){
this.pageMap = this.mapPage();
this.displayedPages = layout.displayedPages;
this.currentChapter.pages = layout.pageCount;
};
@ -5944,13 +5945,13 @@ EPUBJS.Renderer.prototype.reformat = function(){
// Hide and show the render's container .
EPUBJS.Renderer.prototype.visible = function(bool){
if(typeof(bool) === "undefined") {
return this.container.style.visibility;
return this.element.style.visibility;
}
if(bool === true){
this.container.style.visibility = "visible";
if(bool === true && !this.hidden){
this.element.style.visibility = "visible";
}else if(bool === false){
this.container.style.visibility = "hidden";
this.element.style.visibility = "hidden";
}
};
@ -6072,7 +6073,7 @@ EPUBJS.Renderer.prototype.firstElementisTextNode = function(node) {
};
// Walk the node tree from a start element to next visible element
EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.walk = function(node, x, y) {
var r, children, leng,
startNode = node,
prevNode,
@ -6081,9 +6082,8 @@ EPUBJS.Renderer.prototype.walk = function(node) {
var STOP = 10000, ITER=0;
while(!r && stack.length) {
node = stack.shift();
if( this.render.isElementVisible(node) && this.firstElementisTextNode(node)) {
if( this.containsPoint(node, x, y) && this.firstElementisTextNode(node)) {
r = node;
}
@ -6117,6 +6117,164 @@ EPUBJS.Renderer.prototype.walk = function(node) {
return r;
};
// Checks if an element is on the screen
EPUBJS.Renderer.prototype.containsPoint = function(el, x, y){
var rect;
var left;
if(el && typeof el.getBoundingClientRect === 'function'){
rect = el.getBoundingClientRect();
// console.log(el, rect, x, y);
if( rect.width !== 0 &&
rect.height !== 0 && // Element not visible
rect.left >= x &&
x <= rect.left + rect.width) {
return true;
}
}
return false;
};
EPUBJS.Renderer.prototype.sprint = function(root, func) {
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode: function (node) {
if ( ! /^\s*$/.test(node.data) ) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_REJECT;
}
}
}, false);
while ((node = treeWalker.nextNode())) {
func(node);
}
};
EPUBJS.Renderer.prototype.mapPage = function(){
var renderer = this;
var map = [{ start: null, end: null }];
var root = this.render.getBaseElement();
var page = 1;
var width = this.layout.colWidth + this.layout.gap;
var offset = this.formated.pageWidth * (this.chapterPos-1);
var limit = (width * page) - offset;
var prevRange;
var cfi;
var check = function(node) {
var ranges = renderer.splitTextNodeIntoWordsRanges(node);
ranges.forEach(function(range){
var pos = renderer.rangePosition(range);
// console.log(pos.left, pos.top, node);
if(!pos || (pos.width === 0 && pos.height === 0)) {
return;
}
if(pos.left + pos.width < limit) {
if(!map[page-1].start){
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[page-1].start = cfi;
}
} else {
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map.push({
start: cfi,
end: null
});
page += 1;
limit = (width * page) - offset;
}
prevRange = range;
});
};
this.sprint(root, check);
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
// Handle empty map
if(map.length === 1 && !map[0].start) {
range = this.doc.createRange();
range.selectNodeContents(root);
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[0].start = cfi;
map[0].end = cfi;
}
return map;
};
EPUBJS.Renderer.prototype.splitTextNodeIntoWordsRanges = function(node){
var ranges = [];
var text = node.textContent;
var range;
var rect;
var list;
pos = text.indexOf(" ");
if(pos === -1) {
range = this.doc.createRange();
range.selectNodeContents(node);
return [range];
}
range = this.doc.createRange();
range.setStart(node, pos+1);
while ( pos != -1 ) {
pos = text.indexOf(" ", pos + 1);
if(pos > 0) {
range.setEnd(node, pos);
ranges.push(range);
range = this.doc.createRange();
range.setStart(node, pos+1);
}
}
range.setEnd(node, text.length);
ranges.push(range);
return ranges;
};
EPUBJS.Renderer.prototype.rangePosition = function(range){
var rect;
var list;
list = range.getClientRects();
if(list.length) {
rect = list[0];
return rect;
}
return null;
};
/*
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
var range = this.doc.createRange();
@ -6136,19 +6294,32 @@ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
return this.currentChapter.cfiFromRange(range);
};
*/
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(){
var pg;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
}
return this.pageMap[(this.chapterPos * 2) -1].start;
};
EPUBJS.Renderer.prototype.getRange = function(x, y){
EPUBJS.Renderer.prototype.getRange = function(x, y, forceElement){
var range = this.doc.createRange();
var position;
if(typeof document.caretPositionFromPoint !== "undefined"){
forceElement = true; // temp override
if(typeof document.caretPositionFromPoint !== "undefined" && !forceElement){
position = this.doc.caretPositionFromPoint(x, y);
range.setStart(position.offsetNode, position.offset);
} else if(typeof document.caretRangeFromPoint !== "undefined"){
} else if(typeof document.caretRangeFromPoint !== "undefined" && !forceElement){
range = this.doc.caretRangeFromPoint(x, y);
} else {
this.visibileEl = this.findFirstVisible(prevEl);
this.visibileEl = this.findElementAfter(x, y);
range.setStart(this.visibileEl, 1);
}
@ -6161,9 +6332,10 @@ EPUBJS.Renderer.prototype.getRange = function(x, y){
return range;
};
/*
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var startX = 1;
var startY = 1;
var startX = 0;
var startY = 0;
var endX = this.width-1;
var endY = this.height-1;
var startRange = this.getRange(startX, startY);
@ -6179,6 +6351,29 @@ EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
end: endCfi || false
};
};
*/
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var pg;
var startRange, endRange;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
endRange = startRange;
if(this.layout.pageCount > 1) {
endRange = this.pageMap[pg-1];
}
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
endRange = startRange;
}
return {
start: startRange.start,
end: endRange.end
};
};
// Goto a cfi position in the current chapter
EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
@ -6219,6 +6414,18 @@ EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
return startEl;
}
};
// TODO: remove me - unsused
EPUBJS.Renderer.prototype.findElementAfter = function(x, y, startEl){
var el = startEl || this.render.getBaseElement();
var found;
found = this.walk(el, x, y);
if(found) {
return found;
}else{
return el;
}
};
/*

File diff suppressed because one or more lines are too long

View file

@ -196,9 +196,10 @@
book.on('book:pageChanged', function(location){
if(!mouseDown) {
slider.value = location.page;
slider.value = location.anchorPage;
}
currentPage.value = location.page;
currentPage.value = location.anchorPage;
console.log(location.pageRange)
});
</script>
</body>

File diff suppressed because one or more lines are too long

355
reader/js/epub.min.js vendored
View file

@ -2570,30 +2570,37 @@ EPUBJS.Book.prototype.createHiddenRender = function(renderer, _width, _height) {
var box = this.element.getBoundingClientRect();
var width = _width || this.settings.width || box.width;
var height = _height || this.settings.height || box.height;
var hiddenContainer;
var hiddenEl;
renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
this._registerReplacements(renderer);
if(this.settings.forceSingle) {
renderer.forceSingle(true);
}
hiddenContainer = document.createElement("div");
hiddenContainer.style.visibility = "hidden";
hiddenContainer.style.overflow = "hidden";
hiddenContainer.style.width = "0";
hiddenContainer.style.height = "0";
this.element.appendChild(hiddenContainer);
hiddenEl = document.createElement("div");
hiddenEl.style.visibility = "hidden";
hiddenEl.style.overflow = "hidden";
hiddenEl.style.width = "0";
hiddenEl.style.height = "0";
this.element.appendChild(hiddenEl);
hiddenEl.style.width = width + "px";//"0";
hiddenEl.style.height = height +"px"; //"0";
hiddenContainer.appendChild(hiddenEl);
renderer.initialize(hiddenEl, width, height);
return hiddenEl;
renderer.initialize(hiddenEl);
return hiddenContainer;
};
// Generates the pageList array by loading every chapter and paging through them
EPUBJS.Book.prototype.generatePageList = function(width, height){
var pageList = [];
var pager = new EPUBJS.Renderer(this.settings.render_method);
var hiddenElement = this.createHiddenRender(pager, width, height);
var pager = new EPUBJS.Renderer(this.settings.render_method, false); //hidden
var hiddenContainer = this.createHiddenRender(pager, width, height);
var deferred = new RSVP.defer();
var spinePos = -1;
var spineLength = this.spine.length;
@ -2609,14 +2616,26 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
} else {
spinePos = next;
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
pager.displayChapter(chapter, this.globalLayoutProperties).then(function(chap){
var nextPage = true;
pager.pageMap.forEach(function(item){
currentPage += 1;
pageList.push({
"cfi" : item.start,
"page" : currentPage
});
// Page though the entire chapter
while (nextPage) {
nextPage = pager.nextPage();
});
if(pager.pageMap.length % 2 > 0 &&
pager.layoutMethod == "ReflowableSpreads") {
currentPage += 1; // Handle Spreads
pageList.push({
"cfi" : pager.pageMap[pager.pageMap.length - 1].end,
"page" : currentPage
});
}
// Load up the next chapter
nextChapter(done);
});
@ -2626,37 +2645,10 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
var finished = nextChapter().then(function(){
pager.remove();
this.element.removeChild(hiddenElement);
this.element.removeChild(hiddenContainer);
deferred.resolve(pageList);
}.bind(this));
pager.on("renderer:visibleRangeChanged", function(range){
var endX, endY;
var endRange, endCfi;
currentPage += 1;
pageList.push({
"cfi" : range.start,
"page" : currentPage
});
if (pager.layoutMethod == "ReflowableSpreads") {
endX = pager.layout.colWidth + pager.layout.gap + 1;
endY = 1;
endRange = pager.getRange(endX, endY);
if(endRange) {
endCfi = pager.currentChapter.cfiFromRange(endRange);
currentPage += 1;
pageList.push({
"cfi" : endCfi,
"page" : currentPage
});
}
}
});
return deferred.promise;
};
@ -2740,9 +2732,9 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
if(range.end) {
endPage = this.pagination.pageFromCfi(range.end);
if(startPage != endPage) {
//if(startPage != endPage) {
pageRange.push(endPage);
}
//}
}
this.trigger("book:pageChanged", {
"anchorPage": startPage,
@ -3387,21 +3379,21 @@ EPUBJS.Book.prototype._rendered = function(err) {
};
EPUBJS.Book.prototype.applyStyles = function(callback){
if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
this.renderer.applyStyles(this.settings.styles);
EPUBJS.Book.prototype.applyStyles = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
renderer.applyStyles(this.settings.styles);
callback();
};
EPUBJS.Book.prototype.applyHeadTags = function(callback){
if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
this.renderer.applyHeadTags(this.settings.headTags);
EPUBJS.Book.prototype.applyHeadTags = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
renderer.applyHeadTags(this.settings.headTags);
callback();
};
EPUBJS.Book.prototype._registerReplacements = function(renderer){
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs.bind(this), true);
if(this._needsAssetReplacement()) {
@ -3565,7 +3557,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
range.setEnd(endContainer, _range.endOffset);
}
} catch (e) {
console.log("missed");
// console.log("missed");
startContainer = false;
}
@ -3573,13 +3565,14 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
// Fuzzy Match
if(!startContainer) {
console.log("not found, try fuzzy match");
// console.log("not found, try fuzzy match");
startXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
endXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
startContainer = this.contents.evaluate(startXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(startContainer){
// console.log("Found with Fuzzy");
range.setStart(startContainer, _range.startOffset);
if(!_range.collapsed) {
@ -4485,25 +4478,25 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) {
} else if(range.collapsed) {
return this.generateCfiFromElement(start, base); // single element
} else {
startSteps = this.pathTo(startElement);
startSteps = this.pathTo(start);
}
startPath = this.generatePathComponent(startSteps);
startOffset = range.startOffset;
if(!range.collapsed) {
end = range.startContainer;
end = range.endContainer;
if(end.nodeType === 3) { // text node
endElement = end.parentElement;
startIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endSteps = this.pathTo(endElement);
} else {
endSteps = this.pathTo(end);
}
endPath = this.generatePathComponent(endSteps);
endOffset = range.endOffset;
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")";
@ -4764,6 +4757,8 @@ EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _h
documentElement.style[columnAxis] = "horizontal";
documentElement.style[columnWidth] = width+"px";
documentElement.style[columnGap] = gap+"px";
this.colWidth = width;
this.gap = gap;
return {
pageWidth : this.spreadWidth,
@ -4878,6 +4873,8 @@ EPUBJS.Layout.Fixed = function(documentElement, _width, _height){
//-- Scroll
documentElement.style.overflow = "auto";
this.colWidth = width;
this.gap = 0;
return {
pageWidth : width,
@ -4931,12 +4928,14 @@ EPUBJS.Pagination.prototype.pageFromCfi = function(cfi){
} else {
// Otherwise add it to the list of locations
// Insert it in the correct position in the locations page
index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
//index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
index = EPUBJS.core.locationOf(cfi, this.locations, this.epubcfi.compare);
// Get the page at the location just before the new one, or return the first
pg = index-1 >= 0 ? this.pages[index-1] : this.pages[0];
pg = this.pages[index];
if(pg !== undefined) {
// Add the new page in so that the locations and page array match up
this.pages.splice(index, 0, pg);
//this.pages.splice(index, 0, pg);
} else {
pg = -1;
}
@ -5652,7 +5651,7 @@ EPUBJS.Render.Iframe.prototype.unload = function(){
//-- Enable binding events to Render
RSVP.EventTarget.mixin(EPUBJS.Render.Iframe.prototype);
EPUBJS.Renderer = function(renderMethod) {
EPUBJS.Renderer = function(renderMethod, hidden) {
// Dom events to listen for
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
this.upEvent = "mouseup";
@ -5687,6 +5686,7 @@ EPUBJS.Renderer = function(renderMethod) {
this.layoutSettings = {};
this.hidden = hidden || false;
//-- Adds Hook methods to the Book prototype
// Hooks will all return before triggering the callback.
EPUBJS.Hooks.mixin(this);
@ -5911,6 +5911,7 @@ EPUBJS.Renderer.prototype.beforeDisplay = function(callback, renderer){
// Update the renderer with the information passed by the layout
EPUBJS.Renderer.prototype.updatePages = function(layout){
this.pageMap = this.mapPage();
this.displayedPages = layout.displayedPages;
this.currentChapter.pages = layout.pageCount;
};
@ -5945,13 +5946,13 @@ EPUBJS.Renderer.prototype.reformat = function(){
// Hide and show the render's container .
EPUBJS.Renderer.prototype.visible = function(bool){
if(typeof(bool) === "undefined") {
return this.container.style.visibility;
return this.element.style.visibility;
}
if(bool === true){
this.container.style.visibility = "visible";
if(bool === true && !this.hidden){
this.element.style.visibility = "visible";
}else if(bool === false){
this.container.style.visibility = "hidden";
this.element.style.visibility = "hidden";
}
};
@ -6073,7 +6074,7 @@ EPUBJS.Renderer.prototype.firstElementisTextNode = function(node) {
};
// Walk the node tree from a start element to next visible element
EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.walk = function(node, x, y) {
var r, children, leng,
startNode = node,
prevNode,
@ -6082,9 +6083,8 @@ EPUBJS.Renderer.prototype.walk = function(node) {
var STOP = 10000, ITER=0;
while(!r && stack.length) {
node = stack.shift();
if( this.render.isElementVisible(node) && this.firstElementisTextNode(node)) {
if( this.containsPoint(node, x, y) && this.firstElementisTextNode(node)) {
r = node;
}
@ -6118,6 +6118,164 @@ EPUBJS.Renderer.prototype.walk = function(node) {
return r;
};
// Checks if an element is on the screen
EPUBJS.Renderer.prototype.containsPoint = function(el, x, y){
var rect;
var left;
if(el && typeof el.getBoundingClientRect === 'function'){
rect = el.getBoundingClientRect();
// console.log(el, rect, x, y);
if( rect.width !== 0 &&
rect.height !== 0 && // Element not visible
rect.left >= x &&
x <= rect.left + rect.width) {
return true;
}
}
return false;
};
EPUBJS.Renderer.prototype.sprint = function(root, func) {
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode: function (node) {
if ( ! /^\s*$/.test(node.data) ) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_REJECT;
}
}
}, false);
while ((node = treeWalker.nextNode())) {
func(node);
}
};
EPUBJS.Renderer.prototype.mapPage = function(){
var renderer = this;
var map = [{ start: null, end: null }];
var root = this.render.getBaseElement();
var page = 1;
var width = this.layout.colWidth + this.layout.gap;
var offset = this.formated.pageWidth * (this.chapterPos-1);
var limit = (width * page) - offset;
var prevRange;
var cfi;
var check = function(node) {
var ranges = renderer.splitTextNodeIntoWordsRanges(node);
ranges.forEach(function(range){
var pos = renderer.rangePosition(range);
// console.log(pos.left, pos.top, node);
if(!pos || (pos.width === 0 && pos.height === 0)) {
return;
}
if(pos.left + pos.width < limit) {
if(!map[page-1].start){
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[page-1].start = cfi;
}
} else {
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map.push({
start: cfi,
end: null
});
page += 1;
limit = (width * page) - offset;
}
prevRange = range;
});
};
this.sprint(root, check);
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
// Handle empty map
if(map.length === 1 && !map[0].start) {
range = this.doc.createRange();
range.selectNodeContents(root);
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[0].start = cfi;
map[0].end = cfi;
}
return map;
};
EPUBJS.Renderer.prototype.splitTextNodeIntoWordsRanges = function(node){
var ranges = [];
var text = node.textContent;
var range;
var rect;
var list;
pos = text.indexOf(" ");
if(pos === -1) {
range = this.doc.createRange();
range.selectNodeContents(node);
return [range];
}
range = this.doc.createRange();
range.setStart(node, pos+1);
while ( pos != -1 ) {
pos = text.indexOf(" ", pos + 1);
if(pos > 0) {
range.setEnd(node, pos);
ranges.push(range);
range = this.doc.createRange();
range.setStart(node, pos+1);
}
}
range.setEnd(node, text.length);
ranges.push(range);
return ranges;
};
EPUBJS.Renderer.prototype.rangePosition = function(range){
var rect;
var list;
list = range.getClientRects();
if(list.length) {
rect = list[0];
return rect;
}
return null;
};
/*
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
var range = this.doc.createRange();
@ -6137,19 +6295,32 @@ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
return this.currentChapter.cfiFromRange(range);
};
*/
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(){
var pg;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
}
return this.pageMap[(this.chapterPos * 2) -1].start;
};
EPUBJS.Renderer.prototype.getRange = function(x, y){
EPUBJS.Renderer.prototype.getRange = function(x, y, forceElement){
var range = this.doc.createRange();
var position;
if(typeof document.caretPositionFromPoint !== "undefined"){
forceElement = true; // temp override
if(typeof document.caretPositionFromPoint !== "undefined" && !forceElement){
position = this.doc.caretPositionFromPoint(x, y);
range.setStart(position.offsetNode, position.offset);
} else if(typeof document.caretRangeFromPoint !== "undefined"){
} else if(typeof document.caretRangeFromPoint !== "undefined" && !forceElement){
range = this.doc.caretRangeFromPoint(x, y);
} else {
this.visibileEl = this.findFirstVisible(prevEl);
this.visibileEl = this.findElementAfter(x, y);
range.setStart(this.visibileEl, 1);
}
@ -6162,9 +6333,10 @@ EPUBJS.Renderer.prototype.getRange = function(x, y){
return range;
};
/*
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var startX = 1;
var startY = 1;
var startX = 0;
var startY = 0;
var endX = this.width-1;
var endY = this.height-1;
var startRange = this.getRange(startX, startY);
@ -6180,6 +6352,29 @@ EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
end: endCfi || false
};
};
*/
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var pg;
var startRange, endRange;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
endRange = startRange;
if(this.layout.pageCount > 1) {
endRange = this.pageMap[pg-1];
}
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
endRange = startRange;
}
return {
start: startRange.start,
end: endRange.end
};
};
// Goto a cfi position in the current chapter
EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
@ -6220,6 +6415,18 @@ EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
return startEl;
}
};
// TODO: remove me - unsused
EPUBJS.Renderer.prototype.findElementAfter = function(x, y, startEl){
var el = startEl || this.render.getBaseElement();
var found;
found = this.walk(el, x, y);
if(found) {
return found;
}else{
return el;
}
};
/*

View file

@ -320,30 +320,37 @@ EPUBJS.Book.prototype.createHiddenRender = function(renderer, _width, _height) {
var box = this.element.getBoundingClientRect();
var width = _width || this.settings.width || box.width;
var height = _height || this.settings.height || box.height;
var hiddenContainer;
var hiddenEl;
renderer.setMinSpreadWidth(this.settings.minSpreadWidth);
this._registerReplacements(renderer);
if(this.settings.forceSingle) {
renderer.forceSingle(true);
}
hiddenContainer = document.createElement("div");
hiddenContainer.style.visibility = "hidden";
hiddenContainer.style.overflow = "hidden";
hiddenContainer.style.width = "0";
hiddenContainer.style.height = "0";
this.element.appendChild(hiddenContainer);
hiddenEl = document.createElement("div");
hiddenEl.style.visibility = "hidden";
hiddenEl.style.overflow = "hidden";
hiddenEl.style.width = "0";
hiddenEl.style.height = "0";
this.element.appendChild(hiddenEl);
hiddenEl.style.width = width + "px";//"0";
hiddenEl.style.height = height +"px"; //"0";
hiddenContainer.appendChild(hiddenEl);
renderer.initialize(hiddenEl, width, height);
return hiddenEl;
renderer.initialize(hiddenEl);
return hiddenContainer;
};
// Generates the pageList array by loading every chapter and paging through them
EPUBJS.Book.prototype.generatePageList = function(width, height){
var pageList = [];
var pager = new EPUBJS.Renderer(this.settings.render_method);
var hiddenElement = this.createHiddenRender(pager, width, height);
var pager = new EPUBJS.Renderer(this.settings.render_method, false); //hidden
var hiddenContainer = this.createHiddenRender(pager, width, height);
var deferred = new RSVP.defer();
var spinePos = -1;
var spineLength = this.spine.length;
@ -359,14 +366,26 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
} else {
spinePos = next;
chapter = new EPUBJS.Chapter(this.spine[spinePos], this.store);
pager.displayChapter(chapter, this.globalLayoutProperties).then(function(chap){
var nextPage = true;
pager.pageMap.forEach(function(item){
currentPage += 1;
pageList.push({
"cfi" : item.start,
"page" : currentPage
});
// Page though the entire chapter
while (nextPage) {
nextPage = pager.nextPage();
});
if(pager.pageMap.length % 2 > 0 &&
pager.layoutMethod == "ReflowableSpreads") {
currentPage += 1; // Handle Spreads
pageList.push({
"cfi" : pager.pageMap[pager.pageMap.length - 1].end,
"page" : currentPage
});
}
// Load up the next chapter
nextChapter(done);
});
@ -376,37 +395,10 @@ EPUBJS.Book.prototype.generatePageList = function(width, height){
var finished = nextChapter().then(function(){
pager.remove();
this.element.removeChild(hiddenElement);
this.element.removeChild(hiddenContainer);
deferred.resolve(pageList);
}.bind(this));
pager.on("renderer:visibleRangeChanged", function(range){
var endX, endY;
var endRange, endCfi;
currentPage += 1;
pageList.push({
"cfi" : range.start,
"page" : currentPage
});
if (pager.layoutMethod == "ReflowableSpreads") {
endX = pager.layout.colWidth + pager.layout.gap + 1;
endY = 1;
endRange = pager.getRange(endX, endY);
if(endRange) {
endCfi = pager.currentChapter.cfiFromRange(endRange);
currentPage += 1;
pageList.push({
"cfi" : endCfi,
"page" : currentPage
});
}
}
});
return deferred.promise;
};
@ -490,9 +482,9 @@ EPUBJS.Book.prototype.listenToRenderer = function(renderer){
if(range.end) {
endPage = this.pagination.pageFromCfi(range.end);
if(startPage != endPage) {
//if(startPage != endPage) {
pageRange.push(endPage);
}
//}
}
this.trigger("book:pageChanged", {
"anchorPage": startPage,
@ -1137,21 +1129,21 @@ EPUBJS.Book.prototype._rendered = function(err) {
};
EPUBJS.Book.prototype.applyStyles = function(callback){
if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
this.renderer.applyStyles(this.settings.styles);
EPUBJS.Book.prototype.applyStyles = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyStyles", arguments);
renderer.applyStyles(this.settings.styles);
callback();
};
EPUBJS.Book.prototype.applyHeadTags = function(callback){
if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
this.renderer.applyHeadTags(this.settings.headTags);
EPUBJS.Book.prototype.applyHeadTags = function(renderer, callback){
// if(!this.isRendered) return this._q.enqueue("applyHeadTags", arguments);
renderer.applyHeadTags(this.settings.headTags);
callback();
};
EPUBJS.Book.prototype._registerReplacements = function(renderer){
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this), true);
renderer.registerHook("beforeChapterDisplay", this.applyStyles.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", this.applyHeadTags.bind(this, renderer), true);
renderer.registerHook("beforeChapterDisplay", EPUBJS.replace.hrefs.bind(this), true);
if(this._needsAssetReplacement()) {

View file

@ -97,7 +97,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
range.setEnd(endContainer, _range.endOffset);
}
} catch (e) {
console.log("missed");
// console.log("missed");
startContainer = false;
}
@ -105,13 +105,14 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
// Fuzzy Match
if(!startContainer) {
console.log("not found, try fuzzy match");
// console.log("not found, try fuzzy match");
startXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
endXpath = "//text()[contains(.,'" + _range.startContainer.textContent + "')]";
startContainer = this.contents.evaluate(startXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(startContainer){
// console.log("Found with Fuzzy");
range.setStart(startContainer, _range.startOffset);
if(!_range.collapsed) {

View file

@ -407,25 +407,25 @@ EPUBJS.EpubCFI.prototype.generateCfiFromRange = function(range, base) {
} else if(range.collapsed) {
return this.generateCfiFromElement(start, base); // single element
} else {
startSteps = this.pathTo(startElement);
startSteps = this.pathTo(start);
}
startPath = this.generatePathComponent(startSteps);
startOffset = range.startOffset;
if(!range.collapsed) {
end = range.startContainer;
end = range.endContainer;
if(end.nodeType === 3) { // text node
endElement = end.parentElement;
startIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endIndex = 1 + (2 * Array.prototype.indexOf.call(endElement.childNodes, end));
endSteps = this.pathTo(endElement);
} else {
endSteps = this.pathTo(end);
}
endPath = this.generatePathComponent(endSteps);
endOffset = range.endOffset;
return "epubcfi(" + base + "!" + startPath + "/" + startIndex + ":" + startOffset + "," + endPath + "/" + endIndex + ":" + endOffset + ")";

View file

@ -33,6 +33,8 @@ EPUBJS.Layout.Reflowable.prototype.format = function(documentElement, _width, _h
documentElement.style[columnAxis] = "horizontal";
documentElement.style[columnWidth] = width+"px";
documentElement.style[columnGap] = gap+"px";
this.colWidth = width;
this.gap = gap;
return {
pageWidth : this.spreadWidth,
@ -147,6 +149,8 @@ EPUBJS.Layout.Fixed = function(documentElement, _width, _height){
//-- Scroll
documentElement.style.overflow = "auto";
this.colWidth = width;
this.gap = 0;
return {
pageWidth : width,

View file

@ -37,12 +37,14 @@ EPUBJS.Pagination.prototype.pageFromCfi = function(cfi){
} else {
// Otherwise add it to the list of locations
// Insert it in the correct position in the locations page
index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
//index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
index = EPUBJS.core.locationOf(cfi, this.locations, this.epubcfi.compare);
// Get the page at the location just before the new one, or return the first
pg = index-1 >= 0 ? this.pages[index-1] : this.pages[0];
pg = this.pages[index];
if(pg !== undefined) {
// Add the new page in so that the locations and page array match up
this.pages.splice(index, 0, pg);
//this.pages.splice(index, 0, pg);
} else {
pg = -1;
}

View file

@ -1,4 +1,4 @@
EPUBJS.Renderer = function(renderMethod) {
EPUBJS.Renderer = function(renderMethod, hidden) {
// Dom events to listen for
this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click"];
this.upEvent = "mouseup";
@ -33,6 +33,7 @@ EPUBJS.Renderer = function(renderMethod) {
this.layoutSettings = {};
this.hidden = hidden || false;
//-- Adds Hook methods to the Book prototype
// Hooks will all return before triggering the callback.
EPUBJS.Hooks.mixin(this);
@ -257,6 +258,7 @@ EPUBJS.Renderer.prototype.beforeDisplay = function(callback, renderer){
// Update the renderer with the information passed by the layout
EPUBJS.Renderer.prototype.updatePages = function(layout){
this.pageMap = this.mapPage();
this.displayedPages = layout.displayedPages;
this.currentChapter.pages = layout.pageCount;
};
@ -291,13 +293,13 @@ EPUBJS.Renderer.prototype.reformat = function(){
// Hide and show the render's container .
EPUBJS.Renderer.prototype.visible = function(bool){
if(typeof(bool) === "undefined") {
return this.container.style.visibility;
return this.element.style.visibility;
}
if(bool === true){
this.container.style.visibility = "visible";
if(bool === true && !this.hidden){
this.element.style.visibility = "visible";
}else if(bool === false){
this.container.style.visibility = "hidden";
this.element.style.visibility = "hidden";
}
};
@ -419,7 +421,7 @@ EPUBJS.Renderer.prototype.firstElementisTextNode = function(node) {
};
// Walk the node tree from a start element to next visible element
EPUBJS.Renderer.prototype.walk = function(node) {
EPUBJS.Renderer.prototype.walk = function(node, x, y) {
var r, children, leng,
startNode = node,
prevNode,
@ -428,9 +430,8 @@ EPUBJS.Renderer.prototype.walk = function(node) {
var STOP = 10000, ITER=0;
while(!r && stack.length) {
node = stack.shift();
if( this.render.isElementVisible(node) && this.firstElementisTextNode(node)) {
if( this.containsPoint(node, x, y) && this.firstElementisTextNode(node)) {
r = node;
}
@ -464,6 +465,164 @@ EPUBJS.Renderer.prototype.walk = function(node) {
return r;
};
// Checks if an element is on the screen
EPUBJS.Renderer.prototype.containsPoint = function(el, x, y){
var rect;
var left;
if(el && typeof el.getBoundingClientRect === 'function'){
rect = el.getBoundingClientRect();
// console.log(el, rect, x, y);
if( rect.width !== 0 &&
rect.height !== 0 && // Element not visible
rect.left >= x &&
x <= rect.left + rect.width) {
return true;
}
}
return false;
};
EPUBJS.Renderer.prototype.sprint = function(root, func) {
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode: function (node) {
if ( ! /^\s*$/.test(node.data) ) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_REJECT;
}
}
}, false);
while ((node = treeWalker.nextNode())) {
func(node);
}
};
EPUBJS.Renderer.prototype.mapPage = function(){
var renderer = this;
var map = [{ start: null, end: null }];
var root = this.render.getBaseElement();
var page = 1;
var width = this.layout.colWidth + this.layout.gap;
var offset = this.formated.pageWidth * (this.chapterPos-1);
var limit = (width * page) - offset;
var prevRange;
var cfi;
var check = function(node) {
var ranges = renderer.splitTextNodeIntoWordsRanges(node);
ranges.forEach(function(range){
var pos = renderer.rangePosition(range);
// console.log(pos.left, pos.top, node);
if(!pos || (pos.width === 0 && pos.height === 0)) {
return;
}
if(pos.left + pos.width < limit) {
if(!map[page-1].start){
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[page-1].start = cfi;
}
} else {
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map.push({
start: cfi,
end: null
});
page += 1;
limit = (width * page) - offset;
}
prevRange = range;
});
};
this.sprint(root, check);
if(prevRange){
prevRange.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(prevRange);
map[page-1].end = cfi;
}
// Handle empty map
if(map.length === 1 && !map[0].start) {
range = this.doc.createRange();
range.selectNodeContents(root);
range.collapse(true);
cfi = renderer.currentChapter.cfiFromRange(range);
map[0].start = cfi;
map[0].end = cfi;
}
return map;
};
EPUBJS.Renderer.prototype.splitTextNodeIntoWordsRanges = function(node){
var ranges = [];
var text = node.textContent;
var range;
var rect;
var list;
pos = text.indexOf(" ");
if(pos === -1) {
range = this.doc.createRange();
range.selectNodeContents(node);
return [range];
}
range = this.doc.createRange();
range.setStart(node, pos+1);
while ( pos != -1 ) {
pos = text.indexOf(" ", pos + 1);
if(pos > 0) {
range.setEnd(node, pos);
ranges.push(range);
range = this.doc.createRange();
range.setStart(node, pos+1);
}
}
range.setEnd(node, text.length);
ranges.push(range);
return ranges;
};
EPUBJS.Renderer.prototype.rangePosition = function(range){
var rect;
var list;
list = range.getClientRects();
if(list.length) {
rect = list[0];
return rect;
}
return null;
};
/*
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
var range = this.doc.createRange();
@ -483,19 +642,32 @@ EPUBJS.Renderer.prototype.getPageCfi = function(prevEl){
return this.currentChapter.cfiFromRange(range);
};
*/
// Get the cfi of the current page
EPUBJS.Renderer.prototype.getPageCfi = function(){
var pg;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
}
return this.pageMap[(this.chapterPos * 2) -1].start;
};
EPUBJS.Renderer.prototype.getRange = function(x, y){
EPUBJS.Renderer.prototype.getRange = function(x, y, forceElement){
var range = this.doc.createRange();
var position;
if(typeof document.caretPositionFromPoint !== "undefined"){
forceElement = true; // temp override
if(typeof document.caretPositionFromPoint !== "undefined" && !forceElement){
position = this.doc.caretPositionFromPoint(x, y);
range.setStart(position.offsetNode, position.offset);
} else if(typeof document.caretRangeFromPoint !== "undefined"){
} else if(typeof document.caretRangeFromPoint !== "undefined" && !forceElement){
range = this.doc.caretRangeFromPoint(x, y);
} else {
this.visibileEl = this.findFirstVisible(prevEl);
this.visibileEl = this.findElementAfter(x, y);
range.setStart(this.visibileEl, 1);
}
@ -508,9 +680,10 @@ EPUBJS.Renderer.prototype.getRange = function(x, y){
return range;
};
/*
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var startX = 1;
var startY = 1;
var startX = 0;
var startY = 0;
var endX = this.width-1;
var endY = this.height-1;
var startRange = this.getRange(startX, startY);
@ -526,6 +699,29 @@ EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
end: endCfi || false
};
};
*/
EPUBJS.Renderer.prototype.getVisibleRangeCfi = function(prevEl){
var pg;
var startRange, endRange;
if (this.layoutMethod == "ReflowableSpreads") {
pg = this.chapterPos*2;
startRange = this.pageMap[pg-2];
endRange = startRange;
if(this.layout.pageCount > 1) {
endRange = this.pageMap[pg-1];
}
} else {
pg = this.chapterPos;
startRange = this.pageMap[pg-1];
endRange = startRange;
}
return {
start: startRange.start,
end: endRange.end
};
};
// Goto a cfi position in the current chapter
EPUBJS.Renderer.prototype.gotoCfi = function(cfi){
@ -566,6 +762,18 @@ EPUBJS.Renderer.prototype.findFirstVisible = function(startEl){
return startEl;
}
};
// TODO: remove me - unsused
EPUBJS.Renderer.prototype.findElementAfter = function(x, y, startEl){
var el = startEl || this.render.getBaseElement();
var found;
found = this.walk(el, x, y);
if(found) {
return found;
}else{
return el;
}
};
/*