/* eslint-disable consistent-return */ import $ from 'jquery'; import fuzzaldrinPlus from 'fuzzaldrin-plus'; import { isObject } from '~/lib/utils/type_utility'; const BLUR_KEYCODES = [27, 40]; const HAS_VALUE_CLASS = 'has-value'; export class GitLabDropdownFilter { constructor(input, options) { let ref; let timeout; this.input = input; this.options = options; // eslint-disable-next-line no-cond-assign this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true; const $inputContainer = this.input.parent(); const $clearButton = $inputContainer.find('.js-dropdown-input-clear'); $clearButton.on('click', e => { // Clear click e.preventDefault(); e.stopPropagation(); return this.input .val('') .trigger('input') .focus(); }); // Key events timeout = ''; this.input .on('keydown', e => { const keyCode = e.which; if (keyCode === 13 && !options.elIsInput) { e.preventDefault(); } }) .on('input', () => { if (this.input.val() !== '' && !$inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.addClass(HAS_VALUE_CLASS); } else if (this.input.val() === '' && $inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.removeClass(HAS_VALUE_CLASS); } // Only filter asynchronously only if option remote is set if (this.options.remote) { clearTimeout(timeout); // eslint-disable-next-line no-return-assign return (timeout = setTimeout(() => { $inputContainer.parent().addClass('is-loading'); return this.options.query(this.input.val(), data => { $inputContainer.parent().removeClass('is-loading'); return this.options.callback(data); }); }, 250)); } return this.filter(this.input.val()); }); } static shouldBlur(keyCode) { return BLUR_KEYCODES.indexOf(keyCode) !== -1; } filter(searchText) { let group; let results; let tmp; if (this.options.onFilter) { this.options.onFilter(searchText); } const data = this.options.data(); if (data != null && !this.options.filterByText) { results = data; if (searchText !== '') { // When data is an array of objects therefore [object Array] e.g. // [ // { prop: 'foo' }, // { prop: 'baz' } // ] if (Array.isArray(data)) { results = fuzzaldrinPlus.filter(data, searchText, { key: this.options.keys, }); } // If data is grouped therefore an [object Object]. e.g. // { // groupName1: [ // { prop: 'foo' }, // { prop: 'baz' } // ], // groupName2: [ // { prop: 'abc' }, // { prop: 'def' } // ] // } else if (isObject(data)) { results = {}; Object.keys(data).forEach(key => { group = data[key]; tmp = fuzzaldrinPlus.filter(group, searchText, { key: this.options.keys, }); if (tmp.length) { results[key] = tmp.map(item => item); } }); } } return this.options.callback(results); } const elements = this.options.elements(); if (searchText) { // eslint-disable-next-line func-names elements.each(function() { const $el = $(this); const matches = fuzzaldrinPlus.match($el.text().trim(), searchText); if (!$el.is('.dropdown-header')) { if (matches.length) { return $el.show().removeClass('option-hidden'); } return $el.hide().addClass('option-hidden'); } }); } else { elements.show().removeClass('option-hidden'); } elements .parent() .find('.dropdown-menu-empty-item') .toggleClass('hidden', elements.is(':visible')); } }