diff options
Diffstat (limited to 'uikit/static/js/components/autocomplete.js')
-rw-r--r-- | uikit/static/js/components/autocomplete.js | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/uikit/static/js/components/autocomplete.js b/uikit/static/js/components/autocomplete.js new file mode 100644 index 0000000..7031f94 --- /dev/null +++ b/uikit/static/js/components/autocomplete.js @@ -0,0 +1,336 @@ +/*! UIkit 2.21.0 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */ +(function(addon) { + + var component; + + if (window.UIkit) { + component = addon(UIkit); + } + + if (typeof define == "function" && define.amd) { + define("uikit-autocomplete", ["uikit"], function(){ + return component || addon(UIkit); + }); + } + +})(function(UI){ + + "use strict"; + + var active; + + UI.component('autocomplete', { + + defaults: { + minLength: 3, + param: 'search', + method: 'post', + delay: 300, + loadingClass: 'uk-loading', + flipDropdown: false, + skipClass: 'uk-skip', + hoverClass: 'uk-active', + source: null, + renderer: null, + + // template + + template: '<ul class="uk-nav uk-nav-autocomplete uk-autocomplete-results">{{~items}}<li data-value="{{$item.value}}"><a>{{$item.value}}</a></li>{{/items}}</ul>' + }, + + visible : false, + value : null, + selected : null, + + boot: function() { + + // init code + UI.$html.on("focus.autocomplete.uikit", "[data-uk-autocomplete]", function(e) { + + var ele = UI.$(this); + + if (!ele.data("autocomplete")) { + var obj = UI.autocomplete(ele, UI.Utils.options(ele.attr("data-uk-autocomplete"))); + } + }); + + // register outer click for autocompletes + UI.$html.on("click.autocomplete.uikit", function(e) { + if (active && e.target!=active.input[0]) active.hide(); + }); + }, + + init: function() { + + var $this = this, + select = false, + trigger = UI.Utils.debounce(function(e) { + if(select) { + return (select = false); + } + $this.handle(); + }, this.options.delay); + + + this.dropdown = this.find('.uk-dropdown'); + this.template = this.find('script[type="text/autocomplete"]').html(); + this.template = UI.Utils.template(this.template || this.options.template); + this.input = this.find("input:first").attr("autocomplete", "off"); + + if (!this.dropdown.length) { + this.dropdown = UI.$('<div class="uk-dropdown"></div>').appendTo(this.element); + } + + if (this.options.flipDropdown) { + this.dropdown.addClass('uk-dropdown-flip'); + } + + this.dropdown.attr('aria-expanded', 'false'); + + this.input.on({ + "keydown": function(e) { + + if (e && e.which && !e.shiftKey) { + + switch (e.which) { + case 13: // enter + select = true; + + if ($this.selected) { + e.preventDefault(); + $this.select(); + } + break; + case 38: // up + e.preventDefault(); + $this.pick('prev', true); + break; + case 40: // down + e.preventDefault(); + $this.pick('next', true); + break; + case 27: + case 9: // esc, tab + $this.hide(); + break; + default: + break; + } + } + + }, + "keyup": trigger + }); + + this.dropdown.on("click", ".uk-autocomplete-results > *", function(){ + $this.select(); + }); + + this.dropdown.on("mouseover", ".uk-autocomplete-results > *", function(){ + $this.pick(UI.$(this)); + }); + + this.triggercomplete = trigger; + }, + + handle: function() { + + var $this = this, old = this.value; + + this.value = this.input.val(); + + if (this.value.length < this.options.minLength) return this.hide(); + + if (this.value != old) { + $this.request(); + } + + return this; + }, + + pick: function(item, scrollinview) { + + var $this = this, + items = UI.$(this.dropdown.find('.uk-autocomplete-results').children(':not(.'+this.options.skipClass+')')), + selected = false; + + if (typeof item !== "string" && !item.hasClass(this.options.skipClass)) { + selected = item; + } else if (item == 'next' || item == 'prev') { + + if (this.selected) { + var index = items.index(this.selected); + + if (item == 'next') { + selected = items.eq(index + 1 < items.length ? index + 1 : 0); + } else { + selected = items.eq(index - 1 < 0 ? items.length - 1 : index - 1); + } + + } else { + selected = items[(item == 'next') ? 'first' : 'last'](); + } + + selected = UI.$(selected); + } + + if (selected && selected.length) { + this.selected = selected; + items.removeClass(this.options.hoverClass); + this.selected.addClass(this.options.hoverClass); + + // jump to selected if not in view + if (scrollinview) { + + var top = selected.position().top, + scrollTop = $this.dropdown.scrollTop(), + dpheight = $this.dropdown.height(); + + if (top > dpheight || top < 0) { + $this.dropdown.scrollTop(scrollTop + top); + } + } + } + }, + + select: function() { + + if(!this.selected) return; + + var data = this.selected.data(); + + this.trigger("selectitem.uk.autocomplete", [data, this]); + + if (data.value) { + this.input.val(data.value).trigger('change'); + } + + this.hide(); + }, + + show: function() { + if (this.visible) return; + this.visible = true; + this.element.addClass("uk-open"); + + if (active && active!==this) { + active.hide(); + } + + active = this; + + // Update aria + this.dropdown.attr('aria-expanded', 'true'); + + return this; + }, + + hide: function() { + if (!this.visible) return; + this.visible = false; + this.element.removeClass("uk-open"); + + if (active === this) { + active = false; + } + + // Update aria + this.dropdown.attr('aria-expanded', 'false'); + + return this; + }, + + request: function() { + + var $this = this, + release = function(data) { + + if(data) { + $this.render(data); + } + + $this.element.removeClass($this.options.loadingClass); + }; + + this.element.addClass(this.options.loadingClass); + + if (this.options.source) { + + var source = this.options.source; + + switch(typeof(this.options.source)) { + case 'function': + + this.options.source.apply(this, [release]); + + break; + + case 'object': + + if(source.length) { + + var items = []; + + source.forEach(function(item){ + if(item.value && item.value.toLowerCase().indexOf($this.value.toLowerCase())!=-1) { + items.push(item); + } + }); + + release(items); + } + + break; + + case 'string': + + var params ={}; + + params[this.options.param] = this.value; + + UI.$.ajax({ + url: this.options.source, + data: params, + type: this.options.method, + dataType: 'json' + }).done(function(json) { + release(json || []); + }); + + break; + + default: + release(null); + } + + } else { + this.element.removeClass($this.options.loadingClass); + } + }, + + render: function(data) { + + var $this = this; + + this.dropdown.empty(); + + this.selected = false; + + if (this.options.renderer) { + + this.options.renderer.apply(this, [data]); + + } else if(data && data.length) { + + this.dropdown.append(this.template({"items":data})); + this.show(); + + this.trigger('show.uk.autocomplete'); + } + + return this; + } + }); + + return UI.autocomplete; +}); |