mirror of
https://github.com/by-jp/www.byjp.me.git
synced 2025-08-09 22:16:07 +01:00
Adds claps & hearts
I've created a simple mechanism to offer me instant feedback that you liked a post. A clap 👏 or a heart ❤️ appear at the bottom of every post, which uses val.town to keep track of current claps. I'm proud that it works well in both Javascript and non-Javascript worlds!
This commit is contained in:
parent
afd8d589f5
commit
38751361ff
9 changed files with 103 additions and 3 deletions
|
@ -7,3 +7,40 @@ function updateAccentColor() {
|
||||||
}
|
}
|
||||||
setInterval(updateAccentColor, 15000)
|
setInterval(updateAccentColor, 15000)
|
||||||
updateAccentColor()
|
updateAccentColor()
|
||||||
|
|
||||||
|
const performClap = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const btn = e.currentTarget;
|
||||||
|
btn.disabled = true;
|
||||||
|
fetch(btn.parentElement.action, { method: 'POST', headers: new Headers({ 'Accept': 'application/json' }) })
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
localStorage.setItem(clapKey(btn.parentElement.action), data.claps);
|
||||||
|
setClapCount(btn, data.claps);
|
||||||
|
btn.parentElement.classList.add('clapped')
|
||||||
|
btn.disabled = false;
|
||||||
|
})
|
||||||
|
.catch(e => console.error(`Failed to automate the clap: ${e}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
const clapKey = (action) => `clap:${(new URL(action)).pathname}`;
|
||||||
|
|
||||||
|
const setClapCount = (btn, clapCount) => {
|
||||||
|
const count = btn.querySelector('span');
|
||||||
|
if (count) {
|
||||||
|
count.textContent = Math.max(count.textContent, clapCount)
|
||||||
|
} else {
|
||||||
|
const newCount = document.createElement('span');
|
||||||
|
newCount.textContent = clapCount;
|
||||||
|
btn.appendChild(newCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const btn of document.querySelectorAll('form.claps button')) {
|
||||||
|
const lastClappedTo = localStorage.getItem(clapKey(btn.parentElement.action));
|
||||||
|
if (lastClappedTo) {
|
||||||
|
btn.parentElement.classList.add('clapped')
|
||||||
|
setClapCount(btn, lastClappedTo)
|
||||||
|
}
|
||||||
|
btn.addEventListener("click", performClap)
|
||||||
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@ html {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
position:relative;
|
position:relative;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -613,6 +611,26 @@ a[href^="#fn:"] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.claps {
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
&.clapped {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled svg {
|
||||||
|
animation: pulse 500ms infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 1.5em;
|
||||||
|
|
||||||
|
&:only-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.post.poetry {
|
.post.poetry {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
||||||
|
@ -638,6 +656,17 @@ a[href^="#fn:"] {
|
||||||
.post-info {
|
.post-info {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
|
|
||||||
|
form.claps {
|
||||||
|
margin-top: 1em;
|
||||||
|
text-align: center;
|
||||||
|
float: none;
|
||||||
|
display:inline-block;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,4 +1000,10 @@ mark {
|
||||||
vertical-align: -0.125em;
|
vertical-align: -0.125em;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% { opacity: 0.5; }
|
||||||
|
50% { opacity: 1; }
|
||||||
|
100% { opacity: 0.5; }
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,9 @@ date = ["date", "publishDate", "lastmod", ":git"]
|
||||||
# Default theme "light" or "dark"
|
# Default theme "light" or "dark"
|
||||||
defaultTheme = "dark"
|
defaultTheme = "dark"
|
||||||
themeColor = "#252627"
|
themeColor = "#252627"
|
||||||
|
|
||||||
|
clapshost = "byjp-claps.web.val.run"
|
||||||
|
|
||||||
[params.favicon.color]
|
[params.favicon.color]
|
||||||
mask = "#252627"
|
mask = "#252627"
|
||||||
msapplication = "#252627"
|
msapplication = "#252627"
|
||||||
|
|
|
@ -106,6 +106,8 @@
|
||||||
|
|
||||||
{{ if ne .Type "site-infra" }}
|
{{ if ne .Type "site-infra" }}
|
||||||
<div class="post-info">
|
<div class="post-info">
|
||||||
|
{{ partial "claps.html" (dict "url" .RelPermalink) }}
|
||||||
|
|
||||||
{{ if in .Params.tags "from-twitter" }}
|
{{ if in .Params.tags "from-twitter" }}
|
||||||
<p>
|
<p>
|
||||||
{{ partial "svg.html" (dict "name" "twitter") }}
|
{{ partial "svg.html" (dict "name" "twitter") }}
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div class="post-info" id="post-info">
|
<div class="post-info" id="post-info">
|
||||||
|
{{ partial "claps.html" (dict "url" .RelPermalink) }}
|
||||||
{{ partial "tags.html" .Params.tags }}
|
{{ partial "tags.html" .Params.tags }}
|
||||||
|
|
||||||
{{ with .Params.location }}<p>
|
{{ with .Params.location }}<p>
|
||||||
|
|
19
layouts/partials/claps.html
Normal file
19
layouts/partials/claps.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{{- $relperma := .url -}}
|
||||||
|
{{- $style := .style | default "clap" -}}
|
||||||
|
<form class="claps" action="https://{{ site.Params.clapsHost }}{{ $relperma }}" method="post">
|
||||||
|
<button type="submit">
|
||||||
|
{{- partial "svg.html" (dict "name" $style) -}}
|
||||||
|
{{- $url := printf "https://%s" site.Params.clapsHost -}}
|
||||||
|
{{- $cacheKey := print $url (now.Format "-2006-01-02") -}}
|
||||||
|
{{- with resources.GetRemote $url (dict "key" $cacheKey) -}}
|
||||||
|
{{- with .Err -}}
|
||||||
|
{{- errorf "%s" . -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- $data := .Content | transform.Unmarshal -}}
|
||||||
|
{{- with (index $data $relperma) }}<span>{{ . }}</span>{{ end -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- errorf "Unable to get all clap counts" -}}
|
||||||
|
{{- end -}}
|
||||||
|
</button>
|
||||||
|
</form>
|
|
@ -1,4 +1,5 @@
|
||||||
<div class="post-info">
|
<div class="post-info">
|
||||||
|
{{ partial "claps.html" (dict "url" .RelPermalink) }}
|
||||||
{{ partial "tags.html" .Params.tags }}
|
{{ partial "tags.html" .Params.tags }}
|
||||||
{{ partial "series-tags.html" . }}
|
{{ partial "series-tags.html" . }}
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div class="post-info">
|
<div class="post-info">
|
||||||
|
{{ partial "claps.html" (dict "url" .RelPermalink "style" "heart") }}
|
||||||
{{ if in .Params.tags "from-instagram" }}
|
{{ if in .Params.tags "from-instagram" }}
|
||||||
<p>
|
<p>
|
||||||
{{ partial "svg.html" (dict "name" "instagram") }}
|
{{ partial "svg.html" (dict "name" "instagram") }}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
<div class="post-info">
|
<div class="post-info">
|
||||||
<p><date datetime="{{ dateFormat .Site.Params.dateformHTML .Date }}" data-pagefind-sort="date">{{ dateFormat .Site.Params.dateform .Date }}</date></p>
|
<p><date datetime="{{ dateFormat .Site.Params.dateformHTML .Date }}" data-pagefind-sort="date">{{ dateFormat .Site.Params.dateform .Date }}</date></p>
|
||||||
<p><a href="../">back</a></p>
|
<p><a href="../">back</a></p>
|
||||||
|
{{ partial "claps.html" (dict "url" .RelPermalink "style" "heart") }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
Loading…
Reference in a new issue