diff options
Diffstat (limited to 'src/js/love.js')
-rw-r--r-- | src/js/love.js | 125 |
1 files changed, 125 insertions, 0 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 = ''; + }); + }); + } +}); |