{"version":3,"file":"filter-multi-select-bundle.js","sources":["../src/FilterMultiSelect.ts","../src/filter-multi-select.ts"],"sourcesContent":["/*! \n * Multiple select dropdown with filter jQuery plugin.\n * Copyright (C) 2022 Andrew Wagner github.com/andreww1011\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n * \n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n * \n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301\n * USA\n */\nimport $, { map } from 'jquery';\n\nconst NULL_OPTION = new class implements Option {\n initialize(): void {}\n select(): void {}\n deselect(): void {}\n enable(): void {}\n disable(): void {}\n isSelected(): boolean {return false;}\n isDisabled(): boolean {return true;}\n getListItem(): HTMLElement {return document.createElement('div');}\n getSelectedItemBadge(): HTMLElement {return document.createElement('div');}\n getLabel(): string {return 'NULL_OPTION'}\n getValue(): string {return 'NULL_OPTION'}\n show(): void {}\n hide(): void {}\n isHidden(): boolean {return true;}\n focus(): void {}\n activate(): void {}\n deactivate(): void {}\n} \n\ninterface Option {\n initialize(): void;\n select(): void;\n deselect(): void;\n enable(): void;\n disable(): void;\n isSelected(): boolean;\n isDisabled(): boolean;\n getListItem(): HTMLElement;\n getSelectedItemBadge(): HTMLElement;\n getLabel(): string;\n getValue(): string;\n show(): void;\n hide(): void;\n isHidden(): boolean;\n focus(): void;\n activate(): void;\n deactivate(): void;\n}\n\ninterface SelectAllOption extends Option {\n markSelectAll(): void;\n markSelectPartial(): void;\n markSelectAllNotDisabled(): void;\n markDeselect(): void;\n}\n\nconst DEBUG = false;\n\nexport default class FilterMultiSelect {\n\n private static SingleOption = class implements Option {\n protected div: HTMLDivElement;\n protected checkbox: HTMLInputElement;\n protected labelFor: HTMLLabelElement;\n protected closeButton: HTMLButtonElement;\n protected selectedItemBadge: HTMLSpanElement;\n protected fms: FilterMultiSelect;\n protected active: boolean;\n protected disabled: boolean;\n private initiallyChecked: boolean;\n \n constructor(fms: FilterMultiSelect, row: number, name:string, label: string, value: string, checked: boolean, disabled: boolean) {\n this.fms = fms;\n this.div = document.createElement('div');\n this.checkbox = document.createElement('input');\n this.checkbox.type = 'checkbox';\n let id: string = name + '-' + row.toString();\n let nchbx: string = id + '-chbx';\n this.checkbox.id = nchbx;\n this.checkbox.name = name;\n this.checkbox.value = value;\n this.initiallyChecked = checked;\n this.checkbox.checked = false;\n this.checkbox.disabled = disabled;\n this.labelFor = document.createElement('label');\n this.labelFor.htmlFor = nchbx;\n this.labelFor.textContent = label;\n this.div.append(this.checkbox, this.labelFor);\n this.closeButton = document.createElement('button');\n this.closeButton.type = 'button';\n this.closeButton.innerHTML = '×';\n this.selectedItemBadge = document.createElement('span');\n this.selectedItemBadge.setAttribute('data-id',id);\n this.selectedItemBadge.textContent = label;\n this.selectedItemBadge.append(this.closeButton);\n this.disabled = disabled;\n this.active = true;\n }\n \n private log(m: string, e: Event):void {\n if (DEBUG) {\n console.log(e.timeStamp + \" - \" + m + \":\" + e.type + \":\" + e.target)\n }\n }\n \n public initialize(): void {\n this.div.className = 'dropdown-item custom-control';\n this.checkbox.className = 'custom-control-input custom-checkbox';\n this.labelFor.className = 'custom-control-label';\n this.selectedItemBadge.className = 'item';\n if (this.initiallyChecked) {\n this.selectNoDisabledCheck();\n }\n if (this.disabled) {\n this.setDisabledViewState();\n }\n this.fms.update();\n this.checkbox.addEventListener('change', (e: Event) => {\n e.stopPropagation();\n if (this.isDisabled() || this.fms.isDisabled()) {\n e.preventDefault();\n return;\n }\n if (DEBUG) {\n this.log('checkbox',e);\n }\n \n if (this.isSelected()) {\n this.select();\n } else {\n this.deselect();\n }\n let numShown = this.fms.showing.length;\n if (numShown === 1) {\n this.fms.clearFilterAndRefocus();\n }\n }, true);\n this.checkbox.addEventListener('keyup', (e: KeyboardEvent) => {\n if (DEBUG) {\n this.log('checkbox',e);\n }\n switch (e.key) {\n case \"Enter\":\n e.stopPropagation();\n this.checkbox.dispatchEvent(new MouseEvent('click'));\n break;\n default:\n break;\n }\n }, true)\n this.closeButton.addEventListener('click', (e: Event) => {\n e.stopPropagation();\n if (this.isDisabled() || this.fms.isDisabled()) return;\n if (DEBUG) {\n this.log('closeButton',e);\n }\n this.deselect();\n if (!this.fms.isClosed()) {\n this.fms.refocusFilter();\n }\n }, true);\n this.checkbox.tabIndex = -1;\n this.closeButton.tabIndex = -1;\n }\n \n public select(): void {\n if (this.isDisabled()) return;\n this.selectNoDisabledCheck();\n this.fms.update();\n }\n\n private selectNoDisabledCheck(): void {\n if (!this.fms.canSelect() || !this.isActive()) return;\n this.checkbox.checked = true;\n this.fms.queueOption(this);\n this.fms.dispatchSelectedEvent(this);\n }\n \n public deselect(): void {\n if (this.isDisabled()) return;\n this.checkbox.checked = false;\n this.fms.unqueueOption(this);\n this.fms.dispatchDeselectedEvent(this);\n this.fms.update();\n }\n \n public enable(): void {\n this.disabled = false;\n this.setEnabledViewState();\n this.fms.update();\n }\n\n private setEnabledViewState(): void {\n this.checkbox.disabled = false;\n this.selectedItemBadge.classList.remove('disabled');\n }\n \n public disable(): void {\n this.disabled = true;\n this.setDisabledViewState();\n this.fms.update();\n }\n\n private setDisabledViewState(): void {\n this.checkbox.disabled = true;\n this.selectedItemBadge.classList.add('disabled');\n }\n \n public isSelected(): boolean {\n return this.checkbox.checked;\n }\n \n public isDisabled(): boolean {\n return this.checkbox.disabled;\n }\n \n public getListItem(): HTMLElement {\n return this.div;\n }\n \n public getSelectedItemBadge(): HTMLElement {\n return this.selectedItemBadge;\n }\n \n public getLabel(): string {\n return this.labelFor.textContent;\n }\n \n public getValue(): string {\n return this.checkbox.value;\n }\n \n public show(): void {\n this.div.hidden = false;\n }\n \n public hide(): void {\n this.div.hidden = true;\n }\n \n public isHidden(): boolean {\n return this.div.hidden;\n }\n\n public focus(): void {\n this.labelFor.focus();\n }\n\n isActive(): boolean {\n return this.active;\n }\n\n public activate(): void {\n this.active = true;\n if (!this.disabled) {\n this.setEnabledViewState();\n }\n }\n\n public deactivate(): void {\n this.active = false;\n this.setDisabledViewState();\n }\n }\n\n private static createOptions(fms: FilterMultiSelect, name: string, htmlOptions: Array, jsOptions: Array<[label:string, value:string, selected?:boolean, disabled?:boolean]>): Array