diff --git a/js/guest.js b/js/guest.js index c8ce2f1..2ea767f 100644 --- a/js/guest.js +++ b/js/guest.js @@ -9,6 +9,9 @@ import { confetti } from './confetti.js'; export const guest = (() => { + /** + * @type {ReturnType|null} + */ let information = null; const countDownDate = () => { diff --git a/js/like.js b/js/like.js index aebea87..7e0fe78 100644 --- a/js/like.js +++ b/js/like.js @@ -1,5 +1,4 @@ import { dto } from './dto.js'; -import { offline } from './offline.js'; import { storage } from './storage.js'; import { session } from './session.js'; import { confetti } from './confetti.js'; @@ -7,6 +6,9 @@ import { request, HTTP_PATCH, HTTP_POST } from './request.js'; export const like = (() => { + /** + * @type {ReturnType|null} + */ let likes = null; const like = async (button) => { @@ -101,7 +103,7 @@ export const like = (() => { }; const tapTap = async (div) => { - if (!offline.isOnline()) { + if (!navigator.onLine) { return; } diff --git a/js/navbar.js b/js/navbar.js index 45fce34..5233f6c 100644 --- a/js/navbar.js +++ b/js/navbar.js @@ -2,12 +2,20 @@ import { bootstrap } from './bootstrap.js'; export const navbar = (() => { + /** + * @param {HTMLElement} btn + * @returns {void} + */ const buttonNavHome = (btn) => { bootstrap.Tab.getOrCreateInstance(document.getElementById('button-home')).show(); btn.classList.add('active'); document.getElementById('button-mobile-setting').classList.remove('active'); }; + /** + * @param {HTMLElement} btn + * @returns {void} + */ const buttonNavSetting = (btn) => { bootstrap.Tab.getOrCreateInstance(document.getElementById('button-setting')).show(); btn.classList.add('active'); diff --git a/js/offline.js b/js/offline.js index 4ab1dcd..e7c5291 100644 --- a/js/offline.js +++ b/js/offline.js @@ -1,5 +1,8 @@ export const offline = (() => { + /** + * @type {HTMLElement|null} + */ let alert = null; let online = true; diff --git a/js/progress.js b/js/progress.js index fdafdd3..a1f010d 100644 --- a/js/progress.js +++ b/js/progress.js @@ -2,7 +2,14 @@ import { guest } from './guest.js'; export const progress = (() => { + /** + * @type {HTMLElement|null} + */ let info = null; + + /** + * @type {HTMLElement|null} + */ let bar = null; let total = 0; diff --git a/js/session.js b/js/session.js index a050365..b66a782 100644 --- a/js/session.js +++ b/js/session.js @@ -5,7 +5,7 @@ import { request, HTTP_POST, HTTP_GET } from './request.js'; export const session = (() => { /** - * @type {ReturnType} + * @type {ReturnType|null} */ let ses = null; diff --git a/js/theme.js b/js/theme.js index b96c8c9..28fa8a5 100644 --- a/js/theme.js +++ b/js/theme.js @@ -143,26 +143,7 @@ export const theme = (() => { } }; - const spyTop = () => { - const observerTop = new IntersectionObserver((es) => { - es.filter((e) => e.isIntersecting).forEach((e) => { - const themeColor = ['bg-black', 'bg-white'].some((i) => e.target.classList.contains(i)) - ? isDarkMode(themeDark[0], themeLight[0]) - : isDarkMode(themeDark[1], themeLight[1]); - - metaTheme.setAttribute('content', themeColor); - }); - }, { - rootMargin: '0% 0% -95% 0%', - }); - - document.querySelectorAll('section').forEach((e) => observerTop.observe(e)); - }; - - const init = () => { - theme = storage('theme'); - metaTheme = document.querySelector('meta[name="theme-color"]'); - + const initObserver = () => { observerLight = new IntersectionObserver((es, o) => { es.filter((e) => e.isIntersecting).forEach((e) => toLight(e.target)); @@ -184,6 +165,29 @@ export const theme = (() => { const now = metaTheme.getAttribute('content'); metaTheme.setAttribute('content', themeLight.some((i) => i === now) ? themeColors[now] : now); }); + }; + + const spyTop = () => { + const observerTop = new IntersectionObserver((es) => { + es.filter((e) => e.isIntersecting).forEach((e) => { + const themeColor = ['bg-black', 'bg-white'].some((i) => e.target.classList.contains(i)) + ? isDarkMode(themeDark[0], themeLight[0]) + : isDarkMode(themeDark[1], themeLight[1]); + + metaTheme.setAttribute('content', themeColor); + }); + }, { + rootMargin: '0% 0% -95% 0%', + }); + + document.querySelectorAll('section').forEach((e) => observerTop.observe(e)); + }; + + const init = () => { + theme = storage('theme'); + metaTheme = document.querySelector('meta[name="theme-color"]'); + + initObserver(); if (!theme.has('active')) { if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { diff --git a/js/util.js b/js/util.js index 741171f..e30a5f0 100644 --- a/js/util.js +++ b/js/util.js @@ -3,26 +3,35 @@ import { bootstrap } from './bootstrap.js'; export const util = (() => { + /** + * @param {string} id + * @param {number} speed + * @returns {void} + */ const opacity = (id, speed = 0.01) => { - const element = document.getElementById(id); - let op = parseInt(element.style.opacity); + const el = document.getElementById(id); + let op = parseInt(el.style.opacity); let clear = null; const callback = () => { if (op > 0) { - element.style.opacity = op.toFixed(3); + el.style.opacity = op.toFixed(3); op -= speed; return; } clearInterval(clear); clear = null; - element.remove(); + el.remove(); }; clear = setInterval(callback, 10); }; + /** + * @param {string} unsafe + * @returns {string} + */ const escapeHtml = (unsafe) => { return String(unsafe) .replace(/&/g, '&') @@ -32,6 +41,11 @@ export const util = (() => { .replace(/'/g, '''); }; + /** + * @param {function} callback + * @param {number} timeout + * @returns {void} + */ const timeOut = (callback, timeout) => { let clear = null; const c = () => { @@ -72,8 +86,18 @@ export const util = (() => { }; }; + /** + * @param {HTMLElement} svg + * @param {number} timeout + * @param {string} classes + * @returns {void} + */ const animate = (svg, timeout, classes) => timeOut(() => svg.classList.add(classes), timeout); + /** + * @param {HTMLImageElement} img + * @returns {void} + */ const modal = (img) => { document.getElementById('show-modal-image').src = img.src; bootstrap.Modal.getOrCreateInstance('#modal-image').show(); @@ -106,18 +130,29 @@ export const util = (() => { }, timeout); }; + /** + * @param {string} str + * @returns {string} + */ const base64Encode = (str) => { const encoder = new TextEncoder(); const encodedBytes = encoder.encode(str); return btoa(String.fromCharCode(...encodedBytes)); }; + /** + * @param {string} str + * @returns {string} + */ const base64Decode = (str) => { const decoder = new TextDecoder(); const decodedBytes = Uint8Array.from(window.atob(str), (c) => c.charCodeAt(0)); return decoder.decode(decodedBytes); }; + /** + * @returns {void} + */ const closeInformation = () => storage('information').set('info', true); return {