diff options
| author | Eltrac <hi@guhub.cn> | 2025-09-10 16:48:59 +0800 |
|---|---|---|
| committer | Eltrac <hi@guhub.cn> | 2025-09-10 16:48:59 +0800 |
| commit | 8b7d26dfd1fc10e3143ff0d3fa969ed41f21e710 (patch) | |
| tree | 55c3db871329053489b93acea2d329ce8bd427be | |
| parent | 31c6eda88b7793e0ede5ba1ded54b4e5b0ee06ec (diff) | |
feat: add checkbox options
- visitor can now disable umami tracking
- visitor can now hide Batrick
Former-commit-id: c092fca1f824e18586309376478e3ad95fcab3a2
| -rw-r--r-- | assets/js/settings.js | 43 | ||||
| -rw-r--r-- | i18n/en.yml | 1 | ||||
| -rw-r--r-- | i18n/zh.yml | 3 | ||||
| -rw-r--r-- | layouts/_partials/components/back-to-top.html | 97 | ||||
| -rw-r--r-- | layouts/settings.html | 6 |
5 files changed, 99 insertions, 51 deletions
diff --git a/assets/js/settings.js b/assets/js/settings.js index 08e7a1de..5a90c2de 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -58,7 +58,48 @@ } initTextAlterButtons() - //... + // initialize checkbox options + function initCheckboxes() { + const checkboxes = document.querySelectorAll('#checkbox-options input[type="checkbox"]'); + const checkboxOptions = [ + { + id: 'dontAllowTracking', + label: '禁止网站使用 Web 分析工具跟踪用户行为', + storage: 'umami.disabled', + default: 'false' + }, + { + id: 'hideBatrick', + label: '隐藏 Batrick(返回顶部按钮)', + storage: 'geedeapro.ui.hideBatrick', + default: 'false' + } + ] + + checkboxOptions.forEach(checkboxOption => { + // create checkbox + const element = document.createElement('input'); + element.type = 'checkbox'; + element.id = checkboxOption.id; + element.checked = checkboxOption.default; + + // create label + const label = document.createElement('label'); + label.htmlFor = element.id; + label.textContent = checkboxOption.label; + + // add event listener to checkbox + element.addEventListener('change', () => { + localStorage.setItem(checkboxOption.storage, element.checked); + }); + + // append checkbox and label to container + const container = document.getElementById('checkbox-options'); + container.appendChild(element); + container.appendChild(label); + }); + } + initCheckboxes(); }; initializeSettingsPage(); diff --git a/i18n/en.yml b/i18n/en.yml index f9f0e045..0a96d993 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -40,3 +40,4 @@ settings: fontSize: Font Size loremIpsum: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. sampleText: Aa + otherOptions: Other Options diff --git a/i18n/zh.yml b/i18n/zh.yml index f20b61d0..4120717e 100644 --- a/i18n/zh.yml +++ b/i18n/zh.yml @@ -39,4 +39,5 @@ homePageQuote: settings: fontSize: 字体大小 loremIpsum: 对我个人而言,科学和人文谁更有意义不仅仅是一个重大的事件,还可能会改变我的人生。 我们都知道,只要有意义,那么就必须慎重考虑。问题的关键究竟为何? 在这种不可避免的冲突下,我们必须解决这个问题。 这样看来,我们一般认为,抓住了问题的关键,其他一切则会迎刃而解。从这个角度来看,生活中,若科学和人文谁更有意义出现了,我们就不得不考虑它出现了的事实。 塞内加曾经提到过,勇气通往天堂,怯懦通往地狱。这句话看似简单,但其中的阴郁不禁让人深思。所谓科学和人文谁更有意义,关键是科学和人文谁更有意义需要如何写。 那么,我们一般认为,抓住了问题的关键,其他一切则会迎刃而解。 - sampleText: 字。 + sampleText: "字。" + otherOptions: 其他选项 diff --git a/layouts/_partials/components/back-to-top.html b/layouts/_partials/components/back-to-top.html index 43e0807e..7e6786d8 100644 --- a/layouts/_partials/components/back-to-top.html +++ b/layouts/_partials/components/back-to-top.html @@ -14,59 +14,64 @@ </div> <script> +// hide Batrick if set +if (localStorage.getItem('geedeapro.ui.hideBatrick') === 'true') { + document.getElementById('back2top').classList.add('hidden'); +} else { + // Batrick functionality + const backToTop = document.getElementById("back2top") + const backToTopButton = document.getElementById("back2top-button") + const backToTopInstruction = document.getElementById("back2top-instruction") + const seenAndUsedBat = localStorage.getItem("seenAndUsedBat") -const backToTop = document.getElementById("back2top") -const backToTopButton = document.getElementById("back2top-button") -const backToTopInstruction = document.getElementById("back2top-instruction") -const seenAndUsedBat = localStorage.getItem("seenAndUsedBat") - -function hideInstruction() { - backToTopInstruction.remove() -} -if (seenAndUsedBat) hideInstruction() - -// listen to button click and scroll to top -backToTopButton.addEventListener("click", () => { - window.scrollTo({ top: 0, behavior: "smooth" }) - if (!seenAndUsedBat) { - localStorage.setItem("seenAndUsedBat", true); - hideInstruction(); + function hideInstruction() { + backToTopInstruction.remove() } -}) + if (seenAndUsedBat) hideInstruction() -// listen to scroll and toggle button visibility -let lastOffset = window.scrollY + // listen to button click and scroll to top + backToTopButton.addEventListener("click", () => { + window.scrollTo({ top: 0, behavior: "smooth" }) + if (!seenAndUsedBat) { + localStorage.setItem("seenAndUsedBat", true); + hideInstruction(); + } + }) -window.addEventListener("scroll", () => { - const offset = window.scrollY - const batIsHidden = backToTop.classList.contains("-top-25") - const enoughHeight = offset >= 2000 - const isScrollingUp = offset < lastOffset - const isScrollingDown = offset > lastOffset + // listen to scroll and toggle button visibility + let lastOffset = window.scrollY - function hide() { - backToTop.classList.remove("top-0") - backToTop.classList.add("-top-25") - backToTop.classList.remove("animate-head-shake") - } + window.addEventListener("scroll", () => { + const offset = window.scrollY + const batIsHidden = backToTop.classList.contains("-top-25") + const enoughHeight = offset >= 2000 + const isScrollingUp = offset < lastOffset + const isScrollingDown = offset > lastOffset - function show() { - backToTop.classList.remove("-top-25") - backToTop.classList.add("top-0") - backToTop.classList.add("animate-head-shake") - } + function hide() { + backToTop.classList.remove("top-0") + backToTop.classList.add("-top-25") + backToTop.classList.remove("animate-head-shake") + } - if (enoughHeight && isScrollingUp && batIsHidden) { - // show only when scrolling up - show() - } else if (isScrollingDown && !batIsHidden) { - // hide as soon as user scrolls down again - hide() - } + function show() { + backToTop.classList.remove("-top-25") + backToTop.classList.add("top-0") + backToTop.classList.add("animate-head-shake") + } - // hide no matter what if too close to top - if (!enoughHeight) hide() + if (enoughHeight && isScrollingUp && batIsHidden) { + // show only when scrolling up + show() + } else if (isScrollingDown && !batIsHidden) { + // hide as soon as user scrolls down again + hide() + } - lastOffset = offset -}) + // hide no matter what if too close to top + if (!enoughHeight) hide() + + lastOffset = offset + }) +} </script> diff --git a/layouts/settings.html b/layouts/settings.html index 85df3a78..8f373567 100644 --- a/layouts/settings.html +++ b/layouts/settings.html @@ -15,7 +15,8 @@ <button data-text-size="medium" class="{{ $buttonClass }} text-base md:text-lg">{{ T "settings.sampleText" }}</button> <button data-text-size="large" class="{{ $buttonClass }} text-lg md:text-xl">{{ T "settings.sampleText" }}</button> </div> - <div class="leading-relaxed bg-neutral-200/50 py-1 px-4 rounded"> + <div class="leading-relaxed bg-neutral-200/50 py-1 px-4 rounded + h-50 overflow-y-auto"> <p class="markdown-body">{{ T "settings.loremIpsum" . }}</p> </div> </section> @@ -23,8 +24,7 @@ <hr /> <h3>{{ T "settings.otherOptions" . }}</h3> - <input id="allowTracking" type="checkbox" checked /> - <label for="allowTracking">{{ T "settings.allowTracking" . }}</label> + <section id="checkbox-options" class="text-sm"></section> </article> {{ partial "footer.html" . }} {{ end }} |
