diff --git a/exampleSite/content/credits.md b/exampleSite/content/credits.md index 4d2879e0263..1b04636c905 100644 --- a/exampleSite/content/credits.md +++ b/exampleSite/content/credits.md @@ -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 diff --git a/layouts/partials/header.html b/layouts/partials/header.html index abf57c5ff74..0d2465aa38b 100644 --- a/layouts/partials/header.html +++ b/layouts/partials/header.html @@ -11,7 +11,7 @@ - + {{with .Site.Params.themeStyle}} {{else}} diff --git a/layouts/partials/search.html b/layouts/partials/search.html index 5478a318ac6..7ce6351a22f 100644 --- a/layouts/partials/search.html +++ b/layouts/partials/search.html @@ -4,7 +4,7 @@ - + diff --git a/static/css/auto-complete.css b/static/css/auto-complete.css new file mode 100644 index 00000000000..c144cd3899b --- /dev/null +++ b/static/css/auto-complete.css @@ -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; +} diff --git a/static/js/auto-complete.js b/static/js/auto-complete.js new file mode 100644 index 00000000000..7fbde995ed9 --- /dev/null +++ b/static/js/auto-complete.js @@ -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 '
' + item.replace(re, "$1") + '
'; + }, + 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 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 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