So I have this problem, the goal of this code is that when I select 5 buttons
from the table ( maximum number of clickable buttons) the 6th
one that I will click, will make the first of five I clicked to be disabled
, and then let the current one to be clicked. When the body is loaded, a table is created with buttons via js
Example : I select the numbers : 1-2-3-4-5
and if I click the number 6 number 1 gets disabled or at least does not count between the 5 selected and gets the green class removed. I need to make this thing progressive so I will also need to track what is the "first" button I selected and I thought that the "best" way would be store the first one into an array of buttons.
That seems not to work because I get this error when the 5th button is clicked :
Uncaught TypeError: Cannot read properties of undefined (reading 'button')
at button.onclick
And that makes me think that when I access the array it actually can't store the buttons or either does not work. Am I trying to access the array wrongly? (firstButton = array_btn[previous].button)
Assuming the input checks already work to verify that no more than 5 buttons are clicked how can I accomplish this goal? Thank you for the help in advance :) I apologize if some part of the code is still in Italian I did my best to set it as understandable as possible.
HTML :
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lotto</title>
<link rel="stylesheet" href="stile.css" />
<style>
@import url("https://fonts.googleapis.com/css2?family=Josefin Sans&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap");
</style>
<script src="lotto.js"></script>
</head>
<body onl oad="createTable()">
<h1>Benvenuto all'Enalotto !</h1>
<p >
Seleziona dalla tabella sottostante i numeri che vuoi giocare (MASSIMO 5
!)
</p>
<br />
<table id="tab-punt" ></table>
<br /><br />
<p id="stampa" >Stai puntando i seguenti numeri :</p>
<button onclick="randomArray(); check();" id="btnvinto">
Scopri se hai vinto !
</button>
<p id="vincenti" ></p>
<p id="vinto" ></p>
<br /><br />
</body>
</html>
JavaScript :
let num = 1;
function createTable() {
let tabella = document.getElementById("tab-punt");
for (let i = 0; i < 10; i ) {
let nuovaRiga = tabella.insertRow(-1);
for (let j = 0; j < 9; j ) {
let nuovaCella = nuovaRiga.insertCell(j);
nuovaCella.appendChild(createButton(num));
num = 1;
}
}
}
//Creating arrays to store user input
const input = new Array(5);
var click_counter = 0;
var stringa_out = "";
var i = 0;
let lastButton;
let array_btn = [];
let previous;
//Function to create every single button
function createButton(index) {
let button = document.createElement("BUTTON");
button.classList.add("bot-tab");
//All buttons will share this class
button.classList.add("click");
var text = document.createTextNode(index);
button.appendChild(text);
button.onclick = function () {
let firstButton;
let currentButton;
currentButton = this;
array_btn.push({ currentButton });
input[i] = index;
i = 1;
button.classList.add("verde");
click_counter = 1;
if (click_counter === 5) {
firstButton = array_btn[previous].button;
firstButton.disabled = true;
//lastButton = button;
firstButton.classList.remove("verde");
click_counter -= 1;
previous =1;
}
};
return button;
}
CodePudding user response:
The below code should fix you issue, if it does not, let me know your end goal, since the way you are going about this is complex, it could be way more simple.
Let me know the goal, I would be able to give you a more simply code to achieve it.
Notes:
- Only the code from
'let lastButton;
onwards is included - See the comment lines starting with
// <-
for explanation
let lastButton;
let array_btn = [];
let previous = 0; // <- This should be initialised
//Function to create every single button
function createButton(index) {
let button = document.createElement("BUTTON");
button.classList.add("bot-tab");
//All buttons will share this class
button.classList.add("click");
var text = document.createTextNode(index);
button.appendChild(text);
button.onclick = function () {
let firstButton;
let currentButton;
currentButton = this;
array_btn.push({ button: currentButton }); // <- you need to assign button property as it is accessed later on
input[i] = index;
i = 1;
button.classList.add("verde");
click_counter = 1;
if (click_counter === 5) {
console.log(array_btn[previous]);
firstButton = array_btn[previous].button; // <- 'button' property accessed here
firstButton.disabled = true;
//lastButton = button;
firstButton.classList.remove("verde");
click_counter -= 1;
previous =1;
}
};
return button;
}
CodePudding user response:
You don't need any previous
, lastButton
etc variables, just a smarter way to add/remove HTMLButtonElements from your array of currently active (selected) buttons. Here's a possible solution that uses the simpler CSS Grid instead of a Table:
// DOM utility functions:
const el = (sel, par) => (par || document).querySelector(sel);
const els = (sel, par) => (par || document).querySelectorAll(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
// Enalotto game:
const elGrid = el("#buttons");
// Array to store the active HTMLButtonElements
const playedButtons = [];
const playButton = (elBtn) => {
const idx = playedButtons.indexOf(elBtn);
// Remove button if already in array
if (idx > -1) {
playedButtons.splice(idx, 1);
elBtn.classList.remove("is-active");
return; // Exit function here.
}
// Remove first clicked
if (playedButtons.length === 5) {
const elBtnFirst = playedButtons.shift();
elBtnFirst.classList.remove("is-active");
}
// Add to array
playedButtons.push(elBtn);
elBtn.classList.add("is-active");
};
const newButton = (index) => elNew("button", {
type: "button",
textContent: index 1,
className: "bot-tab click",
onclick() {
playButton(this);
}
});
const createButtons = () => {
const buttons = [...Array(90).keys()].map(newButton);
elGrid.append(...buttons);
};
// Init game:
createButtons();
#buttons {
display: grid;
grid-template-columns: repeat(9, 2rem);
grid-template-rows: repeat(10, 2rem);
}
.is-active {
background: green;
}
<div id="buttons"></div>
With the above code, when you want to get an array of the values, lotto numbers the user selected all you need is:
const userNumbers = playedButtons.map(elBtn => elBtn.textContent);
// which gives i.e:
// ["12", "45", "2", "5", "86"]