Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 4 additions & 30 deletions assets/js/lang.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,18 @@
(function () {
const languageSwitchers = document.querySelectorAll('.hextra-language-switcher');

languageSwitchers.forEach((switcher) => {
switcher.addEventListener('click', (e) => {
e.preventDefault();

switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open';

const optionsElement = switcher.nextElementSibling;

optionsElement.classList.toggle('hx:hidden');

// Calculate the position of a language options element.
const switcherRect = switcher.getBoundingClientRect();

// Must be called before optionsElement.clientWidth.
optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`;

const isOnTop = switcher.dataset.location === 'top';
const isRTL = document.body.dir === 'rtl'

// Stuck on the left side of the switcher.
let translateX = switcherRect.left;

if (isOnTop && !isRTL || !isOnTop && isRTL) {
// Stuck on the right side of the switcher.
translateX = switcherRect.right - optionsElement.clientWidth;
}

// Stuck on the top of the switcher.
let translateY = switcherRect.top - window.innerHeight - 15;

if (isOnTop) {
// Stuck on the bottom of the switcher.
translateY = switcherRect.top - window.innerHeight + 180;
}

optionsElement.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`;
toggleMenu(switcher);
});
});

window.addEventListener("resize", () => languageSwitchers.forEach(resizeMenu))

// Dismiss language switcher when clicking outside
document.addEventListener('click', (e) => {
if (e.target.closest('.hextra-language-switcher') === null) {
Expand Down
52 changes: 52 additions & 0 deletions assets/js/switcher-menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
function computeMenuTranslation(switcher, optionsElement) {
// Calculate the position of a language options element.
const switcherRect = switcher.getBoundingClientRect();

// Must be called before optionsElement.clientWidth.
optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`;

const isOnTop = switcher.dataset.location === 'top';
const isOnBottom = switcher.dataset.location === 'bottom';
const isOnBottomRight = switcher.dataset.location === 'bottom-right';
const isRTL = document.body.dir === 'rtl'

// Stuck on the left side of the switcher.
let x = switcherRect.left;

if (isOnTop && !isRTL || isOnBottom && isRTL || isOnBottomRight && !isRTL) {
// Stuck on the right side of the switcher.
x = switcherRect.right - optionsElement.clientWidth;
}

// Stuck on the top of the switcher.
let y = switcherRect.top - window.innerHeight - 10;

if (isOnTop) {
// Stuck on the bottom of the switcher.
y = switcherRect.top - window.innerHeight + optionsElement.clientHeight + switcher.clientHeight + 4;
}

return { x: x, y: y };
}

function toggleMenu(switcher) {
const optionsElement = switcher.nextElementSibling;

optionsElement.classList.toggle('hx:hidden');

// Calculate the position of a language options element.
const translate = computeMenuTranslation(switcher, optionsElement);

optionsElement.style.transform = `translate3d(${translate.x}px, ${translate.y}px, 0)`;
}

function resizeMenu(switcher) {
const optionsElement = switcher.nextElementSibling;

if (optionsElement.classList.contains('hx:hidden')) return;

// Calculate the position of a language options element.
const translate = computeMenuTranslation(switcher, optionsElement);

optionsElement.style.transform = `translate3d(${translate.x}px, ${translate.y}px, 0)`;
}
34 changes: 2 additions & 32 deletions assets/js/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,11 @@
toggler.addEventListener("click", function (e) {
e.preventDefault();

const optionsElement = toggler.nextElementSibling;

optionsElement.classList.toggle('hx:hidden');

// Calculate the position of a language options element.
const switcherRect = toggler.getBoundingClientRect();

// Must be called before optionsElement.clientWidth.
optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`;

const isOnTop = toggler.dataset.location === 'top';
const isOnBottom = toggler.dataset.location === 'bottom';
const isOnBottomRight = toggler.dataset.location === 'bottom-right';
const isRTL = document.body.dir === 'rtl'

// Stuck on the left side of the switcher.
let translateX = switcherRect.left;

if (isOnTop && !isRTL || isOnBottom && isRTL || isOnBottomRight && !isRTL) {
// Stuck on the right side of the switcher.
translateX = switcherRect.right - optionsElement.clientWidth;
}

// Stuck on the top of the switcher.
let translateY = switcherRect.top - window.innerHeight - 15;

if (isOnTop) {
// Stuck on the bottom of the switcher.
translateY = switcherRect.top - window.innerHeight + 150;
}

optionsElement.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`;
toggleMenu(toggler);
});
});

window.addEventListener("resize", () => themeToggleButtons.forEach(resizeMenu))

// Dismiss the menu when clicking outside
document.addEventListener('click', (e) => {
Expand Down
3 changes: 2 additions & 1 deletion layouts/_partials/scripts/core.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- $jsSwitcherMenu := resources.Get "js/switcher-menu.js" -}}
{{- $jsTheme := resources.Get "js/theme.js" | resources.ExecuteAsTemplate "theme.js" . -}}
{{- $jsBanner := resources.Get "js/banner.js" | resources.ExecuteAsTemplate "banner.js" . -}}
{{- $jsMenu := resources.Get "js/menu.js" -}}
Expand All @@ -11,7 +12,7 @@
{{- $jsTocScroll := resources.Get "js/toc-scroll.js" -}}
{{- $jsFavicon := resources.Get "js/favicon.js" | resources.ExecuteAsTemplate "favicon.js" . -}}

{{- $scripts := slice $jsTheme $jsBanner $jsMenu $jsCodeCopy $jsTabs $jsLang $jsNavMenu $jsFileTree $jsSidebar $jsBackToTop $jsTocScroll $jsFavicon | resources.Concat "js/main.js" -}}
{{- $scripts := slice $jsSwitcherMenu $jsTheme $jsBanner $jsMenu $jsCodeCopy $jsTabs $jsLang $jsNavMenu $jsFileTree $jsSidebar $jsBackToTop $jsTocScroll $jsFavicon | resources.Concat "js/main.js" -}}
{{- if hugo.IsProduction -}}
{{- $scripts = $scripts | minify | fingerprint -}}
{{- end -}}
Expand Down