Search: Add UI, elasticlunr.js, demo by indexing current page

This commit is contained in:
Phaiax 2017-10-02 14:32:27 +02:00
parent b1d3b967b7
commit 893dc39b60
4 changed files with 177 additions and 12 deletions

View File

@ -151,11 +151,12 @@ table thead td {
max-width: 100%;
}
.menu-bar {
position: relative;
height: 50px;
display: flex;
justify-content: space-between;
align-items: baseline;
}
.menu-bar i {
position: relative;
margin: 0 10px;
z-index: 10;
line-height: 50px;
@ -174,16 +175,29 @@ table thead td {
.menu-bar .right-buttons {
float: right;
}
#searchbar {
border: 1px solid #BBB;
border-radius: 3px;
padding: 3px 5px;
width: 50px;
transition: width 0.5s ease-in-out;
}
#searchbar:focus, #searchbar:hover, #searchbar.active {
width: 150px;
}
.searchresults-header {
font-weight: bold;
font-size: 1em;
}
.searchresults-outer {
border-bottom: 1px dashed #CCC;
display: none;
}
.menu-title {
display: inline-block;
display: inline;
font-weight: 200;
font-size: 20px;
line-height: 50px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
text-align: center;
margin: 0;
opacity: 0;
@ -924,7 +938,9 @@ table thead td {
#sidebar,
#menu-bar,
.nav-chapters,
.mobile-nav-chapters {
.mobile-nav-chapters,
#searchbar,
#search-go {
display: none;
}
#page-wrapper {

View File

@ -38,11 +38,13 @@ $( document ).ready(function() {
var KEY_CODES = {
PREVIOUS_KEY: 37,
NEXT_KEY: 39
NEXT_KEY: 39,
SEARCH_KEY: 83
};
$(document).on('keydown', function (e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
if ($('#searchbar').is( ":focus" )) { return; }
switch (e.keyCode) {
case KEY_CODES.NEXT_KEY:
e.preventDefault();
@ -56,6 +58,10 @@ $( document ).ready(function() {
window.location.href = $('.nav-chapters.previous').attr('href');
}
break;
case KEY_CODES.SEARCH_KEY:
e.preventDefault();
$('#searchbar').focus();
break;
}
});
@ -82,6 +88,81 @@ $( document ).ready(function() {
sidebar.scrollTop(activeSection.offset().top);
}
// For testing purposes: Index current page
var searchindex = create_text_searchindex();
var current_searchterm = "";
var teaser_size_half = 80;
// Searchbar
$("#searchbar").on('keyup', function (e) {
var display = $('#searchresults');
var outer = $("#searchresults-outer");
var searchterm = e.target.value.trim();
if (searchterm != "") {
// keep searchbar expanded
$(e.target).addClass("active");
// Don't search twice the same
if (current_searchterm == searchterm) { return; }
else { current_searchterm = searchterm; }
// Do the actual search
var results = searchindex.search(searchterm, {
bool: "AND",
expand: true
});
// Display search metrics
var searchheader = "";
if (results.length > 0) {
searchheader = results.length + " search results for '" + searchterm + "':";
} else if (results.length == 1) {
searchheader = results.length + " search result for '" + searchterm + "':";
} else {
searchheader = "No search results for '" + searchterm + "'.";
}
$('#searchresults-header').text(searchheader);
// Clear and insert results
var firstterm = searchterm.split(' ')[0];
display.empty();
for(var i = 0, size = results.length; i < size ; i++){
var result = results[i];
document.lsd = result.doc;
var firstoccurence = result.doc.body.search(firstterm);
var teaser = "";
if (firstoccurence != -1) {
var teaserstartindex = firstoccurence - teaser_size_half;
var nextwordindex = result.doc.body.indexOf(" ", teaserstartindex);
if (nextwordindex != -1) {
teaserstartindex = nextwordindex;
}
var teaserendindex = firstoccurence + teaser_size_half;
nextwordindex = result.doc.body.indexOf(" ", teaserendindex);
if (nextwordindex != -1) {
teaserendindex = nextwordindex;
}
teaser = (teaserstartindex > 0) ? "..." : "";
teaser += result.doc.body.substring(teaserstartindex, teaserendindex) + "...";
} else {
teaser = result.doc.body.substr(0, 80) + "...";
}
display.append('<li><a href="' + result.ref + '">' + result.doc.title + '</a>: '
+ teaser + "</li>");
}
// Display and scroll to results
sidebar.scrollTop(0);
outer.slideDown();
} else {
// searchbar can shrink
$(e.target).removeClass("active");
outer.slideUp();
display.empty();
}
});
// Theme button
$("#theme-toggle").click(function(){
@ -392,3 +473,46 @@ function run_rust_code(code_block) {
},
});
}
function create_text_searchindex() {
var searchindex = elasticlunr(function () {
this.addField('body');
this.addField('title');
this.setRef('id');
});
var content = $("#content");
var paragraphs = content.children();
var curr_title = "";
var curr_body = "";
var curr_ref = "";
var push = function(ref) {
if ((curr_title.length > 0 || curr_body.length > 0) && curr_ref.length > 0) {
var doc = {
"id": curr_ref,
"body": curr_body,
"title": curr_title
}
searchindex.addDoc(doc);
}
curr_body = "";
curr_title = "";
curr_ref = "";
};
paragraphs.each(function(index, element) {
// todo uppercase
var el = $(element);
if (el.prop('nodeName').toUpperCase() == "A") {
// new header, push old paragraph to index
push(index);
curr_title = el.text();
curr_ref = el.attr('href');
} else {
curr_body += " \n " + el.text();
}
// last paragraph
if (index == paragraphs.length - 1) {
push(index);
}
});
return searchindex;
}

10
src/theme/elasticlunr.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -48,6 +48,14 @@
}
</script>
<!-- Fetch elasticlunr.js from CDN but have a local fallback -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/elasticlunr/0.9.6/elasticlunr.min.js"></script>
<script>
if (typeof elasticlunr == 'undefined') {
document.write(unescape("%3Cscript src='elasticlunr.min.js'%3E%3C/script%3E"));
}
</script>
<!-- Fetch store.js from local - TODO add CDN when 2.x.x is available on cdnjs -->
<script src="store.js"></script>
@ -68,6 +76,11 @@
</script>
<div id="sidebar" class="sidebar">
<div id="searchresults-outer" class="searchresults-outer">
<div class="searchresults-header" id="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
{{#toc}}{{/toc}}
</div>
@ -78,6 +91,8 @@
<div class="left-buttons">
<i id="sidebar-toggle" class="fa fa-bars" title="Toggle sidebar"></i>
<i id="theme-toggle" class="fa fa-paint-brush" title="Change theme"></i>
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ...">
<i id="search-go" class="fa fa-search" title="Search!"></i>
</div>
<h1 class="menu-title">{{ book_title }}</h1>