summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--layouts/_partials/posts/action-menu/comment-button.html86
-rw-r--r--layouts/_partials/posts/action-menu/like-button.html122
-rw-r--r--layouts/_partials/scripts.html4
-rw-r--r--layouts/_partials/scripts/action-menu-js.html170
4 files changed, 177 insertions, 205 deletions
diff --git a/layouts/_partials/posts/action-menu/comment-button.html b/layouts/_partials/posts/action-menu/comment-button.html
index 563bf4bd..d646ca27 100644
--- a/layouts/_partials/posts/action-menu/comment-button.html
+++ b/layouts/_partials/posts/action-menu/comment-button.html
@@ -1,4 +1,3 @@
-{{ /* button html */}}
<button class="dark:invert flex items-center justify-center gap-1.5 min-w-12 h-12 px-2 border-none bg-transparent text-gray-600 cursor-pointer relative transition-all duration-200 hover:bg-black/5 hover:rounded-lg group"
id="comments-toggle" title="{{ T "actionMenu.comment" }}" data-tooltip>
<img src="/img/comments.svg" width="20" height="20"
@@ -7,32 +6,67 @@
<span class="text-xs font-bold text-gray-600 min-w-4 text-center bg-white/90 rounded-xl px-1.5 py-0.5 shadow-sm dark:text-gray-400 dark:bg-black/70" id="comment-count">...</span>
</button>
-{{ /* button functionality */}}
<script>
+// initialize button features and comment count
document.addEventListener('DOMContentLoaded', () => {
- const commentsToggle = document.getElementById('comments-toggle');
- const commentsSection = document.getElementById('comments-section');
-
- if (!commentsToggle || !commentsSection) return;
-
- // click on toggle
- commentsToggle.addEventListener('click', function() {
- const isHidden = commentsSection.classList.contains('hidden');
- const entranceAnimation = 'animate-slide-in-down';
- const exitAnimation = 'animate-slide-out-up';
-
- if (isHidden) {
- // swtich on
- commentsSection.classList.remove('hidden', exitAnimation);
- commentsSection.classList.add(entranceAnimation);
- } else {
- // switch off
- commentsSection.classList.remove(entranceAnimation);
- commentsSection.classList.add(exitAnimation);
- setTimeout(() => {
- commentsSection.classList.add('hidden');
- }, 200);
- }
- });
+
+ function initButtonFeature() {
+ const commentsToggle = document.getElementById('comments-toggle');
+ const commentsSection = document.getElementById('comments-section');
+
+ if (!commentsToggle || !commentsSection) return;
+
+ // click on toggle
+ commentsToggle.addEventListener('click', function() {
+ const isHidden = commentsSection.classList.contains('hidden');
+ const entranceAnimation = 'animate-slide-in-down';
+ const exitAnimation = 'animate-slide-out-up';
+
+ if (isHidden) {
+ // swtich on
+ commentsSection.classList.remove('hidden', exitAnimation);
+ commentsSection.classList.add(entranceAnimation);
+ } else {
+ // switch off
+ commentsSection.classList.remove(entranceAnimation);
+ commentsSection.classList.add(exitAnimation);
+ setTimeout(() => {
+ commentsSection.classList.add('hidden');
+ }, 200);
+ }
+ });
+ }
+
+ function initCommentCount() {
+ const commentCountEl = document.getElementById('comment-count');
+ if (!commentCountEl) return;
+
+ const observer = new MutationObserver(() => {
+ // check if giscus is loaded
+ const giscusIframe = document.querySelector('iframe.giscus-frame');
+ if (!giscusIframe) return;
+
+ giscusIframe.addEventListener('load', () => {
+ // receive message from giscus iframe
+ window.addEventListener('message', function(event) {
+ if (event.origin !== 'https://giscus.app') return;
+ const giscusData = event.data;
+ if (giscusData.giscus?.discussion) {
+ const discussion = giscusData.giscus.discussion;
+ const totalComments = (discussion.totalCommentCount || 0) + (discussion.totalReplyCount || 0);
+ // set comment count
+ commentCountEl.textContent = totalComments.toString();
+ // if no discussion found, set to 0
+ } else commentCountEl.textContent = '0';
+ });
+ });
+
+ observer.disconnect();
+ });
+ observer.observe(document.body, { childList: true, subtree: true });
+ }
+
+ initButtonFeature();
+ initCommentCount();
});
</script>
diff --git a/layouts/_partials/posts/action-menu/like-button.html b/layouts/_partials/posts/action-menu/like-button.html
index c4c50c91..c9e793b8 100644
--- a/layouts/_partials/posts/action-menu/like-button.html
+++ b/layouts/_partials/posts/action-menu/like-button.html
@@ -1,17 +1,18 @@
+{{ $pageID := .File.UniqueID | urlize }}
<!-- 点赞按钮 -->
-<div class="relative" id="like-container-{{ .File.UniqueID | urlize }}">
+<div class="relative" id="like-container-{{ $pageID }}">
<button class="dark:invert flex items-center justify-center gap-1.5 min-w-12 h-12 px-2
border-none bg-transparent text-gray-600 cursor-pointer relative transition-all duration-200
hover:bg-black/5 hover:rounded-lg group animate-count-infinite"
- onclick="sendLike('{{ .File.UniqueID | urlize }}')"
- id="like-btn-{{ .File.UniqueID | urlize }}"
+ onclick="sendLike('{{ $pageID }}')"
+ id="like-btn-{{ $pageID }}"
title="{{ T "actionMenu.like" }}"
data-liked-title="{{ T "actionMenu.liked" }}"
data-tooltip>
<img src="/img/heart-organ.svg" width="20" height="20"
alt="{{ T "actionMenu.like" }}"
- class="brightness-40 flex-shrink-0 transition-all duration-300 dark:brightness-70 dark:contrast-120" id="like-icon-{{ .File.UniqueID | urlize }}" />
- <span class="text-xs font-bold text-gray-600 min-w-4 text-center bg-white/90 rounded-xl px-1.5 py-0.5 shadow-sm dark:text-gray-400 dark:bg-black/70" id="like-count-{{ .File.UniqueID | urlize }}">...</span>
+ class="brightness-40 flex-shrink-0 transition-all duration-300 dark:brightness-70 dark:contrast-120" id="like-icon-{{ $pageID }}" />
+ <span class="text-xs font-bold text-gray-600 min-w-4 text-center bg-white/90 rounded-xl px-1.5 py-0.5 shadow-sm dark:text-gray-400 dark:bg-black/70" id="like-count-{{ $pageID }}">...</span>
</button>
</div>
@@ -24,3 +25,114 @@
color: #8B0000 !important;
}
</style>
+
+<script>
+document.addEventListener('DOMContentLoaded', () => {
+ // get page ID to fetch and update like data
+ const pageId = "{{ $pageID }}";
+
+ // get required elements
+ const elements = {
+ count: document.getElementById("like-count-" + pageId),
+ btn: document.getElementById("like-btn-" + pageId),
+ container: document.getElementById("like-container-" + pageId),
+ icon: document.getElementById("like-icon-" + pageId)
+ };
+
+ // return if no page ID found or not in production or no elements
+ if (
+ !pageId || window.location.host !== 'www.geedea.pro' ||
+ !elements.count || !elements.btn || !elements.container
+ ) return;
+
+ function setLikedState() {
+ // update classes
+ elements.icon?.classList.add('liked-heart');
+ elements.icon?.classList.add('animate-heart-beat');
+ elements.count?.classList.add('liked-count');
+ elements.btn.disabled = true;
+ elements.container.classList.add('liked');
+ // update tooltip
+ elements.btn.setAttribute('title',
+ elements.container.classList.contains('liked')
+ ? elements.btn.getAttribute('data-liked-title')
+ : '为这篇文章献上心脏'
+ );
+ }
+
+ async function fetchLikes() {
+ try {
+ const response = await fetch("https://like.guhub.cn/like/" + pageId);
+ const data = await response.json();
+ elements.count.innerText = data.likes ?? 0;
+ if (localStorage.getItem("liked_" + pageId)) {
+ setLikedState();
+ updateOrganFarm(data.likes);
+ }
+ } catch(e) {
+ console.log(e);
+ elements.count.innerText = "❌";
+ }
+ }
+
+ window.sendLike = async function(pageId) {
+ if (localStorage.getItem("liked_" + pageId)) return;
+
+ try {
+ const response = await fetch("https://like.guhub.cn/like/" + pageId, { method: "POST" });
+ const data = await response.json();
+ localStorage.setItem("liked_" + pageId, "1");
+ elements.count.innerText = data.likes ?? 1;
+ updateOrganFarm(data.likes);
+ setLikedState();
+ } catch(e) {
+ console.log(e);
+ alert("点赞失败,请稍后再试");
+ }
+ };
+
+ function updateOrganFarm(count) {
+ const organFarm = document.getElementById("organ-farm");
+ const organCount = count || parseInt(elements.count.innerText);
+ const organImages = [
+ "https://image.guhub.cn/picgo2025/oragn-3.png",
+ "https://image.guhub.cn/picgo2025/organ-1.png",
+ "https://image.guhub.cn/picgo2025/organ-2.png"
+ ];
+
+ if (!organFarm) return;
+ if (organFarm.classList.contains("hidden")) {
+ organFarm.classList.remove("hidden");
+ organFarm.classList.add("animate-slide-in-down");
+ }
+
+ organFarm.innerHTML = "";
+ for (let i = 0; i < organCount; i++) {
+ const img = document.createElement("img");
+ img.className = "transition hover:scale-150 dark:invert";
+
+ const sizeRange = [6, 10];
+ const size = Math.floor(Math.random() * (sizeRange[1] - sizeRange[0] + 1)) + sizeRange[0];
+ img.classList.add(`w-${size}`, `h-${size}`);
+
+ img.src = organImages[Math.floor(Math.random() * organImages.length)];
+ // randomly offset and rotate
+ img.classList.add("rotate-" + Math.floor(Math.random() * 5));
+ img.classList.add("translate-x-" + Math.floor(Math.random() * 5));
+ img.classList.add("translate-y-" + Math.floor(Math.random() * 5));
+ img.classList.add("opacity" + (100 - Math.floor(Math.random() * 3)*10));
+
+ organFarm.appendChild(img);
+ }
+ }
+
+ // fetch likes when action menu is visible
+ const observer = new IntersectionObserver((entries, obs) => {
+ if (entries[0].isIntersecting) {
+ fetchLikes();
+ obs.disconnect();
+ }
+ });
+ observer.observe(document.getElementById("action-menu"));
+});
+</script>
diff --git a/layouts/_partials/scripts.html b/layouts/_partials/scripts.html
index 2b84ea3c..edfb51b3 100644
--- a/layouts/_partials/scripts.html
+++ b/layouts/_partials/scripts.html
@@ -14,7 +14,3 @@
{{ partial "scripts/littlefoot-js" . }}
{{ partial "scripts/libra-js" . }}
{{ partial "scripts/aplayer-js" . }}
-
-{{ if .File }}
- {{ partial "scripts/action-menu-js" (.File.UniqueID | urlize) }}
-{{ end }}
diff --git a/layouts/_partials/scripts/action-menu-js.html b/layouts/_partials/scripts/action-menu-js.html
deleted file mode 100644
index dca99369..00000000
--- a/layouts/_partials/scripts/action-menu-js.html
+++ /dev/null
@@ -1,170 +0,0 @@
-{{ $pageId := . }}
-<script defer>
-/**
- * =================
- * Initialize all Action Menu features
- * - comment count
- * - like
- * =================
- */
-
-/**
- * =================
- * Fetch and set Comment Count
- * =================
- */
-
-function initializeCommentCount() {
- const commentCountEl = document.getElementById('comment-count');
- if (!commentCountEl) return;
-
- const observer = new MutationObserver(() => {
- // check if giscus is loaded
- const giscusIframe = document.querySelector('iframe.giscus-frame');
- if (!giscusIframe) return;
-
- giscusIframe.addEventListener('load', () => {
- // receive message from giscus iframe
- window.addEventListener('message', function(event) {
- if (event.origin !== 'https://giscus.app') return;
- const giscusData = event.data;
- if (giscusData.giscus?.discussion) {
- const discussion = giscusData.giscus.discussion;
- const totalComments = (discussion.totalCommentCount || 0) + (discussion.totalReplyCount || 0);
- // set comment count
- commentCountEl.textContent = totalComments.toString();
- // if no discussion found, set to 0
- } else commentCountEl.textContent = '0';
- });
- });
-
- observer.disconnect();
- });
- observer.observe(document.body, { childList: true, subtree: true });
-}
-
-/**
- * =================
- * Initialize like functionality
- * =================
- */
-
-function initializeLikes(pageId) {
- if (window.location.host !== 'www.geedea.pro') return;
-
- const elements = {
- count: document.getElementById("like-count-" + pageId),
- btn: document.getElementById("like-btn-" + pageId),
- container: document.getElementById("like-container-" + pageId),
- icon: document.getElementById("like-icon-" + pageId)
- };
-
- if (!elements.count || !elements.btn || !elements.container) return;
-
- function setLikedState() {
- // update classes
- elements.icon?.classList.add('liked-heart');
- elements.icon?.classList.add('animate-heart-beat');
- elements.count?.classList.add('liked-count');
- elements.btn.disabled = true;
- elements.container.classList.add('liked');
- // update tooltip
- elements.btn.setAttribute('title',
- elements.container.classList.contains('liked')
- ? elements.btn.getAttribute('data-liked-title')
- : '为这篇文章献上心脏'
- );
- }
-
- async function fetchLikes() {
- try {
- const response = await fetch("https://like.guhub.cn/like/" + pageId);
- const data = await response.json();
- elements.count.innerText = data.likes ?? 0;
- if (localStorage.getItem("liked_" + pageId)) {
- setLikedState();
- updateOrganFarm(data.likes);
- }
- } catch(e) {
- console.log(e);
- elements.count.innerText = "❌";
- }
- }
-
- window.sendLike = async function(pageId) {
- if (localStorage.getItem("liked_" + pageId)) return;
-
- try {
- const response = await fetch("https://like.guhub.cn/like/" + pageId, { method: "POST" });
- const data = await response.json();
- localStorage.setItem("liked_" + pageId, "1");
- elements.count.innerText = data.likes ?? 1;
- updateOrganFarm(data.likes);
- setLikedState();
- } catch(e) {
- console.log(e);
- alert("点赞失败,请稍后再试");
- }
- };
-
- function updateOrganFarm(count) {
- const organFarm = document.getElementById("organ-farm");
- const organCount = count || parseInt(elements.count.innerText);
- const organImages = [
- "https://image.guhub.cn/picgo2025/oragn-3.png",
- "https://image.guhub.cn/picgo2025/organ-1.png",
- "https://image.guhub.cn/picgo2025/organ-2.png"
- ];
-
- if (!organFarm) return;
- if (organFarm.classList.contains("hidden")) {
- organFarm.classList.remove("hidden");
- organFarm.classList.add("animate-slide-in-down");
- }
-
- organFarm.innerHTML = "";
- for (let i = 0; i < organCount; i++) {
- const img = document.createElement("img");
- img.className = "transition hover:scale-150 dark:invert";
-
- const sizeRange = [6, 10];
- const size = Math.floor(Math.random() * (sizeRange[1] - sizeRange[0] + 1)) + sizeRange[0];
- img.classList.add(`w-${size}`, `h-${size}`);
-
- img.src = organImages[Math.floor(Math.random() * organImages.length)];
- // randomly offset and rotate
- img.classList.add("rotate-" + Math.floor(Math.random() * 5));
- img.classList.add("translate-x-" + Math.floor(Math.random() * 5));
- img.classList.add("translate-y-" + Math.floor(Math.random() * 5));
- img.classList.add("opacity" + (100 - Math.floor(Math.random() * 3)*10));
-
- organFarm.appendChild(img);
- }
- }
-
- // fetch likes when action menu is visible
- const observer = new IntersectionObserver((entries, obs) => {
- if (entries[0].isIntersecting) {
- fetchLikes();
- obs.disconnect();
- }
- });
- observer.observe(document.getElementById("action-menu"));
-}
-
-/**
- * =================
- * Load features after DOMContentLoaded
- * =================
- */
-
-function initializeFeatures() {
- const pageId = "{{ $pageId }}";
- if (!pageId) return;
-
- initializeLikes(pageId);
- initializeCommentCount();
-}
-
-document.addEventListener('DOMContentLoaded', initializeFeatures);
-</script>