1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-05 15:32:55 +02:00

Updated Chapter to use cloned document, added find method to get cfi of a string within the chapter, Added Book.chapter method to load a chapter from URL

This commit is contained in:
Fred Chasen 2014-07-09 00:34:49 -07:00
parent 8829d14186
commit 02fba7d148
6 changed files with 197 additions and 13 deletions

2
books

@ -1 +1 @@
Subproject commit 950c742b3d66cc7ac53bd0663a41315f001da1c4
Subproject commit ab9755a74714b647290c861f666515de220935d8

View file

@ -1129,6 +1129,19 @@ EPUBJS.Book.prototype.setGap = function(gap) {
}
};
EPUBJS.Book.prototype.chapter = function(path) {
var spinePos = this.spineIndexByURL[path];
var spineItem;
var chapter;
if(spinePos){
spineItem = this.spine[spinePos];
chapter = new EPUBJS.Chapter(spineItem, this.store);
chapter.load();
}
return chapter;
};
EPUBJS.Book.prototype.unload = function(){
if(this.settings.restore && localStorage) {

View file

@ -10,18 +10,26 @@ EPUBJS.Chapter = function(spineObject, store){
this.pages = 1;
this.store = store;
this.epubcfi = new EPUBJS.EpubCFI();
this.deferred = new RSVP.defer();
this.loaded = this.deferred.promise;
};
EPUBJS.Chapter.prototype.contents = function(_store){
EPUBJS.Chapter.prototype.load = function(_store){
var store = _store || this.store;
var promise;
// if(this.store && (!this.book.online || this.book.contained))
if(store){
return store.get(href);
promise = store.get(this.href);
}else{
return EPUBJS.core.request(href, 'xml');
promise = EPUBJS.core.request(this.absolute, 'xml');
}
promise.then(function(xml){
this.setDocument(xml);
}.bind(this));
return promise;
};
EPUBJS.Chapter.prototype.url = function(_store){
@ -71,13 +79,27 @@ EPUBJS.Chapter.prototype.getID = function(){
};
EPUBJS.Chapter.prototype.unload = function(store){
this.contents = null;
this.document = null;
if(this.tempUrl && store) {
store.revokeUrl(this.tempUrl);
this.tempUrl = false;
}
};
EPUBJS.Chapter.prototype.setDocument = function(_document){
this.document = _document.implementation.createDocument(
_document.namespaceURI, //namespace to use
null, //empty document
_document.doctype //doctype (null for XML)
);
this.contents = this.document.importNode(
_document.documentElement, //node to import
true //clone its descendants
);
this.document.appendChild(this.contents);
this.deferred.resolve(this.contents);
};
EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
var range;
var startXpath, endXpath;
@ -85,17 +107,17 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
var cleanTextContent, cleanEndTextContent;
// Check for Contents
if(!this.contents) return;
if(!this.document) return;
startXpath = EPUBJS.core.getElementXPath(_range.startContainer);
// console.log(startContainer)
endXpath = EPUBJS.core.getElementXPath(_range.endContainer);
startContainer = this.contents.evaluate(startXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
startContainer = this.document.evaluate(startXpath, this.document, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(!_range.collapsed) {
endContainer = this.contents.evaluate(endXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
endContainer = this.document.evaluate(endXpath, this.document, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
range = this.contents.createRange();
range = this.document.createRange();
// Find Exact Range in original document
if(startContainer) {
try {
@ -116,7 +138,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
cleanStartTextContent = EPUBJS.core.cleanStringForXpath(_range.startContainer.textContent);
startXpath = "//text()[contains(.," + cleanStartTextContent + ")]";
startContainer = this.contents.evaluate(startXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
startContainer = this.document.evaluate(startXpath, this.document, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(startContainer){
// console.log("Found with Fuzzy");
@ -125,7 +147,7 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
if(!_range.collapsed) {
cleanEndTextContent = EPUBJS.core.cleanStringForXpath(_range.endContainer.textContent);
endXpath = "//text()[contains(.," + cleanEndTextContent + ")]";
endContainer = this.contents.evaluate(endXpath, this.contents, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
endContainer = this.document.evaluate(endXpath, this.document, EPUBJS.core.nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if(endContainer) {
range.setEnd(endContainer, _range.endOffset);
}
@ -137,3 +159,71 @@ EPUBJS.Chapter.prototype.cfiFromRange = function(_range) {
// Generate the Cfi
return this.epubcfi.generateCfiFromRange(range, this.cfiBase);
};
EPUBJS.Chapter.prototype.find = function(_query){
var chapter = this;
var matches = [];
var query = _query.toLowerCase();
//var xpath = this.document.evaluate(".//text()[contains(translate(., '"+query.toUpperCase()+"', '"+query+"'),'"+query+"')]", this.document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var find = function(node){
// Search String
var text = node.textContent.toLowerCase();
var range = chapter.document.createRange();
var cfi;
var pos;
var last = -1;
while (pos != -1) {
pos = text.indexOf(query, last + 1);
if(pos != -1) {
// If Found, Create Range
range = chapter.document.createRange();
range.setStart(node, pos);
range.setEnd(node, pos + query.length);
//Generate CFI
cfi = chapter.cfiFromRange(range);
//Add CFI to list
matches.push(cfi);
}
last = pos;
}
};
// Grab text nodes
/*
for ( var i=0 ; i < xpath.snapshotLength; i++ ) {
find(xpath.snapshotItem(i));
}
*/
this.textSprint(this.document, function(node){
find(node);
});
// Return List of CFIs
return matches;
};
EPUBJS.Chapter.prototype.textSprint = 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);
var node;
while ((node = treeWalker.nextNode())) {
func(node);
}
};

View file

@ -153,7 +153,7 @@ EPUBJS.Renderer.prototype.load = function(url){
render.then(function(contents) {
var formated;
this.currentChapter.contents = this.render.document;
this.currentChapter.setDocument(this.render.document);
this.contents = contents;
this.doc = this.render.document;

80
tests/chapter.js Normal file
View file

@ -0,0 +1,80 @@
module('Chapter');
asyncTest("Create a Chapter", 2, function() {
var book = ePub('/reader/moby-dick/', { width: 400, height: 600 });
book.ready.all.then(function(){
var chapter = book.chapter("chapter_001.xhtml");
equal(chapter.spinePos, 6, "Chapter Pos is correct" );
equal(chapter.href, "chapter_001.xhtml", "Chapter href is correct" );
start();
});
});
asyncTest("Load a Chapter", 2, function() {
var book = ePub('/reader/moby-dick/', { width: 400, height: 600 });
book.ready.all.then(function(){
var chapter = book.chapter("chapter_001.xhtml");
// var loaded = chapter.load();
start();
equal(chapter.href, "chapter_001.xhtml", "Chapter href is correct" );
stop();
chapter.loaded.then(function(){
equal(chapter.document.firstChild.nodeName, "html", "Document HTML is loaded" );
start();
});
});
});
asyncTest("Find a single query in a Chapter", 3, function() {
var book = ePub('/reader/moby-dick/', { width: 400, height: 600 });
book.ready.all.then(function(){
var chapter = book.chapter("chapter_001.xhtml");
// var loaded = chapter.load();
start();
equal(chapter.href, "chapter_001.xhtml", "Chapter href is correct" );
stop();
chapter.loaded.then(function(){
var results = chapter.find("pythagorean maxim");
equal(results.length, 1, "Results are returned" );
equal(results[0], "epubcfi(/6/14[xchapter_001]!4/2/24/2[c001p0011]/1:227,4/2/24/2[c001p0011]/1:244)", "CFI is generated");
start();
});
});
});
asyncTest("Find a query with several results in a Chapter", 3, function() {
var book = ePub('/reader/moby-dick/', { width: 400, height: 600 });
book.ready.all.then(function(){
var chapter = book.chapter("chapter_001.xhtml");
// var loaded = chapter.load();
start();
equal(chapter.href, "chapter_001.xhtml", "Chapter href is correct");
stop();
chapter.loaded.then(function(){
var results = chapter.find("yet");
equal(results.length, 4, "Results are returned" );
equal(results[3], "epubcfi(/6/14[xchapter_001]!4/2/28/2[c001p0015]/1:314,4/2/28/2[c001p0015]/1:317)", "CFI is generated");
start();
});
});
});

View file

@ -51,6 +51,7 @@
<script src="unarchiver.js"></script>
<script src="pagination.js"></script>
<script src="epubcfi.js"></script>
<script src="chapter.js"></script>
</body>
</html>