UNPKG

digitalmarketplace-frontend

Version:

Digital Marketplace Frontend contains assets and components used in Digital Marketplace projects

1 lines 12.7 kB
{"version":3,"file":"option-select.bundle.mjs","sources":["../../../../src/digitalmarketplace/components/option-select/option-select.ts"],"sourcesContent":["import { DigitalMarketplaceFrontendComponent } from '../../digitalmarketplace-frontend-component'\n\nclass OptionSelect implements DigitalMarketplaceFrontendComponent {\n static moduleName = 'dm-option-select'\n\n $optionSelect: JQuery<HTMLElement>\n $options: JQuery<HTMLInputElement>\n $optionsContainer: JQuery<HTMLElement>\n $optionList: JQuery<HTMLElement>\n $allCheckboxes: JQuery<HTMLElement>\n checkedCheckboxes: HTMLElement[]\n\n constructor ($module: JQuery<HTMLElement>) {\n this.$optionSelect = $module\n this.$options = this.$optionSelect.find<HTMLInputElement>('input[type=\"checkbox\"]')\n this.$optionsContainer = this.$optionSelect.find('.js-options-container')\n this.$optionList = this.$optionsContainer.find('.js-auto-height-inner')\n this.$allCheckboxes = this.$optionsContainer.find('.govuk-checkboxes__item')\n this.checkedCheckboxes = []\n }\n\n init () {\n // Attach listener to update checked count\n this.$optionSelect.on('change', (event) => {\n const changedEl = event.target\n\n if (changedEl.tagName === 'INPUT' && changedEl.getAttribute('type') === 'checkbox') {\n this.updateCheckedCount()\n }\n })\n\n // Replace div.container-head with a button\n this.replaceHeadingSpanWithButton()\n\n // Add js-collapsible class to parent for CSS\n this.$optionSelect.addClass('js-collapsible')\n\n // Add open/close listeners\n this.$optionSelect.find('.js-container-button').on('click', (event) => {\n this.toggleOptionSelect(event)\n })\n\n if (this.$optionSelect.data().closedOnLoad) {\n this.close()\n } else {\n this.setupHeight()\n }\n\n const checkedString = this.checkedString()\n\n if (checkedString) {\n this.attachCheckedCounter(checkedString)\n }\n }\n\n getAllCheckedCheckboxes () {\n this.checkedCheckboxes = []\n\n this.$allCheckboxes.each((_index, checkbox) => {\n if ($(checkbox).find('input[type=checkbox]').is(':checked')) {\n this.checkedCheckboxes.push(checkbox)\n }\n })\n }\n\n replaceHeadingSpanWithButton () {\n /* Replace the span within the heading with a button element. This is based on feedback from Léonie Watson.\n * The button has all of the accessibility hooks that are used by screen readers and etc.\n * We do this in the JavaScript because if the JavaScript is not active then the button shouldn't\n * be there as there is no JS to handle the click event.\n */\n const $containerHead = this.$optionSelect.find('.js-container-button')\n const jsContainerHeadHTML = $containerHead.html()\n\n // Create button and replace the preexisting html with the button.\n const $button = document.createElement('button')\n $button.classList.add('js-container-button', 'dm-option-select__title', 'dm-option-select__button')\n // Add type button to override default type submit when this component is used within a form\n $button.setAttribute('type', 'button')\n $button.setAttribute('aria-expanded', 'true')\n $button.setAttribute('id', $containerHead.attr('id') as string)\n $button.setAttribute('aria-controls', this.$optionsContainer.attr('id') as string)\n $button.innerHTML = jsContainerHeadHTML\n $containerHead.after($button.outerHTML)\n $containerHead.remove()\n }\n\n attachCheckedCounter (checkedString: string) {\n this.$optionSelect.find('.js-container-button').after(`<div class=\"dm-option-select__selected-counter js-selected-counter\">${checkedString}</div>`)\n }\n\n updateCheckedCount () {\n const checkedString = this.checkedString()\n const $checkedStringElement = this.$optionSelect.find('.js-selected-counter')\n\n if (checkedString) {\n if ($checkedStringElement.length) {\n $checkedStringElement.text(checkedString)\n } else {\n this.attachCheckedCounter(checkedString)\n }\n } else {\n $checkedStringElement.remove()\n }\n }\n\n checkedString () {\n this.getAllCheckedCheckboxes()\n const count = this.checkedCheckboxes.length\n\n let checkedString = ''\n\n if (count > 0) {\n checkedString = count + ' selected'\n }\n\n return checkedString\n }\n\n toggleOptionSelect (event: JQuery.ClickEvent) {\n if (this.isClosed()) {\n this.open()\n } else {\n this.close()\n }\n event.preventDefault()\n }\n\n open () {\n if (this.isClosed()) {\n this.$optionSelect.find('.js-container-button').attr('aria-expanded', 'true')\n this.$optionSelect.removeClass('js-closed')\n this.$optionSelect.addClass('js-opened')\n if (!this.$optionsContainer.css('height')) {\n this.setupHeight()\n }\n }\n }\n\n close () {\n this.$optionSelect.removeClass('js-opened')\n this.$optionSelect.addClass('js-closed')\n this.$optionSelect.find('.js-container-button').attr('aria-expanded', 'false')\n }\n\n isClosed () {\n return this.$optionSelect.hasClass('js-closed')\n }\n\n setContainerHeight (height: number) {\n this.$optionsContainer.css('height', height + 'px')\n }\n\n isCheckboxVisible ($checkbox: JQuery<HTMLInputElement>) {\n const initialOptionContainerHeight = this.$optionsContainer.get(0)?.clientHeight as number\n const optionListOffsetTop = (this.$optionList.get(0) as HTMLElement).getBoundingClientRect().top + document.body.scrollTop\n const distanceFromTopOfContainer = (($checkbox.get(0) as HTMLElement).getBoundingClientRect().top + document.body.scrollTop) - optionListOffsetTop\n return distanceFromTopOfContainer < initialOptionContainerHeight\n }\n\n getVisibleCheckboxes () {\n const visibleCheckboxes = this.$options.get().filter((checkbox) => this.isCheckboxVisible($(checkbox)))\n\n // add an extra checkbox, if the label of the first is too long it collapses onto itself\n if (visibleCheckboxes.length < this.$options.length) {\n visibleCheckboxes.push(this.$options.get(visibleCheckboxes.length) as HTMLInputElement)\n }\n\n return visibleCheckboxes\n }\n\n setupHeight () {\n const optionsContainer = this.$optionsContainer.get(0) as HTMLElement\n const optionList = this.$optionList.get(0) as HTMLElement\n\n let initialOptionContainerHeight = optionsContainer.clientHeight\n let height = optionList.offsetHeight\n\n // check whether this is hidden by progressive disclosure,\n // because height calculations won't work\n if (optionsContainer.offsetParent === null) {\n initialOptionContainerHeight = 200\n height = 200\n }\n\n // Resize if the list is only slightly bigger than its container\n if (height < initialOptionContainerHeight + 50) {\n this.setContainerHeight(height + 1)\n return\n }\n\n // Resize to cut last item cleanly in half\n const visibleCheckboxes = this.getVisibleCheckboxes()\n const lastVisibleCheckbox = visibleCheckboxes[visibleCheckboxes.length - 1] as HTMLInputElement\n const position = (lastVisibleCheckbox?.parentNode as HTMLElement).offsetTop // parent element is relative\n this.setContainerHeight(position + (parseFloat(window.getComputedStyle(lastVisibleCheckbox, null).height.replace('px', '')) / 1.5))\n }\n}\n\nexport { OptionSelect }\n"],"names":[],"mappings":"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"}