var AjaxResolver = class { constructor(options) { this._settings = $.extend(true, {}, this.getDefaults(), options); } getDefaults() { return { url: '', method: 'post', queryKey: 'Auto_Query', param: [], timeout: 0, requestThrottling: 500 }; } search(q, cbk) { if (this.jqXHR != null) this.jqXHR.abort(); var data = {}; data[this._settings.queryKey] = q; if (this._settings.param.length > 0) { $.extend(data, FoniaJS.RequestParam(this._settings.param)); } if (this.requestTID) window.clearTimeout(this.requestTID); this.requestTID = window.setTimeout(() => { this.jqXHR = $.ajax(this._settings.url, { method: this._settings.method, data: data, timeout: this._settings.timeout }); this.jqXHR.done(result => { cbk(result.autodata !== undefined ? result.autodata : result); }); this.jqXHR.fail(err => { this._settings.fail?.(err); }); this.jqXHR.always(() => { this.jqXHR = null; }); }, this._settings.requestThrottling); } }; var DropdownV5 = class { constructor(e, formatItemCbk, autoSelect, noResultsText) { this.initialized = false; this.shown = false; this.items = []; this.ddMouseover = false; this._$el = e; this.formatItem = formatItemCbk; this.autoSelect = autoSelect; this.noResultsText = noResultsText; } getElPos() { return $.extend({}, this._$el.position(), { height: this._$el[0].offsetHeight }); } init() { var pos = this.getElPos(); var fontsize = this._$el.css('font-size'); this._dd = $('
') .addClass('bootstrap-autocomplete dropdown-menu') .insertAfter(this._$el) .css({ top: pos.top + this._$el.outerHeight(), left: pos.left, width: this._$el.outerWidth(), 'font-size': fontsize }); this._dd.on('click', '.dropdown-item', evt => { var item = $(evt.currentTarget).data('item'); this.itemSelectedLaunchEvent(item); evt.preventDefault(); }); this._dd.on('keyup', evt => { if (this.shown && evt.which === 27) { this.hide(); this._$el.focus(); return false; } }); this._dd.on('mouseenter', () => { this.ddMouseover = true; }); this._dd.on('mouseleave', () => { this.ddMouseover = false; }); this._dd.on('mouseenter', '.dropdown-item', evt => { if (this.haveResults) { $(evt.currentTarget).closest('div').find('.dropdown-item.active').removeClass('active'); $(evt.currentTarget).addClass('active'); this.mouseover = true; } }); this._dd.on('mouseleave', '.dropdown-item', () => { this.mouseover = false; }); this.initialized = true; } checkInitialized() { if (!this.initialized) this.init(); } get isMouseOver() { return this.mouseover; } get isDdMouseOver() { return this.ddMouseover; } get haveResults() { return this.items.length > 0; } focusNextItem(reversed) { if (!this.haveResults) return; var currElem = this._dd.find('.dropdown-item.active'); var nextElem = reversed ? currElem.prev() : currElem.next(); if (nextElem.length === 0) { nextElem = reversed ? this._dd.find('.dropdown-item').last() : this._dd.find('.dropdown-item').first(); } currElem.removeClass('active'); nextElem.addClass('active'); this.scrollTo(nextElem); } focusPreviousItem() { this.focusNextItem(true); } selectFocusItem() { this._dd.find('.dropdown-item.active').trigger('click'); } get isItemFocused() { return !!(this._dd && this.isShown() && this._dd.find('.dropdown-item.active').length > 0); } show() { if (!this.shown) { this._dd.addClass('show'); this.shown = true; this._$el.trigger('autocomplete.dd.shown'); } } isShown() { return this.shown; } hide() { if (this.shown) { this._dd.removeClass('show'); this.shown = false; this._$el.trigger('autocomplete.dd.hidden'); } } updateItems(items, searchText) { this.items = items; this.searchText = searchText; this.refreshItemList(); } showMatchedText(text, qry) { var startIndex = text.toLowerCase().indexOf(qry.toLowerCase()); if (startIndex > -1) { var endIndex = startIndex + qry.length; return text.slice(0, startIndex) + '' + text.slice(startIndex, endIndex) + '' + text.slice(endIndex); } return text; } refreshItemList() { this.checkInitialized(); this._dd.empty(); var liList = []; if (this.items.length > 0) { this.items.forEach(item => { var itemFormatted = this.formatItem(item); if (typeof itemFormatted === 'string') itemFormatted = { text: itemFormatted }; var itemText = this.showMatchedText(itemFormatted.text, this.searchText); var itemHtml = itemFormatted.html !== undefined ? itemFormatted.html : itemText; var li = $('') .addClass('dropdown-item') .html(itemHtml) .data('item', item); if (itemFormatted.disabled) li.addClass('disabled'); liList.push(li); }); this._dd.append(liList); this.show(); } else if (this.noResultsText !== '') { var li = $('').addClass('dropdown-item disabled').html(this.noResultsText); liList.push(li); this._dd.append(liList); this.show(); } else { this.hide(); } } itemSelectedLaunchEvent(item) { this._$el.trigger('autocomplete.select', item); } scrollTo(el) { var _he = this._dd.height(), _to = this._dd.scrollTop(), _ito = el.position().top, _ihe = el.outerHeight(), _nto = _to, _wra = false; if (_ito < 0) { _wra = el.is(':first-child'); _nto = _wra ? 0 : _to - _he / 2; } else if (_ito > _he - _ihe) { _wra = el.is(':last-child') && _ito > _he; _nto = _wra ? (_ito + _ihe - _he) : _to + _he / 2; } this._dd.scrollTop(_nto); } }; var AutoComplete = class { constructor(element, options) { this._selectedItem = null; this._defaultValue = null; this._defaultText = null; this._settings = { resolver: 'ajax', resolverSettings: {}, minLength: 3, valueKey: 'value', formatResult: this.defaultFormatResult, autoSelect: true, noResultsText: 'Pencarian Tidak Ketemu', preventEnter: false, events: { typed: null, searchPre: null, search: null, searchPost: null, select: null, focus: null }, selectFunc: () => {}, keyFunc: () => {}, breakFocus: false, breakValue: [] }; this._el = element; this._$el = $(this._el); this.manageInlineDataAttributes(); if (typeof options === 'object') { this._settings = $.extend(true, {}, this.getSettings(), options); } this.init(); } manageInlineDataAttributes() { var s = this.getSettings(); if (this._$el.data('url')) s.resolverSettings.url = this._$el.data('url'); if (this._$el.data('default-value')) this._defaultValue = this._$el.data('default-value'); if (this._$el.data('default-text')) this._defaultText = this._$el.data('default-text'); if (this._$el.data('noresults-text') !== undefined) s.noResultsText = this._$el.data('noresults-text'); } getSettings() { return this._settings; } init() { this.bindDefaultEventListeners(); if (this._settings.resolver === 'ajax') { this.resolver = new AjaxResolver(this._settings.resolverSettings); } this._dd = new DropdownV5(this._$el, this._settings.formatResult, this._settings.autoSelect, this._settings.noResultsText); } bindDefaultEventListeners() { this._$el.on('keydown', evt => { var val = this._$el.val(); if ((val === '' || (this._settings.breakValue.length > 0 && this._settings.breakValue.indexOf(val) !== -1))) { this._settings.keyFunc(evt.which, val); } switch (evt.which) { case 9: if (!this._settings.breakFocus) { if (this._dd.isItemFocused) this._dd.selectFocusItem(); this._dd.hide(); } break; case 13: if (this._dd.isItemFocused) this._dd.selectFocusItem(); this._dd.hide(); if (this._settings.preventEnter) evt.preventDefault(); break; case 40: this._dd.focusNextItem(); break; case 38: this._dd.focusPreviousItem(); break; } }); this._$el.on('keyup', evt => { switch (evt.which) { case 16: case 17: case 18: case 39: case 37: case 36: case 35: case 40: case 38: break; case 13: case 27: this._dd.hide(); break; default: this._selectedItem = null; this.handlerTyped(this._$el.val()); } }); this._$el.on('blur', () => { if (this._settings.breakFocus) return; if (!this._dd.isMouseOver && this._dd.isDdMouseOver && this._dd.isShown()) { setTimeout(() => { this._$el.focus(); }); this._$el.focus(); } else if (!this._dd.isMouseOver) { this._dd.hide(); } }); this._$el.on('autocomplete.select', (evt, item) => { this._selectedItem = item; this.itemSelectedDefaultHandler(item); }); this._$el.on('paste', evt => { setTimeout(() => { this._$el.trigger('keyup', evt); }, 0); }); } handlerTyped(newValue) { if (this._settings.events.typed !== null) { newValue = this._settings.events.typed(newValue, this._$el); if (!newValue) return; } if (newValue.length >= this._settings.minLength) { this._searchText = newValue; this.handlerPreSearch(); } else { this._dd.hide(); } } handlerPreSearch() { if (this._settings.events.searchPre !== null) { var newValue = this._settings.events.searchPre(this._searchText, this._$el); if (!newValue) return; this._searchText = newValue; } this.handlerDoSearch(); } handlerDoSearch() { if (this._settings.events.search !== null) { this._settings.events.search(this._searchText, results => { this.postSearchCallback(results); }, this._$el); } else if (this.resolver) { this.resolver.search(this._searchText, results => { this.postSearchCallback(results); }); } } postSearchCallback(results) { if (this._settings.events.searchPost) { results = this._settings.events.searchPost(results, this._$el); if (typeof results === 'boolean' && !results) return; } this.handlerStartShow(results); } handlerStartShow(results) { var bcVal = results[0]?.bc ?? 0; if (results.length === 1 && bcVal === 1) { this._$el.trigger('autocomplete.select', results[0]); this._dd.hide(); } else { this._dd.updateItems(results, this._searchText); } } itemSelectedDefaultHandler(item) { if (item != null) { var itemFormatted = this._settings.formatResult(item); if (typeof itemFormatted === 'string') itemFormatted = { text: itemFormatted }; this._$el.val(itemFormatted.text); } else { this._$el.val(''); } this._selectedItem = item; this._settings.selectFunc(item); this._dd.hide(); } defaultFormatResult(item) { if (typeof item === 'string') return { text: item }; if (item.text) return item; return { text: item.toString() }; } manageAPI(APICmd, params) { if (APICmd === 'set') this.itemSelectedDefaultHandler(params); else if (APICmd === 'clear') this.itemSelectedDefaultHandler(null); else if (APICmd === 'show') this._$el.trigger('keyup'); else if (APICmd === 'updateResolver') this.resolver = new AjaxResolver(params); } }; AutoComplete.NAME = 'autoComplete'; // jQuery plugin wrapper $.fn[AutoComplete.NAME] = function (optionsOrAPI, optionalParams) { return this.each(function () { var pluginClass = $(this).data(AutoComplete.NAME); if (!pluginClass) { pluginClass = new AutoComplete(this, optionsOrAPI); $(this).data(AutoComplete.NAME, pluginClass); } pluginClass.manageAPI(optionsOrAPI, optionalParams); }); };