Search: Add UI, elasticlunr.js, demo by indexing current page
This commit is contained in:
parent
b1d3b967b7
commit
893dc39b60
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue