From bc62b3c3caaf6abd021e94952b166644f535f51f Mon Sep 17 00:00:00 2001 From: Michael Umfahrer Date: Wed, 28 Sep 2016 10:34:07 +0200 Subject: [PATCH] Add select callback, and enable tab to trigger selection --- src/Autocomplete.js | 1140 ++++++++++++++++++++++--------------------- 1 file changed, 574 insertions(+), 566 deletions(-) diff --git a/src/Autocomplete.js b/src/Autocomplete.js index f6cf96a..802d75a 100644 --- a/src/Autocomplete.js +++ b/src/Autocomplete.js @@ -5,570 +5,578 @@ // //////////////////////////////////// (function(window, document, undefined) { - "use strict"; - - var AutocompleteProto; - var Autocomplete = function(element, options) { - if ((this.element = (typeof(element) === "string") ? $(element) : element)) { - if ((this.element.tagName || "").toLowerCase() === "input") { - this.boundCheckValue = bind(this.checkValue, this); - this.cache = {}; - this.container = null; - this.delayTimer = null; - this.elementHasFocus = false; - this.highlightIdx = -1; - this.lastValue = ""; - this.lastOnInputValue = null; - this.shownValues = []; - this.throttle = -1; - this.usesTouch = (window.ontouchstart !== undefined); - this.values = []; - this.setOptions(options); - this.init(); - } - } - }; - - ////////////////////////////////////////////////////////////////////////////////// - (AutocompleteProto = Autocomplete.prototype).nothing = function(){}; - - ////////////////////////////////////////////////////////////////////////////////// - AutocompleteProto.setOptions = function(options) { - var hasOwnProp = Object.prototype.hasOwnProperty, - option; - - this.options = { - useNativeInterface : true, - offsetTop : 0, - offsetLeft : 0, - maxChoices : 6, - highlightColor : "#ffffff", - highlightBgColor : "#3399ff", - srcType : "", // "array", "dom", "xml" - srcData : "", - onInput : this.nothing, - onInputDelay : 0 - }; - - if (options) { - for (option in this.options) { - if (hasOwnProp.call(this.options, option) && options[option] !== undefined) { - this.options[option] = options[option]; - } - } - } - }; - - ////////////////////////////////////////////////////////////////////////////////// - AutocompleteProto.init = function() { - var srcType = this.options.srcType, - datalist, datalistId, boundSetElementFocus; - - // Get values: - this.values = (srcType === "array") ? (this.options.srcData || []).concat() : - (srcType === "dom") ? this.getDomValues() : - (srcType === "xml") ? this.getXmlValues() : []; - - // Get datalist element, set it's innerHTML if source type not "dom": - if (datalistSupported && this.options.useNativeInterface) { - if (this.options.onInput !== this.nothing) { - addEvent(this.element, "input", this.boundCheckValue); - } - return this.setDatalist(); - } - - // Remove any attached datalist element if not using native interface: - if (datalistSupported && (datalistId = this.element.getAttribute("list"))) { - if ((datalist = $(datalistId))) { - datalist.parentNode.removeChild(datalist); - } - this.element.removeAttribute("list"); - } - - // Attach behaviors: - boundSetElementFocus = bind(this.setElementFocus, this); - addEvent(this.element, "focus", boundSetElementFocus); - addEvent(this.element, "blur", boundSetElementFocus); - if (document.activeElement === this.element) { - boundSetElementFocus({ type : "focus" }); - } - }; - - ////////////////////////////////////////////////////////////////////////////////// - AutocompleteProto.getDomValues = function() { - var datalistId = this.element.getAttribute("list"), - container = (datalistId) ? ($(datalistId) || {}).parentNode : null, - options = (container) ? container.getElementsByTagName("option") : [], - option, i, v, - values = []; - - for (i=0, v=0; option=options[i]; i++) { - if ((option = option.value) !== undefined) { - values[v++] = option; - } - } - return values; - }; - - ////////////////////////////////////////////////////////////////////////////////// - AutocompleteProto.getXmlValues = function() { - var xml = parseXML(this.options.srcData), - nodes, node, n, value, v, - values = []; - - if ((nodes = (xml.getElementsByTagName("datalist")[0] || {}).childNodes)) { - for (n=0, v=0; node=nodes[n]; n++) { - if (node.nodeName === "option" && (value = node.getAttribute("value")) !== null) { - values[v++] = value; - } - } - } - - return values; - }; - - ////////////////////////////////////////////////////////////////////////////////// - AutocompleteProto.setDatalist = function() { - var datalistId = this.element.getAttribute("list"), - container = (this.container = (datalistId && $(datalistId))); - - // Generate datalist or set options HTML if source type not "dom": - if (!container) { - container = (this.container = document.createElement("datalist")); - container.id = "list" + Math.ceil(Math.random() * 50000); - container.innerHTML = this.generateDatalistOptionsHtml(); - this.element.parentNode.appendChild(container); - this.element.setAttribute("list", container.id); - } else if (this.options.srcType !== "dom") { - container.innerHTML = this.generateDatalistOptionsHtml(); - } - }; - - ////////////////////////////////////////////////////////////////////////////////// - AutocompleteProto.generateDatalistOptionsHtml = function() { - if (this.values.length) { - return "