Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes Android search by replacing horsey with pixabay autocomplete. #84

Merged
merged 1 commit into from
Oct 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion exampleSite/content/credits.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ description = "contributors and packages used by hugo-theme-docdock"
* [font awesome](http://fontawesome.io/) - the iconic font and CSS framework
* [jQuery](https://jquery.com) - The Write Less, Do More, JavaScript Library
* [lunr](https://lunrjs.com) - Lunr enables you to provide a great search experience without the need for external, server-side, search services...
* [horsey](https://bevacqua.github.io/horsey/) - Progressive and customizable autocomplete component
* [JavaScript-autoComplete](https://github.com/Pixabay/JavaScript-autoComplete) - An extremely lightweight and powerful vanilla JavaScript completion suggester.
* [clipboard.js](https://zenorocha.github.io/clipboard.js) - copy text to clipboard
* [highlight.js](https://highlightjs.org) - Javascript syntax highlighter
* [modernizr](https://modernizr.com) - A JavaScript toolkit that allows web developers to use new CSS3 and HTML5 features while maintaining a fine level of control over browsers that don't support
Expand Down
2 changes: 1 addition & 1 deletion layouts/partials/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<link href="{{"css/font-awesome.min.css" | relURL}}" rel="stylesheet">
<link href="{{"css/hybrid.css" | relURL}}" rel="stylesheet">
<link href="{{"css/featherlight.min.css" | relURL}}" rel="stylesheet">
<link href="{{"css/horsey.css" | relURL}}" rel="stylesheet">
<link href="{{"css/auto-complete.css" | relURL}}" rel="stylesheet">
{{with .Site.Params.themeStyle}}
<link href="{{(printf "css/%s.css" .) | relURL}}" rel="stylesheet">
{{else}}
Expand Down
2 changes: 1 addition & 1 deletion layouts/partials/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<span data-search-clear=""><i class="fa fa-close"></i></span>
</div>
<script type="text/javascript" src="{{"js/lunr.min.js" | relURL}}"></script>
<script type="text/javascript" src="{{"js/horsey.js" | relURL}}"></script>
<script type="text/javascript" src="{{"js/auto-complete.js" | relURL}}"></script>
<script type="text/javascript">
var baseurl = "{{.Site.BaseURL}}";
</script>
Expand Down
49 changes: 49 additions & 0 deletions static/css/auto-complete.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.autocomplete-suggestions {
text-align: left;
cursor: default;
border: 1px solid #ccc;
border-top: 0;
background: #fff;
box-shadow: 1px 2px 6px;
transition: left 0.1s ease-in-out;

/* core styles should not be changed */
position: absolute;
display: none;
z-index: 9999;
max-height: 70vh;
width: 265px;
overflow: hidden;
overflow-y: hidden;
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;
}
223 changes: 223 additions & 0 deletions static/js/auto-complete.js
Original file line number Diff line number Diff line change
@@ -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;
})();
Loading