{"version":3,"names":[],"mappings":"","sources":["vendor/autocomplete.js"],"sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.AutoComplete = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o @baptistedonaux\r\n */\r\nvar AutoComplete = (function () {\r\n // Constructor\r\n function AutoComplete(params, selector) {\r\n if (params === void 0) { params = {}; }\r\n if (selector === void 0) { selector = \"[data-autocomplete]\"; }\r\n if (Array.isArray(selector)) {\r\n selector.forEach(function (s) {\r\n new AutoComplete(params, s);\r\n });\r\n }\r\n else if (typeof selector == \"string\") {\r\n var elements = document.querySelectorAll(selector);\r\n Array.prototype.forEach.call(elements, function (input) {\r\n new AutoComplete(params, input);\r\n });\r\n }\r\n else {\r\n var specificParams = AutoComplete.merge(AutoComplete.defaults, params, {\r\n DOMResults: document.createElement(\"div\")\r\n });\r\n AutoComplete.prototype.create(specificParams, selector);\r\n return specificParams;\r\n }\r\n }\r\n AutoComplete.prototype.create = function (params, element) {\r\n params.Input = element;\r\n if (params.Input.nodeName.match(/^INPUT$/i) && (params.Input.hasAttribute(\"type\") === false || params.Input.getAttribute(\"type\").match(/^TEXT|SEARCH$/i))) {\r\n params.Input.setAttribute(\"autocomplete\", \"off\");\r\n params._Position(params);\r\n params.Input.parentNode.appendChild(params.DOMResults);\r\n params.$Listeners = {\r\n blur: params._Blur.bind(params),\r\n destroy: AutoComplete.prototype.destroy.bind(null, params),\r\n focus: params._Focus.bind(params),\r\n keyup: AutoComplete.prototype.event.bind(null, params, EventType.KEYUP),\r\n keydown: AutoComplete.prototype.event.bind(null, params, EventType.KEYDOWN),\r\n position: params._Position.bind(params)\r\n };\r\n for (var event in params.$Listeners) {\r\n params.Input.addEventListener(event, params.$Listeners[event]);\r\n }\r\n }\r\n };\r\n AutoComplete.prototype.getEventsByType = function (params, type) {\r\n var mappings = {};\r\n for (var key in params.KeyboardMappings) {\r\n var event = EventType.KEYUP;\r\n if (params.KeyboardMappings[key].Event !== undefined) {\r\n event = params.KeyboardMappings[key].Event;\r\n }\r\n if (event == type) {\r\n mappings[key] = params.KeyboardMappings[key];\r\n }\r\n }\r\n return mappings;\r\n };\r\n AutoComplete.prototype.event = function (params, type, event) {\r\n var eventIdentifier = function (condition) {\r\n if ((match === true && mapping.Operator == ConditionOperator.AND) || (match === false && mapping.Operator == ConditionOperator.OR)) {\r\n condition = AutoComplete.merge({\r\n Not: false\r\n }, condition);\r\n if (condition.hasOwnProperty(\"Is\")) {\r\n if (condition.Is == event.keyCode) {\r\n match = !condition.Not;\r\n }\r\n else {\r\n match = condition.Not;\r\n }\r\n }\r\n else if (condition.hasOwnProperty(\"From\") && condition.hasOwnProperty(\"To\")) {\r\n if (event.keyCode >= condition.From && event.keyCode <= condition.To) {\r\n match = !condition.Not;\r\n }\r\n else {\r\n match = condition.Not;\r\n }\r\n }\r\n }\r\n };\r\n for (var name in AutoComplete.prototype.getEventsByType(params, type)) {\r\n var mapping = AutoComplete.merge({\r\n Operator: ConditionOperator.AND\r\n }, params.KeyboardMappings[name]), match = ConditionOperator.AND == mapping.Operator;\r\n mapping.Conditions.forEach(eventIdentifier);\r\n if (match === true) {\r\n mapping.Callback.call(params, event);\r\n }\r\n }\r\n };\r\n AutoComplete.prototype.makeRequest = function (params, callback) {\r\n var propertyHttpHeaders = Object.getOwnPropertyNames(params.HttpHeaders), request = new XMLHttpRequest(), method = params._HttpMethod(), url = params._Url(), queryParams = params._Pre(), queryParamsStringify = params._QueryArg() + \"=\" + queryParams;\r\n if (method.match(/^GET$/i)) {\r\n if (url.indexOf(\"?\") !== -1) {\r\n url += \"&\" + queryParamsStringify;\r\n }\r\n else {\r\n url += \"?\" + queryParamsStringify;\r\n }\r\n }\r\n request.open(method, url, true);\r\n for (var i = propertyHttpHeaders.length - 1; i >= 0; i--) {\r\n request.setRequestHeader(propertyHttpHeaders[i], params.HttpHeaders[propertyHttpHeaders[i]]);\r\n }\r\n request.onreadystatechange = function () {\r\n if (request.readyState == 4 && request.status == 200) {\r\n params.$Cache[queryParams] = request.response;\r\n callback(request.response);\r\n }\r\n };\r\n return request;\r\n };\r\n AutoComplete.prototype.ajax = function (params, request, timeout) {\r\n if (timeout === void 0) { timeout = true; }\r\n if (params.$AjaxTimer) {\r\n window.clearTimeout(params.$AjaxTimer);\r\n }\r\n if (timeout === true) {\r\n params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);\r\n }\r\n else {\r\n if (params.Request) {\r\n params.Request.abort();\r\n }\r\n params.Request = request;\r\n params.Request.send(params._QueryArg() + \"=\" + params._Pre());\r\n }\r\n };\r\n AutoComplete.prototype.cache = function (params, callback) {\r\n var response = params._Cache(params._Pre());\r\n if (response === undefined) {\r\n var request = AutoComplete.prototype.makeRequest(params, callback);\r\n AutoComplete.prototype.ajax(params, request);\r\n }\r\n else {\r\n callback(response);\r\n }\r\n };\r\n AutoComplete.prototype.destroy = function (params) {\r\n for (var event in params.$Listeners) {\r\n params.Input.removeEventListener(event, params.$Listeners[event]);\r\n }\r\n params.DOMResults.parentNode.removeChild(params.DOMResults);\r\n };\r\n return AutoComplete;\r\n}());\r\nAutoComplete.merge = function () {\r\n var merge = {}, tmp;\r\n for (var i = 0; i < arguments.length; i++) {\r\n for (tmp in arguments[i]) {\r\n merge[tmp] = arguments[i][tmp];\r\n }\r\n }\r\n return merge;\r\n};\r\nAutoComplete.defaults = {\r\n Delay: 150,\r\n EmptyMessage: \"No result here\",\r\n Highlight: {\r\n getRegex: function (value) {\r\n return new RegExp(value, \"ig\");\r\n },\r\n transform: function (value) {\r\n return \"\" + value + \"\";\r\n }\r\n },\r\n HttpHeaders: {\r\n \"Content-type\": \"application/x-www-form-urlencoded\"\r\n },\r\n Limit: 0,\r\n MinChars: 0,\r\n HttpMethod: \"GET\",\r\n QueryArg: \"q\",\r\n Url: null,\r\n KeyboardMappings: {\r\n \"Enter\": {\r\n Conditions: [{\r\n Is: 13,\r\n Not: false\r\n }],\r\n Callback: function () {\r\n if (this.DOMResults.getAttribute(\"class\").indexOf(\"open\") != -1) {\r\n var liActive = this.DOMResults.querySelector(\"li.active\");\r\n if (liActive !== null) {\r\n this._Select(liActive);\r\n this.DOMResults.setAttribute(\"class\", \"autocomplete\");\r\n }\r\n }\r\n },\r\n Operator: ConditionOperator.AND,\r\n Event: EventType.KEYUP\r\n },\r\n \"KeyUpAndDown_down\": {\r\n Conditions: [{\r\n Is: 38,\r\n Not: false\r\n },\r\n {\r\n Is: 40,\r\n Not: false\r\n }],\r\n Callback: function (event) {\r\n event.preventDefault();\r\n },\r\n Operator: ConditionOperator.OR,\r\n Event: EventType.KEYDOWN\r\n },\r\n \"KeyUpAndDown_up\": {\r\n Conditions: [{\r\n Is: 38,\r\n Not: false\r\n },\r\n {\r\n Is: 40,\r\n Not: false\r\n }],\r\n Callback: function (event) {\r\n event.preventDefault();\r\n var first = this.DOMResults.querySelector(\"li:first-child:not(.locked)\"), last = this.DOMResults.querySelector(\"li:last-child:not(.locked)\"), active = this.DOMResults.querySelector(\"li.active\");\r\n if (active) {\r\n var currentIndex = Array.prototype.indexOf.call(active.parentNode.children, active), position = currentIndex + (event.keyCode - 39), lisCount = this.DOMResults.getElementsByTagName(\"li\").length;\r\n if (position < 0) {\r\n position = lisCount - 1;\r\n }\r\n else if (position >= lisCount) {\r\n position = 0;\r\n }\r\n active.classList.remove(\"active\");\r\n active.parentElement.children.item(position).classList.add(\"active\");\r\n }\r\n else if (last && event.keyCode == 38) {\r\n last.classList.add(\"active\");\r\n }\r\n else if (first) {\r\n first.classList.add(\"active\");\r\n }\r\n },\r\n Operator: ConditionOperator.OR,\r\n Event: EventType.KEYUP\r\n },\r\n \"AlphaNum\": {\r\n Conditions: [{\r\n Is: 13,\r\n Not: true\r\n }, {\r\n From: 35,\r\n To: 40,\r\n Not: true\r\n }],\r\n Callback: function () {\r\n var oldValue = this.Input.getAttribute(\"data-autocomplete-old-value\"), currentValue = this._Pre();\r\n if (currentValue !== \"\" && currentValue.length >= this._MinChars()) {\r\n if (!oldValue || currentValue != oldValue) {\r\n this.DOMResults.setAttribute(\"class\", \"autocomplete open\");\r\n }\r\n AutoComplete.prototype.cache(this, function (response) {\r\n this._Render(this._Post(response));\r\n this._Open();\r\n }.bind(this));\r\n }\r\n },\r\n Operator: ConditionOperator.AND,\r\n Event: EventType.KEYUP\r\n }\r\n },\r\n DOMResults: null,\r\n Request: null,\r\n Input: null,\r\n /**\r\n * Return the message when no result returns\r\n */\r\n _EmptyMessage: function () {\r\n var emptyMessage = \"\";\r\n if (this.Input.hasAttribute(\"data-autocomplete-empty-message\")) {\r\n emptyMessage = this.Input.getAttribute(\"data-autocomplete-empty-message\");\r\n }\r\n else if (this.EmptyMessage !== false) {\r\n emptyMessage = this.EmptyMessage;\r\n }\r\n else {\r\n emptyMessage = \"\";\r\n }\r\n return emptyMessage;\r\n },\r\n /**\r\n * Returns the maximum number of results\r\n */\r\n _Limit: function () {\r\n var limit = this.Input.getAttribute(\"data-autocomplete-limit\");\r\n if (isNaN(limit) || limit === null) {\r\n return this.Limit;\r\n }\r\n return parseInt(limit, 10);\r\n },\r\n /**\r\n * Returns the minimum number of characters entered before firing ajax\r\n */\r\n _MinChars: function () {\r\n var minchars = this.Input.getAttribute(\"data-autocomplete-minchars\");\r\n if (isNaN(minchars) || minchars === null) {\r\n return this.MinChars;\r\n }\r\n return parseInt(minchars, 10);\r\n },\r\n /**\r\n * Apply transformation on labels response\r\n */\r\n _Highlight: function (label) {\r\n return label.replace(this.Highlight.getRegex(this._Pre()), this.Highlight.transform);\r\n },\r\n /**\r\n * Returns the HHTP method to use\r\n */\r\n _HttpMethod: function () {\r\n if (this.Input.hasAttribute(\"data-autocomplete-method\")) {\r\n return this.Input.getAttribute(\"data-autocomplete-method\");\r\n }\r\n return this.HttpMethod;\r\n },\r\n /**\r\n * Returns the query param to use\r\n */\r\n _QueryArg: function () {\r\n if (this.Input.hasAttribute(\"data-autocomplete-param-name\")) {\r\n return this.Input.getAttribute(\"data-autocomplete-param-name\");\r\n }\r\n return this.QueryArg;\r\n },\r\n /**\r\n * Returns the URL to use for AJAX request\r\n */\r\n _Url: function () {\r\n if (this.Input.hasAttribute(\"data-autocomplete\")) {\r\n return this.Input.getAttribute(\"data-autocomplete\");\r\n }\r\n return this.Url;\r\n },\r\n /**\r\n * Manage the close\r\n */\r\n _Blur: function (now) {\r\n if (now === void 0) { now = false; }\r\n if (now) {\r\n this.DOMResults.setAttribute(\"class\", \"autocomplete\");\r\n }\r\n else {\r\n var params = this;\r\n setTimeout(function () {\r\n params._Blur(true);\r\n }, 150);\r\n }\r\n },\r\n /**\r\n * Manage the cache\r\n */\r\n _Cache: function (value) {\r\n return this.$Cache[value];\r\n },\r\n /**\r\n * Manage the open\r\n */\r\n _Focus: function () {\r\n var oldValue = this.Input.getAttribute(\"data-autocomplete-old-value\");\r\n if ((!oldValue || this.Input.value != oldValue) && this._MinChars() <= this.Input.value.length) {\r\n this.DOMResults.setAttribute(\"class\", \"autocomplete open\");\r\n }\r\n },\r\n /**\r\n * Bind all results item if one result is opened\r\n */\r\n _Open: function () {\r\n var params = this;\r\n Array.prototype.forEach.call(this.DOMResults.getElementsByTagName(\"li\"), function (li) {\r\n if (li.getAttribute(\"class\") != \"locked\") {\r\n li.onclick = function () {\r\n params._Select(li);\r\n };\r\n }\r\n });\r\n },\r\n /**\r\n * Position the results HTML element\r\n */\r\n _Position: function () {\r\n this.DOMResults.setAttribute(\"class\", \"autocomplete\");\r\n this.DOMResults.setAttribute(\"style\", \"top:\" + (this.Input.offsetTop + this.Input.offsetHeight) + \"px;left:\" + this.Input.offsetLeft + \"px;width:\" + this.Input.clientWidth + \"px;\");\r\n },\r\n /**\r\n * Execute the render of results DOM element\r\n */\r\n _Render: function (response) {\r\n var ul;\r\n if (typeof response == \"string\") {\r\n ul = this._RenderRaw(response);\r\n }\r\n else {\r\n ul = this._RenderResponseItems(response);\r\n }\r\n if (this.DOMResults.hasChildNodes()) {\r\n this.DOMResults.removeChild(this.DOMResults.childNodes[0]);\r\n }\r\n this.DOMResults.appendChild(ul);\r\n },\r\n /**\r\n * ResponseItems[] rendering\r\n */\r\n _RenderResponseItems: function (response) {\r\n var ul = document.createElement(\"ul\"), li = document.createElement(\"li\"), limit = this._Limit();\r\n // Order\r\n if (limit < 0) {\r\n response = response.reverse();\r\n }\r\n else if (limit === 0) {\r\n limit = response.length;\r\n }\r\n for (var item = 0; item < Math.min(Math.abs(limit), response.length); item++) {\r\n li.innerHTML = response[item].Label;\r\n li.setAttribute(\"data-autocomplete-value\", response[item].Value);\r\n ul.appendChild(li);\r\n li = document.createElement(\"li\");\r\n }\r\n return ul;\r\n },\r\n /**\r\n * string response rendering (RAW HTML)\r\n */\r\n _RenderRaw: function (response) {\r\n var ul = document.createElement(\"ul\"), li = document.createElement(\"li\");\r\n if (response.length > 0) {\r\n this.DOMResults.innerHTML = response;\r\n }\r\n else {\r\n var emptyMessage = this._EmptyMessage();\r\n if (emptyMessage !== \"\") {\r\n li.innerHTML = emptyMessage;\r\n li.setAttribute(\"class\", \"locked\");\r\n ul.appendChild(li);\r\n }\r\n }\r\n return ul;\r\n },\r\n /**\r\n * Deal with request response\r\n */\r\n _Post: function (response) {\r\n try {\r\n var returnResponse = [];\r\n //JSON return\r\n var json = JSON.parse(response);\r\n if (Object.keys(json).length === 0) {\r\n return \"\";\r\n }\r\n if (Array.isArray(json)) {\r\n for (var i = 0; i < Object.keys(json).length; i++) {\r\n returnResponse[returnResponse.length] = { \"Value\": json[i], \"Label\": this._Highlight(json[i]) };\r\n }\r\n }\r\n else {\r\n for (var value in json) {\r\n returnResponse.push({\r\n \"Value\": value,\r\n \"Label\": this._Highlight(json[value])\r\n });\r\n }\r\n }\r\n return returnResponse;\r\n }\r\n catch (event) {\r\n //HTML return\r\n return response;\r\n }\r\n },\r\n /**\r\n * Return the autocomplete value to send (before request)\r\n */\r\n _Pre: function () {\r\n return this.Input.value;\r\n },\r\n /**\r\n * Choice one result item\r\n */\r\n _Select: function (item) {\r\n if (item.hasAttribute(\"data-autocomplete-value\")) {\r\n this.Input.value = item.getAttribute(\"data-autocomplete-value\");\r\n }\r\n else {\r\n this.Input.value = item.innerHTML;\r\n }\r\n this.Input.setAttribute(\"data-autocomplete-old-value\", this.Input.value);\r\n },\r\n _SelectFirst: function (item) {\r\n if (this.DOMResults.getAttribute(\"class\").indexOf(\"open\") != -1) {\r\n var liActive = this.DOMResults.querySelector(\"li.active\");\r\n if (liActive !== null) {\r\n this._Select(liActive);\r\n this.DOMResults.setAttribute(\"class\", \"autocomplete\");\r\n }\r\n }\r\n },\r\n $AjaxTimer: null,\r\n $Cache: {},\r\n $Listeners: {}\r\n};\r\nmodule.exports = AutoComplete;\r\n\r\n},{}]},{},[1])(1)\r\n});\r\n"],"file":"autocomplete.js"}