const smRadio = document.createElement('template') smRadio.innerHTML = `
` window.customElements.define('sm-radio', class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }).append(smRadio.content.cloneNode(true)) this.radio = this.shadowRoot.querySelector('.radio'); this.reset = this.reset.bind(this) this.dispatchChangeEvent = this.dispatchChangeEvent.bind(this) this.dispatchGroupEvent = this.dispatchGroupEvent.bind(this) this.handleKeyDown = this.handleKeyDown.bind(this) this.handleClick = this.handleClick.bind(this) this.handleRadioGroup = this.handleRadioGroup.bind(this) this.uniqueId this.options } static get observedAttributes() { return ['value', 'disabled', 'checked'] } get disabled() { return this.hasAttribute('disabled') } set disabled(val) { if (val) { this.setAttribute('disabled', '') } else { this.removeAttribute('disabled') } } get checked() { return this.hasAttribute('checked') } set checked(value) { if (value) { this.setAttribute('checked', '') } else { this.removeAttribute('checked') } } set value(val) { this.setAttribute('value', val) } get value() { return this.getAttribute('value') } reset() { this.removeAttribute('checked') } dispatchChangeEvent() { this.dispatchEvent(new CustomEvent('change', this.options)) } dispatchGroupEvent() { if (this.hasAttribute('name') && this.getAttribute('name').trim() !== '') { this.dispatchEvent(new CustomEvent(`changed${this.getAttribute('name')}`, this.options)) } } handleKeyDown(e) { if (e.code === "Space") { e.preventDefault() this.handleClick() } } handleClick() { if (!this.hasAttribute('checked')) { this.setAttribute('checked', '') this.dispatchGroupEvent() } } handleRadioGroup(e) { if (e.detail.uid !== this.uniqueId) { this.reset() } } randString(length) { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < length; i++) result += characters.charAt(Math.floor(Math.random() * characters.length)); return result; } connectedCallback() { this.uniqueId = this.randString(8) this.options = { bubbles: true, composed: true, detail: { uid: this.uniqueId, value: this.value, } } if (!this.hasAttribute('disabled')) { this.setAttribute('tabindex', '0') } this.setAttribute('role', 'radio') if (!this.hasAttribute('checked')) { this.setAttribute('aria-checked', 'false') } this.addEventListener('keydown', this.handleKeyDown) this.addEventListener('click', this.handleClick) if (this.hasAttribute('name') && this.getAttribute('name').trim() !== '') { document.addEventListener(`changed${this.getAttribute('name')}`, this.handleRadioGroup) } } attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { if (name === 'checked') { this.dispatchChangeEvent() } else if (name === 'disabled') { if (this.hasAttribute('disabled')) { this.removeAttribute('tabindex') } else { this.setAttribute('tabindex', '0') } } } } disconnectedCallback() { this.removeEventListener('keydown', this.handleKeyDown) this.removeEventListener('change', this.handleClick) } });