Html
<select name="custom-selector" data-custom-select>
<option selected disabled>Se de fede valgmuligheder i denne vælger</option>
<option value="test7">Test 7</option>
<option disabled value="test8">Test 8</option>
<option value="test9">Test 9</option>
<option value="test10">Test 10</option>
<option value="test11">Test 11</option>
<option value="test12">Test 12</option>
</select>
JavaScript - CustomSelectModule.ts
const dropdownHeader: string = "[data-dropdown-header]";
const selectItem: string = "[data-custom-select]";
export class customSelectModule {
activeClass: string = "is-active";
hiddenClass: string = "is-hidden";
constructor() {
this.createDropdown();
this.toggleDropdownContent();
this.addEventListeners();
}
private createDropdown = () => {
let selectItems = document.querySelectorAll(selectItem)
for (let i = 0; i < selectItems.length; i++) {
let selectHtmlItem: HTMLElement = < HTMLElement>selectItems[i];
// creating dropdown container
let dropdown: HTMLElement = document.createElement("div");
dropdown.classList.add("dropdown");
dropdown.setAttribute("data-dropdown", "");
dropdown.setAttribute("data-dropdown-close-on-click", "");
dropdown.setAttribute("data-dropdown-set-header", "");
dropdown.setAttribute("data-custom-selector", "");
dropdown.setAttribute("data-close-attr", "");
// creating header container
let dropdownHeader: HTMLElement = document.createElement("div");
dropdownHeader.classList.add("dropdown__header");
dropdownHeader.setAttribute("data-dropdown-header", "");
// creating header element
let dropdownHeaderSpan: HTMLElement = document.createElement("span");
dropdownHeaderSpan.classList.add("dropdown__header-text");
// creating content container
let dropdownContent: HTMLElement = document.createElement("div");
dropdownContent.classList.add("dropdown__content");
dropdownContent.setAttribute("data-dropdown-content", "");
// creating UL element for list
let dropdownContentList: HTMLElement = document.createElement("ul");
dropdownContentList.classList.add("dropdown__content-list", "reset-ul");
// getting option elements from select element in the DOM
let select: HTMLCollection = selectHtmlItem.children;
// adding scroll, if more than 12 items in option list
if (select.length > 12) {
dropdownContent.style.overflowY = "scroll";
}
// setting first element as initial header
dropdownHeaderSpan.innerHTML = select[0].innerHTML;
// looping select elements, and adding them to content list
for (let i = 1; i < select.length; i++) {
let option: HTMLOptionElement = < HTMLOptionElement>select[i];
let content: string = option.innerHTML;
let value: string = option.value;
let dropdownContentListItem = document.createElement("li");
dropdownContentListItem.classList.add("dropdown__content-list-item");
dropdownContentListItem.setAttribute("data-custom-selector-value", value);
dropdownContentListItem.setAttribute("data-custom-selector-item", "");
dropdownContentListItem.innerHTML = content;
if (select[i].hasAttribute("disabled")) {
dropdownContentListItem.setAttribute("data-custom-selector-disabled", "disabled");
}
else {
dropdownContentListItem.setAttribute("tabindex", "0");
}
if (select[i].hasAttribute("selected")) {
dropdownHeaderSpan.innerHTML = select[i].innerHTML;
}
dropdownContentList.appendChild(dropdownContentListItem);
}
// adding elements together
dropdownHeader.appendChild(dropdownHeaderSpan);
dropdown.appendChild(dropdownHeader);
dropdownContent.appendChild(dropdownContentList);
dropdown.appendChild(dropdownContent);
// hiding old select element, and adding new to DOM
selectHtmlItem.classList.add(this.hiddenClass);
selectHtmlItem.parentNode.insertBefore(dropdown, selectHtmlItem)
}
};
private addEventListeners = () => {
let allSelectors = document.querySelectorAll("[data-custom-selector]");
for (let i = 0; i < allSelectors.length; i++) {
let singleSelector = allSelectors[i];
let parentIndex = i;
let allSelectorItems = singleSelector.querySelectorAll("[data-custom-selector-item]")
for (let i = 0; i < allSelectorItems.length; i++) {
let element: HTMLElement = < HTMLElement>allSelectorItems[i];
element.addEventListener("click", () => { customSelectModule.onClickHandler(element, parentIndex) });
element.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
customSelectModule.onClickHandler(element, parentIndex)
}
});
}
}
}
static onClickHandler = (item: HTMLElement, parentIndex: number) => {
let oldSelect = document.querySelectorAll(selectItem)[parentIndex];
if (item.hasAttribute("data-custom-selector-disabled") == false) {
// get element from old select to be set to "selected"
let selectedOption: HTMLOptionElement = oldSelect.querySelector(
"[value='" + item.getAttribute("data-custom-selector-value") + "']"
);
// removing any selected attributes from old select
for (let i = 0; i < oldSelect.children.length; i++) {
if (oldSelect.children[i].hasAttribute("selected")) {
oldSelect.children[i].removeAttribute("selected");
}
}
// setting selected attribute on the selected option
selectedOption.setAttribute("selected", "selected");
// setting clicked value as the dropdown header
let value: string = item.innerText;
item.offsetParent.parentNode.querySelector(dropdownHeader).firstChild.textContent = value;
// removing active class from dropdown element
let itemDropdownParent: HTMLElement = < HTMLElement>item.offsetParent.parentNode
itemDropdownParent.classList.remove("is-active");
}
};
private toggleDropdownContent = () => {
let allDropdowns = document.querySelectorAll("[data-dropdown]");
for (let i = 0; i < allDropdowns.length; i++)
{
let dropdownElement: HTMLElement = < HTMLElement>allDropdowns[i];
let index = i;
dropdownElement.querySelector(dropdownHeader).addEventListener("click", () => {
let allDropdownElements = document.querySelectorAll("[data-dropdown]");
for (let i = 0; i < allDropdownElements.length; i++) {
if (i != index) {
allDropdownElements[i].classList.remove(this.activeClass);
}
}
let target: HTMLElement = < HTMLElement>event.currentTarget;
target.parentElement.classList.toggle(this.activeClass);
})
}
};
}