Reputation: 33
I am working on a project of a leaderboard. It is not a real thing, just a demo for learning purposes as I am a newbie.
To the point. The user can click the voting button, which will add one vote, change the info on the button to "thank you for voting" and finally disable all the remaining buttons, because in real world you are usually allowed to vote once a day. It took my some time, but it is worikig fine.
I was wondering if there is an easy way to let the user vote more often, let's say every 10 sec. The reason I want to allow it is because the content of the leaderboard is JS generated and if a player gets more votes than others they will go up on the board automatically (and then I can probably practice using localStorage and transition of some sort).
The code for voting function is this:
function voting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.addEventListener('click', (e) => {
button.innerHTML = 'thanks for voting!';
button.classList.replace(`vote-btn`, 'voted');
const target = e.target.closest('button');
const targetData = target.dataset.btnId;
if (targetData === playerPaul) {
document.getElementById(targetData).innerText = countPaul + 1;
disableVoting();
}
The if statements go one for all the players.
The voting buttons are disabled:
function disableVoting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.disabled = true;
button.classList.add('no-cursor');
})
}
My idea was to add another function to fire up after a given time. This function would undo the disabeling function and allow voting again.
function intervalVoting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.disabled = false;
button.classList.remove('no-cursor');
voting();
})
}
I tried adding setInterval(intervalVoting, 10000)
to disableVoting() like so:
function disableVoting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.disabled = true;
button.classList.add('no-cursor');
setInterval(intervalVoting, 10000);
})
}
What is does it allows to give another vote after 10sec but only on players that havent't been voted on.
Upvotes: 1
Views: 116
Reputation: 13356
Any more easily to refactor implementation would choose an approach which introduces atomar tasks implemented as meaningfully named function statements.
In addition, and depending on the markup, one could choose event-delegation in order to not having separately to subscribe an own handler function to each vote-button.
One also could drop some css class-names in favor of more generic and expressive selector-based styling-rules.
function updateVoteCount(target) {
const countValue = parseInt(target.dataset.voteCount, 10) + 1;
target.dataset.voteCount = countValue;
target.textContent = countValue;
}
function restoreVoting(target) {
target.classList.remove('voted');
target.textContent = target.dataset.btnTextBeforeVote;
target.disabled = false;
}
function temporarilyDisableVoting(target) {
target.disabled = true;
setTimeout(restoreVoting, 10_000, target);
}
function temporarilyDisableAnyListItemVoting(listRoot) {
listRoot
.querySelectorAll('.vote-btn')
.forEach(temporarilyDisableVoting);
}
function handlePlayerListItemVote({ target }) {
target = target.closest('.vote-btn');
const listRoot = target && target.closest('.player-list');
if (listRoot !== null) {
temporarilyDisableAnyListItemVoting(listRoot);
target.classList.add('voted');
target.textContent = target.dataset.btnTextAfterVote;
updateVoteCount(
target.closest('li').querySelector('[data-vote-count]')
);
}
}
document
.querySelector('.player-list')
.addEventListener('click', handlePlayerListItemVote);
body { margin: 0; }
p { margin: 5px 0; }
button.vote-btn:not(:disabled) { cursor: pointer; }
button.vote-btn.voted { background-color: #cf0; }
<ul class="player-list">
<li>
<p>
Player Foo - upvotes:
<span data-vote-count="0">0</span>
</p>
<button
class="vote-btn"
data-btn-text-after-vote="thanks for voting!"
data-btn-text-before-vote="feel free to vote"
>feel free to vote</button>
</li>
<li>
<p>
Player Bar - upvotes:
<span data-vote-count="0">0</span>
</p>
<button
class="vote-btn"
data-btn-text-after-vote="thanks for voting!"
data-btn-text-before-vote="feel free to vote"
>feel free to vote</button>
</li>
<li>
<p>
Player Baz - upvotes:
<span data-vote-count="0">0</span>
</p>
<button
class="vote-btn"
data-btn-text-after-vote="thanks for voting!"
data-btn-text-before-vote="feel free to vote"
>feel free to vote</button>
</li>
</ul>
Upvotes: 0