UNPKG

@vsblty/ng-autocomplete

Version:

A fork of Angular autocomplete

1 lines 58.4 kB
{"version":3,"file":"vsblty-ng-autocomplete.mjs","sources":["../../../projects/autocomplete-lib/src/lib/highlight.pipe.ts","../../../projects/autocomplete-lib/src/lib/autocomplete.component.ts","../../../projects/autocomplete-lib/src/lib/autocomplete.component.html","../../../projects/autocomplete-lib/src/lib/autocomplete-lib.module.ts","../../../projects/autocomplete-lib/src/public_api.ts","../../../projects/autocomplete-lib/src/vsblty-ng-autocomplete.ts"],"sourcesContent":["import {Pipe, PipeTransform} from '@angular/core';\n\n@Pipe({\n name: 'highlight'\n})\nexport class HighlightPipe implements PipeTransform {\n transform(text: any, search: any, searchKeyword?: any): any {\n let pattern = search.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, '\\\\$&');\n pattern = pattern.split(' ').filter((t) => {\n return t.length > 0;\n }).join('|');\n const regex = new RegExp(pattern, 'gi');\n\n if (!search) {\n return text;\n }\n\n if (searchKeyword) {\n const name = text[searchKeyword].replace(regex, (match) => `<b>${match}</b>`);\n // copy original object\n const textCopied = {...text};\n // set bold value into searchKeyword of copied object\n textCopied[searchKeyword] = name;\n return textCopied;\n } else {\n return search ? text.replace(regex, (match) => `<b>${match}</b>`) : text;\n }\n }\n}\n","import {\n AfterViewInit,\n Component, ContentChild,\n ElementRef,\n EventEmitter, forwardRef,\n Input, OnChanges,\n OnInit,\n Output,\n Renderer2,\n SimpleChanges, TemplateRef,\n ViewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { fromEvent, Observable } from 'rxjs';\nimport { debounceTime, filter, map } from 'rxjs/operators';\n\n/**\n * Keyboard events\n */\nconst isArrowUp = keyCode => keyCode === 38;\nconst isArrowDown = keyCode => keyCode === 40;\nconst isArrowUpDown = keyCode => isArrowUp(keyCode) || isArrowDown(keyCode);\nconst isEnter = keyCode => keyCode === 13;\nconst isBackspace = keyCode => keyCode === 8;\nconst isDelete = keyCode => keyCode === 46;\nconst isESC = keyCode => keyCode === 27;\nconst isTab = keyCode => keyCode === 9;\n\n\n@Component({\n selector: 'ng-autocomplete',\n templateUrl: './autocomplete.component.html',\n styleUrls: ['./autocomplete.component.scss'],\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => AutocompleteComponent),\n multi: true\n }\n ],\n encapsulation: ViewEncapsulation.None,\n host: {\n '(document:click)': 'handleClick($event)',\n 'class': 'ng-autocomplete'\n },\n})\n\nexport class AutocompleteComponent implements OnInit, OnChanges, AfterViewInit, ControlValueAccessor {\n @ViewChild('searchInput') searchInput: ElementRef; // input element\n @ViewChild('filteredListElement') filteredListElement: ElementRef; // element of items\n @ViewChild('historyListElement') historyListElement: ElementRef; // element of history items\n\n inputKeyUp$: Observable<any>;\n inputKeyDown$: Observable<any>;\n\n public query = ''; // search query\n public filteredList = []; // list of items\n public historyList = []; // list of history items\n public isHistoryListVisible = true;\n public elementRef;\n public selectedIdx = -1;\n public toHighlight = '';\n public notFound = false;\n public isFocused = false;\n public isOpen = false;\n public isScrollToEnd = false;\n public overlay = false;\n private manualOpen = undefined;\n private manualClose = undefined;\n\n\n // @Inputs\n /**\n * Data of items list.\n * It can be array of strings or array of objects.\n */\n @Input() public data: Array<any> = [];\n @Input() public searchKeyword: string; // keyword to filter the list\n @Input() public placeholder: string = '';\n @Input() public heading: string = '';\n @Input() public initialValue: any;\n /**\n * History identifier of history list\n * When valid history identifier is given, then component stores selected item to local storage of user's browser.\n * If it is null then history is hidden.\n * History list is visible if at least one history item is stored.\n */\n @Input() public historyIdentifier: string;\n /**\n * Heading text of history list.\n * If it is null then history heading is hidden.\n */\n @Input() public historyHeading: string = 'Recently selected';\n @Input() public historyListMaxNumber: number = 15; // maximum number of items in the history list.\n @Input() public notFoundText: string = 'Not found'; // set custom text when filter returns empty result\n @Input() public isLoading: boolean; // loading mask\n @Input() public debounceTime: number; // delay time while typing\n @Input() public disabled: boolean; // input disable/enable\n /**\n * The minimum number of characters the user must type before a search is performed.\n */\n @Input() public minQueryLength: number = 1;\n\n /**\n * Focus first item in the list\n */\n @Input() public focusFirst: boolean = false;\n\n /**\n * Custom filter function\n */\n @Input() public customFilter: (items: any[], query: string) => any[];\n\n /**\n * Custom result render function\n * @param value - selected value to be rendered inside input field\n */\n @Input() public selectedValueRender: (value: any) => string;\n\n // @Output events\n /** Event that is emitted whenever an item from the list is selected. */\n @Output() selected: EventEmitter<any> = new EventEmitter<any>();\n\n /** Event that is emitted whenever an input is changed. */\n @Output() inputChanged: EventEmitter<any> = new EventEmitter<any>();\n\n /** Event that is emitted whenever an input is focused. */\n @Output() readonly inputFocused: EventEmitter<void> = new EventEmitter<void>();\n\n /** Event that is emitted whenever an input is cleared. */\n @Output() readonly inputCleared: EventEmitter<void> = new EventEmitter<void>();\n\n /** Event that is emitted when the autocomplete panel is opened. */\n @Output() readonly opened: EventEmitter<void> = new EventEmitter<void>();\n\n /** Event that is emitted when the autocomplete panel is closed. */\n @Output() readonly closed: EventEmitter<void> = new EventEmitter<void>();\n\n /** Event that is emitted when scrolled to the end of items. */\n @Output() readonly scrolledToEnd: EventEmitter<void> = new EventEmitter<void>();\n\n\n // Custom templates\n @Input() itemTemplate !: TemplateRef<any>;\n @Input() notFoundTemplate !: TemplateRef<any>;\n @ContentChild(TemplateRef) customTemplate !: TemplateRef<any>;\n\n /**\n * Propagates new value when model changes\n */\n propagateChange: any = () => {\n };\n\n onTouched: any = () => {\n };\n\n /**\n * Writes a new value from the form model into the view,\n * Updates model\n */\n writeValue(value: any = '') {\n this.query = this.selectedValueRender !== undefined ? this.selectedValueRender(value) : this.defaultWriteValue(value);\n }\n\n private defaultWriteValue(value: any) {\n return value && !this.isTypeString(value) ? value[this.searchKeyword] : value;\n }\n\n /**\n * Registers a handler that is called when something in the view has changed\n */\n registerOnChange(fn) {\n this.propagateChange = fn;\n }\n\n /**\n * Registers a handler specifically for when a control receives a touch event\n */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /**\n * Event that is called when the value of an input element is changed\n */\n onChange(event) {\n this.propagateChange(event.target.value);\n }\n\n constructor(elementRef: ElementRef, private renderer: Renderer2) {\n this.elementRef = elementRef;\n }\n\n /**\n * Event that is called when the control status changes to or from DISABLED\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n }\n\n ngOnInit(): void {\n }\n\n ngAfterViewInit() {\n this.initEventStream();\n this.handleScroll();\n }\n\n /**\n * Set initial value\n * @param value\n */\n public setInitialValue(value: any) {\n if (this.initialValue) {\n this.select(value);\n }\n }\n\n /**\n * Update search results\n */\n ngOnChanges(changes: SimpleChanges): void {\n this.setInitialValue(this.initialValue);\n if (\n changes &&\n changes.data &&\n Array.isArray(changes.data.currentValue)\n ) {\n this.handleItemsChange();\n if (!changes.data.firstChange && this.isFocused) {\n this.handleOpen();\n }\n }\n }\n\n /**\n * Items change\n */\n public handleItemsChange() {\n this.isScrollToEnd = false;\n if (!this.isOpen) {\n return;\n }\n\n this.filteredList = this.data;\n this.notFound = !this.filteredList || this.filteredList.length === 0;\n\n // Filter list when updating data and panel is open\n if (this.isOpen) {\n this.filterList();\n }\n }\n\n /**\n * Filter data\n */\n public filterList() {\n this.selectedIdx = -1;\n this.initSearchHistory();\n if (this.query != null && this.data) {\n this.toHighlight = this.query;\n this.filteredList = this.customFilter !== undefined ? this.customFilter([...this.data], this.query) : this.defaultFilterFunction();\n // If [focusFirst]=\"true\" automatically focus the first match\n if (this.filteredList.length > 0 && this.focusFirst) {\n this.selectedIdx = 0;\n }\n } else {\n this.notFound = false;\n }\n }\n\n /**\n * Default filter function, used unless customFilter is provided\n */\n public defaultFilterFunction(): any[] {\n return this.data.filter((item: any) => {\n if (typeof item === 'string') {\n // string logic, check equality of strings\n return item.toLowerCase().indexOf(this.query.toLowerCase()) > -1;\n } else if (typeof item === 'object' && item instanceof Object) {\n // object logic, check property equality\n return item[this.searchKeyword] ? item[this.searchKeyword].toLowerCase().indexOf(this.query.toLowerCase()) > -1 : \"\";\n }\n });\n }\n\n\n /**\n * Check if item is a string in the list.\n * @param item\n */\n isTypeString(item) {\n return typeof item === 'string';\n }\n\n /**\n * Select item in the list.\n * @param item\n */\n public select(item) {\n this.query = !this.isTypeString(item) ? item[this.searchKeyword] : item;\n this.isOpen = true;\n this.overlay = false;\n this.selected.emit(item);\n this.propagateChange(item);\n\n if (this.initialValue) {\n // check if history already exists in localStorage and then update\n const history = window.localStorage.getItem(`${this.historyIdentifier}`);\n if (history) {\n let existingHistory = JSON.parse(localStorage[`${this.historyIdentifier}`]);\n if (!(existingHistory instanceof Array)) existingHistory = [];\n\n // check if selected item exists in existingHistory\n if (!existingHistory.some((existingItem) => !this.isTypeString(existingItem)\n ? existingItem[this.searchKeyword] == item[this.searchKeyword] : existingItem == item)) {\n existingHistory.unshift(item);\n localStorage.setItem(`${this.historyIdentifier}`, JSON.stringify(existingHistory));\n\n // check if items don't exceed max allowed number\n if (existingHistory.length >= this.historyListMaxNumber) {\n existingHistory.splice(existingHistory.length - 1, 1);\n localStorage.setItem(`${this.historyIdentifier}`, JSON.stringify(existingHistory));\n }\n } else {\n // if selected item exists in existingHistory swap to top in array\n if (!this.isTypeString(item)) {\n // object logic\n const copiedExistingHistory = existingHistory.slice(); // copy original existingHistory array\n const selectedIndex = copiedExistingHistory.map((el) => el[this.searchKeyword]).indexOf(item[this.searchKeyword]);\n copiedExistingHistory.splice(selectedIndex, 1);\n copiedExistingHistory.splice(0, 0, item);\n localStorage.setItem(`${this.historyIdentifier}`, JSON.stringify(copiedExistingHistory));\n } else {\n // string logic\n const copiedExistingHistory = existingHistory.slice(); // copy original existingHistory array\n copiedExistingHistory.splice(copiedExistingHistory.indexOf(item), 1);\n copiedExistingHistory.splice(0, 0, item);\n localStorage.setItem(`${this.historyIdentifier}`, JSON.stringify(copiedExistingHistory));\n }\n }\n } else {\n this.saveHistory(item);\n }\n } else {\n this.saveHistory(item);\n }\n this.handleClose();\n }\n\n /**\n * Document click\n * @param e event\n */\n public handleClick(e) {\n let clickedComponent = e.target;\n let inside = false;\n do {\n if (clickedComponent === this.elementRef.nativeElement) {\n inside = true;\n if (this.filteredList.length) {\n this.handleOpen();\n }\n }\n clickedComponent = clickedComponent.parentNode;\n } while (clickedComponent);\n if (!inside) {\n this.handleClose();\n }\n }\n\n /**\n * Handle body overlay\n */\n handleOverlay() {\n this.overlay = false;\n }\n\n /**\n * Scroll items\n */\n public handleScroll() {\n this.renderer.listen(this.filteredListElement.nativeElement, 'scroll', () => {\n this.scrollToEnd();\n });\n }\n\n /**\n * Define panel state\n */\n setPanelState(event) {\n if (event) {\n event.stopPropagation();\n }\n // If controls are untouched\n if (typeof this.manualOpen === 'undefined'\n && typeof this.manualClose === 'undefined') {\n this.isOpen = false;\n this.handleOpen();\n }\n\n // If one of the controls is untouched and other is deactivated\n if (typeof this.manualOpen === 'undefined'\n && this.manualClose === false\n || typeof this.manualClose === 'undefined'\n && this.manualOpen === false) {\n this.isOpen = false;\n this.handleOpen();\n }\n\n // if controls are touched but both are deactivated\n if (this.manualOpen === false && this.manualClose === false) {\n this.isOpen = false;\n this.handleOpen();\n }\n\n // if open control is touched and activated\n if (this.manualOpen) {\n this.isOpen = false;\n this.handleOpen();\n this.manualOpen = false;\n }\n\n // if close control is touched and activated\n if (this.manualClose) {\n this.isOpen = true;\n this.handleClose();\n this.manualClose = false;\n }\n }\n\n /**\n * Manual controls\n */\n open() {\n this.manualOpen = true;\n this.isOpen = false;\n this.handleOpen();\n }\n\n close() {\n this.manualClose = true;\n this.isOpen = true;\n this.handleClose();\n }\n\n focus() {\n this.handleFocus(event);\n }\n\n clear() {\n this.remove(event);\n }\n\n /**\n * Remove search query\n */\n public remove(e) {\n e.stopPropagation();\n this.query = '';\n this.inputCleared.emit();\n this.propagateChange(this.query);\n this.setPanelState(e);\n\n if (this.data && !this.data.length) {\n this.notFound = false;\n }\n }\n\n /**\n * Initialize historyList search\n */\n initSearchHistory() {\n this.isHistoryListVisible = false;\n if (this.historyIdentifier && !this.query) {\n const history = window.localStorage.getItem(`${this.historyIdentifier}`);\n if (history) {\n this.isHistoryListVisible = true;\n this.filteredList = [];\n this.historyList = history ? JSON.parse(history) : [];\n } else {\n this.isHistoryListVisible = false;\n }\n } else {\n this.isHistoryListVisible = false;\n }\n }\n\n handleOpen() {\n if (this.isOpen || this.isOpen && !this.isLoading) {\n return;\n }\n // If data exists\n if (this.data && this.data.length) {\n this.isOpen = true;\n this.overlay = true;\n this.filterList();\n this.opened.emit();\n }\n }\n\n handleClose() {\n if (!this.isOpen) {\n this.isFocused = false;\n return;\n }\n this.isOpen = false;\n this.overlay = false;\n this.filteredList = [];\n this.selectedIdx = -1;\n this.notFound = false;\n this.isHistoryListVisible = false;\n this.isFocused = false;\n this.closed.emit();\n }\n\n handleFocus(e) {\n this.searchInput.nativeElement.focus();\n if (this.isFocused) {\n return;\n }\n this.inputFocused.emit(e);\n // if data exists then open\n if (this.data && this.data.length) {\n this.setPanelState(e);\n }\n this.isFocused = true;\n }\n\n scrollToEnd(): void {\n if (this.isScrollToEnd) {\n return;\n }\n\n const scrollTop = this.filteredListElement.nativeElement\n .scrollTop;\n const scrollHeight = this.filteredListElement.nativeElement\n .scrollHeight;\n const elementHeight = this.filteredListElement.nativeElement\n .clientHeight;\n const atBottom = elementHeight != 0 && scrollTop > ((scrollHeight - elementHeight) * 0.95);\n\n if (atBottom) {\n this.scrolledToEnd.emit();\n this.isScrollToEnd = true;\n }\n }\n\n /**\n * Initialize keyboard events\n */\n initEventStream() {\n this.inputKeyUp$ = fromEvent(\n this.searchInput.nativeElement, 'keyup'\n ).pipe(map(\n (e: any) => e\n ));\n\n this.inputKeyDown$ = fromEvent(\n this.searchInput.nativeElement,\n 'keydown'\n ).pipe(map(\n (e: any) => e\n ));\n\n this.listenEventStream();\n }\n\n /**\n * Listen keyboard events\n */\n listenEventStream() {\n // key up event\n this.inputKeyUp$\n .pipe(\n filter(e =>\n !isArrowUpDown(e.keyCode) &&\n !isEnter(e.keyCode) &&\n !isESC(e.keyCode) &&\n !isTab(e.keyCode)),\n debounceTime(this.debounceTime)\n ).subscribe(e => {\n this.onKeyUp(e);\n });\n\n // cursor up & down\n this.inputKeyDown$.pipe(filter(\n e => isArrowUpDown(e.keyCode)\n )).subscribe(e => {\n e.preventDefault();\n this.onFocusItem(e);\n });\n\n // enter keyup\n this.inputKeyUp$.pipe(filter(e => isEnter(e.keyCode))).subscribe(e => {\n //this.onHandleEnter();\n });\n\n // enter keydown\n this.inputKeyDown$.pipe(filter(e => isEnter(e.keyCode))).subscribe(e => {\n this.onHandleEnter();\n });\n\n // ESC\n this.inputKeyUp$.pipe(\n filter(e => isESC(e.keyCode),\n debounceTime(100))\n ).subscribe(e => {\n this.onEsc();\n });\n\n // TAB\n this.inputKeyDown$.pipe(\n filter(e => isTab(e.keyCode))\n ).subscribe(e => {\n this.onTab();\n });\n\n // delete\n this.inputKeyDown$.pipe(\n filter(e => isBackspace(e.keyCode) || isDelete(e.keyCode))\n ).subscribe(e => {\n this.onDelete();\n });\n }\n\n /**\n * on keyup == when input changed\n * @param e event\n */\n onKeyUp(e) {\n this.notFound = false; // search results are unknown while typing\n // if input is empty\n if (!this.query) {\n this.notFound = false;\n this.inputChanged.emit(e.target.value);\n this.inputCleared.emit();\n this.setPanelState(e);\n }\n // note that '' can be a valid query\n if (!this.query && this.query !== '') {\n return;\n }\n // if query >= to minQueryLength\n if (this.query.length >= this.minQueryLength) {\n this.inputChanged.emit(e.target.value);\n this.filterList();\n\n // If no results found\n if (!this.filteredList.length && !this.isLoading) {\n this.notFoundText ? this.notFound = true : this.notFound = false;\n }\n\n if (this.data && !this.data.length) {\n this.isOpen = true;\n }\n }\n }\n\n\n /**\n * Keyboard arrow top and arrow bottom\n * @param e event\n */\n onFocusItem(e) {\n // move arrow up and down on filteredList or historyList\n if (!this.historyList.length || !this.isHistoryListVisible) {\n // filteredList\n const totalNumItem = this.filteredList.length;\n if (e.key === 'ArrowDown') {\n let sum = this.selectedIdx;\n sum = (this.selectedIdx === null) ? 0 : sum + 1;\n this.selectedIdx = (totalNumItem + sum) % totalNumItem;\n this.scrollToFocusedItem(this.selectedIdx);\n } else if (e.key === 'ArrowUp') {\n if (this.selectedIdx == -1) {\n this.selectedIdx = 0;\n }\n this.selectedIdx = (totalNumItem + this.selectedIdx - 1) % totalNumItem;\n this.scrollToFocusedItem(this.selectedIdx);\n }\n } else {\n // historyList\n const totalNumItem = this.historyList.length;\n if (e.key === 'ArrowDown') {\n let sum = this.selectedIdx;\n sum = (this.selectedIdx === null) ? 0 : sum + 1;\n this.selectedIdx = (totalNumItem + sum) % totalNumItem;\n this.scrollToFocusedItem(this.selectedIdx);\n } else if (e.key === 'ArrowUp') {\n if (this.selectedIdx == -1) {\n this.selectedIdx = 0;\n }\n this.selectedIdx = (totalNumItem + this.selectedIdx - 1) % totalNumItem;\n this.scrollToFocusedItem(this.selectedIdx);\n }\n }\n }\n\n /**\n * Scroll to focused item\n * * @param index\n */\n scrollToFocusedItem(index) {\n let listElement = null;\n // Define list element\n if (!this.historyList.length || !this.isHistoryListVisible) {\n // filteredList element\n listElement = this.filteredListElement.nativeElement;\n } else {\n // historyList element\n listElement = this.historyListElement.nativeElement;\n }\n\n const items = Array.prototype.slice.call(listElement.childNodes).filter((node: any) => {\n if (node.nodeType === 1) {\n // if node is element\n return node.className.includes('item');\n } else {\n return false;\n }\n });\n\n if (!items.length) {\n return;\n }\n\n const listHeight = listElement.offsetHeight;\n const itemHeight = items[index].offsetHeight;\n const visibleTop = listElement.scrollTop;\n const visibleBottom = listElement.scrollTop + listHeight - itemHeight;\n const targetPosition = items[index].offsetTop;\n\n if (targetPosition < visibleTop) {\n listElement.scrollTop = targetPosition;\n }\n\n if (targetPosition > visibleBottom) {\n listElement.scrollTop = targetPosition - listHeight + itemHeight;\n }\n }\n\n /**\n * Select item on enter click\n */\n onHandleEnter() {\n // click enter to choose item from filteredList or historyList\n if (this.selectedIdx > -1) {\n if (!this.historyList.length || !this.isHistoryListVisible) {\n // filteredList\n this.query = !this.isTypeString(this.filteredList[this.selectedIdx])\n ? this.filteredList[this.selectedIdx][this.searchKeyword]\n : this.filteredList[this.selectedIdx];\n\n this.saveHistory(this.filteredList[this.selectedIdx]);\n this.select(this.filteredList[this.selectedIdx]);\n } else {\n // historyList\n this.query = !this.isTypeString(this.historyList[this.selectedIdx])\n ? this.historyList[this.selectedIdx][this.searchKeyword]\n : this.historyList[this.selectedIdx];\n this.saveHistory(this.historyList[this.selectedIdx]);\n this.select(this.historyList[this.selectedIdx]);\n }\n }\n this.isHistoryListVisible = false;\n this.handleClose();\n }\n\n /**\n * Esc click\n */\n onEsc() {\n this.searchInput.nativeElement.blur();\n this.handleClose();\n }\n\n /**\n * Tab click\n */\n onTab() {\n this.searchInput.nativeElement.blur();\n this.handleClose();\n }\n\n /**\n * Delete click\n */\n onDelete() {\n this.isOpen = true;\n }\n\n\n /**\n * Select item to save in localStorage\n * @param selected\n */\n saveHistory(selected) {\n if (this.historyIdentifier) {\n // check if selected item exists in historyList\n if (!this.historyList.some((item) => !this.isTypeString(item)\n ? item[this.searchKeyword] == selected[this.searchKeyword] : item == selected)) {\n this.saveHistoryToLocalStorage([selected, ...this.historyList]);\n\n // check if items don't exceed max allowed number\n if (this.historyList.length >= this.historyListMaxNumber) {\n this.historyList.splice(this.historyList.length - 1, 1);\n this.saveHistoryToLocalStorage([selected, ...this.historyList]);\n }\n } else {\n // if selected item exists in historyList swap to top in array\n if (!this.isTypeString(selected)) {\n // object logic\n const copiedHistoryList = this.historyList.slice(); // copy original historyList array\n const selectedIndex = copiedHistoryList.map((item) => item[this.searchKeyword]).indexOf(selected[this.searchKeyword]);\n copiedHistoryList.splice(selectedIndex, 1);\n copiedHistoryList.splice(0, 0, selected);\n this.saveHistoryToLocalStorage([...copiedHistoryList]);\n } else {\n // string logic\n const copiedHistoryList = this.historyList.slice(); // copy original historyList array\n copiedHistoryList.splice(this.historyList.indexOf(selected), 1);\n copiedHistoryList.splice(0, 0, selected);\n this.saveHistoryToLocalStorage([...copiedHistoryList]);\n }\n }\n }\n }\n\n /**\n * Save item in localStorage\n * @param selected\n */\n saveHistoryToLocalStorage(selected) {\n window.localStorage.setItem(\n `${this.historyIdentifier}`,\n JSON.stringify(selected)\n );\n }\n\n /**\n * Remove item from localStorage\n * @param index\n * @param e event\n */\n removeHistoryItem(index, e) {\n e.stopPropagation();\n this.historyList = this.historyList.filter((v, i) => i !== index);\n this.saveHistoryToLocalStorage(this.historyList);\n if (this.historyList.length == 0) {\n window.localStorage.removeItem(`${this.historyIdentifier}`);\n this.filterList();\n }\n }\n\n /**\n * Reset localStorage\n * @param e event\n */\n resetHistoryList(e) {\n e.stopPropagation();\n this.historyList = [];\n window.localStorage.removeItem(`${this.historyIdentifier}`);\n this.filterList();\n }\n}\n","<div class=\"autocomplete-container\" aria-owns=\"suggestions suggestions-history\" [attr.aria-expanded]=\"isOpen\"\n [ngClass]=\"{ 'active': isOpen}\">\n <div class=\"input-container\">\n <input #searchInput\n type=\"text\"\n attr.aria-label=\"{{placeholder}}\"\n aria-autocomplete=\"list\"\n role=\"combobox\"\n placeholder={{placeholder}}\n [(ngModel)]=query\n (input)=\"onChange($event)\"\n (focus)=handleFocus($event)\n (blur)=onTouched($event)\n [disabled]=\"disabled\"\n autocomplete=\"off\">\n <div class=\"x\" *ngIf=\"query && !isLoading && !disabled\" (click)=\"remove($event)\">\n <i class=\"material-icons\" aria-label=\"Close\">close</i>\n </div>\n <!--Loading mask-->\n <div class=\"sk-fading-circle\" *ngIf=\"isLoading\">\n <div class=\"sk-circle1 sk-circle\"></div>\n <div class=\"sk-circle2 sk-circle\"></div>\n <div class=\"sk-circle3 sk-circle\"></div>\n <div class=\"sk-circle4 sk-circle\"></div>\n <div class=\"sk-circle5 sk-circle\"></div>\n <div class=\"sk-circle6 sk-circle\"></div>\n <div class=\"sk-circle7 sk-circle\"></div>\n <div class=\"sk-circle8 sk-circle\"></div>\n <div class=\"sk-circle9 sk-circle\"></div>\n <div class=\"sk-circle10 sk-circle\"></div>\n <div class=\"sk-circle11 sk-circle\"></div>\n <div class=\"sk-circle12 sk-circle\"></div>\n </div>\n </div>\n\n <!--FilteredList items-->\n <div class=\"suggestions-container\" id=\"suggestions\" role=\"listbox\"\n [ngClass]=\"{ 'is-hidden': isHistoryListVisible, 'is-visible': !isHistoryListVisible}\">\n <!--FilteredList heading-->\n <div class=\"heading\" *ngIf=\"filteredList.length > 0 && heading\">\n <div class=\"text\">{{heading}}</div>\n </div>\n\n <ul #filteredListElement>\n <li *ngFor=\"let item of filteredList; let idx = index\" class=\"item\">\n <!--string logic-->\n <div [class.complete-selected]=\"idx === selectedIdx\" *ngIf='isTypeString(item)'\n (click)=\"select(item)\">\n <ng-container\n *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item | highlight: toHighlight }\">\n </ng-container>\n </div>\n <!--object logic-->\n <div [class.complete-selected]=\"idx === selectedIdx\" *ngIf='!isTypeString(item)'\n (click)=\"select(item)\">\n <ng-container\n *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item | highlight: toHighlight : searchKeyword }\">\n </ng-container>\n </div>\n </li>\n </ul>\n </div>\n\n <!--HistoryList items-->\n <div class=\"suggestions-container\" id=\"suggestions-history\" role=\"listbox\"\n [ngClass]=\"{ 'is-hidden': !isHistoryListVisible, 'is-visible': isHistoryListVisible}\">\n <!--HistoryList heading-->\n <div class=\"heading\" *ngIf=\"historyList.length > 0 && historyHeading\">\n <div class=\"text\">{{historyHeading}}</div>\n <div class=\"x\" (click)=\"resetHistoryList($event)\">\n <i class=\"material-icons\" aria-label=\"Delete\">delete</i>\n </div>\n </div>\n\n <ul #historyListElement>\n <li *ngFor=\"let item of historyList; let idx = index\" class=\"item\">\n <!--string logic-->\n <div [class.complete-selected]=\"idx === selectedIdx\" *ngIf='isTypeString(item)' (click)=\"select(item)\">\n <ng-container\n *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\">\n </ng-container>\n </div>\n <!--object logic-->\n <div [class.complete-selected]=\"idx === selectedIdx\" *ngIf='!isTypeString(item)' (click)=\"select(item)\">\n <ng-container\n *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\">\n </ng-container>\n </div>\n <div class=\"x\" (click)=\"removeHistoryItem(idx, $event)\">\n <i class=\"material-icons\" aria-label=\"Close\">close</i>\n </div>\n </li>\n </ul>\n </div>\n\n <!--Not found-->\n <div class=\"not-found\" *ngIf=\"isLoading ? !isLoading && notFound : notFound\">\n <ng-container\n *ngTemplateOutlet=\"notFoundTemplate; context: { $implicit: notFoundText }\">\n </ng-container>\n </div>\n</div>\n<div class=\"autocomplete-overlay\" *ngIf=\"overlay\" (click)=\"handleOverlay()\"></div>\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { AutocompleteComponent } from './autocomplete.component';\nimport { HighlightPipe } from './highlight.pipe';\n\n@NgModule({\n imports: [\n CommonModule,\n FormsModule,\n ],\n declarations: [AutocompleteComponent, HighlightPipe],\n exports: [ AutocompleteComponent, HighlightPipe]\n})\nexport class AutocompleteLibModule {\n}\n","/*\n * Public API Surface of autocomplete-lib\n */\n\nexport * from './lib/autocomplete-lib.module';\nexport * from './lib/autocomplete.component';\nexport * from './lib/highlight.pipe';\n\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["i3.HighlightPipe"],"mappings":"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