UNPKG

@coreui/coreui-pro

Version:

The most popular front-end framework for developing responsive, mobile-first projects on the web rewritten by the CoreUI Team

964 lines (936 loc) 34.3 kB
/*! * CoreUI multi-select.js v5.14.2 (https://coreui.io) * Copyright 2025 The CoreUI Team (https://github.com/orgs/coreui/people) * Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./base-component.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/index.js')) : typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/data', './dom/event-handler', './dom/selector-engine', './util/index'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MultiSelect = factory(global["@popperjs/core"], global.BaseComponent, global.Data, global.EventHandler, global.SelectorEngine, global.Index)); })(this, (function (Popper, BaseComponent, Data, EventHandler, SelectorEngine, index_js) { 'use strict'; function _interopNamespaceDefault(e) { const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } }); if (e) { for (const k in e) { if (k !== 'default') { const d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: () => e[k] }); } } } n.default = e; return Object.freeze(n); } const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper); /** * -------------------------------------------------------------------------- * CoreUI PRO multi-select.js * License (https://coreui.io/pro/license/) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME = 'multi-select'; const DATA_KEY = 'coreui.multi-select'; const EVENT_KEY = `.${DATA_KEY}`; const DATA_API_KEY = '.data-api'; const ARROW_UP_KEY = 'ArrowUp'; const ARROW_DOWN_KEY = 'ArrowDown'; const BACKSPACE_KEY = 'Backspace'; const DELETE_KEY = 'Delete'; const ENTER_KEY = 'Enter'; const ESCAPE_KEY = 'Escape'; const TAB_KEY = 'Tab'; const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button const SELECTOR_CLEANER = '.form-multi-select-cleaner'; const SELECTOR_OPTGROUP = '.form-multi-select-optgroup'; const SELECTOR_OPTION = '.form-multi-select-option'; const SELECTOR_OPTIONS = '.form-multi-select-options'; const SELECTOR_OPTIONS_EMPTY = '.form-multi-select-options-empty'; const SELECTOR_SEARCH = '.form-multi-select-search'; const SELECTOR_SELECT = '.form-multi-select'; const SELECTOR_SELECTION = '.form-multi-select-selection'; const SELECTOR_VISIBLE_ITEMS = '.form-multi-select-options .form-multi-select-option:not(.disabled):not(:disabled)'; const EVENT_CHANGED = `changed${EVENT_KEY}`; const EVENT_CLICK = `click${EVENT_KEY}`; const EVENT_HIDE = `hide${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; const EVENT_KEYUP = `keyup${EVENT_KEY}`; const EVENT_SEARCH = `search${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`; const CLASS_NAME_CLEANER = 'form-multi-select-cleaner'; const CLASS_NAME_DISABLED = 'disabled'; const CLASS_NAME_INPUT_GROUP = 'form-multi-select-input-group'; const CLASS_NAME_LABEL = 'label'; const CLASS_NAME_SELECT = 'form-multi-select'; const CLASS_NAME_SELECT_DROPDOWN = 'form-multi-select-dropdown'; const CLASS_NAME_SELECT_ALL = 'form-multi-select-all'; const CLASS_NAME_OPTGROUP = 'form-multi-select-optgroup'; const CLASS_NAME_OPTGROUP_LABEL = 'form-multi-select-optgroup-label'; const CLASS_NAME_OPTION = 'form-multi-select-option'; const CLASS_NAME_OPTION_WITH_CHECKBOX = 'form-multi-select-option-with-checkbox'; const CLASS_NAME_OPTIONS = 'form-multi-select-options'; const CLASS_NAME_OPTIONS_EMPTY = 'form-multi-select-options-empty'; const CLASS_NAME_SEARCH = 'form-multi-select-search'; const CLASS_NAME_SELECTED = 'form-multi-selected'; const CLASS_NAME_SELECTION = 'form-multi-select-selection'; const CLASS_NAME_SELECTION_TAGS = 'form-multi-select-selection-tags'; const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_TAG = 'form-multi-select-tag'; const CLASS_NAME_TAG_DELETE = 'form-multi-select-tag-delete'; const Default = { ariaCleanerLabel: 'Clear all selections', cleaner: true, container: false, disabled: false, invalid: false, multiple: true, name: null, options: false, optionsMaxHeight: 'auto', optionsStyle: 'checkbox', placeholder: 'Select...', required: false, search: false, searchNoResultsLabel: 'No results found', selectAll: true, selectAllLabel: 'Select all options', selectionType: 'tags', selectionTypeCounterText: 'item(s) selected', valid: false, value: null }; const DefaultType = { ariaCleanerLabel: 'string', cleaner: 'boolean', container: '(string|element|boolean)', disabled: 'boolean', invalid: 'boolean', multiple: 'boolean', name: '(string|null)', options: '(boolean|array)', optionsMaxHeight: '(number|string)', optionsStyle: 'string', placeholder: 'string', required: 'boolean', search: '(boolean|string)', searchNoResultsLabel: 'string', selectAll: 'boolean', selectAllLabel: 'string', selectionType: 'string', selectionTypeCounterText: 'string', valid: 'boolean', value: '(string|array|null)' }; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class MultiSelect extends BaseComponent { constructor(element, config) { super(element, config); this._configureNativeSelect(); this._indicatorElement = null; this._selectAllElement = null; this._selectionElement = null; this._selectionCleanerElement = null; this._searchElement = null; this._togglerElement = null; this._optionsElement = null; this._clone = null; this._menu = null; this._selected = []; this._options = this._getOptions(); this._popper = null; this._search = ''; if (this._config.options.length > 0) { this._createNativeOptions(this._element, this._config.options); } this._createSelect(); this._addEventListeners(); Data.set(this._element, DATA_KEY, this); } // Getters static get Default() { return Default; } static get DefaultType() { return DefaultType; } static get NAME() { return NAME; } // Public toggle() { return this._isShown() ? this.hide() : this.show(); } show() { if (this._config.disabled || this._isShown()) { return; } EventHandler.trigger(this._element, EVENT_SHOW); this._clone.classList.add(CLASS_NAME_SHOW); this._clone.setAttribute('aria-expanded', true); if (this._config.container) { this._menu.style.minWidth = `${this._clone.offsetWidth}px`; this._menu.classList.add(CLASS_NAME_SHOW); } EventHandler.trigger(this._element, EVENT_SHOWN); this._createPopper(); if (this._config.search) { SelectorEngine.findOne(SELECTOR_SEARCH, this._clone).focus(); } } hide() { EventHandler.trigger(this._element, EVENT_HIDE); if (this._popper) { this._popper.destroy(); } if (this._config.search) { this._searchElement.value = ''; } this._onSearchChange(this._searchElement); this._clone.classList.remove(CLASS_NAME_SHOW); this._clone.setAttribute('aria-expanded', 'false'); if (this._config.container) { this._menu.classList.remove(CLASS_NAME_SHOW); } EventHandler.trigger(this._element, EVENT_HIDDEN); } dispose() { if (this._popper) { this._popper.destroy(); } super.dispose(); } search(text) { this._search = text.length > 0 ? text.toLowerCase() : text; this._filterOptionsList(); EventHandler.trigger(this._element, EVENT_SEARCH); } update(config) { if (config.value) { this.deselectAll(); } this._config = { ...this._config, ...this._configAfterMerge(config) }; this._selected = []; this._options = this._getOptions(); this._menu.remove(); this._clone.remove(); this._element.innerHTML = ''; this._createNativeOptions(this._element, this._options); this._createSelect(); this._addEventListeners(); } selectAll(options = this._options) { for (const option of options) { if (option.disabled) { continue; } if (option.label) { this.selectAll(option.options); continue; } this._selectOption(option.value, option.text); } } deselectAll(options = this._options) { for (const option of options) { if (option.disabled) { continue; } if (option.label) { this.deselectAll(option.options); continue; } this._deselectOption(option.value); } } getValue() { return this._selected; } // Private _addEventListeners() { EventHandler.on(this._clone, EVENT_CLICK, () => { if (!this._config.disabled) { this.show(); } }); EventHandler.on(this._clone, EVENT_KEYDOWN, event => { if (event.key === ESCAPE_KEY) { this.hide(); return; } if (this._config.search === 'global' && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { this._searchElement.focus(); } }); EventHandler.on(this._menu, EVENT_KEYDOWN, event => { if (this._config.search === 'global' && (event.key.length === 1 || event.key === BACKSPACE_KEY || event.key === DELETE_KEY)) { this._searchElement.focus(); } }); EventHandler.on(this._togglerElement, EVENT_KEYDOWN, event => { if (!this._isShown() && (event.key === ENTER_KEY || event.key === ARROW_DOWN_KEY)) { event.preventDefault(); this.show(); return; } if (this._isShown() && event.key === ARROW_DOWN_KEY) { event.preventDefault(); this._selectMenuItem(event); } }); EventHandler.on(this._indicatorElement, EVENT_CLICK, event => { event.preventDefault(); event.stopPropagation(); this.toggle(); }); EventHandler.on(this._searchElement, EVENT_KEYUP, () => { this._onSearchChange(this._searchElement); }); EventHandler.on(this._searchElement, EVENT_KEYDOWN, event => { if (!this._isShown()) { this.show(); } if (event.key === ARROW_DOWN_KEY && this._searchElement.value.length === this._searchElement.selectionStart) { this._selectMenuItem(event); return; } if ((event.key === BACKSPACE_KEY || event.key === DELETE_KEY) && event.target.value.length === 0) { this._deselectLastOption(); } this._searchElement.focus(); }); EventHandler.on(this._selectAllElement, EVENT_CLICK, event => { event.preventDefault(); event.stopPropagation(); this.selectAll(); }); EventHandler.on(this._optionsElement, EVENT_CLICK, event => { event.preventDefault(); event.stopPropagation(); this._onOptionsClick(event.target); }); EventHandler.on(this._selectionCleanerElement, EVENT_CLICK, event => { if (!this._config.disabled) { event.preventDefault(); event.stopPropagation(); this.deselectAll(); } }); EventHandler.on(this._optionsElement, EVENT_KEYDOWN, event => { if (event.key === ENTER_KEY) { this._onOptionsClick(event.target); } if ([ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { event.preventDefault(); this._selectMenuItem(event); } }); } _getClassNames() { return this._element.classList.value.split(' '); } _getOptions() { if (this._config.options) { return this._getOptionsFromConfig(); } return this._getOptionsFromElement(); } _getOptionsFromConfig(options = this._config.options) { const _options = []; for (const option of options) { if (option.options && Array.isArray(option.options)) { _options.push({ label: option.label, options: this._getOptionsFromConfig(option.options) }); continue; } const value = String(option.value); const isSelected = option.selected || this._config.value && this._config.value.includes(value); _options.push({ ...option, value, ...(isSelected && { selected: true }), ...(option.disabled && { disabled: true }) }); if (isSelected) { this._selected.push({ value: String(option.value), text: option.text }); } } return _options; } _getOptionsFromElement(node = this._element) { const nodes = Array.from(node.childNodes).filter(element => element.nodeName === 'OPTION' || element.nodeName === 'OPTGROUP'); const options = []; for (const node of nodes) { if (node.nodeName === 'OPTION' && node.value) { const value = String(node.value); const text = node.innerHTML; const isSelected = node.selected || this._config.value && this._config.value.includes(node.value); options.push({ value, text, selected: isSelected, disabled: node.disabled }); if (node.selected || isSelected) { this._selected.push({ value, text: node.innerHTML, ...(node.disabled && { disabled: true }) }); } } if (node.nodeName === 'OPTGROUP') { options.push({ label: node.label, options: this._getOptionsFromElement(node) }); } } return options; } _configureNativeSelect() { this._element.classList.add(CLASS_NAME_SELECT); if (this._config.multiple) { this._element.setAttribute('multiple', true); } if (this._config.required) { this._element.setAttribute('required', true); } } _createNativeOptions(parentElement, options) { for (const option of options) { if (typeof option.options === 'undefined') { const opt = document.createElement('OPTION'); opt.value = option.value; if (option.disabled === true) { opt.setAttribute('disabled', 'disabled'); } if (option.selected === true) { opt.setAttribute('selected', 'selected'); } opt.innerHTML = option.text; parentElement.append(opt); } else { const optgroup = document.createElement('optgroup'); optgroup.label = option.label; this._createNativeOptions(optgroup, option.options); parentElement.append(optgroup); } } } _hideNativeSelect() { this._element.tabIndex = '-1'; this._element.style.display = 'none'; } _createSelect() { const multiSelectEl = document.createElement('div'); multiSelectEl.classList.add(CLASS_NAME_SELECT); multiSelectEl.classList.toggle('is-invalid', this._config.invalid); multiSelectEl.classList.toggle('is-valid', this._config.valid); multiSelectEl.setAttribute('aria-expanded', 'false'); if (this._config.disabled) { this._element.classList.add(CLASS_NAME_DISABLED); } for (const className of this._getClassNames()) { multiSelectEl.classList.add(className); } this._clone = multiSelectEl; this._element.parentNode.insertBefore(multiSelectEl, this._element.nextSibling); this._createSelection(); this._createButtons(); if (this._config.search) { this._createSearchInput(); this._updateSearch(); } if (this._config.name || this._element.id || this._element.name) { this._element.setAttribute('name', this._config.name || this._element.name || `multi-select-${this._element.id}`); } this._createOptionsContainer(); this._hideNativeSelect(); this._updateOptionsList(); } _createSelection() { const togglerEl = document.createElement('div'); togglerEl.classList.add(CLASS_NAME_INPUT_GROUP); this._togglerElement = togglerEl; if (!this._config.search && !this._config.disabled) { togglerEl.tabIndex = 0; } const selectionEl = document.createElement('div'); selectionEl.classList.add(CLASS_NAME_SELECTION); if (this._config.multiple && this._config.selectionType === 'tags') { selectionEl.classList.add(CLASS_NAME_SELECTION_TAGS); } togglerEl.append(selectionEl); this._clone.append(togglerEl); this._updateSelection(); this._selectionElement = selectionEl; } _createButtons() { const buttons = document.createElement('div'); buttons.classList.add('form-multi-select-buttons'); if (!this._config.disabled && this._config.cleaner && this._config.multiple) { const cleaner = document.createElement('button'); cleaner.type = 'button'; cleaner.classList.add(CLASS_NAME_CLEANER); cleaner.style.display = 'none'; cleaner.setAttribute('aria-label', this._config.ariaCleanerLabel); buttons.append(cleaner); this._selectionCleanerElement = cleaner; } const indicator = document.createElement('button'); indicator.type = 'button'; indicator.classList.add('form-multi-select-indicator'); if (this._config.disabled) { indicator.tabIndex = -1; } buttons.append(indicator); this._indicatorElement = indicator; this._togglerElement.append(buttons); this._updateSelectionCleaner(); } _createPopper() { if (typeof Popper__namespace === 'undefined') { throw new TypeError('CoreUI\'s multi select require Popper (https://popper.js.org)'); } const popperConfig = { modifiers: [{ name: 'preventOverflow', options: { boundary: 'clippingParents' } }, { name: 'offset', options: { offset: [0, 2] } }], placement: index_js.isRTL() ? 'bottom-end' : 'bottom-start' }; this._popper = Popper__namespace.createPopper(this._togglerElement, this._menu, popperConfig); } _createSearchInput() { const input = document.createElement('input'); input.classList.add(CLASS_NAME_SEARCH); if (this._config.disabled) { input.disabled = true; } this._searchElement = input; this._updateSearchSize(); this._selectionElement.append(input); } _createOptionsContainer() { const dropdownDiv = document.createElement('div'); dropdownDiv.classList.add(CLASS_NAME_SELECT_DROPDOWN); if (this._config.selectAll && this._config.multiple) { const selectAllButton = document.createElement('button'); selectAllButton.type = 'button'; selectAllButton.classList.add(CLASS_NAME_SELECT_ALL); selectAllButton.innerHTML = this._config.selectAllLabel; this._selectAllElement = selectAllButton; dropdownDiv.append(selectAllButton); } const optionsDiv = document.createElement('div'); optionsDiv.classList.add(CLASS_NAME_OPTIONS); if (this._config.optionsMaxHeight !== 'auto') { optionsDiv.style.maxHeight = `${this._config.optionsMaxHeight}px`; optionsDiv.style.overflow = 'auto'; } dropdownDiv.append(optionsDiv); const { container } = this._config; if (container) { container.append(dropdownDiv); } else { this._clone.append(dropdownDiv); } this._createOptions(optionsDiv, this._options); this._optionsElement = optionsDiv; this._menu = dropdownDiv; } _createOptions(parentElement, options) { for (const option of options) { if (typeof option.value !== 'undefined') { const optionDiv = document.createElement('div'); optionDiv.classList.add(CLASS_NAME_OPTION); if (option.disabled) { optionDiv.classList.add(CLASS_NAME_DISABLED); } if (this._config.optionsStyle === 'checkbox') { optionDiv.classList.add(CLASS_NAME_OPTION_WITH_CHECKBOX); } optionDiv.dataset.value = String(option.value); optionDiv.tabIndex = 0; optionDiv.innerHTML = option.text; parentElement.append(optionDiv); } if (typeof option.label !== 'undefined') { const optgroup = document.createElement('div'); optgroup.classList.add(CLASS_NAME_OPTGROUP); const optgrouplabel = document.createElement('div'); optgrouplabel.innerHTML = option.label; optgrouplabel.classList.add(CLASS_NAME_OPTGROUP_LABEL); optgroup.append(optgrouplabel); this._createOptions(optgroup, option.options); parentElement.append(optgroup); } } } _createTag(value, text, disabled) { const tag = document.createElement('div'); tag.classList.add(CLASS_NAME_TAG); tag.dataset.value = value; tag.innerHTML = text; if (!this._config.disabled && disabled !== true) { const closeBtn = document.createElement('button'); closeBtn.type = 'button'; closeBtn.classList.add(CLASS_NAME_TAG_DELETE); closeBtn.setAttribute('aria-label', 'Close'); EventHandler.on(closeBtn, EVENT_CLICK, event => { event.preventDefault(); event.stopPropagation(); tag.remove(); this._deselectOption(value); }); tag.append(closeBtn); } return tag; } _onOptionsClick(element) { if (!element.classList.contains(CLASS_NAME_OPTION) || element.classList.contains(CLASS_NAME_LABEL)) { return; } const value = String(element.dataset.value); const { text } = this._findOptionByValue(value); if (this._config.multiple && element.classList.contains(CLASS_NAME_SELECTED)) { this._deselectOption(value); } else if (this._config.multiple && !element.classList.contains(CLASS_NAME_SELECTED)) { this._selectOption(value, text); } else if (!this._config.multiple) { this._selectOption(value, text); } if (!this._config.multiple) { this.hide(); this.search(''); this._searchElement.value = null; } } _findOptionByValue(value, options = this._options) { for (const option of options) { if (String(option.value) === value) { return option; } if (option.options && Array.isArray(option.options)) { const found = this._findOptionByValue(value, option.options); if (found) { return found; } } } return null; } _selectOption(value, text) { if (!this._config.multiple) { this.deselectAll(); } if (this._selected.filter(option => option.value === String(value)).length === 0) { this._selected.push({ value: String(value), text }); } const nativeOption = SelectorEngine.findOne(`option[value="${value}"]`, this._element); if (nativeOption) { nativeOption.selected = true; } const option = SelectorEngine.findOne(`[data-value="${value}"]`, this._optionsElement); if (option) { option.classList.add(CLASS_NAME_SELECTED); } EventHandler.trigger(this._element, EVENT_CHANGED, { value: this._selected }); this._updateSelection(); this._updateSelectionCleaner(); this._updateSearch(); this._updateSearchSize(); } _deselectOption(value) { this._selected = this._selected.filter(option => option.value !== String(value)); SelectorEngine.findOne(`option[value="${value}"]`, this._element).selected = false; const option = SelectorEngine.findOne(`[data-value="${value}"]`, this._optionsElement); if (option) { option.classList.remove(CLASS_NAME_SELECTED); } EventHandler.trigger(this._element, EVENT_CHANGED, { value: this._selected }); this._updateSelection(); this._updateSelectionCleaner(); this._updateSearch(); this._updateSearchSize(); } _deselectLastOption() { if (this._selected.length > 0) { const last = this._selected.findLast(option => option.disabled !== true); if (last) { this._deselectOption(last.value); } } } _updateSelection() { const selection = SelectorEngine.findOne(SELECTOR_SELECTION, this._clone); const search = SelectorEngine.findOne(SELECTOR_SEARCH, this._clone); if (this._selected.length === 0 && !this._config.search) { selection.innerHTML = `<span class="form-multi-select-placeholder">${this._config.placeholder}</span>`; return; } if (this._config.multiple && this._config.selectionType === 'counter' && !this._config.search) { selection.innerHTML = `${this._selected.length} ${this._config.selectionTypeCounterText}`; } if (this._config.multiple && this._config.selectionType === 'tags') { selection.innerHTML = ''; for (const option of this._selected) { selection.append(this._createTag(option.value, option.text, option.disabled)); } } if (this._config.multiple && this._config.selectionType === 'text') { selection.innerHTML = this._selected.map((option, index) => `<span>${option.text}${index === this._selected.length - 1 ? '' : ','}&nbsp;</span>`).join(''); } if (!this._config.multiple && this._selected.length > 0 && !this._config.search) { selection.innerHTML = this._selected[0].text; } if (search) { selection.append(search); } if (this._popper) { this._popper.update(); } } _updateSelectionCleaner() { if (!this._config.cleaner || this._selectionCleanerElement === null) { return; } const selectionCleaner = SelectorEngine.findOne(SELECTOR_CLEANER, this._clone); if (this._selected.length > 0) { selectionCleaner.style.removeProperty('display'); return; } selectionCleaner.style.display = 'none'; } _updateSearch() { if (!this._config.search) { return; } // Select single if (!this._config.multiple && this._selected.length > 0) { this._searchElement.placeholder = this._selected[0].text; return; } if (!this._config.multiple && this._selected.length === 0) { this._searchElement.placeholder = this._config.placeholder; return; } // Select multiple if (this._config.multiple && this._selected.length > 0 && this._config.selectionType !== 'counter') { this._searchElement.removeAttribute('placeholder'); return; } if (this._config.multiple && this._selected.length === 0) { this._searchElement.placeholder = this._config.placeholder; return; } if (this._config.multiple && this._config.selectionType === 'counter') { this._searchElement.placeholder = `${this._selected.length} ${this._config.selectionTypeCounterText}`; } } _updateSearchSize(size = 2) { if (!this._searchElement || !this._config.multiple) { return; } if (this._selected.length > 0 && (this._config.selectionType === 'tags' || this._config.selectionType === 'text')) { this._searchElement.size = size; return; } if (this._selected.length === 0 && (this._config.selectionType === 'tags' || this._config.selectionType === 'text')) { this._searchElement.removeAttribute('size'); } } _onSearchChange(element) { if (element) { this.search(element.value); this._updateSearchSize(element.value.length + 1); } } _updateOptionsList(options = this._options) { for (const option of options) { if (option.label) { this._updateOptionsList(option.options); continue; } if (option.selected) { this._selectOption(option.value, option.text); } } } _isVisible(element) { const style = window.getComputedStyle(element); return style.display !== 'none'; } _isShown() { return this._clone.classList.contains(CLASS_NAME_SHOW); } _filterOptionsList() { const options = SelectorEngine.find(SELECTOR_OPTION, this._menu); let visibleOptions = 0; for (const option of options) { // eslint-disable-next-line unicorn/prefer-includes if (option.textContent.toLowerCase().indexOf(this._search) === -1) { option.style.display = 'none'; } else { option.style.removeProperty('display'); visibleOptions++; } const optgroup = option.closest(SELECTOR_OPTGROUP); if (optgroup) { // eslint-disable-next-line unicorn/prefer-array-some if (SelectorEngine.children(optgroup, SELECTOR_OPTION).filter(element => this._isVisible(element)).length > 0) { optgroup.style.removeProperty('display'); } else { optgroup.style.display = 'none'; } } } if (visibleOptions > 0) { if (SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu).remove(); } return; } if (visibleOptions === 0) { const placeholder = document.createElement('div'); placeholder.classList.add(CLASS_NAME_OPTIONS_EMPTY); placeholder.innerHTML = this._config.searchNoResultsLabel; if (!SelectorEngine.findOne(SELECTOR_OPTIONS_EMPTY, this._menu)) { SelectorEngine.findOne(SELECTOR_OPTIONS, this._menu).append(placeholder); } } } _selectMenuItem({ key, target }) { const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index_js.isVisible(element)); if (!items.length) { return; } // if target isn't included in items (e.g. when expanding the dropdown) // allow cycling to get the last item in case key equals ARROW_UP_KEY index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus(); } _configAfterMerge(config) { if (config.container === true) { config.container = document.body; } if (typeof config.container === 'object' || typeof config.container === 'string') { config.container = index_js.getElement(config.container); } if (typeof config.value === 'number') { config.value = [String(config.value)]; } if (typeof config.value === 'string') { config.value = config.value.split(/,\s*/).map(String); } return config; } // Static static multiSelectInterface(element, config) { const data = MultiSelect.getOrCreateInstance(element, config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } } static jQueryInterface(config) { return this.each(function () { MultiSelect.multiSelectInterface(this, config); }); } static clearMenus(event) { if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) { return; } const selects = SelectorEngine.find(SELECTOR_SELECT); for (let i = 0, len = selects.length; i < len; i++) { const context = Data.get(selects[i], DATA_KEY); ({ relatedTarget: selects[i] }); if (event && event.type === 'click') ; if (!context) { continue; } if (!context._clone.classList.contains(CLASS_NAME_SHOW)) { continue; } if (context._clone.contains(event.target)) { continue; } context.hide(); EventHandler.trigger(context._element, EVENT_HIDDEN); } } } /** * Data API implementation */ EventHandler.on(window, EVENT_LOAD_DATA_API, () => { for (const ms of SelectorEngine.find(SELECTOR_SELECT)) { if (ms.tabIndex !== -1) { MultiSelect.multiSelectInterface(ms); } } }); EventHandler.on(document, EVENT_CLICK_DATA_API, MultiSelect.clearMenus); EventHandler.on(document, EVENT_KEYUP_DATA_API, MultiSelect.clearMenus); /** * jQuery */ index_js.defineJQueryPlugin(MultiSelect); return MultiSelect; })); //# sourceMappingURL=multi-select.js.map