/* * Created by David Adams * https://codeshack.io/dynamic-select-images-html-javascript/ * * Released under the MIT license */ class DynamicSelect { constructor(element, options = {}) { let defaults = { placeholder: 'Select an option', columns: 1, name: '', width: '', height: '', data: [], onChange: function() {} }; this.options = Object.assign(defaults, options); this.selectElement = typeof element === 'string' ? document.querySelector(element) : element; for(const prop in this.selectElement.dataset) { if (this.options[prop] !== undefined) { this.options[prop] = this.selectElement.dataset[prop]; } } this.name = this.selectElement.getAttribute('name') ? this.selectElement.getAttribute('name') : 'dynamic-select-' + Math.floor(Math.random() * 1000000); if (!this.options.data.length) { let options = this.selectElement.querySelectorAll('option'); for (let i = 0; i < options.length; i++) { this.options.data.push({ value: options[i].value, text: options[i].innerHTML, img: options[i].getAttribute('data-img'), selected: options[i].selected, html: options[i].getAttribute('data-html'), imgWidth: options[i].getAttribute('data-img-width'), imgHeight: options[i].getAttribute('data-img-height') }); } } this.element = this._template(); this.selectElement.replaceWith(this.element); this._updateSelected(); this._eventHandlers(); } _template() { let optionsHTML = ''; for (let i = 0; i < this.data.length; i++) { let optionWidth = 100 / this.columns; let optionContent = ''; if (this.data[i].html) { optionContent = this.data[i].html; } else { optionContent = ` ${this.data[i].img ? `${this.data[i].text}` : ''} ${this.data[i].text ? '' + this.data[i].text + '' : ''} `; } optionsHTML += `
${optionContent}
`; } let template = `
${this.placeholder}
${optionsHTML}
`; let element = document.createElement('div'); element.innerHTML = template; return element; } _eventHandlers() { this.element.querySelectorAll('.dynamic-select-option').forEach(option => { option.onclick = () => { this.element.querySelectorAll('.dynamic-select-selected').forEach(selected => selected.classList.remove('dynamic-select-selected')); option.classList.add('dynamic-select-selected'); this.element.querySelector('.dynamic-select-header').innerHTML = option.innerHTML; this.element.querySelector('input').value = option.getAttribute('data-value'); this.data.forEach(data => data.selected = false); this.data.filter(data => data.value == option.getAttribute('data-value'))[0].selected = true; this.element.querySelector('.dynamic-select-header').classList.remove('dynamic-select-header-active'); this.options.onChange(option.getAttribute('data-value'), option.querySelector('.dynamic-select-option-text') ? option.querySelector('.dynamic-select-option-text').innerHTML : '', option); }; }); this.element.querySelector('.dynamic-select-header').onclick = () => { this.element.querySelector('.dynamic-select-header').classList.toggle('dynamic-select-header-active'); }; if (this.selectElement.id && document.querySelector('label[for="' + this.selectElement.id + '"]')) { document.querySelector('label[for="' + this.selectElement.id + '"]').onclick = () => { this.element.querySelector('.dynamic-select-header').classList.toggle('dynamic-select-header-active'); }; } document.addEventListener('click', event => { if (!event.target.closest('.' + this.name) && !event.target.closest('label[for="' + this.selectElement.id + '"]')) { this.element.querySelector('.dynamic-select-header').classList.remove('dynamic-select-header-active'); } }); } _updateSelected() { if (this.selectedValue) { this.element.querySelector('.dynamic-select-header').innerHTML = this.element.querySelector('.dynamic-select-selected').innerHTML; } } get selectedValue() { let selected = this.data.filter(option => option.selected); selected = selected.length ? selected[0].value : ''; return selected; } set data(value) { this.options.data = value; } get data() { return this.options.data; } set selectElement(value) { this.options.selectElement = value; } get selectElement() { return this.options.selectElement; } set element(value) { this.options.element = value; } get element() { return this.options.element; } set placeholder(value) { this.options.placeholder = value; } get placeholder() { return this.options.placeholder; } set columns(value) { this.options.columns = value; } get columns() { return this.options.columns; } set name(value) { this.options.name = value; } get name() { return this.options.name; } set width(value) { this.options.width = value; } get width() { return this.options.width; } set height(value) { this.options.height = value; } get height() { return this.options.height; } } document.querySelectorAll('[data-dynamic-select]').forEach(select => new DynamicSelect(select));