Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save micah1701/1da155bfcb26059462accb55c4952e7c to your computer and use it in GitHub Desktop.
Save micah1701/1da155bfcb26059462accb55c4952e7c to your computer and use it in GitHub Desktop.
A JavaScript class that converts an existing HTML Select input element to a functioning Bulma.io Dropdown component with a search filter
class htmlSelect2BulmaDropownWithFilter {
constructor(HTMLSelectElement_or_ElementId) {
this.selectElement = (typeof (HTMLSelectElement_or_ElementId) == "string") ? document.getElementById(HTMLSelectElement_or_ElementId) : HTMLSelectElement_or_ElementId;
if (this.originalOptions == null) {
this.originalOptions = Array.from(this.selectElement.options).map(option => ({ value: option.value, text: option.text }));
}
this.options = Array.from(this.selectElement.options).map(option => ({ value: option.value, text: option.text })); //selectElement.options;
this.filter = "";
this.filteredOptions = [];
this.selectElement.parentElement.querySelectorAll('.dropdown').forEach(dropdownElement => {
dropdownElement.remove();
});
this.dropdown = this.selectElement.insertAdjacentElement('afterend', this.drawDropdown());
this.dropdownContent = this.dropdown.querySelector('.dropdown-content');
this.input = this.dropdown.querySelector('input');
this.init();
}
drawDropdown() {
const dropdown = document.createElement('div');
dropdown.classList.add('dropdown');
const dropdownTrigger = document.createElement('div');
dropdownTrigger.classList.add('dropdown-trigger');
const field = document.createElement('div');
field.classList.add('field');
const control = document.createElement('p');
control.classList.add('control', 'is-expanded', 'has-icons-right');
const input = document.createElement('input');
input.classList.add('input', 'is-clickable');
input.type = 'search';
input.placeholder = 'Search...';
const icon = document.createElement('span');
icon.classList.add('icon', 'is-right', 'is-small');
const i = document.createElement('i');
i.classList.add('fa', 'fa-search');
icon.appendChild(i);
control.appendChild(input);
control.appendChild(icon);
field.appendChild(control);
dropdownTrigger.appendChild(field);
dropdown.appendChild(dropdownTrigger);
const dropdownContent = document.createElement('div');
dropdownContent.classList.add('dropdown-content');
const dropdownMenu = document.createElement('div');
dropdownMenu.classList.add('dropdown-menu', 'is-clickable');
dropdownMenu.role = 'menu';
dropdownMenu.appendChild(dropdownContent);
dropdown.appendChild(dropdownMenu);
return dropdown;
}
filterOptions() {
return Array.from(this.options).filter(option => option.text.toLowerCase().includes(this.filter.toLowerCase()));
}
resetOptions() {
this.options.length = 0; //clear options array
this.originalOptions.forEach(option => {
this.options.push(option); //rebuild options array
});
this.filteredOptions = this.options;// reset filtered options to original options
this.drawOptions(); //redraw dropdown content
}
drawOptions() {
this.dropdownContent.innerHTML = "";
this.filteredOptions.forEach(option => {
const dropdownItem = document.createElement('div');
dropdownItem.classList.add('dropdown-item', 'is-clickable');
dropdownItem.innerHTML = option.text;
dropdownItem.setAttribute('data-value', option.value);
dropdownItem.addEventListener('click', () => {
this.selectEvent(dropdownItem);
});
this.dropdownContent.appendChild(dropdownItem);
});
}
selectEvent(selectedOption) {
this.input.value = selectedOption.innerHTML;
this.selectElement.value = selectedOption.getAttribute('data-value');
//trigger change event on the original select element
let triggerOnChange = document.createEvent("HTMLEvents");
triggerOnChange.initEvent("change", false, true);
this.selectElement.dispatchEvent(triggerOnChange);
}
inputEvent() {
this.filter = this.input.value;
if (this.filter.length == 0) {
this.resetOptions();
return;
}
this.filteredOptions = this.filterOptions();
console.log("filtered options", this.filteredOptions);
console.log("regular options", this.options);
this.drawOptions();
}
init() {
this.resetOptions();
this.selectElement.classList.add('is-hidden');
this.input.addEventListener('input', this.inputEvent.bind(this));
this.input.addEventListener('focus', () => {
this.dropdown.classList.add('is-active');
});
this.input.addEventListener('blur', () => {
setTimeout(() => {
this.dropdown.classList.remove('is-active');
}, 250);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment