My web-app is about forecasting on sports games. My page shows all the matches and the points you can get out of each outcome from a match (Madrid = 12 points VS Barcelone = 15 points). So a user check a box from a match and select for him the right outcome. I would like each time the user check a box, to show him the number of boxes he checked.
Here is my Javascript to count the box checked :
const updateCount = function() { var x = document.querySelectorAll(".square:checked").length; document.querySelector(".plus").innerHTML = x; };
Here is the HTML where the number of box checked will be displayed
<div class=" d-flex pt-2"> <h3 class="typos">Matchs pronostiqués</h3> <h3 class="typos pts" style="font-weight: bold; padding-left: 5px;"><%= current_user.forecasts.where(confirmed: true, season_id: Season.last.id).count %>/50</h3> <span class="plus"></span> </div>
Here is my Javascript in order to know which game the user forecasted and which outcome he selected :
const selectOutcome = () => { const selects = document.querySelectorAll(".square"); selects.forEach((outcome)=>{ outcome.addEventListener("click",(event) => { $('input[type="checkbox"]').on('change', function() { $(this).siblings('input[type="checkbox"]').not(this).prop('checked', false); }); const result = event.currentTarget.dataset.outcome; console.log(result); const id = event.currentTarget.parentNode.dataset.id; console.log(id); const box = event.currentTarget.checked; console.log(box); const url = 'store_outcome?result='+result+'&match='+id+'&box='+box fetch(url) .then(response => response.json()) .then((data) => { console.log(data); }); }); }); } const validePanier = () => { const panier = document.getElementById('panier'); panier.addEventListener("click", (event) =>{ console.log("click") const player = document.getElementById('season_player').value; fetch('confirm_pending?player='+player) .then(response => response.json()) .then((data) => { console.log(data); }); }) }
Here is my HTML, for each match I have in my database, a match is going to appear in front in this way.
<% @matches.each do |match| %> <% if Time.parse(match.kick_off) > Time.now && current_user.forecasts.find_by(match_id: match.id, confirmed: true).nil? && match.points_home.present? %> <% if match.sport == "football" %> <div class="d-flex justify-content-center mb-2 mt-2"> <h4 class="typopo"><%= match.league %></h4> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h3 class="tit"><%= DateTime.parse(match.kick_off).to_date%></h3><h3 class="typopo pl-2">-</h3> <h3 class="typopo pl-2"><%= match.kick_off.to_s.gsub("T", " ").split[1].gsub("+", " ").split[0]%></h3> </div> <div class="d-flex flex-row justify-content-around mb-4 mt-4" data-id="<%= match.id %>"> <div class="d-flex flex-column align-items-center col-4"> <div class="row"> <h3 class="typopo"><%= image_tag "#{match.team_home_logo_url}", width: 50 %></h3> </div> <div class="row text-align-center"> <h3 class="tit"><%= match.team_home %></h3> </div> </div> <div class="d-flex flex-column justify-content-center"> <p class="typopo text-center">VS</p> <div class="d-flex flex-row align-items-center col-4"> <div class="displaysquares" data-id="<%= match.id %>"> <input type="checkbox" class="square" onclick="updateCount()" data-outcome="1"></input> <input type="checkbox" class="square" onclick="updateCount()" data-outcome="NULL"></input> <input type="checkbox" class="square" onclick="updateCount()" data-outcome="2"></input> </div> </div> </div>
There is a data-id. The purpose is when a user check a box, I can get the id of the match, in order to create the right forecast for the right game.
Advertisement
Answer
I would delegate instead of having inline event handlers
Here I COUNT the checkboxes – why do you not want the VALUE of a checked RADIO?
Note I wrapped all matches in <div id="matches">...</div>
document.getElementById("matches").addEventListener("change", function(e) { const tgt = e.target; if (tgt.classList.contains("square")) { const parent = tgt.closest(".displaysquares"); var x = parent.querySelectorAll(".square:checked").length; document.querySelector(".plus").innerHTML += parent.dataset.id + ": " + x +"<br/>" ; } })
<span class="plus"></span> <div id="matches"> <div class="d-flex justify-content-center mb-2 mt-2"> <h4 class="typopo">League 1</h4> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h3 class="tit"> Some date </h3> <h3 class="typopo pl-2">-</h3> <h3 class="typopo pl-2">Some string</h3> </div> <div class="d-flex flex-row justify-content-around mb-4 mt-4" data-id="MATCH 1"> <div class="d-flex flex-column align-items-center col-4"> <div class="row"> <h3 class="typopo">TEAM LOGO </h3> </div> <div class="row text-align-center"> <h3 class="tit">Some other team string</h3> </div> </div> <div class="d-flex flex-column justify-content-center"> <p class="typopo text-center">VS</p> <div class="d-flex flex-row align-items-center col-4"> <div class="displaysquares" data-id="MATCH 1"> <input type="checkbox" class="square" data-outcome="1"> <input type="checkbox" class="square" data-outcome="NULL"> <input type="checkbox" class="square" data-outcome="2"> </div> </div> </div> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h4 class="typopo">League 2</h4> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h3 class="tit"> Some date </h3> <h3 class="typopo pl-2">-</h3> <h3 class="typopo pl-2">Some string</h3> </div> <div class="d-flex flex-row justify-content-around mb-4 mt-4" data-id="MATCH 2"> <div class="d-flex flex-column align-items-center col-4"> <div class="row"> <h3 class="typopo">TEAM LOGO </h3> </div> <div class="row text-align-center"> <h3 class="tit">Some other team string</h3> </div> </div> <div class="d-flex flex-column justify-content-center"> <p class="typopo text-center">VS</p> <div class="d-flex flex-row align-items-center col-4"> <div class="displaysquares" data-id="MATCH 2"> <input type="checkbox" class="square" data-outcome="1"> <input type="checkbox" class="square" data-outcome="NULL"> <input type="checkbox" class="square" data-outcome="2"> </div> </div> </div> </div> </div>
Using Radios instead
const matches = document.getElementById("matches") matches.addEventListener("change", function(e) { const tgt = e.target; if (tgt.classList.contains("square")) { var x = [...matches.querySelectorAll(".square:checked")].map(chk => chk.closest(".displaysquares").dataset.id + ": "+chk.dataset.outcome) document.querySelector(".plus").innerHTML = x.join("<br/>"); } })
<span class="plus"></span> <div id="matches"> <div class="d-flex justify-content-center mb-2 mt-2"> <h4 class="typopo">League 1</h4> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h3 class="tit"> Some date </h3> <h3 class="typopo pl-2">-</h3> <h3 class="typopo pl-2">Some string</h3> </div> <div class="d-flex flex-row justify-content-around mb-4 mt-4" data-id="MATCH 1"> <div class="d-flex flex-column align-items-center col-4"> <div class="row"> <h3 class="typopo">TEAM LOGO </h3> </div> <div class="row text-align-center"> <h3 class="tit">Some other team string</h3> </div> </div> <div class="d-flex flex-column justify-content-center"> <p class="typopo text-center">VS</p> <div class="d-flex flex-row align-items-center col-4"> <div class="displaysquares" data-id="MATCH 1"> <input type="radio" name="outcome1" class="square" data-outcome="1"> <input type="radio" name="outcome1" class="square" data-outcome="NULL"> <input type="radio" name="outcome1" class="square" data-outcome="2"> </div> </div> </div> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h4 class="typopo">League 2</h4> </div> <div class="d-flex justify-content-center mb-2 mt-2"> <h3 class="tit"> Some date </h3> <h3 class="typopo pl-2">-</h3> <h3 class="typopo pl-2">Some string</h3> </div> <div class="d-flex flex-row justify-content-around mb-4 mt-4" data-id="MATCH 2"> <div class="d-flex flex-column align-items-center col-4"> <div class="row"> <h3 class="typopo">TEAM LOGO </h3> </div> <div class="row text-align-center"> <h3 class="tit">Some other team string</h3> </div> </div> <div class="d-flex flex-column justify-content-center"> <p class="typopo text-center">VS</p> <div class="d-flex flex-row align-items-center col-4"> <div class="displaysquares" data-id="MATCH 2"> <input type="radio" name="outcome2" class="square" data-outcome="1"> <input type="radio" name="outcome2" class="square" data-outcome="NULL"> <input type="radio" name="outcome2" class="square" data-outcome="2"> </div> </div> </div> </div> </div>