diff options
Diffstat (limited to 'src/js')
-rw-r--r-- | src/js/love.js | 125 | ||||
-rw-r--r-- | src/js/sidenotes.js | 2 | ||||
-rw-r--r-- | src/js/theme.js | 126 | ||||
-rw-r--r-- | src/js/zen.js | 36 |
4 files changed, 280 insertions, 9 deletions
diff --git a/src/js/love.js b/src/js/love.js new file mode 100644 index 0000000..66f47d4 --- /dev/null +++ b/src/js/love.js @@ -0,0 +1,125 @@ +window.addEventListener('DOMContentLoaded', () => { + // This script insert a love button at the end of an article page + + const articles = document.querySelectorAll('article'); + + function getCurrentPageLang() { + return document.documentElement.lang || "en"; + } + function getLikeEndPoint() { + let currentArticleName = window.location.pathname.split('/')[2]; + if (currentArticleName.indexOf('.') > 0) { + currentArticleName = currentArticleName.slice(0, currentArticleName.lastIndexOf('.')) + } + + return `${window.location.origin}/like/${currentArticleName}`; + } + + const isAnArticle = articles.length === 1; // The front page have multiple articles. + + if (isAnArticle) { + const article = articles[0]; + const likes = article.querySelector('.likes'); + const nbLikes = article.querySelector('.nbLikes'); + const footnotes = article.querySelector('.footnotes'); + + likes.style="display: 'block';"; + const updateNbLikes = () => { + fetch(getLikeEndPoint(), { + method: 'GET', + headers: { + 'i-love-what-you-do': '<3', + }, + }).then((res) => { + if (res.ok) { + res.text().then((text) => nbLikes.textContent = text); + } else { + nbLikes.textContent = ""; + } + }); + }; + + updateNbLikes(); + + if (footnotes) { + // We want: article.insertBefore(likes, footnotes); + footnotes.before(likes); + } + + const icon = likes.querySelector('.icon'); + const messagesLike = likes.querySelector('.likesNotes'); + + icon.addEventListener('mouseover', () => { + for (const c of icon.children) { + const path = c.querySelector('path'); + path?.classList.add('anim'); + } + }); + + icon.addEventListener('mouseout', () => { + for (const c of icon.children) { + const path = c.querySelector('path'); + path?.classList.remove('anim'); + } + }); + + icon.addEventListener('click', () => { + const c = icon.children[1]; + const lang = getCurrentPageLang(); + + const path = c.querySelector('path'); + + path.classList.add('anim-click'); + path.getAnimations().forEach(anim => { + anim.cancel(); + anim.play(); + }); + + fetch(getLikeEndPoint(), { + method: 'POST', + headers: { + 'i-love-what-you-do': '<3', + 'lang': lang, + }, + }).then(response => { + const t = response.text(); + + if (response.ok) { + messagesLike.classList.remove('err'); + t.then(t => messagesLike.textContent = t); + updateNbLikes(); + } else { + t.then(t => { + // In case of error, we want to be able to set the initial message back + const previousText = messagesLike.textContent; + const timeoutErr = 3000; + const wasAnError = messagesLike.classList.contains('err'); + + // Set the error + messagesLike.classList.add('err'); + if (Math.floor(response.status / 100) == 4) { + messagesLike.textContent = t; + } else { + messagesLike.textContent = lang == 'fr' ? 'Désolé, le service est indisponible.' : 'Sorry, service unavailable.'; + } + + // Set the initial message back + if(!wasAnError) { + setTimeout(() => { + if(messagesLike.classList.contains('err')) { + messagesLike.classList.remove('err'); + messagesLike.textContent = previousText; + } + }, timeoutErr); + } + }); + } + }).catch(() => { + // In case of exception error. We don't want to set back the initial message. + messagesLike.classList.add('err'); + messagesLike.textContent = lang == 'fr' ? 'Désolé, le service est indisponible.' : 'Sorry, service unavailable.'; + messageText = ''; + }); + }); + } +}); diff --git a/src/js/sidenotes.js b/src/js/sidenotes.js index 8ab99f9..851e11b 100644 --- a/src/js/sidenotes.js +++ b/src/js/sidenotes.js @@ -28,7 +28,7 @@ const resize = () => { const newSidenotes = notes.map(sidenoteLi => { const div = document.createElement('div'); const refName = sidenoteLi.querySelector('.data-footnote-backref').attributes.href.value; - const refSideNode = article.querySelector(refName); + const refSideNode = article.querySelector(`#${CSS.escape(refName.slice(1))}`); const sup = document.createElement('sup'); sup.textContent = refSideNode.textContent + ' '; diff --git a/src/js/theme.js b/src/js/theme.js new file mode 100644 index 0000000..8239c69 --- /dev/null +++ b/src/js/theme.js @@ -0,0 +1,126 @@ +window.addEventListener('DOMContentLoaded', () => { + const storageTheme = window.localStorage?.getItem('theme'); + const preferesDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + + let isDark = preferesDark; + + const hid = document.querySelector('#hid'); + const html = document.querySelector('html'); + const aside = document.querySelector('#side-bar'); + const sidenotes = document.querySelector('.sidenotes'); + const footnotes = document.querySelector('.footnotes'); + const harr = document.querySelector('#harr'); + const links = document.querySelectorAll('a'); + const likes = document.querySelectorAll('.likes'); + const tables = document.querySelectorAll('table'); + const codes = document.querySelectorAll('p code'); + + if (storageTheme === 'dark' || storageTheme === 'light') { + const theme = storageTheme; + isDark = storageTheme === 'dark'; + hid.classList.add(theme); + html.classList.add(theme); + aside.classList.add(theme); + sidenotes.classList.add(theme); + harr.classList.add(theme); + + if(footnotes) { + footnotes.classList.add(theme); + } + + for (let link of links) { + link.classList.add(theme); + } + for (let likeBox of likes) { + likeBox.classList.add(theme); + } + for (let table of tables) { + table.classList.add(theme); + } + for (let code of codes) { + code.classList.add(theme); + } + + for (const article of document.querySelectorAll('article')) { + article.classList.add(theme); + } + + for (const article of document.querySelectorAll('article')) { + article.classList.add(theme); + } + } + + function toogleTheme() { + const arg = isDark ? ['dark', 'light'] : ['light', 'dark']; + const theme = arg[1]; + + if (!hid.classList.replace(...arg)) { + hid.classList.add(theme); + } + + if (!html.classList.replace(...arg)) { + html.classList.add(theme); + } + + if (!aside.classList.replace(...arg)) { + aside.classList.add(theme); + } + + if (!sidenotes.classList.replace(...arg)) { + sidenotes.classList.add(theme); + } + if (footnotes && !footnotes.classList.replace(...arg)) { + footnotes.classList.add(theme); + } + + + + if (!harr.classList.replace(...arg)) { + harr.classList.add(theme); + } + + for (let link of links) { + if (!link.classList.replace(...arg)) { + link.classList.add(theme); + } + } + for (let table of tables) { + if (!table.classList.replace(...arg)) { + table.classList.add(theme); + } + } + for (let code of codes) { + if (!code.classList.replace(...arg)) { + code.classList.add(theme); + } + } + for (let like of likes) { + if (!like.classList.replace(...arg)) { + like.classList.add(theme); + } + } + + for (const article of document.querySelectorAll('article')) { + if (!article.classList.replace(...arg)) { + article.classList.add(theme); + } + } + + isDark = !isDark; + if (window.localStorage) { + window.localStorage.setItem('theme', isDark ? 'dark' : 'light'); + } + } + + const sun = document.querySelector('.sun'); + const moon = document.querySelector('.moon'); + + sun.addEventListener('click', toogleTheme); + moon.addEventListener('click', toogleTheme); + + if (isDark) { + hid.classList.add('dark'); + } else { + hid.classList.add('light'); + } +}); diff --git a/src/js/zen.js b/src/js/zen.js index d897603..be5f7d7 100644 --- a/src/js/zen.js +++ b/src/js/zen.js @@ -1,17 +1,25 @@ window.addEventListener('DOMContentLoaded', () => { let firstTime = window.location.pathname != '/' && window.pageYOffset < 800; const toggleArrow = document.querySelector('#harr'); + const hid = document.querySelector('#hid'); const initValue = document.body.style.getPropertyValue('--width_panel_bis'); toggleArrow.addEventListener('click', () => { if (toggleArrow.classList.contains('hide_arrow_off')) { + firstTime = false; showAbout(); + showHID(); setTimeout(() => { toggleArrow.classList.remove('hide_arrow_off'); }, 1000); } else { toggleArrow.classList.add('hide_arrow_off'); hideAbout(); + + // If the screen is smaller than 500px, hide the HID + if (window.screen.availWidth <= 500) { + hideHID(); + } } }); @@ -23,20 +31,32 @@ window.addEventListener('DOMContentLoaded', () => { document.body.style.setProperty('--width_panel_bis', initValue); } + function hideHID() { + hid.style.setProperty('display', 'none'); + } + + function showHID() { + hid.style.setProperty('display', ''); + } + window.addEventListener('scroll', () => { + if(!toggleArrow) return; if (window.pageYOffset >= 800) { - if (toggleArrow) { - if (firstTime) { - toggleArrow.click(); - firstTime = false; - } else { - toggleArrow.classList.add('hide_arrow_show'); - } + if (firstTime && document.body.style.getPropertyValue('--width_panel_bis') === initValue) { + toggleArrow.click(); + firstTime = true; } + + toggleArrow.classList.add('hide_arrow_show'); // A hideAbout(header, articles); - } else if (toggleArrow && !toggleArrow.classList.contains('hide_arrow_off')) { + } else if (!toggleArrow.classList.contains('hide_arrow_off')) { // A showAbout(header, articles); toggleArrow.classList.remove('hide_arrow_show'); } + + if(firstTime && window.pageYOffset === 0 && document.body.style.getPropertyValue('--width_panel_bis') !== initValue) { + toggleArrow.click(); + firstTime = true; + } }); }); |