diff options
| author | Eltrac <hi@guhub.cn> | 2025-03-31 15:35:05 +0800 |
|---|---|---|
| committer | Eltrac <hi@guhub.cn> | 2025-03-31 15:35:05 +0800 |
| commit | e9d529d21e4de47ab12d12f33700473b64b65b40 (patch) | |
| tree | 37954d8fb4b355a58f12dc81f2f7d56404ee1ff6 | |
| parent | eaf64fd84a25ce96b9f7ed975f59e41f5deae947 (diff) | |
refactor: move some JavaScript to individual js file
Former-commit-id: 39cbc197460a0b073e72167218c6cc5d0040bfac
| -rw-r--r-- | assets/js/fancybox.js | 39 | ||||
| -rw-r--r-- | assets/js/lazyload.js | 47 | ||||
| -rw-r--r-- | layouts/partials/head/headscript.html | 5 | ||||
| -rw-r--r-- | layouts/partials/scripts.html | 92 |
4 files changed, 100 insertions, 83 deletions
diff --git a/assets/js/fancybox.js b/assets/js/fancybox.js new file mode 100644 index 00000000..15b70e48 --- /dev/null +++ b/assets/js/fancybox.js @@ -0,0 +1,39 @@ +/* + * fancybox.js + * - initialize fancybox library + * - automatically wrap images + */ + +document.addEventListener("DOMContentLoaded", function () { + document + .querySelectorAll(".markdown-body img:not(figure img, .no-fancybox)") + .forEach((img) => { + if (img.closest("figure")) return; // 跳过已经在 <figure> 内的 <img> + + let src = img.getAttribute("src"); + let alt = img.getAttribute("alt") || ""; // 获取 alt 作为 title + + // 创建 <a> 标签包裹 <img> + let link = document.createElement("a"); + link.setAttribute("href", src); + link.setAttribute("data-fancybox", "gallery"); // Fancybox 组 + link.setAttribute("data-caption", alt); // 设置 title + link.setAttribute("aria-label", alt); // 辅助功能优化 + + // 创建 <figcaption> 并添加 <h4> + let figcaption = document.createElement("figcaption"); + let captionTitle = document.createElement("h4"); + captionTitle.textContent = alt; + figcaption.appendChild(captionTitle); + + // 创建 <figure> 并包裹 <a> + <figcaption> + let figure = document.createElement("figure"); + figure.appendChild(link); + figure.appendChild(figcaption); + + // 替换原始 img + img.parentNode.insertBefore(figure, img); + link.appendChild(img); // 将 img 插入 <a> + }); +}); +Fancybox.bind("[data-fancybox]"); diff --git a/assets/js/lazyload.js b/assets/js/lazyload.js new file mode 100644 index 00000000..be271cdc --- /dev/null +++ b/assets/js/lazyload.js @@ -0,0 +1,47 @@ +/** + * lazyload.js + * - implement native `loading="lazy"` method + * - replace placeholders + */ + +document.addEventListener("DOMContentLoaded", () => { + const allImages = document.querySelectorAll("img"); + const images = document.querySelectorAll("img[data-src]"); + + // if there is a low-res temporary image placeholder + // replace it with real image afterwords + const loadImage = (image) => { + const loadingImage = image.src; // Store current loading image (if any) + const realImage = image.dataset.src; // Get the real image URL from data-src + image.src = loadingImage; // Optionally, reset the src to the placeholder + image.onload = () => { + image.classList.add("fade-in"); // Optional: Apply fade-in effect after loading + }; + image.src = realImage; // Now, load the actual image + image.removeAttribute("data-src"); // Clean up after lazy loading + }; + + // observe view port change + // load image when scrolled into view + const observer = new IntersectionObserver( + (entries, observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + loadImage(entry.target); + observer.unobserve(entry.target); // Stop observing once the image has loaded + } + }); + }, + { threshold: 0.1 }, + ); + + // initialize native lazyloading + allImages.forEach((img) => { + img.setAttribute("loading", "lazy"); + }); + + // lazy load + images.forEach((image) => { + observer.observe(image); // Start observing each image + }); +}); diff --git a/layouts/partials/head/headscript.html b/layouts/partials/head/headscript.html index 84767bd5..1dec4c13 100644 --- a/layouts/partials/head/headscript.html +++ b/layouts/partials/head/headscript.html @@ -1,11 +1,6 @@ <script src="https://d3js.org/d3.v7.min.js"></script> <script src="https://unpkg.com/cal-heatmap/dist/cal-heatmap.min.js"></script> <script> -/* === littlefoot options === */ -var littlefootOptions = { - dismissOnUnhover: true -} - /* === umami tracking === */ if (window.location.hostname !== 'localhost') { // track traffic diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index bd6002b1..b22c8989 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -1,84 +1,20 @@ <!-- third-party libraries --> -{{ range .Site.Params.externalJSFiles -}} -<script src="{{ $.Site.Params.staticPrefix }}{{ . | relURL }}"></script> +{{- range .Site.Params.externalJSFiles }} + <script src="{{ $.Site.Params.staticPrefix }}{{ . | relURL }}"></script> {{- end }} -<script type="module"> - /* === lazyload === */ - document.addEventListener("DOMContentLoaded", () => { - const allImages = document.querySelectorAll("img"); - const images = document.querySelectorAll("img[data-src]"); - const loadImage = (image) => { - const loadingImage = image.src; // Store current loading image (if any) - const realImage = image.dataset.src; // Get the real image URL from data-src - image.src = loadingImage; // Optionally, reset the src to the placeholder - image.onload = () => { - image.classList.add("fade-in"); // Optional: Apply fade-in effect after loading - }; - image.src = realImage; // Now, load the actual image - image.removeAttribute("data-src"); // Clean up after lazy loading - }; - - const observer = new IntersectionObserver( - (entries, observer) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - loadImage(entry.target); - observer.unobserve(entry.target); // Stop observing once the image has loaded - } - }); - }, - { threshold: 0.1 }, - ); - - // initialize native lazyloading - allImages.forEach((img) => { - img.setAttribute("loading", "lazy"); - }); - - // lazy load - images.forEach((image) => { - observer.observe(image); // Start observing each image - }); - }); - - /* === Fancybox === */ - document.addEventListener("DOMContentLoaded", function () { - document - .querySelectorAll( - ".markdown-body img:not(figure img, .no-fancybox)", - ) - .forEach((img) => { - if (img.closest("figure")) return; // 跳过已经在 <figure> 内的 <img> - - let src = img.getAttribute("src"); - let alt = img.getAttribute("alt") || ""; // 获取 alt 作为 title - - // 创建 <a> 标签包裹 <img> - let link = document.createElement("a"); - link.setAttribute("href", src); - link.setAttribute("data-fancybox", "gallery"); // Fancybox 组 - link.setAttribute("data-caption", alt); // 设置 title - link.setAttribute("aria-label", alt); // 辅助功能优化 - - // 创建 <figcaption> 并添加 <h4> - let figcaption = document.createElement("figcaption"); - let captionTitle = document.createElement("h4"); - captionTitle.textContent = alt; - figcaption.appendChild(captionTitle); - - // 创建 <figure> 并包裹 <a> + <figcaption> - let figure = document.createElement("figure"); - figure.appendChild(link); - figure.appendChild(figcaption); +{{- $lazyload := resources.Get "js/lazyload.js" | minify }} +{{- if $lazyload }} + <script>{{ $lazyload.Content | safeJS }}</script> +{{- end }} - // 替换原始 img - img.parentNode.insertBefore(figure, img); - link.appendChild(img); // 将 img 插入 <a> - }); - }); - Fancybox.bind("[data-fancybox]"); +{{- $fancybox := resources.Get "js/fancybox.js" | minify }} +{{- if $fancybox }} + <script>{{ $fancybox.Content | safeJS }}</script> +{{- end }} - /* === littlefoot === */ - littlefoot.littlefoot(littlefootOptions); +<script> + littlefoot.littlefoot({ + dismissOnUnhover: true + }); </script> |
