Add client-side search, modified from atom from https://github.com/chinchang/super-search
This commit is contained in:
80
static/super-search.css
Normal file
80
static/super-search.css
Normal file
@@ -0,0 +1,80 @@
|
||||
/* super-search
|
||||
Author: Kushagra Gour (http://kushagragour.in)
|
||||
MIT Licensed
|
||||
*/
|
||||
.super-search-btn {
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
top: 15px;
|
||||
fill: #DDD;
|
||||
}
|
||||
.super-search-btn:hover {
|
||||
fill: #BBB;
|
||||
}
|
||||
|
||||
.super-search {
|
||||
position: fixed;
|
||||
background-color: rgba(100, 100, 100, 0.85);
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
transition: 0.2s ease;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
.super-search__close-btn {
|
||||
fill: #DDD;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 15px;
|
||||
z-index: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
.super-search__input {
|
||||
border: 0;
|
||||
font-size: 50px;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
color: #999;
|
||||
width: 100%;
|
||||
padding: 10px 31px;
|
||||
text-align: center;
|
||||
transform: translateY(-100%);
|
||||
transition: 0.15s ease-out 150ms;
|
||||
}
|
||||
.is-active .super-search__input {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.super-search__results {
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
height: calc(100% - 110px);
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
.super-search__results.is-hidden {
|
||||
opacity: 0;
|
||||
transform: translateY(-1vh);
|
||||
}
|
||||
|
||||
.super-search__results > li > a {
|
||||
display: block;
|
||||
position: relative;
|
||||
background-color: #f9f9f9;
|
||||
color: #666;
|
||||
padding: 17px;
|
||||
margin: 12px 14px;
|
||||
box-shadow: 0 3px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.super-search__result-date {
|
||||
color: #BBB;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
}
|
||||
.super-search.is-active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
137
static/super-search.js
Normal file
137
static/super-search.js
Normal file
@@ -0,0 +1,137 @@
|
||||
/* super-search
|
||||
Author: Kushagra Gour (http://kushagragour.in)
|
||||
MIT Licensed
|
||||
*/
|
||||
(function () {
|
||||
var searchFile = '/feed.xml',
|
||||
searchEl,
|
||||
searchInputEl,
|
||||
searchResultsEl,
|
||||
currentInputValue = '',
|
||||
lastSearchResultHash,
|
||||
posts = [];
|
||||
|
||||
// Changes XML to JSON
|
||||
// Modified version from here: http://davidwalsh.name/convert-xml-json
|
||||
function xmlToJson(xml) {
|
||||
// Create the return object
|
||||
var obj = {};
|
||||
if (xml.nodeType == 3) { // text
|
||||
obj = xml.nodeValue;
|
||||
}
|
||||
|
||||
// do children
|
||||
// If all text nodes inside, get concatenated text from them.
|
||||
var textNodes = [].slice.call(xml.childNodes).filter(function (node) { return node.nodeType === 3; });
|
||||
if (xml.hasChildNodes() && xml.childNodes.length === textNodes.length) {
|
||||
obj = [].slice.call(xml.childNodes).reduce(function (text, node) { return text + node.nodeValue; }, '');
|
||||
}
|
||||
else if (xml.hasChildNodes()) {
|
||||
for(var i = 0; i < xml.childNodes.length; i++) {
|
||||
var item = xml.childNodes.item(i);
|
||||
var nodeName = item.nodeName;
|
||||
if (typeof(obj[nodeName]) == "undefined") {
|
||||
obj[nodeName] = xmlToJson(item);
|
||||
} else {
|
||||
if (typeof(obj[nodeName].push) == "undefined") {
|
||||
var old = obj[nodeName];
|
||||
obj[nodeName] = [];
|
||||
obj[nodeName].push(old);
|
||||
}
|
||||
obj[nodeName].push(xmlToJson(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function getPostsFromXml(xml) {
|
||||
var json = xmlToJson(xml);
|
||||
return json.entry;
|
||||
}
|
||||
|
||||
window.toggleSearch = function toggleSearch() {
|
||||
searchEl.classList.toggle('is-active');
|
||||
if (searchEl.classList.contains('is-active')) {
|
||||
// while opening
|
||||
searchInputEl.value = '';
|
||||
} else {
|
||||
// while closing
|
||||
searchResultsEl.classList.add('is-hidden');
|
||||
}
|
||||
setTimeout(function () {
|
||||
searchInputEl.focus();
|
||||
}, 210);
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
var currentResultHash, d;
|
||||
|
||||
currentInputValue = searchInputEl.value;
|
||||
if (!currentInputValue || currentInputValue.length < 3) {
|
||||
lastSearchResultHash = '';
|
||||
searchResultsEl.classList.add('is-hidden');
|
||||
return;
|
||||
}
|
||||
searchResultsEl.style.offsetWidth;
|
||||
|
||||
var matchingPosts = posts.filter(function (post) {
|
||||
if (post.title.indexOf(currentInputValue) !== -1 || post.content.indexOf(currentInputValue) !== -1) {
|
||||
console.log(post)
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!matchingPosts.length) {
|
||||
searchResultsEl.classList.add('is-hidden');
|
||||
}
|
||||
currentResultHash = matchingPosts.reduce(function(hash, post) { return post.title + hash; }, '');
|
||||
if (matchingPosts.length && currentResultHash !== lastSearchResultHash) {
|
||||
searchResultsEl.classList.remove('is-hidden');
|
||||
searchResultsEl.innerHTML = matchingPosts.map(function (post) {
|
||||
d = new Date(post.updated);
|
||||
return '<li><a href="' + post.id + '">' + post.title + ' <span class="search__result-date">[' + d.toUTCString().replace(/.*(\d{2})\s+(\w{3})\s+(\d{4}).*/,'$2 $1, $3') + ']</span></a></li>';
|
||||
}).join('');
|
||||
}
|
||||
lastSearchResultHash = currentResultHash;
|
||||
}
|
||||
|
||||
function init(options) {
|
||||
searchFile = options.searchFile || searchFile;
|
||||
searchEl = document.querySelector(options.searchSelector || '#js-super-search');
|
||||
searchInputEl = document.querySelector(options.inputSelector || '#js-super-search__input');
|
||||
searchResultsEl = document.querySelector(options.resultsSelector || '#js-super-search__results');
|
||||
|
||||
var xmlhttp=new XMLHttpRequest();
|
||||
xmlhttp.open('GET', searchFile);
|
||||
xmlhttp.onreadystatechange = function () {
|
||||
if (xmlhttp.readyState != 4) return;
|
||||
if (xmlhttp.status != 200 && xmlhttp.status != 304) { return; }
|
||||
var node = (new DOMParser).parseFromString(xmlhttp.responseText, 'text/xml');
|
||||
node = node.children[0];
|
||||
posts = getPostsFromXml(node);
|
||||
}
|
||||
xmlhttp.send();
|
||||
|
||||
// Toggle on ESC key
|
||||
window.addEventListener('keyup', function onKeyPress(e) {
|
||||
if (e.which === 27) {
|
||||
toggleSearch();
|
||||
}
|
||||
});
|
||||
// Open on '/' key
|
||||
window.addEventListener('keypress', function onKeyPress(e) {
|
||||
if (e.which === 47 && !searchEl.classList.contains('is-active')) {
|
||||
toggleSearch();
|
||||
}
|
||||
});
|
||||
|
||||
searchInputEl.addEventListener('input', function onInputChange() {
|
||||
handleInput();
|
||||
});
|
||||
}
|
||||
|
||||
init.toggle = toggleSearch;
|
||||
|
||||
window.superSearch = init;
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user