Add client-side search, modified from atom from https://github.com/chinchang/super-search
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
<link href="http://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css" />
|
<link href="http://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css" />
|
||||||
<link href="{{ site.static_prefix }}/style/default-common.css" rel="stylesheet" type="text/css" />
|
<link href="{{ site.static_prefix }}/style/default-common.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="{{ site.static_prefix }}/style/default-print.css" media="print" rel="stylesheet" type="text/css" />
|
<link href="{{ site.static_prefix }}/style/default-print.css" media="print" rel="stylesheet" type="text/css" />
|
||||||
|
<link href="{{ site.static_prefix }}/super-search.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/{{ site.baseurl }}/blog/atom.xml" type="application/atom+xml" rel="alternate" title="{{ site.title }}" />
|
<link href="/{{ site.baseurl }}/blog/atom.xml" type="application/atom+xml" rel="alternate" title="{{ site.title }}" />
|
||||||
|
|
||||||
{% if page.description %}
|
{% if page.description %}
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
<meta property="og:description" content="{{ page.description }}" />
|
<meta property="og:description" content="{{ page.description }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<script src="{{ site.static_prefix }}/super-search.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var _gaq = _gaq || [];
|
var _gaq = _gaq || [];
|
||||||
_gaq.push(['_setAccount', '{{ site.analytics }}']);
|
_gaq.push(['_setAccount', '{{ site.analytics }}']);
|
||||||
@@ -36,10 +38,19 @@
|
|||||||
var headers = {{ site.headers | implode }};
|
var headers = {{ site.headers | implode }};
|
||||||
var header = headers[Math.floor(Math.random() * headers.length)];
|
var header = headers[Math.floor(Math.random() * headers.length)];
|
||||||
document.getElementById('masthead').style.backgroundImage = "url('/asset/header/" + header + ".jpg')";
|
document.getElementById('masthead').style.backgroundImage = "url('/asset/header/" + header + ".jpg')";
|
||||||
|
|
||||||
|
superSearch({
|
||||||
|
searchFile: '/blog/atom.xml'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="layout-{{ page.layout }}{% if page.body_class %} {{ page.body_class }}{% endif %}">
|
<body class="layout-{{ page.layout }}{% if page.body_class %} {{ page.body_class }}{% endif %}">
|
||||||
|
<div class="super-search" id="js-super-search">
|
||||||
|
<a href="javascript:void(0)" onclick="superSearch.toggle()" class="super-search__close-btn">X</a>
|
||||||
|
<input type="text" placeholder="Type here to search" class="super-search__input" id="js-super-search__input">
|
||||||
|
<ul class="super-search__results" id="js-super-search__results"></ul>
|
||||||
|
</div>
|
||||||
<header id="masthead" role="banner">
|
<header id="masthead" role="banner">
|
||||||
<a href="/{{ site.baseurl }}" title="{{ site.title }}" rel="home"></a>
|
<a href="/{{ site.baseurl }}" title="{{ site.title }}" rel="home"></a>
|
||||||
</header>
|
</header>
|
||||||
@@ -49,6 +60,13 @@
|
|||||||
<li><a href="/{{ site.baseurl }}/blog/">blog</a></li>
|
<li><a href="/{{ site.baseurl }}/blog/">blog</a></li>
|
||||||
<li><a href="/{{ site.baseurl }}/gallery/">gallery</a></li>
|
<li><a href="/{{ site.baseurl }}/gallery/">gallery</a></li>
|
||||||
<li><a href="/{{ site.baseurl }}/about.html">about</a></li>
|
<li><a href="/{{ site.baseurl }}/about.html">about</a></li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)" title="or press '/' to search" onclick="toggleSearch()" class="search-btn">
|
||||||
|
<svg style="width:20px;height:20px" viewBox="0 0 24 24">
|
||||||
|
<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% if page.print_blurb %}
|
{% if page.print_blurb %}
|
||||||
<ul class="print-only">
|
<ul class="print-only">
|
||||||
@@ -63,6 +81,6 @@
|
|||||||
·
|
·
|
||||||
<a href="mailto:{{ site.email }}">email</a>
|
<a href="mailto:{{ site.email }}">email</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<article>
|
<article>
|
||||||
|
|||||||
@@ -5,20 +5,20 @@ layout: null
|
|||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<id>{{ site.absolute }}/{{ site.baseurl }}/</id>
|
<id>{{ site.absolute }}/{{ site.baseurl }}/</id>
|
||||||
<title>{{ site.author }}</title>
|
<title>{{ site.author }}</title>
|
||||||
<link href="{{ site.absolute }}/{{ site.baseurl }}/blog/atom.xml" rel="self" />
|
<link href="{{ site.absolute }}{{ site.baseurl }}/blog/atom.xml" rel="self" />
|
||||||
<link href="{{ site.absolute }}/{{ site.baseurl }}/" />
|
<link href="{{ site.absolute }}{{ site.baseurl }}/" />
|
||||||
<updated>{{ site.time|date_to_xmlschema }}</updated>
|
<updated>{{ site.time | date_to_xmlschema }}</updated>
|
||||||
<author>
|
<author>
|
||||||
<name>{{ site.author }}</name>
|
<name>{{ site.author }}</name>
|
||||||
<email>{{ site.email }}</email>
|
<email>{{ site.email }}</email>
|
||||||
</author>
|
</author>
|
||||||
{% for post in site.posts %}
|
{% for post in site.posts %}
|
||||||
<entry>
|
<entry>
|
||||||
<id>{{ site.absolute }}/{{ post.id }}</id>
|
<id>{{ site.absolute }}/{{ site.baseurl }}{{ post.url }}</id>
|
||||||
<title>{{ post.title }}</title>
|
<title>{{ post.title | xml_escape }}</title>
|
||||||
<link href="{{ site.absolute }}/{{ site.baseurl }}{{ post.url }}"/>
|
<link href="{{ site.absolute }}/{{ site.baseurl }}{{ post.url }}"/>
|
||||||
<updated>{{ post.date|date_to_xmlschema }}</updated>
|
<updated>{{ post.date | date_to_xmlschema }}</updated>
|
||||||
<content type="html">{{ post.content|xml_escape }}</content>
|
<content type="html">{{ post.content | xml_escape }}</content>
|
||||||
</entry>
|
</entry>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</feed>
|
</feed>
|
||||||
|
|||||||
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