Search: Refactor, refine history behaviour, add breadcrumbs
This commit is contained in:
parent
379c6ff616
commit
c487a95d24
|
@ -212,6 +212,17 @@ ul#searchresults {
|
||||||
ul#searchresults li {
|
ul#searchresults li {
|
||||||
margin: 10px 0px;
|
margin: 10px 0px;
|
||||||
}
|
}
|
||||||
|
ul#searchresults span.breadcrumbs {
|
||||||
|
float: right;
|
||||||
|
color: #CCC;
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
ul#searchresults span.teaser {
|
||||||
|
display: block;
|
||||||
|
clear: both;
|
||||||
|
margin: 5px 0 0 20px;
|
||||||
|
}
|
||||||
.menu-title {
|
.menu-title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -1,179 +1,329 @@
|
||||||
$( document ).ready(function() {
|
$( document ).ready(function() {
|
||||||
|
|
||||||
// Helpers for searching
|
// Search functionality
|
||||||
function create_test_searchindex() {
|
//
|
||||||
var searchindex = elasticlunr(function () {
|
// Usage: call init() on startup. You can use hasFocus() to disable prevent keyhandling
|
||||||
this.addField('body');
|
// while the user is typing his search.
|
||||||
this.addField('title');
|
var search = {
|
||||||
this.setRef('id');
|
searchbar : $('#searchbar'),
|
||||||
});
|
searchbar_outer : $('#searchbar-outer'),
|
||||||
var content = $("#content");
|
searchresults : $('#searchresults'),
|
||||||
var paragraphs = content.children();
|
searchresults_outer : $("#searchresults-outer"),
|
||||||
var curr_title = "";
|
searchresults_header : $("#searchresults-header"),
|
||||||
var curr_body = "";
|
searchicon : $("#search-icon"),
|
||||||
var curr_ref = "";
|
content : $('#content'),
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseURL(url) {
|
searchindex : null,
|
||||||
var a = document.createElement('a');
|
searchoptions : {
|
||||||
a.href = url;
|
|
||||||
return {
|
|
||||||
source: url,
|
|
||||||
protocol: a.protocol.replace(':',''),
|
|
||||||
host: a.hostname,
|
|
||||||
port: a.port,
|
|
||||||
params: (function(){
|
|
||||||
var ret = {};
|
|
||||||
var seg = a.search.replace(/^\?/,'').split('&');
|
|
||||||
var len = seg.length, i = 0, s;
|
|
||||||
for (;i<len;i++) {
|
|
||||||
if (!seg[i]) { continue; }
|
|
||||||
s = seg[i].split('=');
|
|
||||||
ret[s[0]] = s[1];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
})(),
|
|
||||||
file: (a.pathname.match(/\/([^/?#]+)$/i) || [,''])[1],
|
|
||||||
hash: a.hash.replace('#',''),
|
|
||||||
path: a.pathname.replace(/^([^/])/,'/$1')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderURL(urlobject) {
|
|
||||||
var url = urlobject.protocol + "://" + urlobject.host;
|
|
||||||
if (urlobject.port != "") {
|
|
||||||
url += ":" + urlobject.port;
|
|
||||||
}
|
|
||||||
url += urlobject.path;
|
|
||||||
var joiner = "?";
|
|
||||||
for(var prop in urlobject.params) {
|
|
||||||
if(urlobject.params.hasOwnProperty(prop)) {
|
|
||||||
url += joiner + prop + "=" + urlobject.params[prop];
|
|
||||||
joiner = "&";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (urlobject.hash != "") {
|
|
||||||
url += "#" + urlobject.hash;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
var current_searchterm = "";
|
|
||||||
var teaser_size_half = 80;
|
|
||||||
|
|
||||||
function doSearch(searchindex, searchterm) {
|
|
||||||
var display = $('#searchresults');
|
|
||||||
|
|
||||||
// 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",
|
bool: "AND",
|
||||||
expand: true
|
expand: true,
|
||||||
});
|
fields: {
|
||||||
|
title: {boost: 1},
|
||||||
|
body: {boost: 1},
|
||||||
|
breadcrumbs: {boost: 0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mark_exclude : [], // ['.hljs']
|
||||||
|
current_searchterm : "",
|
||||||
|
teaser_size_half : 80,
|
||||||
|
resultcount_limit : 30,
|
||||||
|
SEARCH_PARAM : 'search',
|
||||||
|
MARK_PARAM : 'highlight',
|
||||||
|
|
||||||
// Display search metrics
|
SEARCH_HOTKEY_KEYCODE: 83,
|
||||||
var searchheader = "";
|
ESCAPE_KEYCODE: 27,
|
||||||
if (results.length > 0) {
|
|
||||||
searchheader = results.length + " search results for '" + searchterm + "':";
|
formatSearchMetric : function(count, searchterm) {
|
||||||
} else if (results.length == 1) {
|
if (count == 1) {
|
||||||
searchheader = results.length + " search result for '" + searchterm + "':";
|
return count + " search result for '" + searchterm + "':";
|
||||||
} else {
|
} else if (count == 0) {
|
||||||
searchheader = "No search results for '" + searchterm + "'.";
|
return "No search results for '" + searchterm + "'.";
|
||||||
|
} else {
|
||||||
|
return count + " search results for '" + searchterm + "':";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$('#searchresults-header').text(searchheader);
|
,
|
||||||
|
create_test_searchindex : function () {
|
||||||
// Clear and insert results
|
var searchindex = elasticlunr(function () {
|
||||||
var firstterm = searchterm.split(' ')[0];
|
this.addField('body');
|
||||||
display.empty();
|
this.addField('title');
|
||||||
for(var i = 0, size = results.length; i < size ; i++){
|
this.addField('breadcrumbs')
|
||||||
var result = results[i];
|
this.setRef('id');
|
||||||
var firstoccurence = result.doc.body.search(firstterm);
|
});
|
||||||
|
var base_breadcrumbs = "";
|
||||||
|
var active_chapter = $('.sidebar ul a.active');
|
||||||
|
base_breadcrumbs = active_chapter.text().split('. ', 2)[1]; // demo
|
||||||
|
while (true) {
|
||||||
|
var parent_ul = active_chapter.parents('ul');
|
||||||
|
if (parent_ul.length == 0) break;
|
||||||
|
var parent_li = parent_ul.parents('li');
|
||||||
|
if (parent_li.length == 0) break;
|
||||||
|
var pre_li = parent_li.prev('li');
|
||||||
|
if (pre_li.length == 0) break;
|
||||||
|
base_breadcrumbs = pre_li.text().split('. ', 2)[1] + ' » ' + base_breadcrumbs;
|
||||||
|
active_chapter = pre_li;
|
||||||
|
}
|
||||||
|
var paragraphs = this.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,
|
||||||
|
"breadcrumbs": base_breadcrumbs //"Header1 » Header2"
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.searchindex = searchindex;
|
||||||
|
}
|
||||||
|
,
|
||||||
|
parseURL : function (url) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
return {
|
||||||
|
source: url,
|
||||||
|
protocol: a.protocol.replace(':',''),
|
||||||
|
host: a.hostname,
|
||||||
|
port: a.port,
|
||||||
|
params: (function(){
|
||||||
|
var ret = {};
|
||||||
|
var seg = a.search.replace(/^\?/,'').split('&');
|
||||||
|
var len = seg.length, i = 0, s;
|
||||||
|
for (;i<len;i++) {
|
||||||
|
if (!seg[i]) { continue; }
|
||||||
|
s = seg[i].split('=');
|
||||||
|
ret[s[0]] = s[1];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
})(),
|
||||||
|
file: (a.pathname.match(/\/([^/?#]+)$/i) || [,''])[1],
|
||||||
|
hash: a.hash.replace('#',''),
|
||||||
|
path: a.pathname.replace(/^([^/])/,'/$1')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
,
|
||||||
|
renderURL : function (urlobject) {
|
||||||
|
var url = urlobject.protocol + "://" + urlobject.host;
|
||||||
|
if (urlobject.port != "") {
|
||||||
|
url += ":" + urlobject.port;
|
||||||
|
}
|
||||||
|
url += urlobject.path;
|
||||||
|
var joiner = "?";
|
||||||
|
for(var prop in urlobject.params) {
|
||||||
|
if(urlobject.params.hasOwnProperty(prop)) {
|
||||||
|
url += joiner + prop + "=" + urlobject.params[prop];
|
||||||
|
joiner = "&";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (urlobject.hash != "") {
|
||||||
|
url += "#" + urlobject.hash;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
,
|
||||||
|
formatSearchResult : function (result, searchterms) {
|
||||||
|
// Show text around first occurrence of first search term.
|
||||||
|
var firstoccurence = result.doc.body.search(searchterms[0]);
|
||||||
var teaser = "";
|
var teaser = "";
|
||||||
if (firstoccurence != -1) {
|
if (firstoccurence != -1) {
|
||||||
var teaserstartindex = firstoccurence - teaser_size_half;
|
var teaserstartindex = firstoccurence - this.teaser_size_half;
|
||||||
var nextwordindex = result.doc.body.indexOf(" ", teaserstartindex);
|
var nextwordindex = result.doc.body.indexOf(" ", teaserstartindex);
|
||||||
if (nextwordindex != -1) {
|
if (nextwordindex != -1) {
|
||||||
teaserstartindex = nextwordindex;
|
teaserstartindex = nextwordindex;
|
||||||
}
|
}
|
||||||
var teaserendindex = firstoccurence + teaser_size_half;
|
var teaserendindex = firstoccurence + this.teaser_size_half;
|
||||||
nextwordindex = result.doc.body.indexOf(" ", teaserendindex);
|
nextwordindex = result.doc.body.indexOf(" ", teaserendindex);
|
||||||
if (nextwordindex != -1) {
|
if (nextwordindex != -1) {
|
||||||
teaserendindex = nextwordindex;
|
teaserendindex = nextwordindex;
|
||||||
}
|
}
|
||||||
teaser = (teaserstartindex > 0) ? "..." : "";
|
teaser = (teaserstartindex > 0) ? "... " : "";
|
||||||
teaser += result.doc.body.substring(teaserstartindex, teaserendindex) + "...";
|
teaser += result.doc.body.substring(teaserstartindex, teaserendindex) + " ...";
|
||||||
} else {
|
} else {
|
||||||
teaser = result.doc.body.substr(0, 80) + "...";
|
teaser = result.doc.body.substr(0, this.teaser_size_half * 2) + " ...";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The ?MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor
|
||||||
var url = result.ref.split("#");
|
var url = result.ref.split("#");
|
||||||
if (url.length == 1) {
|
if (url.length == 1) {
|
||||||
url.push("");
|
url.push("");
|
||||||
}
|
}
|
||||||
|
|
||||||
display.append('<li><a href="' + url[0] + '?highlight=' + searchterm + '#' + url[1] + '">'
|
return $('<li><a href="'
|
||||||
+ result.doc.title + '</a>: ' + teaser + "</li>");
|
+ url[0] + '?' + this.MARK_PARAM + '=' + searchterms + '#' + url[1]
|
||||||
|
+ '">' + result.doc.title + '</a>'
|
||||||
|
+ '<span class="breadcrumbs">' + result.doc.breadcrumbs + '</span>'
|
||||||
|
+ '<span class="teaser">' + teaser + '</span>'
|
||||||
|
+ '</li>');
|
||||||
}
|
}
|
||||||
|
,
|
||||||
|
doSearch : function (searchterm) {
|
||||||
|
|
||||||
// Display and scroll to results
|
// Don't search the same twice
|
||||||
$("#menu-bar").scrollTop(0);
|
if (this.current_searchterm == searchterm) { return; }
|
||||||
$("#searchresults-outer").slideDown();
|
else { this.current_searchterm = searchterm; }
|
||||||
}
|
|
||||||
|
|
||||||
function doSearchOrHighlightFromUrl() {
|
if (this.searchindex == null) { return; }
|
||||||
// Check current URL for search request
|
|
||||||
var url = parseURL(window.location.href);
|
// Do the actual search
|
||||||
if (url.params.hasOwnProperty('search')) {
|
var results = this.searchindex.search(searchterm, this.searchoptions);
|
||||||
$("#searchbar-outer").slideDown();
|
var resultcount = (results.length > this.resultcount_limit)
|
||||||
$("#searchbar")[0].value = url.params['search'];
|
? this.resultcount_limit : results.length;
|
||||||
$("#searchbar").trigger('keyup');
|
|
||||||
} else {
|
// Display search metrics
|
||||||
$("#searchbar-outer").slideUp();
|
this.searchresults_header.text(this.formatSearchMetric(resultcount, searchterm));
|
||||||
|
|
||||||
|
// Clear and insert results
|
||||||
|
var searchterms = searchterm.split(' ');
|
||||||
|
this.searchresults.empty();
|
||||||
|
for(var i = 0; i < resultcount ; i++){
|
||||||
|
this.searchresults.append(this.formatSearchResult(results[i], searchterms));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display and scroll to results
|
||||||
|
this.searchresults_outer.slideDown();
|
||||||
|
// this.searchicon.scrollTop(0);
|
||||||
}
|
}
|
||||||
|
,
|
||||||
|
doSearchOrMarkFromUrl : function () {
|
||||||
|
// Check current URL for search request
|
||||||
|
var url = this.parseURL(window.location.href);
|
||||||
|
if (url.params.hasOwnProperty(this.SEARCH_PARAM)
|
||||||
|
&& url.params[this.SEARCH_PARAM] != "") {
|
||||||
|
this.searchbar_outer.slideDown();
|
||||||
|
this.searchbar[0].value = url.params[this.SEARCH_PARAM];
|
||||||
|
this.searchbarKeyUpHandler();
|
||||||
|
} else {
|
||||||
|
this.searchbar_outer.slideUp();
|
||||||
|
}
|
||||||
|
|
||||||
if (url.params.hasOwnProperty('highlight')) {
|
if (url.params.hasOwnProperty(this.MARK_PARAM)) {
|
||||||
var words = url.params['highlight'].split(' ');
|
var words = url.params[this.MARK_PARAM].split(' ');
|
||||||
var header = $('#' + url.hash);
|
var header = $('#' + url.hash);
|
||||||
$('.content').mark(words, {
|
this.content.mark(words, {
|
||||||
// exclude : ['.hljs']
|
exclude : this.mark_exclude
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
,
|
||||||
|
init : function () {
|
||||||
|
// For testing purposes: Index current page
|
||||||
|
this.create_test_searchindex();
|
||||||
|
|
||||||
|
// Set up events
|
||||||
|
var this_ = this;
|
||||||
|
this.searchicon.click( function(e) { this_.searchIconClickHandler(); } );
|
||||||
|
this.searchbar.on('keyup', function(e) { this_.searchbarKeyUpHandler(); } );
|
||||||
|
$(document).on('keydown', function (e) { this_.globalKeyHandler(e); });
|
||||||
|
// If the user uses the browser buttons, do the same as if a reload happened
|
||||||
|
window.onpopstate = function(e) { this_.doSearchOrMarkFromUrl(); };
|
||||||
|
|
||||||
|
// If reloaded, do the search or mark again, depending on the current url parameters
|
||||||
|
this.doSearchOrMarkFromUrl();
|
||||||
|
}
|
||||||
|
,
|
||||||
|
hasFocus : function () {
|
||||||
|
return this.searchbar.is(':focus');
|
||||||
|
}
|
||||||
|
,
|
||||||
|
globalKeyHandler : function (e) {
|
||||||
|
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
|
||||||
|
if (e.keyCode == this.ESCAPE_KEYCODE) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.searchbar.removeClass("active");
|
||||||
|
// this.searchbar[0].value = "";
|
||||||
|
this.setSearchUrlParameters("",
|
||||||
|
(this.searchbar[0].value.trim() != 0) ? "push" : "replace");
|
||||||
|
this.unfocusSearchbar();
|
||||||
|
this.searchbar_outer.slideUp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.hasFocus() && e.keyCode == this.SEARCH_HOTKEY_KEYCODE) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.searchbar_outer.slideDown()
|
||||||
|
this.searchbar.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
unfocusSearchbar : function () {
|
||||||
|
// hacky, but just focusing a div only works once
|
||||||
|
var tmp = $('<input style="position: absolute; opacity: 0;">');
|
||||||
|
tmp.insertAfter(this.searchicon);
|
||||||
|
tmp.focus();
|
||||||
|
tmp.remove();
|
||||||
|
}
|
||||||
|
,
|
||||||
|
searchIconClickHandler : function () {
|
||||||
|
this.searchbar_outer.slideToggle();
|
||||||
|
this.searchbar.focus();
|
||||||
|
// TODO:
|
||||||
|
// If invisible, clear URL search parameter
|
||||||
|
}
|
||||||
|
,
|
||||||
|
searchbarKeyUpHandler : function () {
|
||||||
|
var searchterm = this.searchbar[0].value.trim();
|
||||||
|
if (searchterm != "") {
|
||||||
|
this.searchbar.addClass("active");
|
||||||
|
this.doSearch(searchterm);
|
||||||
|
} else {
|
||||||
|
this.searchbar.removeClass("active");
|
||||||
|
this.searchresults_outer.slideUp();
|
||||||
|
this.searchresults.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setSearchUrlParameters(searchterm, "if_begin_search");
|
||||||
|
|
||||||
|
// Remove marks
|
||||||
|
this.content.unmark();
|
||||||
|
}
|
||||||
|
,
|
||||||
|
setSearchUrlParameters : function(searchterm, action) {
|
||||||
|
// Update url with ?SEARCH_PARAM= parameter, remove ?MARK_PARAM and #heading-anchor
|
||||||
|
var url = this.parseURL(window.location.href);
|
||||||
|
var first_search = ! url.params.hasOwnProperty(this.SEARCH_PARAM);
|
||||||
|
if (searchterm != "" || action == "if_begin_search") {
|
||||||
|
url.params[this.SEARCH_PARAM] = searchterm;
|
||||||
|
delete url.params[this.MARK_PARAM];
|
||||||
|
url.hash = "";
|
||||||
|
} else {
|
||||||
|
delete url.params[this.SEARCH_PARAM];
|
||||||
|
}
|
||||||
|
// A new search will also add a new history item, so the user can go back
|
||||||
|
// to the page prior to searching. A updated search term will only replace
|
||||||
|
// the url.
|
||||||
|
if (action == "push" || (action == "if_begin_search" && first_search) ) {
|
||||||
|
history.pushState({}, document.title, this.renderURL(url));
|
||||||
|
} else if (action == "replace" || (action == "if_begin_search" && !first_search) ) {
|
||||||
|
history.replaceState({}, document.title, this.renderURL(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interesting DOM Elements
|
||||||
|
var sidebar = $("#sidebar");
|
||||||
|
|
||||||
// url
|
// url
|
||||||
var url = window.location.pathname;
|
var url = window.location.pathname;
|
||||||
|
@ -213,13 +363,12 @@ $( 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; }
|
if (search.hasFocus()) { return; }
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case KEY_CODES.NEXT_KEY:
|
case KEY_CODES.NEXT_KEY:
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -233,17 +382,9 @@ $( 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-outer").slideDown()
|
|
||||||
$('#searchbar').focus();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Interesting DOM Elements
|
|
||||||
var sidebar = $("#sidebar");
|
|
||||||
|
|
||||||
// Help keyboard navigation by always focusing on page content
|
// Help keyboard navigation by always focusing on page content
|
||||||
$(".page").focus();
|
$(".page").focus();
|
||||||
|
|
||||||
|
@ -264,52 +405,8 @@ $( document ).ready(function() {
|
||||||
sidebar.scrollTop(activeSection.offset().top);
|
sidebar.scrollTop(activeSection.offset().top);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For testing purposes: Index current page
|
// Search
|
||||||
var searchindex = create_test_searchindex();
|
search.init();
|
||||||
|
|
||||||
$("#search-icon").click(function(e) {
|
|
||||||
var outer = $("#searchbar-outer");
|
|
||||||
outer.slideToggle();
|
|
||||||
// TODO:
|
|
||||||
// If invisible, clear URL search parameter
|
|
||||||
});
|
|
||||||
|
|
||||||
// Searchbar
|
|
||||||
$("#searchbar").on('keyup', function (e) {
|
|
||||||
var display = $('#searchresults');
|
|
||||||
var outer = $("#searchresults-outer");
|
|
||||||
|
|
||||||
var searchterm = e.target.value.trim();
|
|
||||||
if (searchterm != "") {
|
|
||||||
$(e.target).addClass("active");
|
|
||||||
|
|
||||||
doSearch(searchindex, searchterm);
|
|
||||||
} else {
|
|
||||||
$(e.target).removeClass("active");
|
|
||||||
outer.slideUp();
|
|
||||||
display.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = parseURL(window.location.href);
|
|
||||||
var first_search = ! url.params.hasOwnProperty("search");
|
|
||||||
url.params["search"] = searchterm;
|
|
||||||
delete url.params["highlight"];
|
|
||||||
url.hash = "";
|
|
||||||
if (first_search) {
|
|
||||||
history.pushState({}, document.title, renderURL(url));
|
|
||||||
} else {
|
|
||||||
history.replaceState({}, document.title, renderURL(url));
|
|
||||||
}
|
|
||||||
$('.content').unmark();
|
|
||||||
});
|
|
||||||
|
|
||||||
window.onpopstate = function(e) {
|
|
||||||
doSearchOrHighlightFromUrl();
|
|
||||||
};
|
|
||||||
|
|
||||||
doSearchOrHighlightFromUrl();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Theme button
|
// Theme button
|
||||||
$("#theme-toggle").click(function(){
|
$("#theme-toggle").click(function(){
|
||||||
|
|
Loading…
Reference in New Issue