summaryrefslogtreecommitdiffstats
path: root/sitestatic/homepage.js
diff options
context:
space:
mode:
authorJelle van der Waa <jelle@vdwaa.nl>2018-11-24 22:48:07 +0100
committerJelle van der Waa <jelle@archlinux.org>2019-02-18 16:42:51 +0100
commit37a51bc78902a213dde155a76a9fa290cd776fd7 (patch)
tree31494a41fcb4bd000248e66779b81fed71f8d460 /sitestatic/homepage.js
parentd1674c1d12f3e57c3a22ed6103b2d022016700e5 (diff)
downloadarchweb-37a51bc78902a213dde155a76a9fa290cd776fd7.tar.gz
archweb-37a51bc78902a213dde155a76a9fa290cd776fd7.zip
homepage: use self written typeahead implementation
Use a self written typeahead inmplemenation which gets rid of the jQuery requirement. This saves upgrading issues and reduces the amount of data to be loaded for the homepage by half.
Diffstat (limited to 'sitestatic/homepage.js')
-rw-r--r--sitestatic/homepage.js157
1 files changed, 133 insertions, 24 deletions
diff --git a/sitestatic/homepage.js b/sitestatic/homepage.js
index d0dc3444..b46cf0b4 100644
--- a/sitestatic/homepage.js
+++ b/sitestatic/homepage.js
@@ -1,26 +1,135 @@
-!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return e&&this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),(e.browser.chrome||e.browser.webkit||e.browser.msie)&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e(function(){e("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})})}(window.jQuery);
-
-function setupTypeahead() {
- $('#pkgsearch-field').typeahead({
- source: function(query, callback) {
- $.getJSON('/opensearch/packages/suggest', {q: query}, function(data) {
- callback(data[1]);
- });
- },
- matcher: function(item) { return true; },
- sorter: function(items) { return items; },
- menu: '<ul class="pkgsearch-typeahead"></ul>',
- items: 10,
- updater: function(item) {
- $('#pkgsearch-field').val(item);
- $('#pkgsearch-form').submit();
- return item;
+"use strict";
+
+(function() {
+ const input = document.getElementById('pkgsearch-field');
+ const form = document.getElementById('pkgsearch-form');
+ var list;
+
+ function resetResults() {
+ if (!list) return;
+ list.style.display = "none";
+ list.innerHTML = "";
+ }
+
+ function getCompleteList() {
+ if (!list) {
+ list = document.createElement("UL");
+ list.setAttribute("class", "pkgsearch-typeahead"); // remove
+ form.appendChild(list);
+ setListLocation();
+ }
+ return list;
+ }
+
+ function onListClick(e) {
+ let target = e.target;
+ while (!target.getAttribute('data-value')) {
+ target = target.parentNode;
+ }
+ input.value = target.getAttribute('data-value');
+ form.submit();
+ }
+
+ function setListLocation() {
+ if (!list) return;
+ const rects = input.getClientRects()[0];
+ list.style.top = (rects.y + rects.height) + "px";
+ list.style.left = rects.x + "px";
+ }
+
+ function loadData(data) {
+ const letter = data[0];
+ const pkgs = data[1].slice(0, 10); // Show maximum of 10 results
+
+ resetResults();
+
+ if (pkgs.length === 0) {
+ return;
+ }
+
+ const ul = getCompleteList();
+ ul.style.display = "block";
+ const fragment = document.createDocumentFragment();
+
+ for (let i = 0; i < pkgs.length; i++) {
+ const item = document.createElement("li");
+ const text = pkgs[i].replace(letter, '<b>' + letter + '</b>');
+ item.innerHTML = '<a href="#">' + text + '</a>';
+ item.setAttribute('data-value', pkgs[i]);
+ fragment.appendChild(item);
+ }
+
+ ul.appendChild(fragment);
+ ul.addEventListener('click', onListClick);
+ }
+
+ function fetchData(letter) {
+ fetch('/opensearch/packages/suggest?q=' + letter).then(function(response) {
+ return response.json();
+ }).then(function(data) {
+ loadData(data);
+ });
+ }
+
+ function onInputClick() {
+ if (input.value === "") {
+ resetResults();
+ return;
+ }
+ fetchData(input.value);
+ }
+
+ function onKeyDown(e) {
+ if (!list) return;
+
+ const elem = document.querySelector(".pkgsearch-typeahead li.active");
+ switch(e.keyCode) {
+ case 13: // enter
+ if (elem) {
+ input.value = elem.getAttribute('data-value');
+ form.submit();
+ } else {
+ form.submit();
}
- }).attr('autocomplete', 'off');
- $('#pkgsearch-field').keyup(function(e) {
- if (e.keyCode === 13 &&
- $('ul.pkgsearch-typeahead li.active').size() === 0) {
- $('#pkgsearch-form').submit();
+ e.preventDefault();
+ break;
+ case 38: // up
+ if (elem && elem.previousElementSibling) {
+ elem.className = "";
+ elem.previousElementSibling.className = "active";
}
- });
-}
+ e.preventDefault();
+ break;
+ case 40: // down
+ if (elem && elem.nextElementSibling) {
+ elem.className = "";
+ elem.nextElementSibling.className = "active";
+ } else if (!elem && list.childElementCount !== 0) {
+ list.children[0].className = "active";
+ }
+ e.preventDefault();
+ break;
+ }
+ }
+
+ // debounce https://davidwalsh.name/javascript-debounce-function
+ function debounce(func, wait, immediate) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) func.apply(context, args);
+ };
+ }
+
+ input.addEventListener("input", onInputClick);
+ input.addEventListener("keydown", onKeyDown);
+ window.addEventListener('resize', debounce(setListLocation, 150));
+ document.addEventListener("click", resetResults);
+}());