Reputation: 709
Currently I have a Thumbs up and Thumbs down button that allows the user to click thumbs-up and down multiple times keeps count of each item (Similar to YouTube). I would like to set it up where If a user clicks on thumbs down, the thumbs up count resets, and vice versa. Is there a way to do this conditionally?
$().ready(function() {
display();
});
function display() {
$("#book-items").html("");
let content = "";
let col = "";
for (let i in GV_MOVIES) {
content += "<li class='flex-item'>";
col = `<div class="img-cnt"><img src='${GV_MOVIES[i].image}'/></div><div class="book-title"> ${GV_MOVIES[i].title} </div> `;
content += col;
let val = GV_MOVIES[i].thumbsUp + " +";
content += "<div class='group'>";
let btn = `<button class='btnUp' onClick='javascript:upClick(${i})'><div>${val}</div></button>`;
content += btn;
val = GV_MOVIES[i].thumbsDown + " -";
btn = `<button class='btnDown' onClick='javascript:downClick(${i})'><div>${val}</div></button>`;
content += btn + "</div>";
content += "</div>";
}
$("#book-items").html(content);
}
function upClick(idx) {
GV_MOVIES[idx].thumbsUp++;
display();
}
function downClick(idx) {
GV_MOVIES[idx].thumbsDown++;
display();
}
//var GV_MOVIES = []
var GV_MOVIES = [{
id: 1,
title: "Anne of Greene Gables",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/cJmt614/greengable.jpg"
},
{
id: 2,
title: "Island Of The Blue Dolphins",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/y0PDkJP/dolphin.jpg"
},
{
id: 3,
title: "The Tipping Point",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/tp4H24J/tippingpoint.jpg"
},
{
id: 4,
title: "The Reckoning",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/3z0HWyw/reckomning.jpg"
}
];
#book-items {
display: flex;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
flex-flow: row wrap;
justify-content: space-around;
padding: 0;
margin: 0;
list-style: none;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-align-content: stretch;
-ms-flex-line-pack: stretch;
align-content: stretch;
}
.flex-item {
background: #fff5f3;
width: 180px;
margin-top: 10px;
font-weight: bold;
font-size: 3em;
text-align: center;
padding: 16px;
}
img {
width: 100%;
height: auto;
}
.btnUp {
background-image: url(https://i.ibb.co/H4MZMFT/thumbsupdown.png);
background-repeat: no-repeat;
background-position: 4px 0;
background-clip: content-box;
border: none;
}
button {
position: relative;
}
.btnDown,
.btnUp {
height: 50px;
width: 50px;
background-size: 80px;
}
.btnDown div,
.btnUp div {
position: absolute;
left: 19px;
top: 60px;
}
.btnDown {
background-image: url(https://i.ibb.co/H4MZMFT/thumbsupdown.png);
background-repeat: no-repeat;
background-position: -33px 0;
background-clip: content-box;
border: none;
}
.group {
padding: 2px;
height: 80px;
}
.book-title {
font-size: 0.3em;
font-family: arial;
height: 59px;
width: 50%;
padding: 10px;
display: table-cell;
vertical-align: middle;
}
.img-cnt {
width: 180px;
height: 282px;
}
@media only screen and (min-device-width: 320px) and (max-device-width: 850px) {
.flex-item {
width: 470px;
padding: 6px;
}
.img-cnt {
width: 100%;
height: auto;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='book-items'></div>
Upvotes: 1
Views: 184
Reputation: 122888
It is generally not a good idea to use inline event handlers. Here's your snippet using Event Delegation and a data-attribute for identification of the clicked button. This way it's easy to identify the corresponding element of the GV_MOVIES
array and modify the value of thumbsUp
as well of that of thumbsDown
.
I streamlined your code a bit. Toggling thumbsUp/-Down now does not require a complete rewrite of div#book-items
anymore.
const GV_MOVIES = getData();
document.addEventListener('click', handle);
display();
function handle(evt) {
if (evt.target.closest('[data-id]')) {
return toggleUpDown(evt.target);
}
}
function toggleUpDown(origin) {
const clickedUp = origin.classList.contains("btnUp");
GV_MOVIES[origin.dataset.id].thumbsUp = +(clickedUp);
GV_MOVIES[origin.dataset.id].thumbsDown = +(!clickedUp);
const parent = origin.closest('li');
parent.querySelector(".btnUp [data-value]").dataset.value =
`${GV_MOVIES[origin.dataset.id].thumbsUp} +`;
parent.querySelector(".btnDown [data-value]").dataset.value =
`${GV_MOVIES[origin.dataset.id].thumbsDown} -`;
}
function display() {
const items = $("#book-items");
items.html("");
for (let i in GV_MOVIES) {
items.append($(
`<li class='flex-item'>
<div class="img-cnt">
<img src='${GV_MOVIES[i].image}'/>
</div>
<div class="book-title"> ${GV_MOVIES[i].title}</div>
<div class='group'>
<button class='btnUp' data-id='${i}'>
<div data-value="${GV_MOVIES[i].thumbsUp + " +"}"></div>
</button>
<button class='btnDown' data-id='${i}'>
<div data-value="${GV_MOVIES[i].thumbsDown + " -"}"></div>
</button>
</div>
</li>`));
}
}
function getData() {
return [{
id: 1,
title: "Anne of Greene Gables",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/cJmt614/greengable.jpg"
},
{
id: 2,
title: "Island Of The Blue Dolphins",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/y0PDkJP/dolphin.jpg"
},
];
}
[data-value]:after {
content: attr(data-value);
}
#book-items {
display: flex;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
flex-flow: row wrap;
justify-content: space-around;
padding: 0;
margin: 0;
list-style: none;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-align-content: stretch;
-ms-flex-line-pack: stretch;
align-content: stretch;
}
.flex-item {
background: #fff5f3;
width: 180px;
margin-top: 10px;
font-weight: bold;
font-size: 3em;
text-align: center;
padding: 16px;
}
img {
width: 100%;
height: auto;
}
.btnUp {
background-image: url(https://i.ibb.co/H4MZMFT/thumbsupdown.png);
background-repeat: no-repeat;
background-position: 4px 0;
background-clip: content-box;
border: none;
}
button {
position: relative;
}
.btnDown,
.btnUp {
height: 50px;
width: 50px;
background-size: 80px;
}
.btnDown div,
.btnUp div {
position: absolute;
left: 19px;
top: 60px;
}
.btnDown {
background-image: url(https://i.ibb.co/H4MZMFT/thumbsupdown.png);
background-repeat: no-repeat;
background-position: -33px 0;
background-clip: content-box;
border: none;
}
.group {
padding: 2px;
height: 80px;
}
.book-title {
font-size: 0.3em;
font-family: arial;
height: 59px;
width: 50%;
padding: 10px;
display: table-cell;
vertical-align: middle;
}
.img-cnt {
width: 180px;
height: 282px;
}
@media only screen and (min-device-width: 320px) and (max-device-width: 850px) {
.flex-item {
width: 470px;
padding: 6px;
}
.img-cnt {
width: 100%;
height: auto;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='book-items'></div>
Upvotes: 1
Reputation: 177685
Here is an improved version which does not reload the list on every click
Also the generation of the display is vastly simplified and I use a data attribute for the storing of the index of the movie
Lastly I delegate the click to the container
$().ready(display);
function display() {
$("#book-items").html(GV_MOVIES.map((movie, i) =>
`<div class='flex-item'>
<div class="img-cnt"><img src='${movie.image}'/></div>
<div class="book-title">${movie.title}</div>
<div class='group'>
<button class='vote btnUp' data-idx="${i}">${movie.thumbsUp}</button>
<button class='vote btnDown' data-idx="${i}">${movie.thumbsDown}</button>
</div>
</div>`).join("")
)
.on("click", ".vote", function() { // delegation
const $parent = $(this).closest("div");
const idx = $(this).data("idx");
let val = +$(this).text();
if (val === 0) $(this).text(1);
$(this).siblings().eq(0).text(0);
GV_MOVIES[idx].thumbsUp = $parent.find(".btnUp").text();
GV_MOVIES[idx].thumbsDown = $parent.find(".btnDown").text();
});
}
//var GV_MOVIES = []
var GV_MOVIES = [{
id: 1,
title: "Anne of Greene Gables",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/cJmt614/greengable.jpg"
},
{
id: 2,
title: "Island Of The Blue Dolphins",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/y0PDkJP/dolphin.jpg"
},
{
id: 3,
title: "The Tipping Point",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/tp4H24J/tippingpoint.jpg"
},
{
id: 4,
title: "The Reckoning",
thumbsUp: 0,
thumbsDown: 0,
image: "https://i.ibb.co/3z0HWyw/reckomning.jpg"
}
];
#book-items {
display: flex;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
flex-flow: row wrap;
justify-content: space-around;
padding: 0;
margin: 0;
list-style: none;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-align-content: stretch;
-ms-flex-line-pack: stretch;
align-content: stretch;
}
.flex-item {
background: #fff5f3;
width: 180px;
margin-top: 10px;
font-weight: bold;
font-size: 3em;
text-align: center;
padding: 16px;
}
img {
width: 100%;
height: auto;
}
.btnUp {
background-image: url(https://i.ibb.co/H4MZMFT/thumbsupdown.png);
background-repeat: no-repeat;
background-position: 4px 0;
background-clip: content-box;
border: none;
}
button {
position: relative;
}
.btnDown,
.btnUp {
height: 50px;
width: 50px;
background-size: 80px;
}
.btnDown div,
.btnUp div {
position: absolute;
left: 19px;
top: 60px;
}
.btnDown {
background-image: url(https://i.ibb.co/H4MZMFT/thumbsupdown.png);
background-repeat: no-repeat;
background-position: -33px 0;
background-clip: content-box;
border: none;
}
.group {
padding: 2px;
height: 80px;
}
.book-title {
font-size: 0.3em;
font-family: arial;
height: 59px;
width: 50%;
padding: 10px;
display: table-cell;
vertical-align: middle;
}
.img-cnt {
width: 180px;
height: 282px;
}
@media only screen and (min-device-width: 320px) and (max-device-width: 850px) {
.flex-item {
width: 470px;
padding: 6px;
}
.img-cnt {
width: 100%;
height: auto;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='book-items'></div>
Upvotes: 0
Reputation: 3763
Well as I understand, the thumbsUp counter needs to be set to 0 when the thumbsDown button is clicked. The thumbsDown counter needs to be set to 0 when the thumbsUp button is clicked. This can be done by modifying the upClick and downClick buttons so they work as follows:
function upClick(idx) {
GV_MOVIES[idx].thumbsUp++;
GV_MOVIES[idx].thumbsDown = 0;
display();
}
function downClick(idx) {
GV_MOVIES[idx].thumbsDown++;
GV_MOVIES[idx].thumbsUp = 0;
display();
}
Upvotes: 1