mirror of
https://github.com/McShelby/hugo-theme-relearn.git
synced 2024-11-23 07:47:54 +00:00
Replace horsey with Pixabay's autocomplete (#75)
This commit is contained in:
parent
209497b45e
commit
ff5ef7c020
7 changed files with 299 additions and 1633 deletions
|
@ -14,7 +14,7 @@
|
||||||
<link href="{{"css/hybrid.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
<link href="{{"css/hybrid.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
||||||
<link href="{{"css/featherlight.min.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
<link href="{{"css/featherlight.min.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
||||||
<link href="{{"css/perfect-scrollbar.min.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
<link href="{{"css/perfect-scrollbar.min.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
||||||
<link href="{{"css/horsey.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
<link href="{{"css/auto-complete.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
||||||
<link href="{{"css/theme.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
<link href="{{"css/theme.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
||||||
<link href="{{"css/hugo-theme.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
<link href="{{"css/hugo-theme.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
|
||||||
{{with .Site.Params.themeVariant}}
|
{{with .Site.Params.themeVariant}}
|
||||||
|
@ -92,4 +92,4 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
{{.value|safeHTML}}
|
{{.value|safeHTML}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{ $assetBusting := not .Site.Params.disableAssetsBusting }}
|
{{ $assetBusting := not .Site.Params.disableAssetsBusting }}
|
||||||
<script type="text/javascript" src="{{"js/lunr.min.js" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}"></script>
|
<script type="text/javascript" src="{{"js/lunr.min.js" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}"></script>
|
||||||
<script type="text/javascript" src="{{"js/horsey.js" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}"></script>
|
<script type="text/javascript" src="{{"js/auto-complete.js" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
{{ if .Site.IsMultiLingual }}
|
{{ if .Site.IsMultiLingual }}
|
||||||
var baseurl = "{{.Site.BaseURL}}{{.Site.LanguagePrefix}}";
|
var baseurl = "{{.Site.BaseURL}}{{.Site.LanguagePrefix}}";
|
||||||
|
|
47
static/css/auto-complete.css
Normal file
47
static/css/auto-complete.css
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
.autocomplete-suggestions {
|
||||||
|
text-align: left;
|
||||||
|
cursor: default;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-top: 0;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: -1px 1px 3px rgba(0,0,0,.1);
|
||||||
|
|
||||||
|
/* core styles should not be changed */
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
z-index: 9999;
|
||||||
|
max-height: 254px;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
.autocomplete-suggestion {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 7px;
|
||||||
|
line-height: 23px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion b {
|
||||||
|
font-weight: normal;
|
||||||
|
color: #1f8dd6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion.selected {
|
||||||
|
background: #333;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion:hover {
|
||||||
|
background: #444;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion > .context {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
.sey-list {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
list-style-type: none;
|
|
||||||
box-shadow: 1px 2px 6px;
|
|
||||||
background-color: #fff;
|
|
||||||
color: #333;
|
|
||||||
transition: left 0.1s ease-in-out;
|
|
||||||
max-height: 70vh;
|
|
||||||
overflow: auto;
|
|
||||||
width: 265px;
|
|
||||||
}
|
|
||||||
.sey-show {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.sey-hide {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.sey-item {
|
|
||||||
cursor: pointer;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
padding: 7px;
|
|
||||||
}
|
|
||||||
.sey-item:hover {
|
|
||||||
background-color: #444;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.sey-selected {
|
|
||||||
background-color: #333;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
223
static/js/auto-complete.js
Normal file
223
static/js/auto-complete.js
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
JavaScript autoComplete v1.0.4
|
||||||
|
Copyright (c) 2014 Simon Steinberger / Pixabay
|
||||||
|
GitHub: https://github.com/Pixabay/JavaScript-autoComplete
|
||||||
|
License: http://www.opensource.org/licenses/mit-license.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
var autoComplete = (function(){
|
||||||
|
// "use strict";
|
||||||
|
function autoComplete(options){
|
||||||
|
if (!document.querySelector) return;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
function hasClass(el, className){ return el.classList ? el.classList.contains(className) : new RegExp('\\b'+ className+'\\b').test(el.className); }
|
||||||
|
|
||||||
|
function addEvent(el, type, handler){
|
||||||
|
if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
|
||||||
|
}
|
||||||
|
function removeEvent(el, type, handler){
|
||||||
|
// if (el.removeEventListener) not working in IE11
|
||||||
|
if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
|
||||||
|
}
|
||||||
|
function live(elClass, event, cb, context){
|
||||||
|
addEvent(context || document, event, function(e){
|
||||||
|
var found, el = e.target || e.srcElement;
|
||||||
|
while (el && !(found = hasClass(el, elClass))) el = el.parentElement;
|
||||||
|
if (found) cb.call(el, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var o = {
|
||||||
|
selector: 0,
|
||||||
|
source: 0,
|
||||||
|
minChars: 3,
|
||||||
|
delay: 150,
|
||||||
|
offsetLeft: 0,
|
||||||
|
offsetTop: 1,
|
||||||
|
cache: 1,
|
||||||
|
menuClass: '',
|
||||||
|
renderItem: function (item, search){
|
||||||
|
// escape special characters
|
||||||
|
search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||||
|
var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
|
||||||
|
return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>';
|
||||||
|
},
|
||||||
|
onSelect: function(e, term, item){}
|
||||||
|
};
|
||||||
|
for (var k in options) { if (options.hasOwnProperty(k)) o[k] = options[k]; }
|
||||||
|
|
||||||
|
// init
|
||||||
|
var elems = typeof o.selector == 'object' ? [o.selector] : document.querySelectorAll(o.selector);
|
||||||
|
for (var i=0; i<elems.length; i++) {
|
||||||
|
var that = elems[i];
|
||||||
|
|
||||||
|
// create suggestions container "sc"
|
||||||
|
that.sc = document.createElement('div');
|
||||||
|
that.sc.className = 'autocomplete-suggestions '+o.menuClass;
|
||||||
|
|
||||||
|
that.autocompleteAttr = that.getAttribute('autocomplete');
|
||||||
|
that.setAttribute('autocomplete', 'off');
|
||||||
|
that.cache = {};
|
||||||
|
that.last_val = '';
|
||||||
|
|
||||||
|
that.updateSC = function(resize, next){
|
||||||
|
var rect = that.getBoundingClientRect();
|
||||||
|
that.sc.style.left = Math.round(rect.left + (window.pageXOffset || document.documentElement.scrollLeft) + o.offsetLeft) + 'px';
|
||||||
|
that.sc.style.top = Math.round(rect.bottom + (window.pageYOffset || document.documentElement.scrollTop) + o.offsetTop) + 'px';
|
||||||
|
that.sc.style.width = Math.round(rect.right - rect.left) + 'px'; // outerWidth
|
||||||
|
if (!resize) {
|
||||||
|
that.sc.style.display = 'block';
|
||||||
|
if (!that.sc.maxHeight) { that.sc.maxHeight = parseInt((window.getComputedStyle ? getComputedStyle(that.sc, null) : that.sc.currentStyle).maxHeight); }
|
||||||
|
if (!that.sc.suggestionHeight) that.sc.suggestionHeight = that.sc.querySelector('.autocomplete-suggestion').offsetHeight;
|
||||||
|
if (that.sc.suggestionHeight)
|
||||||
|
if (!next) that.sc.scrollTop = 0;
|
||||||
|
else {
|
||||||
|
var scrTop = that.sc.scrollTop, selTop = next.getBoundingClientRect().top - that.sc.getBoundingClientRect().top;
|
||||||
|
if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0)
|
||||||
|
that.sc.scrollTop = selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight;
|
||||||
|
else if (selTop < 0)
|
||||||
|
that.sc.scrollTop = selTop + scrTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(window, 'resize', that.updateSC);
|
||||||
|
document.body.appendChild(that.sc);
|
||||||
|
|
||||||
|
live('autocomplete-suggestion', 'mouseleave', function(e){
|
||||||
|
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (sel) setTimeout(function(){ sel.className = sel.className.replace('selected', ''); }, 20);
|
||||||
|
}, that.sc);
|
||||||
|
|
||||||
|
live('autocomplete-suggestion', 'mouseover', function(e){
|
||||||
|
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (sel) sel.className = sel.className.replace('selected', '');
|
||||||
|
this.className += ' selected';
|
||||||
|
}, that.sc);
|
||||||
|
|
||||||
|
live('autocomplete-suggestion', 'mousedown', function(e){
|
||||||
|
if (hasClass(this, 'autocomplete-suggestion')) { // else outside click
|
||||||
|
var v = this.getAttribute('data-val');
|
||||||
|
that.value = v;
|
||||||
|
o.onSelect(e, v, this);
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
}
|
||||||
|
}, that.sc);
|
||||||
|
|
||||||
|
that.blurHandler = function(){
|
||||||
|
try { var over_sb = document.querySelector('.autocomplete-suggestions:hover'); } catch(e){ var over_sb = 0; }
|
||||||
|
if (!over_sb) {
|
||||||
|
that.last_val = that.value;
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
setTimeout(function(){ that.sc.style.display = 'none'; }, 350); // hide suggestions on fast input
|
||||||
|
} else if (that !== document.activeElement) setTimeout(function(){ that.focus(); }, 20);
|
||||||
|
};
|
||||||
|
addEvent(that, 'blur', that.blurHandler);
|
||||||
|
|
||||||
|
var suggest = function(data){
|
||||||
|
var val = that.value;
|
||||||
|
that.cache[val] = data;
|
||||||
|
if (data.length && val.length >= o.minChars) {
|
||||||
|
var s = '';
|
||||||
|
for (var i=0;i<data.length;i++) s += o.renderItem(data[i], val);
|
||||||
|
that.sc.innerHTML = s;
|
||||||
|
that.updateSC(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
that.keydownHandler = function(e){
|
||||||
|
var key = window.event ? e.keyCode : e.which;
|
||||||
|
// down (40), up (38)
|
||||||
|
if ((key == 40 || key == 38) && that.sc.innerHTML) {
|
||||||
|
var next, sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (!sel) {
|
||||||
|
next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last
|
||||||
|
next.className += ' selected';
|
||||||
|
console.log(next);
|
||||||
|
that.value = next.getAttribute('data-val');
|
||||||
|
} else {
|
||||||
|
next = (key == 40) ? sel.nextSibling : sel.previousSibling;
|
||||||
|
if (next) {
|
||||||
|
sel.className = sel.className.replace('selected', '');
|
||||||
|
next.className += ' selected';
|
||||||
|
that.value = next.getAttribute('data-val');
|
||||||
|
}
|
||||||
|
else { sel.className = sel.className.replace('selected', ''); that.value = that.last_val; next = 0; }
|
||||||
|
}
|
||||||
|
that.updateSC(0, next);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// esc
|
||||||
|
else if (key == 27) { that.value = that.last_val; that.sc.style.display = 'none'; }
|
||||||
|
// enter
|
||||||
|
else if (key == 13 || key == 9) {
|
||||||
|
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (sel && that.sc.style.display != 'none') { o.onSelect(e, sel.getAttribute('data-val'), sel); setTimeout(function(){ that.sc.style.display = 'none'; }, 20); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(that, 'keydown', that.keydownHandler);
|
||||||
|
|
||||||
|
that.keyupHandler = function(e){
|
||||||
|
var key = window.event ? e.keyCode : e.which;
|
||||||
|
if (!key || (key < 35 || key > 40) && key != 13 && key != 27) {
|
||||||
|
var val = that.value;
|
||||||
|
if (val.length >= o.minChars) {
|
||||||
|
if (val != that.last_val) {
|
||||||
|
that.last_val = val;
|
||||||
|
clearTimeout(that.timer);
|
||||||
|
if (o.cache) {
|
||||||
|
if (val in that.cache) { suggest(that.cache[val]); return; }
|
||||||
|
// no requests if previous suggestions were empty
|
||||||
|
for (var i=1; i<val.length-o.minChars; i++) {
|
||||||
|
var part = val.slice(0, val.length-i);
|
||||||
|
if (part in that.cache && !that.cache[part].length) { suggest([]); return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
that.timer = setTimeout(function(){ o.source(val, suggest) }, o.delay);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
that.last_val = val;
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(that, 'keyup', that.keyupHandler);
|
||||||
|
|
||||||
|
that.focusHandler = function(e){
|
||||||
|
that.last_val = '\n';
|
||||||
|
that.keyupHandler(e)
|
||||||
|
};
|
||||||
|
if (!o.minChars) addEvent(that, 'focus', that.focusHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public destroy method
|
||||||
|
this.destroy = function(){
|
||||||
|
for (var i=0; i<elems.length; i++) {
|
||||||
|
var that = elems[i];
|
||||||
|
removeEvent(window, 'resize', that.updateSC);
|
||||||
|
removeEvent(that, 'blur', that.blurHandler);
|
||||||
|
removeEvent(that, 'focus', that.focusHandler);
|
||||||
|
removeEvent(that, 'keydown', that.keydownHandler);
|
||||||
|
removeEvent(that, 'keyup', that.keyupHandler);
|
||||||
|
if (that.autocompleteAttr)
|
||||||
|
that.setAttribute('autocomplete', that.autocompleteAttr);
|
||||||
|
else
|
||||||
|
that.removeAttribute('autocomplete');
|
||||||
|
document.body.removeChild(that.sc);
|
||||||
|
that = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return autoComplete;
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
if (typeof define === 'function' && define.amd)
|
||||||
|
define('autoComplete', function () { return autoComplete; });
|
||||||
|
else if (typeof module !== 'undefined' && module.exports)
|
||||||
|
module.exports = autoComplete;
|
||||||
|
else
|
||||||
|
window.autoComplete = autoComplete;
|
||||||
|
})();
|
1571
static/js/horsey.js
1571
static/js/horsey.js
File diff suppressed because one or more lines are too long
|
@ -58,31 +58,33 @@ function search(query) {
|
||||||
// Let's get started
|
// Let's get started
|
||||||
initLunr();
|
initLunr();
|
||||||
$( document ).ready(function() {
|
$( document ).ready(function() {
|
||||||
var horseyList = horsey($("#search-by").get(0), {
|
var searchList = new autoComplete({
|
||||||
suggestions: function (value, done) {
|
/* selector for the search box element */
|
||||||
var query = $("#search-by").val();
|
selector: $("#search-by").get(0),
|
||||||
var results = search(query);
|
/* source is the callback to perform the search */
|
||||||
done(results);
|
source: function(term, response) {
|
||||||
|
response(search(term));
|
||||||
},
|
},
|
||||||
filter: function (q, suggestion) {
|
/* renderItem displays individual search results */
|
||||||
return true;
|
renderItem: function(item, term) {
|
||||||
|
var numContextWords = 2;
|
||||||
|
var text = item.content.match(
|
||||||
|
"(?:\\s?(?:[\\w]+)\\s?){0,"+numContextWords+"}" +
|
||||||
|
term+"(?:\\s?(?:[\\w]+)\\s?){0,"+numContextWords+"}");
|
||||||
|
item.context = text;
|
||||||
|
return '<div class="autocomplete-suggestion" ' +
|
||||||
|
'data-term="' + term + '" ' +
|
||||||
|
'data-title="' + item.title + '" ' +
|
||||||
|
'data-uri="'+ item.uri + '" ' +
|
||||||
|
'data-context="' + item.context + '">' +
|
||||||
|
'» ' + item.title +
|
||||||
|
'<div class="context">' +
|
||||||
|
(item.context || '') +'</div>' +
|
||||||
|
'</div>';
|
||||||
},
|
},
|
||||||
set: function (value) {
|
/* onSelect callback fires when a search suggestion is chosen */
|
||||||
location.href=value.uri;
|
onSelect: function(e, term, item) {
|
||||||
},
|
location.href = item.getAttribute('data-uri');
|
||||||
render: function (li, suggestion) {
|
}
|
||||||
var uri = suggestion.uri.substring(1,suggestion.uri.length);
|
|
||||||
|
|
||||||
suggestion.href = baseurl + uri;
|
|
||||||
|
|
||||||
var query = $("#search-by").val();
|
|
||||||
var numWords = 2;
|
|
||||||
var text = suggestion.content.match("(?:\\s?(?:[\\w]+)\\s?){0,"+numWords+"}"+query+"(?:\\s?(?:[\\w]+)\\s?){0,"+numWords+"}");
|
|
||||||
suggestion.context = text;
|
|
||||||
var image = '<div>' + '» ' + suggestion.title + '</div><div style="font-size:12px">' + (suggestion.context || '') +'</div>';
|
|
||||||
li.innerHTML = image;
|
|
||||||
},
|
|
||||||
limit: 10
|
|
||||||
});
|
});
|
||||||
horseyList.refreshPosition();
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue