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%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.menu-bar {
|
.menu-bar {
|
||||||
position: relative;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
.menu-bar i {
|
.menu-bar i {
|
||||||
position: relative;
|
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
|
@ -174,16 +175,29 @@ table thead td {
|
||||||
.menu-bar .right-buttons {
|
.menu-bar .right-buttons {
|
||||||
float: right;
|
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 {
|
.menu-title {
|
||||||
display: inline-block;
|
display: inline;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -924,7 +938,9 @@ table thead td {
|
||||||
#sidebar,
|
#sidebar,
|
||||||
#menu-bar,
|
#menu-bar,
|
||||||
.nav-chapters,
|
.nav-chapters,
|
||||||
.mobile-nav-chapters {
|
.mobile-nav-chapters,
|
||||||
|
#searchbar,
|
||||||
|
#search-go {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#page-wrapper {
|
#page-wrapper {
|
||||||
|
|
|
@ -38,11 +38,13 @@ $( document ).ready(function() {
|
||||||
|
|
||||||
var KEY_CODES = {
|
var KEY_CODES = {
|
||||||
PREVIOUS_KEY: 37,
|
PREVIOUS_KEY: 37,
|
||||||
NEXT_KEY: 39
|
NEXT_KEY: 39,
|
||||||
|
SEARCH_KEY: 83
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).on('keydown', function (e) {
|
$(document).on('keydown', function (e) {
|
||||||
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
|
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
|
||||||
|
if ($('#searchbar').is( ":focus" )) { return; }
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case KEY_CODES.NEXT_KEY:
|
case KEY_CODES.NEXT_KEY:
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -56,6 +58,10 @@ $( document ).ready(function() {
|
||||||
window.location.href = $('.nav-chapters.previous').attr('href');
|
window.location.href = $('.nav-chapters.previous').attr('href');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case KEY_CODES.SEARCH_KEY:
|
||||||
|
e.preventDefault();
|
||||||
|
$('#searchbar').focus();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -82,6 +88,81 @@ $( document ).ready(function() {
|
||||||
sidebar.scrollTop(activeSection.offset().top);
|
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 button
|
||||||
$("#theme-toggle").click(function(){
|
$("#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>
|
</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 -->
|
<!-- Fetch store.js from local - TODO add CDN when 2.x.x is available on cdnjs -->
|
||||||
<script src="store.js"></script>
|
<script src="store.js"></script>
|
||||||
|
|
||||||
|
@ -68,6 +76,11 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="sidebar" class="sidebar">
|
<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}}
|
{{#toc}}{{/toc}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -78,6 +91,8 @@
|
||||||
<div class="left-buttons">
|
<div class="left-buttons">
|
||||||
<i id="sidebar-toggle" class="fa fa-bars" title="Toggle sidebar"></i>
|
<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>
|
<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>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">{{ book_title }}</h1>
|
<h1 class="menu-title">{{ book_title }}</h1>
|
||||||
|
|
Loading…
Reference in New Issue