睿能科技
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

91 lines
2.9 KiB

import "./common.js";
//#region js/contact.js
/**
* 自定义下拉组件
* 将原生 <select> 替换为可自定义样式的下拉
*/
function initCustomSelects() {
document.querySelectorAll(".c-field__select").forEach((native) => {
if (native.dataset.customized) return;
native.dataset.customized = "true";
native.classList.add("c-custom-select__native");
native.tabIndex = -1;
const wrapper = document.createElement("div");
native.parentNode.insertBefore(wrapper, native);
wrapper.appendChild(native);
wrapper.className = "c-custom-select";
const trigger = document.createElement("button");
trigger.type = "button";
trigger.className = "c-custom-select__trigger";
trigger.setAttribute("aria-haspopup", "listbox");
trigger.setAttribute("aria-expanded", "false");
wrapper.appendChild(trigger);
const dropdown = document.createElement("div");
dropdown.className = "c-custom-select__dropdown";
dropdown.setAttribute("role", "listbox");
wrapper.appendChild(dropdown);
function renderOptions() {
dropdown.innerHTML = "";
Array.from(native.options).forEach((opt, i) => {
if (opt.disabled) return;
const btn = document.createElement("button");
btn.type = "button";
btn.className = "c-custom-select__option";
btn.setAttribute("role", "option");
btn.dataset.value = opt.value;
btn.textContent = opt.textContent;
if (opt.selected && opt.value) btn.classList.add("is-active");
btn.addEventListener("click", () => selectOption(i));
dropdown.appendChild(btn);
});
}
function updateTrigger() {
const sel = native.selectedIndex;
const opt = native.options[sel];
trigger.textContent = opt ? opt.textContent : "";
trigger.classList.toggle("is-placeholder", !opt || opt.disabled);
dropdown.querySelectorAll(".c-custom-select__option").forEach((btn) => {
btn.classList.toggle("is-active", btn.dataset.value === native.value);
});
}
function selectOption(index) {
native.selectedIndex = index;
native.dispatchEvent(new Event("change", { bubbles: true }));
updateTrigger();
close();
}
function open() {
renderOptions();
dropdown.classList.add("is-visible");
trigger.classList.add("is-open");
trigger.setAttribute("aria-expanded", "true");
}
function close() {
dropdown.classList.remove("is-visible");
trigger.classList.remove("is-open");
trigger.setAttribute("aria-expanded", "false");
}
function toggle() {
dropdown.classList.contains("is-visible") ? close() : open();
}
trigger.addEventListener("click", toggle);
document.addEventListener("click", (e) => {
if (!wrapper.contains(e.target)) close();
});
wrapper.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
close();
trigger.focus();
}
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
toggle();
}
});
updateTrigger();
});
}
$(function() {
initCustomSelects();
});
//#endregion