-
Notifications
You must be signed in to change notification settings - Fork 394
/
autocomplete.min.js.map
1 lines (1 loc) · 28.3 KB
/
autocomplete.min.js.map
1
{"version":3,"file":"autocomplete.min.js","sources":["autocomplete.ts"],"sourcesContent":["/**\n * Copyright (c) 2016 Denys Krasnoshchok\n * \n * Homepage: https://smartscheduling.com/en/documentation/autocomplete\n * Source: https://github.com/kraaden/autocomplete\n * \n * MIT License\n */\n\nexport const enum EventTrigger {\n Keyboard = 0,\n Focus = 1,\n Mouse = 2,\n /**\n * Fetch is triggered manually by calling `fetch` function returned in `AutocompleteResult`\n */\n Manual = 3\n}\n\nexport interface AutocompleteItem {\n label?: string;\n group?: string;\n}\n\nexport interface AutocompleteEvent<T extends Event> {\n /**\n * Native event object passed by browser to the event handler\n */\n event: T;\n\n /**\n * Fetch data and display autocomplete\n */\n fetch: () => void;\n}\n\nexport interface AutocompleteSettings<T extends AutocompleteItem> {\n /**\n * Autocomplete will be attached to this element.\n */\n input: HTMLInputElement | HTMLTextAreaElement;\n\n /**\n * Provide your own container for the widget.\n * If not specified, a new DIV element will be created.\n */\n container?: HTMLDivElement;\n\n /**\n * This method allows you to override the default rendering function for items.\n * It must return a DIV element or undefined to skip rendering.\n */\n render?: (item: T, currentValue: string, index: number) => HTMLDivElement | undefined;\n\n /**\n * This method allows you to override the default rendering function for item groups.\n * It must return a DIV element or undefined to skip rendering.\n */\n renderGroup?: (name: string, currentValue: string) => HTMLDivElement | undefined;\n\n /**\n * If specified, the autocomplete DOM element will have this class assigned to it.\n */\n className?: string;\n\n /**\n * Specify the minimum text length required to show autocomplete.\n */\n minLength?: number;\n\n /**\n * The message that will be showed when there are no suggestions that match the entered value.\n */\n emptyMsg?: string;\n\n /**\n * This method will be called when user choose an item in autocomplete. The selected item will be passed as the first parameter.\n */\n onSelect: (item: T, input: HTMLInputElement | HTMLTextAreaElement) => void;\n\n /**\n * Show autocomplete on focus event. Focus event will ignore the `minLength` property and will always call `fetch`.\n */\n showOnFocus?: boolean;\n\n /**\n * This method will be called to prepare suggestions and then pass them to autocomplete.\n * @param {string} text - text in the input field\n * @param {(items: T[] | false) => void} update - a callback function that must be called after suggestions are prepared\n * @param {EventTrigger} trigger - type of the event that triggered the fetch\n * @param {number} cursorPos - position of the cursor in the input field\n */\n fetch: (text: string, update: (items: T[] | false) => void, trigger: EventTrigger, cursorPos: number) => void;\n\n /**\n * Enforces that the fetch function will only be called once within the specified time frame (in milliseconds) and\n * delays execution. This prevents flooding your server with AJAX requests.\n */\n debounceWaitMs?: number;\n\n /**\n * Callback for additional autocomplete customization\n * @param {HTMLInputElement | HTMLTextAreaElement} input - input box associated with autocomplete\n * @param {ClientRect | DOMRect} inputRect - size of the input box and its position relative to the viewport\n * @param {HTMLDivElement} container - container with suggestions\n * @param {number} maxHeight - max height that can be used by autocomplete\n */\n customize?: (input: HTMLInputElement | HTMLTextAreaElement, inputRect: ClientRect | DOMRect, container: HTMLDivElement, maxHeight: number) => void;\n\n /**\n * Prevents automatic form submit when ENTER is pressed\n */\n preventSubmit?: boolean;\n\n /**\n * Prevents the first item in the list from being selected automatically. This option allows you\n * to submit a custom text by pressing ENTER even when autocomplete is displayed.\n */\n disableAutoSelect?: boolean;\n\n /**\n * Provide your keyup event handler to display autocomplete when a key is pressed that doesn't modify the content. You can also perform some additional actions.\n */\n keyup?: (e: AutocompleteEvent<KeyboardEvent>) => void;\n\n /**\n * Allows to display autocomplete on mouse clicks or perform some additional actions.\n */\n click?: (e: AutocompleteEvent<MouseEvent>) => void;\n}\n\nexport interface AutocompleteResult {\n /**\n * Remove event handlers, DOM elements and ARIA/accessibility attributes created by the widget.\n */\n destroy: () => void;\n\n /**\n * This function allows to manually start data fetching and display autocomplete. Note that\n * it does not automatically place focus on the input field, so you may need to do so manually\n * in certain situations.\n */\n fetch: () => void;\n}\n\nexport default function autocomplete<T extends AutocompleteItem>(settings: AutocompleteSettings<T>): AutocompleteResult {\n\n // just an alias to minimize JS file size\n const doc = document;\n\n const container: HTMLDivElement = settings.container || doc.createElement('div');\n container.id = container.id || 'autocomplete-' + uid();\n const containerStyle = container.style;\n const debounceWaitMs = settings.debounceWaitMs || 0;\n const preventSubmit = settings.preventSubmit || false;\n const disableAutoSelect = settings.disableAutoSelect || false;\n const customContainerParent = container.parentElement;\n\n let items: T[] = [];\n let inputValue = '';\n let minLen = 2;\n const showOnFocus = settings.showOnFocus;\n let selected: T | undefined;\n let fetchCounter = 0;\n let debounceTimer: number | undefined;\n let destroyed = false;\n let suppressAutocomplete = false;\n\n if (settings.minLength !== undefined) {\n minLen = settings.minLength;\n }\n\n if (!settings.input) {\n throw new Error('input undefined');\n }\n\n const input: HTMLInputElement | HTMLTextAreaElement = settings.input;\n\n container.className = 'autocomplete ' + (settings.className || '');\n container.setAttribute('role', 'listbox');\n\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', container.id);\n input.setAttribute('aria-owns', container.id);\n input.setAttribute('aria-activedescendant', '');\n input.setAttribute('aria-haspopup', 'listbox');\n\n // IOS implementation for fixed positioning has many bugs, so we will use absolute positioning\n containerStyle.position = 'absolute';\n\n /**\n * Generate a very complex textual ID that greatly reduces the chance of a collision with another ID or text.\n */\n function uid(): string {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n }\n\n /**\n * Detach the container from DOM\n */\n function detach() {\n const parent = container.parentNode;\n if (parent) {\n parent.removeChild(container);\n }\n }\n\n /**\n * Clear debouncing timer if assigned\n */\n function clearDebounceTimer() {\n if (debounceTimer) {\n window.clearTimeout(debounceTimer);\n }\n }\n\n /**\n * Attach the container to DOM\n */\n function attach() {\n if (!container.parentNode) {\n (customContainerParent || doc.body).appendChild(container);\n }\n }\n\n /**\n * Check if container for autocomplete is displayed\n */\n function containerDisplayed(): boolean {\n return !!container.parentNode;\n }\n\n /**\n * Clear autocomplete state and hide container\n */\n function clear() {\n // prevent the update call if there are pending AJAX requests\n fetchCounter++;\n\n items = [];\n inputValue = '';\n selected = undefined;\n input.setAttribute('aria-activedescendant', '');\n input.setAttribute('aria-expanded', 'false');\n detach();\n }\n\n /**\n * Update autocomplete position\n */\n function updatePosition() {\n if (!containerDisplayed()) {\n return;\n }\n\n input.setAttribute('aria-expanded', 'true');\n\n containerStyle.height = 'auto';\n containerStyle.width = input.offsetWidth + 'px';\n\n let maxHeight = 0;\n let inputRect: DOMRect | undefined;\n\n function calc() {\n const docEl = doc.documentElement as HTMLElement;\n const clientTop = docEl.clientTop || doc.body.clientTop || 0;\n const clientLeft = docEl.clientLeft || doc.body.clientLeft || 0;\n const scrollTop = window.pageYOffset || docEl.scrollTop;\n const scrollLeft = window.pageXOffset || docEl.scrollLeft;\n\n inputRect = input.getBoundingClientRect();\n\n const top = inputRect.top + input.offsetHeight + scrollTop - clientTop;\n const left = inputRect.left + scrollLeft - clientLeft;\n\n containerStyle.top = top + 'px';\n containerStyle.left = left + 'px';\n\n maxHeight = window.innerHeight - (inputRect.top + input.offsetHeight);\n\n if (maxHeight < 0) {\n maxHeight = 0;\n }\n\n containerStyle.top = top + 'px';\n containerStyle.bottom = '';\n containerStyle.left = left + 'px';\n containerStyle.maxHeight = maxHeight + 'px';\n }\n\n // the calc method must be called twice, otherwise the calculation may be wrong on resize event (chrome browser)\n calc();\n calc();\n\n if (settings.customize && inputRect) {\n settings.customize(input, inputRect, container, maxHeight);\n }\n }\n\n /**\n * Redraw the autocomplete div element with suggestions\n */\n function update() {\n\n container.innerHTML = '';\n input.setAttribute('aria-activedescendant', '');\n\n // function for rendering autocomplete suggestions\n let render = function (item: T, _: string, __: number): HTMLDivElement | undefined {\n const itemElement = doc.createElement('div');\n itemElement.textContent = item.label || '';\n return itemElement;\n };\n if (settings.render) {\n render = settings.render;\n }\n\n // function to render autocomplete groups\n let renderGroup = function (groupName: string, _: string): HTMLDivElement | undefined {\n const groupDiv = doc.createElement('div');\n groupDiv.textContent = groupName;\n return groupDiv;\n };\n if (settings.renderGroup) {\n renderGroup = settings.renderGroup;\n }\n\n const fragment = doc.createDocumentFragment();\n let prevGroup = uid();\n\n items.forEach(function (item: T, index: number): void {\n if (item.group && item.group !== prevGroup) {\n prevGroup = item.group;\n const groupDiv = renderGroup(item.group, inputValue);\n if (groupDiv) {\n groupDiv.className += ' group';\n fragment.appendChild(groupDiv);\n }\n }\n const div = render(item, inputValue, index);\n if (div) {\n div.id = `${container.id}_${index}`;\n div.setAttribute('role', 'option');\n div.addEventListener('click', function (ev: MouseEvent): void {\n suppressAutocomplete = true;\n try {\n settings.onSelect(item, input);\n } finally {\n suppressAutocomplete = false;\n }\n clear();\n ev.preventDefault();\n ev.stopPropagation();\n });\n if (item === selected) {\n div.className += ' selected';\n div.setAttribute('aria-selected', 'true');\n input.setAttribute('aria-activedescendant', div.id);\n }\n fragment.appendChild(div);\n }\n });\n container.appendChild(fragment);\n if (items.length < 1) {\n if (settings.emptyMsg) {\n const empty = doc.createElement('div');\n empty.id = `${container.id}_${uid()}`;\n empty.className = 'empty';\n empty.textContent = settings.emptyMsg;\n container.appendChild(empty);\n input.setAttribute('aria-activedescendant', empty.id);\n } else {\n clear();\n return;\n }\n }\n\n attach();\n updatePosition();\n\n updateScroll();\n }\n\n function updateIfDisplayed() {\n if (containerDisplayed()) {\n update();\n }\n }\n\n function resizeEventHandler() {\n updateIfDisplayed();\n }\n\n function scrollEventHandler(e: Event) {\n if (e.target !== container) {\n updateIfDisplayed();\n } else {\n e.preventDefault();\n }\n }\n\n function inputEventHandler() {\n if (!suppressAutocomplete) {\n fetch(EventTrigger.Keyboard);\n }\n }\n\n /**\n * Automatically move scroll bar if selected item is not visible\n */\n function updateScroll() {\n const elements = container.getElementsByClassName('selected');\n if (elements.length > 0) {\n let element = elements[0] as HTMLDivElement;\n\n // make group visible\n const previous = element.previousElementSibling as HTMLDivElement;\n if (previous && previous.className.indexOf('group') !== -1 && !previous.previousElementSibling) {\n element = previous;\n }\n\n if (element.offsetTop < container.scrollTop) {\n container.scrollTop = element.offsetTop;\n } else {\n const selectBottom = element.offsetTop + element.offsetHeight;\n const containerBottom = container.scrollTop + container.offsetHeight;\n if (selectBottom > containerBottom) {\n container.scrollTop += selectBottom - containerBottom;\n }\n }\n }\n }\n\n function selectPreviousSuggestion() {\n const index = items.indexOf(selected!);\n\n selected = index === -1\n ? undefined\n : items[(index + items.length - 1) % items.length];\n }\n\n function selectNextSuggestion() {\n const index = items.indexOf(selected!);\n\n selected = items.length < 1\n ? undefined\n : index === -1\n ? items[0]\n : items[(index + 1) % items.length];\n }\n\n function handleArrowAndEscapeKeys(ev: KeyboardEvent, key: 'ArrowUp' | 'ArrowDown' | 'Escape') {\n const containerIsDisplayed = containerDisplayed();\n\n if (key === 'Escape') {\n clear();\n } else {\n if (!containerIsDisplayed || items.length < 1) {\n return;\n }\n key === 'ArrowUp'\n ? selectPreviousSuggestion()\n : selectNextSuggestion();\n update();\n }\n\n ev.preventDefault();\n\n if (containerIsDisplayed) {\n ev.stopPropagation();\n }\n }\n\n function handleEnterKey(ev: KeyboardEvent) {\n if (selected) {\n suppressAutocomplete = true;\n try {\n settings.onSelect(selected, input);\n } finally {\n suppressAutocomplete = false;\n }\n clear();\n }\n\n if (preventSubmit) {\n ev.preventDefault();\n }\n }\n\n function keydownEventHandler(ev: KeyboardEvent) {\n const key = ev.key;\n\n switch (key) {\n case 'ArrowUp':\n case 'ArrowDown':\n case 'Escape':\n handleArrowAndEscapeKeys(ev, key);\n break;\n case 'Enter':\n handleEnterKey(ev);\n break;\n default:\n break;\n }\n }\n\n function focusEventHandler() {\n if (showOnFocus) {\n fetch(EventTrigger.Focus);\n }\n }\n\n function fetch(trigger: EventTrigger) {\n if (input.value.length >= minLen || trigger === EventTrigger.Focus) {\n clearDebounceTimer();\n debounceTimer = window.setTimeout(\n () => startFetch(input.value, trigger, input.selectionStart || 0),\n trigger === EventTrigger.Keyboard || trigger === EventTrigger.Mouse ? debounceWaitMs : 0);\n } else {\n clear();\n }\n }\n\n function startFetch(inputText: string, trigger: EventTrigger, cursorPos: number) {\n if (destroyed) return;\n const savedFetchCounter = ++fetchCounter;\n settings.fetch(inputText, function (elements: T[] | false): void {\n if (fetchCounter === savedFetchCounter && elements) {\n items = elements;\n inputValue = inputText;\n selected = (items.length < 1 || disableAutoSelect) ? undefined : items[0];\n update();\n }\n }, trigger, cursorPos);\n }\n\n function keyupEventHandler(e: KeyboardEvent) {\n if (settings.keyup) {\n settings.keyup({\n event: e,\n fetch: () => fetch(EventTrigger.Keyboard)\n });\n return;\n }\n\n if (!containerDisplayed() && e.key === 'ArrowDown') {\n fetch(EventTrigger.Keyboard);\n }\n }\n\n function clickEventHandler(e: MouseEvent) {\n settings.click && settings.click({\n event: e,\n fetch: () => fetch(EventTrigger.Mouse)\n });\n }\n\n function blurEventHandler() {\n // when an item is selected by mouse click, the blur event will be initiated before the click event and remove DOM elements,\n // so that the click event will never be triggered. In order to avoid this issue, DOM removal should be delayed.\n setTimeout(() => {\n if (doc.activeElement !== input) {\n clear();\n }\n }, 200);\n }\n\n function manualFetch() {\n startFetch(input.value, EventTrigger.Manual, input.selectionStart || 0);\n }\n\n /**\n * Fixes #26: on long clicks focus will be lost and onSelect method will not be called\n */\n container.addEventListener('mousedown', function (evt: Event) {\n evt.stopPropagation();\n evt.preventDefault();\n });\n\n /**\n * Fixes #30: autocomplete closes when scrollbar is clicked in IE\n * See: https://stackoverflow.com/a/9210267/13172349\n */\n container.addEventListener('focus', () => input.focus());\n\n /**\n * This function will remove DOM elements and clear event handlers\n */\n function destroy() {\n input.removeEventListener('focus', focusEventHandler);\n input.removeEventListener('keyup', keyupEventHandler as EventListenerOrEventListenerObject)\n input.removeEventListener('click', clickEventHandler as EventListenerOrEventListenerObject)\n input.removeEventListener('keydown', keydownEventHandler as EventListenerOrEventListenerObject);\n input.removeEventListener('input', inputEventHandler as EventListenerOrEventListenerObject);\n input.removeEventListener('blur', blurEventHandler);\n window.removeEventListener('resize', resizeEventHandler);\n doc.removeEventListener('scroll', scrollEventHandler, true);\n input.removeAttribute('role');\n input.removeAttribute('aria-expanded');\n input.removeAttribute('aria-autocomplete');\n input.removeAttribute('aria-controls');\n input.removeAttribute('aria-activedescendant');\n input.removeAttribute('aria-owns');\n input.removeAttribute('aria-haspopup');\n clearDebounceTimer();\n clear();\n destroyed = true;\n }\n\n // setup event handlers\n input.addEventListener('keyup', keyupEventHandler as EventListenerOrEventListenerObject);\n input.addEventListener('click', clickEventHandler as EventListenerOrEventListenerObject);\n input.addEventListener('keydown', keydownEventHandler as EventListenerOrEventListenerObject);\n input.addEventListener('input', inputEventHandler as EventListenerOrEventListenerObject);\n input.addEventListener('blur', blurEventHandler);\n input.addEventListener('focus', focusEventHandler);\n window.addEventListener('resize', resizeEventHandler);\n doc.addEventListener('scroll', scrollEventHandler, true);\n\n return {\n destroy,\n fetch: manualFetch\n };\n}\n"],"names":["settings","doc","document","container","createElement","id","uid","selected","debounceTimer","containerStyle","style","debounceWaitMs","preventSubmit","disableAutoSelect","customContainerParent","parentElement","items","inputValue","minLen","showOnFocus","fetchCounter","destroyed","suppressAutocomplete","undefined","minLength","input","Error","Date","now","toString","Math","random","substring","clearDebounceTimer","window","clearTimeout","containerDisplayed","parentNode","clear","parent","setAttribute","removeChild","update","innerHTML","render","item","_","__","itemElement","textContent","label","renderGroup","groupName","groupDiv","fragment","createDocumentFragment","prevGroup","forEach","index","group","className","appendChild","div","addEventListener","ev","onSelect","preventDefault","stopPropagation","length","emptyMsg","empty","body","height","width","offsetWidth","inputRect","maxHeight","calc","customize","docEl","documentElement","clientTop","clientLeft","scrollTop","pageYOffset","scrollLeft","pageXOffset","top","getBoundingClientRect","offsetHeight","left","innerHeight","bottom","updatePosition","elements","getElementsByClassName","element","previous","previousElementSibling","indexOf","offsetTop","selectBottom","containerBottom","updateScroll","updateIfDisplayed","resizeEventHandler","scrollEventHandler","e","target","inputEventHandler","fetch","handleArrowAndEscapeKeys","key","containerIsDisplayed","selectNextSuggestion","keydownEventHandler","handleEnterKey","focusEventHandler","trigger","value","setTimeout","startFetch","selectionStart","inputText","cursorPos","savedFetchCounter","keyupEventHandler","keyup","event","clickEventHandler","click","blurEventHandler","activeElement","position","evt","focus","destroy","removeEventListener","removeAttribute"],"mappings":"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"}