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

Updated CFI and added search example

This commit is contained in:
Fred Chasen 2013-12-20 15:01:03 -08:00
parent d06e5b219e
commit 7eb6622c8e
15 changed files with 510 additions and 37 deletions

View file

@ -679,9 +679,8 @@ EPUBJS.plugins = EPUBJS.plugins || {};
EPUBJS.filePath = EPUBJS.filePath || "/epubjs/"; EPUBJS.filePath = EPUBJS.filePath || "/epubjs/";
(function() { (function(root) {
var root = this;
var previousEpub = root.ePub || {}; var previousEpub = root.ePub || {};
var ePub = root.ePub = function() { var ePub = root.ePub = function() {
@ -734,7 +733,7 @@ EPUBJS.filePath = EPUBJS.filePath || "/epubjs/";
//Node //Node
module.exports = ePub; module.exports = ePub;
})(); })(window);
EPUBJS.Book = function(options){ EPUBJS.Book = function(options){
var book = this; var book = this;
@ -1886,7 +1885,7 @@ EPUBJS.EpubCFI.prototype.pathTo = function(node) {
var stack = [], var stack = [],
children; children;
while(node && node.parentNode !== null) { while(node && node.parentNode.nodeName == "html" && node.parentNode !== null) {
children = node.parentNode.children; children = node.parentNode.children;
stack.unshift({ stack.unshift({
@ -1934,7 +1933,6 @@ EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
cfi.chapter = this.getChapter(cfiStr); cfi.chapter = this.getChapter(cfiStr);
cfi.fragment = this.getFragment(cfiStr); cfi.fragment = this.getFragment(cfiStr);
cfi.spinePos = (parseInt(cfi.chapter.split("/")[2]) / 2 - 1 ) || 0; cfi.spinePos = (parseInt(cfi.chapter.split("/")[2]) / 2 - 1 ) || 0;
chapId = cfi.chapter.match(/\[(.*)\]/); chapId = cfi.chapter.match(/\[(.*)\]/);
@ -1984,9 +1982,9 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
children = Array.prototype.slice.call(element.children), children = Array.prototype.slice.call(element.children),
num, index, part, num, index, part,
has_id, id; has_id, id;
sections.shift(); //-- html // sections.shift(); //-- html
while(sections.length > 0) { while(sections.length > 0) {
part = sections.shift(); part = sections.shift();
@ -1998,7 +1996,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
}else{ }else{
element = children[part.index]; element = children[part.index];
if(!children) console.error("No Kids", element); if(!children) console.error("No Kids", element);
} }

4
build/epub.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -379,11 +379,108 @@ EPUBJSR.app.init = (function($){
} }
return init; return init;
})(jQuery); })(jQuery);
EPUBJSR.search = {};
// Search Server -- https://github.com/futurepress/epubjs-search
EPUBJSR.search.SERVER = "http://localhost:5000";
EPUBJSR.search.request = function(q, callback) {
var fetch = $.ajax({
dataType: "json",
url: EPUBJSR.search.SERVER + "/search?q=" + encodeURIComponent(q)
});
fetch.fail(function(err) {
console.error(err);
});
fetch.done(function(results) {
callback(results);
});
};
EPUBJSR.search.View = function() {
var $searchBox = $("#searchBox"),
$searchResults = $("#searchResults"),
$tocView = $("#toc"),
$searchView = $("#searchView"),
iframeDoc;
$searchBox.on("search", function(e) {
var q = $searchBox.val();
e.preventDefault();
//-- SearchBox is empty or cleared
if(q == '') {
$searchResults.empty();
$searchView.removeClass("shown");
$tocView.removeClass("hidden");
$(iframeDoc).find('body').unhighlight();
iframeDoc = false;
return;
}
if(!$searchView.hasClass("shown")) {
$searchView.addClass("shown");
$tocView.addClass("hidden");
}
$searchResults.empty();
$searchResults.append("<li><p>Searching...</p></li>");
EPUBJSR.search.request(q, function(data) {
var results = data.results;
$searchResults.empty();
if(iframeDoc) {
$(iframeDoc).find('body').unhighlight();
}
if(results.length == 0) {
$searchResults.append("<li><p>No Results Found</p></li>");
return;
}
iframeDoc = $("#area iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { element: 'span' });
results.forEach(function(result) {
var $li = $("<li></li>");
var $item = $("<a href='"+result.href+"' data-cfi='"+result.cfi+"'><span>"+result.title+"</span><p>"+result.highlight+"</p></a>");
$item.on("click", function(e) {
var $this = $(this),
cfi = $this.data("cfi");
Book.gotoCfi(cfi);
Book.on("renderer:chapterDisplayed", function() {
iframeDoc = $("#area iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { element: 'span' });
})
e.preventDefault();
});
$li.append($item);
$searchResults.append($li);
});
});
});
};
//-- http://stackoverflow.com/questions/2124684/jquery-how-click-anywhere-outside-of-the-div-the-div-fades-out //-- http://stackoverflow.com/questions/2124684/jquery-how-click-anywhere-outside-of-the-div-the-div-fades-out
jQuery.fn.extend({ jQuery.fn.extend({

View file

@ -153,8 +153,13 @@ body {
opacity: 1; opacity: 1;
} }
#search { #searchBox {
width: 155px; width: 155px;
float: left;
margin-left: 5px;
margin-top: -5px;
/*
border-radius: 5px; border-radius: 5px;
background: #9b9b9b; background: #9b9b9b;
float: left; float: left;
@ -163,7 +168,8 @@ body {
padding: 3px 10px; padding: 3px 10px;
color: #000; color: #000;
border: none; border: none;
outline: none; outline: none; */
} }
input::-webkit-input-placeholder { input::-webkit-input-placeholder {
@ -208,6 +214,8 @@ input:-moz-placeholder {
-moz-transition: visibility 0 ease .5s; -moz-transition: visibility 0 ease .5s;
} }
#sidebar.open #toc { #sidebar.open #toc {
overflow-y: auto; overflow-y: auto;
visibility: visible; visibility: visible;
@ -271,6 +279,59 @@ input:-moz-placeholder {
display: block; display: block;
} }
#toc.hidden {
display: none;
}
#searchView {
width: 300px;
height: 100%;
display: none;
}
#searchResults {
margin-top: 50px;
margin-bottom: 50px;
padding-left: 20px;
display: block;
}
#searchResults li {
margin-bottom:10px;
width: 225px;
font-family: Georgia, "Times New Roman", Times, serif;
list-style: none;
}
#searchResults a {
color: #AAA;
text-decoration: none;
}
#searchResults p {
text-decoration: none;
font-size: 12px;
line-height: 16px;
}
#searchResults p .match {
background: #ccc;
color: #000;
}
#searchResults li > p {
color: #AAA;
}
#searchResults li a:hover {
color: #E2E2E2;
}
#searchView.shown {
display: block;
overflow-y: scroll;
}
#settingsPanel { #settingsPanel {
display:none; display:none;
} }
@ -297,6 +358,7 @@ input:-moz-placeholder {
#settingsPanel .large { font-size:large; } #settingsPanel .large { font-size:large; }
#settingsPanel .xlarge { font-size:x-large; } #settingsPanel .xlarge { font-size:x-large; }
.highlight { background-color: yellow }
@media only screen and (max-width: 1040px) { @media only screen and (max-width: 1040px) {
#area{ #area{

View file

@ -452,23 +452,24 @@ input[type="radio"] {
* 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof). * (include `-moz` to future-proof).
*/ */
/*
input[type="search"] { input[type="search"] {
-webkit-appearance: textfield; /* 1 */ -webkit-appearance: textfield;
-moz-box-sizing: content-box; -moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */ -webkit-box-sizing: content-box;
box-sizing: content-box; box-sizing: content-box;
} }
*/
/* /*
* Removes inner padding and search cancel button in Safari 5 and Chrome * Removes inner padding and search cancel button in Safari 5 and Chrome
* on OS X. * on OS X.
*/ */
input[type="search"]::-webkit-search-cancel-button, /* input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration { input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none; -webkit-appearance: none;
} } */
/* /*
* Removes inner padding and border in Firefox 3+. * Removes inner padding and border in Firefox 3+.

View file

@ -64,18 +64,21 @@
<script async src="../hooks/default/smartimages.js"></script> <script async src="../hooks/default/smartimages.js"></script>
<!-- Reader --> <!-- Reader -->
<script async src="../reader/utils.js"></script> <script src="../reader/utils.js"></script>
<script async src="../reader/app.js"></script> <script src="../reader/app.js"></script>
<!-- Full Screen --> <!-- Full Screen -->
<script src="js/libs/screenfull.min.js"></script> <script src="js/libs/screenfull.min.js"></script>
<!-- Highlights -->
<script src="js/libs/jquery.highlight.js"></script>
<script async src="../hooks/extensions/highlight.js"></script>
</head> </head>
<body> <body>
<div id="sidebar"> <div id="sidebar">
<div id="controls"> <div id="controls">
<input id="search" placeholder="search"> <input id="searchBox" placeholder="search" type="search">
<a id="network"><img id="store" src="../demo/img/save.png" save="../demo/img/save.png" data-saved="../demo/img/saved.png"></a> <a id="network"><img id="store" src="../demo/img/save.png" save="../demo/img/save.png" data-saved="../demo/img/saved.png"></a>
<a id="setting"><img id="settings" src="../demo/img/settings.png"></a> <a id="setting"><img id="settings" src="../demo/img/settings.png"></a>
<a id="fullscreen"> <a id="fullscreen">
@ -85,6 +88,9 @@
</div> </div>
<div id="toc"> <div id="toc">
</div> </div>
<div id="searchView">
<ul id="searchResults"></ul>
</div>
<div id="settingsPanel"> <div id="settingsPanel">
</div> </div>
@ -105,5 +111,6 @@
<div id="loader"><img src="../demo/img/loader.gif"></div> <div id="loader"><img src="../demo/img/loader.gif"></div>
</div> </div>
</body> </body>
</html> </html>

4
demo/js/epub.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,108 @@
/*
* jQuery Highlight plugin
*
* Based on highlight v3 by Johann Burkard
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
*
* Code a little bit refactored and cleaned (in my humble opinion).
* Most important changes:
* - has an option to highlight only entire words (wordsOnly - false by default),
* - has an option to be case sensitive (caseSensitive - false by default)
* - highlight element tag and class names can be specified in options
*
* Usage:
* // wrap every occurrance of text 'lorem' in content
* // with <span class='highlight'> (default options)
* $('#content').highlight('lorem');
*
* // search for and highlight more terms at once
* // so you can save some time on traversing DOM
* $('#content').highlight(['lorem', 'ipsum']);
* $('#content').highlight('lorem ipsum');
*
* // search only for entire word 'lorem'
* $('#content').highlight('lorem', { wordsOnly: true });
*
* // don't ignore case during search of term 'lorem'
* $('#content').highlight('lorem', { caseSensitive: true });
*
* // wrap every occurrance of term 'ipsum' in content
* // with <em class='important'>
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
*
* // remove default highlight
* $('#content').unhighlight();
*
* // remove custom highlight
* $('#content').unhighlight({ element: 'em', className: 'important' });
*
*
* Copyright (c) 2009 Bartek Szopka
*
* Licensed under MIT license.
*
*/
jQuery.extend({
highlight: function (node, re, nodeName, className) {
if (node.nodeType === 3) {
var match = node.data.match(re);
if (match) {
var highlight = document.createElement(nodeName || 'span');
highlight.className = className || 'highlight';
var wordNode = node.splitText(match.index);
wordNode.splitText(match[0].length);
var wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
return 1; //skip added node in parent
}
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
for (var i = 0; i < node.childNodes.length; i++) {
i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
}
}
return 0;
}
});
jQuery.fn.unhighlight = function (options) {
var settings = { className: 'highlight', element: 'span' };
jQuery.extend(settings, options);
return this.find(settings.element + "." + settings.className).each(function () {
var parent = this.parentNode;
parent.replaceChild(this.firstChild, this);
parent.normalize();
}).end();
};
jQuery.fn.highlight = function (words, options) {
var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
jQuery.extend(settings, options);
if (words.constructor === String) {
words = [words];
}
words = jQuery.grep(words, function(word, i){
return word != '';
});
words = jQuery.map(words, function(word, i) {
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
});
if (words.length == 0) { return this; };
var flag = settings.caseSensitive ? "" : "i";
var pattern = "(" + words.join("|") + ")";
if (settings.wordsOnly) {
pattern = "\\b" + pattern + "\\b";
}
var re = new RegExp(pattern, flag);
return this.each(function () {
jQuery.highlight(this, re, settings.element, settings.className);
});
};

View file

@ -1 +1 @@
var EPUBJSR=EPUBJSR||{};EPUBJSR.app={},EPUBJSR.app.init=function(a){"use strict";function b(b){var e=window.location.search.match(/book=(.*)/),b=b||(e?e[1]:"moby-dick");return k=a(window).width(),k>550?a("#main").width(k-m):a("#main").width(k),j=new EPUBJS.Book({bookPath:b,restore:!0}),j.on("book:online",g),j.on("book:offline",h),j.getMetadata().then(c),j.getToc().then(d),j.ready.all.then(f),j.renderTo("area"),a(function(){i()}),j}function c(b){var c=b.bookTitle,d=b.creator,e=a("#book-title"),f=a("#chapter-title"),g=a("#title-seperator");document.title=c+" "+d,e.html(c),f.html(d),g.show()}function d(b){var c,d,f=a("#toc");f.empty(),d=e(b,1),f.append(d),c=a(".toc_link"),c.on("click",function(b){var c=a(this),d=c.data("url");a(".openChapter").removeClass("openChapter"),c.parents("li").addClass("openChapter"),j.goto(d),b.preventDefault()})}function e(b,c){var d=a("<ul>"),f=1==c?"chapter":"section";return b.forEach(function(b){var g,h=a("<li id='toc-"+b.id+"'>"),i=a("<a class='toc_link "+f+"' href='#/"+b.href+"' data-url='"+b.href+"'>"+b.label+"</a>");h.append(i),b.subitems&&b.subitems.length&&(c++,g=e(b.subitems,c),h.append(g)),d.append(h)}),d}function f(){var b=a("#divider"),c=a("#loader");c.hide(),j.single||b.addClass("show")}function g(){var b=a("#store");l=!1,b.attr("src",b.data("save"))}function h(){var b=a("#store");l=!0,b.attr("src",b.data("saved"))}function i(){function b(){n.addClass("open"),h.addClass("closed"),p.attr("src",p.data("close"))}function c(){i.css("pointer-events","visible"),n.removeClass("open"),h.removeClass("closed"),p.attr("src",p.data("open"))}function d(){t.hide(),s.show()}function e(){s.hide(),t.show()}var f=a("#next"),g=a("#prev"),h=a("#main"),i=a("#area"),n=a("#sidebar"),o=a("#open"),p=o.find("img"),q=a("#network"),r=a("#setting"),s=a("#settingsPanel"),t=a("#toc"),u=a("#fullscreen"),v=a("#fullscreenicon"),w=a("#cancelfullscreenicon"),x=a(window);x.on("resize",function(){k=a(window).width(),k>550?h.width(k-m):h.width(k)}),f.on("click",function(){j.nextPage()}),g.on("click",function(){j.prevPage()}),r.on("click",function(){s.is(":visible")?e():d()}),u.on("click",function(){screenfull.toggle(a("#container")[0]),v.toggle(),w.toggle()});var y=!1;a(document).keydown(function(a){return y?void 0:37==a.keyCode?(g.trigger("click"),y=!0,setTimeout(function(){y=!1},100),!1):39==a.keyCode?(f.trigger("click"),y=!0,setTimeout(function(){y=!1},100),!1):void 0}),o.on("click",function(){n.hasClass("open")?c():b()}),q.on("click",function(){l=!l,j.fromStorage(l)})}var j,k,l=!1,m=0;return b}(jQuery),jQuery.fn.extend({clickOutside:function(a,b){var c=this;return jQuery(document).on("click.offer",function(d){b&&jQuery.inArray(d.target,b)>-1||jQuery.contains(c[0],d.target)||(jQuery(document).off("click.offer"),a(d,c))}),this}}); var EPUBJSR=EPUBJSR||{};EPUBJSR.app={},EPUBJSR.app.init=function(a){"use strict";function b(b){var e=window.location.search.match(/book=(.*)/),b=b||(e?e[1]:"moby-dick");return k=a(window).width(),k>550?a("#main").width(k-m):a("#main").width(k),j=new EPUBJS.Book({bookPath:b,restore:!0}),j.on("book:online",g),j.on("book:offline",h),j.getMetadata().then(c),j.getToc().then(d),j.ready.all.then(f),j.renderTo("area"),a(function(){i()}),j}function c(b){var c=b.bookTitle,d=b.creator,e=a("#book-title"),f=a("#chapter-title"),g=a("#title-seperator");document.title=c+" "+d,e.html(c),f.html(d),g.show()}function d(b){var c,d,f=a("#toc");f.empty(),d=e(b,1),f.append(d),c=a(".toc_link"),c.on("click",function(b){var c=a(this),d=c.data("url");a(".openChapter").removeClass("openChapter"),c.parents("li").addClass("openChapter"),j.goto(d),b.preventDefault()})}function e(b,c){var d=a("<ul>"),f=1==c?"chapter":"section";return b.forEach(function(b){var g,h=a("<li id='toc-"+b.id+"'>"),i=a("<a class='toc_link "+f+"' href='#/"+b.href+"' data-url='"+b.href+"'>"+b.label+"</a>");h.append(i),b.subitems&&b.subitems.length&&(c++,g=e(b.subitems,c),h.append(g)),d.append(h)}),d}function f(){var b=a("#divider"),c=a("#loader");c.hide(),j.single||b.addClass("show")}function g(){var b=a("#store");l=!1,b.attr("src",b.data("save"))}function h(){var b=a("#store");l=!0,b.attr("src",b.data("saved"))}function i(){function b(){n.addClass("open"),h.addClass("closed"),p.attr("src",p.data("close"))}function c(){i.css("pointer-events","visible"),n.removeClass("open"),h.removeClass("closed"),p.attr("src",p.data("open"))}function d(){t.hide(),s.show()}function e(){s.hide(),t.show()}var f=a("#next"),g=a("#prev"),h=a("#main"),i=a("#area"),n=a("#sidebar"),o=a("#open"),p=o.find("img"),q=a("#network"),r=a("#setting"),s=a("#settingsPanel"),t=a("#toc"),u=a("#fullscreen"),v=a("#fullscreenicon"),w=a("#cancelfullscreenicon"),x=a(window);x.on("resize",function(){k=a(window).width(),k>550?h.width(k-m):h.width(k)}),f.on("click",function(){j.nextPage()}),g.on("click",function(){j.prevPage()}),r.on("click",function(){s.is(":visible")?e():d()}),u.on("click",function(){screenfull.toggle(a("#container")[0]),v.toggle(),w.toggle()});var y=!1;a(document).keydown(function(a){return y?void 0:37==a.keyCode?(g.trigger("click"),y=!0,setTimeout(function(){y=!1},100),!1):39==a.keyCode?(f.trigger("click"),y=!0,setTimeout(function(){y=!1},100),!1):void 0}),o.on("click",function(){n.hasClass("open")?c():b()}),q.on("click",function(){l=!l,j.fromStorage(l)})}var j,k,l=!1,m=0;return b}(jQuery),EPUBJSR.search={},EPUBJSR.search.SERVER="http://localhost:5000",EPUBJSR.search.request=function(a,b){var c=$.ajax({dataType:"json",url:EPUBJSR.search.SERVER+"/search?q="+encodeURIComponent(a)});c.fail(function(a){console.error(a)}),c.done(function(a){b(a)})},EPUBJSR.search.View=function(){var a,b=$("#searchBox"),c=$("#searchResults"),d=$("#toc"),e=$("#searchView");b.on("search",function(f){var g=b.val();return f.preventDefault(),""==g?(c.empty(),e.removeClass("shown"),d.removeClass("hidden"),$(a).find("body").unhighlight(),a=!1,void 0):(e.hasClass("shown")||(e.addClass("shown"),d.addClass("hidden")),c.empty(),c.append("<li><p>Searching...</p></li>"),EPUBJSR.search.request(g,function(b){var d=b.results;return c.empty(),a&&$(a).find("body").unhighlight(),0==d.length?(c.append("<li><p>No Results Found</p></li>"),void 0):(a=$("#area iframe")[0].contentDocument,$(a).find("body").highlight(g,{element:"span"}),d.forEach(function(b){var d=$("<li></li>"),e=$("<a href='"+b.href+"' data-cfi='"+b.cfi+"'><span>"+b.title+"</span><p>"+b.highlight+"</p></a>");e.on("click",function(b){var c=$(this),d=c.data("cfi");Book.gotoCfi(d),Book.on("renderer:chapterDisplayed",function(){a=$("#area iframe")[0].contentDocument,$(a).find("body").highlight(g,{element:"span"})}),b.preventDefault()}),d.append(e),c.append(d)}),void 0)}),void 0)})},jQuery.fn.extend({clickOutside:function(a,b){var c=this;return jQuery(document).on("click.offer",function(d){b&&jQuery.inArray(d.target,b)>-1||jQuery.contains(c[0],d.target)||(jQuery(document).off("click.offer"),a(d,c))}),this}});

92
examples/search.html Executable file
View file

@ -0,0 +1,92 @@
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="stylesheet" href="../demo/css/normalize.css">
<link rel="stylesheet" href="../demo/css/main.css">
<link rel="stylesheet" href="../demo/css/popup.css">
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="epubjs/libs/jquery-1.9.0.min.js"><\/script>')</script>
-->
<script src="../libs/jquery/jquery-1.9.0.js"></script>
<script>
"use strict";
document.onreadystatechange = function () {
if (document.readyState == "complete") {
EPUBJS.VERSION = "0.1.6";
EPUBJS.filePath = "js/libs/";
EPUBJS.cssPath = "css/";
// fileStorage.filePath = EPUBJS.filePath;
EPUBJSR.app.init("moby-dick/");
}
};
$(function() {
EPUBJSR.search.View();
});
</script>
<script src="../build/epub.min.js"></script>
<!-- Reader -->
<script src="../reader/utils.js"></script>
<script src="../reader/app.js"></script>
<script src="../reader/search.js"></script>
<!-- Full Screen -->
<script src="../demo/js/libs/screenfull.min.js"></script>
<!-- Highlights -->
<script src="../demo/js/libs/jquery.highlight.js"></script>
<script src="../hooks/extensions/highlight.js"></script>
</head>
<body>
<div id="sidebar">
<div id="controls">
<input id="searchBox" placeholder="search" type="search">
<a id="network"><img id="store" src="../demo/img/save.png" save="../demo/img/save.png" data-saved="../demo/img/saved.png"></a>
<a id="setting"><img id="settings" src="../demo/img/settings.png"></a>
<a id="fullscreen">
<img id="fullscreenicon" src="../demo/img/fullscreen.png">
<img id="cancelfullscreenicon" src="../demo/img/cancelfullscreen.png" style="display: none">
</a>
</div>
<div id="toc">
</div>
<div id="searchView">
<ul id="searchResults"></ul>
</div>
<div id="settingsPanel">
</div>
</div>
<div id="main">
<div id="opener">
<a id="open"><img src="../demo/img/menu-icon.png" data-close="../demo/img/close.png" data-open="../demo/img/menu-icon.png"></a>
</div>
<div id="titlebar">
<span id="book-title"></span>
<span id="title-seperator">&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span id="chapter-title"> </span>
</div>
<div id="divider"></div>
<div id="prev" class="arrow"></div>
<div id="area"></div>
<div id="next" class="arrow"></div>
<div id="loader"><img src="../demo/img/loader.gif"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,14 @@
EPUBJS.Hooks.register("beforeChapterDisplay").highlight = function(callback, renderer){
// EPUBJS.core.addScript("js/libs/jquery.highlight.js", null, renderer.doc.head);
var s = document.createElement("style");
s.innerHTML =".highlight { background: yellow; font-weight: normal; }";
renderer.doc.body.appendChild(s);
if(callback) callback();
}

View file

@ -379,8 +379,7 @@ EPUBJSR.app.init = (function($){
} }
return init; return init;
})(jQuery); })(jQuery);

97
reader/search.js Normal file
View file

@ -0,0 +1,97 @@
EPUBJSR.search = {};
// Search Server -- https://github.com/futurepress/epubjs-search
EPUBJSR.search.SERVER = "http://localhost:5000";
EPUBJSR.search.request = function(q, callback) {
var fetch = $.ajax({
dataType: "json",
url: EPUBJSR.search.SERVER + "/search?q=" + encodeURIComponent(q)
});
fetch.fail(function(err) {
console.error(err);
});
fetch.done(function(results) {
callback(results);
});
};
EPUBJSR.search.View = function() {
var $searchBox = $("#searchBox"),
$searchResults = $("#searchResults"),
$tocView = $("#toc"),
$searchView = $("#searchView"),
iframeDoc;
$searchBox.on("search", function(e) {
var q = $searchBox.val();
e.preventDefault();
//-- SearchBox is empty or cleared
if(q == '') {
$searchResults.empty();
$searchView.removeClass("shown");
$tocView.removeClass("hidden");
$(iframeDoc).find('body').unhighlight();
iframeDoc = false;
return;
}
if(!$searchView.hasClass("shown")) {
$searchView.addClass("shown");
$tocView.addClass("hidden");
}
$searchResults.empty();
$searchResults.append("<li><p>Searching...</p></li>");
EPUBJSR.search.request(q, function(data) {
var results = data.results;
$searchResults.empty();
if(iframeDoc) {
$(iframeDoc).find('body').unhighlight();
}
if(results.length == 0) {
$searchResults.append("<li><p>No Results Found</p></li>");
return;
}
iframeDoc = $("#area iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { element: 'span' });
results.forEach(function(result) {
var $li = $("<li></li>");
var $item = $("<a href='"+result.href+"' data-cfi='"+result.cfi+"'><span>"+result.title+"</span><p>"+result.highlight+"</p></a>");
$item.on("click", function(e) {
var $this = $(this),
cfi = $this.data("cfi");
Book.gotoCfi(cfi);
Book.on("renderer:chapterDisplayed", function() {
iframeDoc = $("#area iframe")[0].contentDocument;
$(iframeDoc).find('body').highlight(q, { element: 'span' });
})
e.preventDefault();
});
$li.append($item);
$searchResults.append($li);
});
});
});
};

View file

@ -7,9 +7,8 @@ EPUBJS.plugins = EPUBJS.plugins || {};
EPUBJS.filePath = EPUBJS.filePath || "/epubjs/"; EPUBJS.filePath = EPUBJS.filePath || "/epubjs/";
(function() { (function(root) {
var root = this;
var previousEpub = root.ePub || {}; var previousEpub = root.ePub || {};
var ePub = root.ePub = function() { var ePub = root.ePub = function() {
@ -62,4 +61,4 @@ EPUBJS.filePath = EPUBJS.filePath || "/epubjs/";
//Node //Node
module.exports = ePub; module.exports = ePub;
})(); })(window);

View file

@ -45,7 +45,7 @@ EPUBJS.EpubCFI.prototype.pathTo = function(node) {
var stack = [], var stack = [],
children; children;
while(node && node.parentNode !== null) { while(node && node.parentNode.nodeName == "html" && node.parentNode !== null) {
children = node.parentNode.children; children = node.parentNode.children;
stack.unshift({ stack.unshift({
@ -93,7 +93,6 @@ EPUBJS.EpubCFI.prototype.parse = function(cfiStr) {
cfi.chapter = this.getChapter(cfiStr); cfi.chapter = this.getChapter(cfiStr);
cfi.fragment = this.getFragment(cfiStr); cfi.fragment = this.getFragment(cfiStr);
cfi.spinePos = (parseInt(cfi.chapter.split("/")[2]) / 2 - 1 ) || 0; cfi.spinePos = (parseInt(cfi.chapter.split("/")[2]) / 2 - 1 ) || 0;
chapId = cfi.chapter.match(/\[(.*)\]/); chapId = cfi.chapter.match(/\[(.*)\]/);
@ -143,9 +142,9 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
children = Array.prototype.slice.call(element.children), children = Array.prototype.slice.call(element.children),
num, index, part, num, index, part,
has_id, id; has_id, id;
sections.shift(); //-- html // sections.shift(); //-- html
while(sections.length > 0) { while(sections.length > 0) {
part = sections.shift(); part = sections.shift();
@ -157,7 +156,7 @@ EPUBJS.EpubCFI.prototype.getElement = function(cfi, _doc) {
}else{ }else{
element = children[part.index]; element = children[part.index];
if(!children) console.error("No Kids", element); if(!children) console.error("No Kids", element);
} }