mirror of
https://github.com/jgthms/bulma
synced 2026-03-15 02:04:29 -07:00
Init v1
This commit is contained in:
373
docs/assets/javascript/main.js
Normal file
373
docs/assets/javascript/main.js
Normal file
@@ -0,0 +1,373 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Init JS elements
|
||||
const $readys = document.querySelectorAll(".js-ready");
|
||||
$readys.forEach((el) => el.classList.add("is-ready"));
|
||||
|
||||
const $animateds = document.querySelectorAll(".js-animated");
|
||||
$animateds.forEach((el) => el.classList.add("is-animated"));
|
||||
|
||||
// Amis
|
||||
|
||||
const $amis = document.getElementById("amis");
|
||||
const $pied = document.getElementById("pied");
|
||||
|
||||
if ($amis || $pied) {
|
||||
fetch("https://jgthms.com/amis/new.json")
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((response) => {
|
||||
response.forEach((item) => {
|
||||
const el = document.createElement("a");
|
||||
el.className = "bd-ami";
|
||||
el.href = item.url;
|
||||
el.target = "_blank";
|
||||
el.title = item.title || item.id;
|
||||
|
||||
if (item.color) {
|
||||
el.style = `--color: ${item.color};`;
|
||||
}
|
||||
|
||||
const extension = item.svg ? ".svg" : ".png";
|
||||
const img = document.createElement("img");
|
||||
img.src = `https://jgthms.com/amis/images/${item.id}${extension}`;
|
||||
|
||||
el.appendChild(img);
|
||||
|
||||
if ($amis) {
|
||||
$amis.appendChild(el);
|
||||
}
|
||||
|
||||
if (item.pied && $pied) {
|
||||
el.className = "bd-ami bd-ami-footer";
|
||||
$pied.appendChild(el);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// TOGGLES
|
||||
const $toggles = document.querySelectorAll(".js-toggle");
|
||||
|
||||
$toggles.forEach((el) => {
|
||||
el.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const target = el.dataset.target;
|
||||
const $target = document.getElementById(target);
|
||||
el.classList.toggle("is-active");
|
||||
$target.classList.toggle("is-active");
|
||||
});
|
||||
});
|
||||
|
||||
// MODALS
|
||||
// Functions to open and close a modal
|
||||
function openModal($el) {
|
||||
$el.classList.add("is-active");
|
||||
}
|
||||
|
||||
function closeModal($el) {
|
||||
$el.classList.remove("is-active");
|
||||
}
|
||||
|
||||
function closeAllModals() {
|
||||
(document.querySelectorAll(".modal") || []).forEach(($modal) => {
|
||||
closeModal($modal);
|
||||
});
|
||||
}
|
||||
|
||||
(document.querySelectorAll(".js-modal-trigger") || []).forEach(($trigger) => {
|
||||
const modal = $trigger.dataset.target;
|
||||
const $target = document.getElementById(modal);
|
||||
|
||||
$trigger.addEventListener("click", () => {
|
||||
openModal($target);
|
||||
});
|
||||
});
|
||||
|
||||
(
|
||||
document.querySelectorAll(
|
||||
".modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button",
|
||||
) || []
|
||||
).forEach(($close) => {
|
||||
const $target = $close.closest(".modal");
|
||||
|
||||
$close.addEventListener("click", () => {
|
||||
closeModal($target);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape") {
|
||||
closeAllModals();
|
||||
}
|
||||
});
|
||||
|
||||
// DROPDOWNS
|
||||
const $clickableDropdowns = document.querySelectorAll(
|
||||
".dropdown:not(.is-hoverable)",
|
||||
);
|
||||
|
||||
if ($clickableDropdowns.length > 0) {
|
||||
$clickableDropdowns.forEach(($dropdown) => {
|
||||
$dropdown.querySelector("button").addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
$dropdown.classList.toggle("is-active");
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("click", () => {
|
||||
closeDropdowns();
|
||||
});
|
||||
}
|
||||
|
||||
function closeDropdowns() {
|
||||
$clickableDropdowns.forEach(($el) => {
|
||||
$el.classList.remove("is-active");
|
||||
});
|
||||
}
|
||||
|
||||
// THEMES
|
||||
const STORAGE_KEY = "bulma-theme";
|
||||
const SYSTEM_THEME = "system";
|
||||
const DEFAULT_THEME = "light";
|
||||
|
||||
const state = {
|
||||
chosenTheme: SYSTEM_THEME, // light|dark|system
|
||||
appliedTheme: DEFAULT_THEME, // light|dark
|
||||
OSTheme: null, // light|dark|null
|
||||
};
|
||||
|
||||
const $themeCycle = document.getElementById("js-cycle");
|
||||
const $themeSwitchers = document.querySelectorAll(".js-themes button");
|
||||
const $darkmodes = document.querySelectorAll(".js-darkmode");
|
||||
|
||||
const updateThemeUI = () => {
|
||||
if (state.appliedTheme === "light") {
|
||||
$themeCycle.className = "bd-cycle js-burger is-sun";
|
||||
} else {
|
||||
$themeCycle.className = "bd-cycle js-burger is-moon";
|
||||
}
|
||||
|
||||
$themeSwitchers.forEach((el) => {
|
||||
const swatchTheme = el.dataset.scheme;
|
||||
|
||||
if (state.chosenTheme === swatchTheme) {
|
||||
el.classList.add("is-active");
|
||||
} else {
|
||||
el.classList.remove("is-active");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const setTheme = (theme, save = true) => {
|
||||
state.chosenTheme = theme;
|
||||
state.appliedTheme = theme;
|
||||
|
||||
if (theme === SYSTEM_THEME) {
|
||||
state.appliedTheme = state.OSTheme;
|
||||
document.documentElement.removeAttribute("data-theme");
|
||||
window.localStorage.removeItem(STORAGE_KEY);
|
||||
} else {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
|
||||
if (save) {
|
||||
window.localStorage.setItem(STORAGE_KEY, theme);
|
||||
}
|
||||
}
|
||||
|
||||
updateThemeUI();
|
||||
};
|
||||
|
||||
const toggleTheme = () => {
|
||||
if (state.appliedTheme === "light") {
|
||||
setTheme("dark");
|
||||
} else {
|
||||
setTheme("light");
|
||||
}
|
||||
};
|
||||
|
||||
const detectOSTheme = () => {
|
||||
if (!window.matchMedia) {
|
||||
// matchMedia method not supported
|
||||
return DEFAULT_THEME;
|
||||
}
|
||||
|
||||
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
// OS theme setting detected as dark
|
||||
return "dark";
|
||||
} else if (window.matchMedia("(prefers-color-scheme: light)").matches) {
|
||||
return "light";
|
||||
}
|
||||
|
||||
return DEFAULT_THEME;
|
||||
};
|
||||
|
||||
// On load, check if any preference was saved
|
||||
const localTheme = window.localStorage.getItem(STORAGE_KEY);
|
||||
state.OSTheme = detectOSTheme();
|
||||
|
||||
if (localTheme) {
|
||||
setTheme(localTheme, false);
|
||||
} else {
|
||||
setTheme(SYSTEM_THEME);
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
$themeSwitchers.forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
const theme = el.dataset.scheme;
|
||||
setTheme(theme);
|
||||
});
|
||||
});
|
||||
|
||||
$darkmodes.forEach((el) => {
|
||||
el.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
toggleTheme();
|
||||
});
|
||||
});
|
||||
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: dark)")
|
||||
.addEventListener("change", (event) => {
|
||||
const theme = event.matches ? "dark" : "light";
|
||||
state.OSTheme = theme;
|
||||
setTheme(theme);
|
||||
});
|
||||
|
||||
// BURGERS
|
||||
const $burgers = document.querySelectorAll(".js-burger");
|
||||
|
||||
$burgers.forEach((el) => {
|
||||
el.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const targetID = el.dataset.target;
|
||||
const $target = document.getElementById(targetID);
|
||||
el.classList.toggle("is-active");
|
||||
$target.classList.toggle("is-active");
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
|
||||
const onClickOutside = (menuSelector) => {
|
||||
document.addEventListener("click", (e) => {
|
||||
const menus = document.querySelectorAll(menuSelector);
|
||||
|
||||
menus.forEach((el) => {
|
||||
if (!el.contains(e.target) && el.classList.contains("is-active")) {
|
||||
el.classList.remove("is-active");
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onClickOutside(".js-menu");
|
||||
|
||||
// TABS
|
||||
const $tabs = document.querySelectorAll(".js-tabs");
|
||||
|
||||
$tabs.forEach(($tab) => {
|
||||
const buttons = $tab.querySelectorAll(".bd-tabs-nav button");
|
||||
const tabs = $tab.querySelectorAll(".bd-tabs-item");
|
||||
|
||||
buttons.forEach((el, i) => {
|
||||
el.addEventListener("click", () => {
|
||||
buttons.forEach((button) => {
|
||||
if (el === button) {
|
||||
button.classList.add("bd-is-active");
|
||||
} else {
|
||||
button.classList.remove("bd-is-active");
|
||||
}
|
||||
});
|
||||
|
||||
tabs.forEach((tab, j) => {
|
||||
if (i === j) {
|
||||
tab.classList.add("bd-is-active");
|
||||
} else {
|
||||
tab.classList.remove("bd-is-active");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// CLIPBOARD
|
||||
const $highlights = document.querySelectorAll(".highlight");
|
||||
let itemsProcessed = 0;
|
||||
|
||||
if ($highlights.length > 0) {
|
||||
$highlights.forEach(($el) => {
|
||||
const copyEl = '<button class="button bd-copy">Copy</button>';
|
||||
// const expandEl =
|
||||
// '<button class="button is-small bd-expand">Expand</button>';
|
||||
$el.insertAdjacentHTML("beforeend", copyEl);
|
||||
|
||||
const $parent = $el.parentNode;
|
||||
|
||||
if ($parent && $parent.classList.contains("bd-is-more")) {
|
||||
const showEl =
|
||||
'<button class="button is-small bd-show"><span class="icon"><i class="fas fa-code"></i></span><strong>Show code</strong></button>';
|
||||
$parent.insertAdjacentHTML("afterbegin", showEl);
|
||||
}
|
||||
|
||||
itemsProcessed++;
|
||||
|
||||
if (itemsProcessed === $highlights.length) {
|
||||
addHighlightControls();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addHighlightControls() {
|
||||
const $highlightButtons = document.querySelectorAll(
|
||||
".highlight .bd-copy, .highlight .bd-expand",
|
||||
);
|
||||
|
||||
$highlightButtons.forEach(($el) => {
|
||||
$el.addEventListener("mouseenter", () => {
|
||||
$el.parentNode.classList.add("bd-is-hovering");
|
||||
$el.parentNode.parentNode.classList.add("bd-is-hovering");
|
||||
});
|
||||
|
||||
$el.addEventListener("mouseleave", () => {
|
||||
$el.parentNode.classList.remove("bd-is-hovering");
|
||||
$el.parentNode.parentNode.classList.remove("bd-is-hovering");
|
||||
});
|
||||
});
|
||||
|
||||
const $highlightExpands = document.querySelectorAll(
|
||||
".bd-snippet .bd-expand",
|
||||
);
|
||||
|
||||
$highlightExpands.forEach(($el) => {
|
||||
$el.addEventListener("click", () => {
|
||||
$el.parentNode.firstElementChild.style.maxHeight = "none";
|
||||
});
|
||||
});
|
||||
|
||||
const $highlightShows = document.querySelectorAll(".bd-snippet .bd-show");
|
||||
|
||||
$highlightShows.forEach(($el) => {
|
||||
$el.addEventListener("click", () => {
|
||||
const text = $el.querySelector("strong").textContent;
|
||||
const newText = text === "Show code" ? "Hide code" : "Show code";
|
||||
$el.querySelector("strong").textContent = newText;
|
||||
$el.parentNode.classList.toggle("bd-is-more-clipped");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
new window.ClipboardJS(".bd-copy", {
|
||||
target: (trigger) => {
|
||||
return trigger.previousElementSibling.firstElementChild;
|
||||
},
|
||||
});
|
||||
|
||||
new window.ClipboardJS(".bd-clipboard");
|
||||
}, 100);
|
||||
});
|
||||
Reference in New Issue
Block a user