const player = (name, symbol) => {
return { name, symbol };
};
const Player1 = player("Player1", "X");
const Player2 = player("Player2", "O");
console.log(Player1);
for (i = 0; i < 9; i++) {
const getBoard = document.getElementById("board");
const createBoard = document.createElement("div");
getBoard.appendChild(createBoard);
createBoard.className = "game-board";
}
function createPItem(name) {
let p = document.createElement("p");
p.textContent = name;
p.className = "text";
return p;
}
const board = document.querySelector(".game-board");
board.addEventListener("click", selectBoard);
function selectBoard() {
board.appendChild(createPItem(`${Player1.symbol}`));
board.className = "complete-board";
}
body {
background-color: #fffdfa;
}
.title {
font-size: 42px;
font-family: "Dancing Script", cursive;
}
.player-turn {
font-size: 24px;
}
.content {
background-color: #fffdfa;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 700px;
width: 800px;
margin: 0 auto;
border-radius: 8px;
}
.board {
display: flex;
flex-flow: row wrap;
align-content: center;
justify-content: space-evenly;
gap: 10px;
background-color: #fff;
height: 500px;
width: 600px;
}
.board div,
.complete-board {
display: flex;
justify-content: center;
align-items: center;
border: 2px solid #000;
background-color: #3c4048;
width: 175px;
height: 150px;
}
.board div:hover {
background-color: #f4e06d;
transform: scale(1.1);
transition: 0.8s;
box-shadow: 5px 5px 0 rgba(0, 0, 0, 0.5);
}
.complete-board {
background-color: #f4e06d !important;
}
.text {
font-size: 64px;
}
.btn {
display: inline-block;
background-color: #4649ff;
padding: 0.5em 2em;
margin-top: 20px;
cursor: pointer;
font-family: "Poor Story", cursive;
font-size: 2rem;
letter-spacing: 0.4rem;
transition: all 0.3s;
text-decoration: none;
}
.btn:hover {
box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.5);
}
.parallelogram {
transform: skew(-20deg);
}
.skew-fix {
display: inline-block;
transform: skew(20deg);
}
<!DOCTYPE html>
<html lang="en">
<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" />
<link rel="stylesheet" href="styles.css" />
<title>Tic Tac Toe</title>
</head>
<body>
<div class="content">
<p class="title">Tic Tac Toe</p>
<p class="player-turn">Player X turn</p>
<div id="board" class="board"></div>
<a id="btn" class="btn parallelogram">
<span class="skew-fix">Reset ></span>
</a>
</div>
<script src="app.js"></script>
</body>
</html>
I'm making Tic Tac Toe and I have a function that creates two players, assigning a symbol to each of them.
const player = (name, symbol) => {
return { name, symbol };
};
const Player1 = player("Player1", "X");
const Player2 = player("Player2", "O");
I also have this HTML which creates a board
<div class="content">
<p class="title">Tic Tac Toe</p>
<p class="player-turn">Player X turn</p>
<div id="board" class="board"></div>
</div>
and using a combination of display: flex and this for loop I create 9 divs that fit perfectly inside the game board.
for (i = 0; i < 9; i++) {
const getBoard = document.getElementById("board");
const createBoard = document.createElement("div");
getBoard.appendChild(createBoard);
createBoard.className = "game-board";
}
I have a function that creates a p element & assigns a class to it to get the proper font-size.
function createPItem(name) {
let p = document.createElement("p");
p.textContent = name;
p.className = "text";
return p;
}
And finally an eventListener that selects the gameBoard class that I click on and adds some text.
const board = document.querySelector(".game-board");
board.addEventListener("click", selectBoard);
function selectBoard() {
board.appendChild(createPItem(`${Player1.symbol}`));
board.className = "complete-board";
}
When I click the first div inside my board class, the above code works perfect and creates / assigns the p tag. Inside the p tag is the letter "X" which is what I want to happen. But when I click on any other div, nothing happens and I don't know why.
What I've tried
I've tried a combination of several different things, including changing the for loop to give each div a class name like board${i} but not only does that seem tacky, it didn't actually work and instead filled in every divs textContent all at once.
The issue is because you use querySelector(".game-board"), which will only select the first .game-board element. You need to use querySelectorAll() to find all elements with that class, and then loop over them to add the event handler.
In addition the selectBoard() function needs to be amended to accept the Event object as an argument so you can get a reference to the clicked element without relying on global variables:
const board = document.querySelectorAll(".game-board");
board.forEach(el => el.addEventListener("click", selectBoard));
function selectBoard(e) {
e.target.appendChild(createPItem(`${Player1.symbol}`));
e.target.className = "complete-board";
}
Here's a full working version:
const player = (name, symbol) => ({ name, symbol });
const Player1 = player("Player1", "X");
const Player2 = player("Player2", "O");
for (i = 0; i < 9; i++) {
const getBoard = document.querySelector("#board");
const createBoard = document.createElement("div");
getBoard.appendChild(createBoard);
createBoard.className = "game-board";
}
function createPItem(name) {
let p = document.createElement("p");
p.textContent = name;
p.className = "text";
return p;
}
const board = document.querySelectorAll(".game-board");
board.forEach(el => el.addEventListener("click", selectBoard));
function selectBoard(e) {
e.target.appendChild(createPItem(`${Player1.symbol}`));
e.target.className = "complete-board";
e.target.removeEventListener('click', selectBoard); // prevent additional clicks
}
#board {
display: flex;
flex-wrap: wrap;
width: 150px;
border: 1px solid #000;
}
#board .game-board,
#board .complete-board {
flex: 1 1 30%;
border: 1px solid #000;
height: 50px;
}
#board .complete-board {
background-color: #CCC;
text-align: center;
}
<div id="board" class="board"></div>
Related
I am making a small project where you can make flashcards that populate a grid inside of a div that has a class of "grid-cards". At the very bottom of my Codepen Javascript code you can see I attempted to save all the created flashcards to localStorage so when the user refreshes the created flashcards will still be there.
//Add Question button toggle and close button function
const addQuestionBtn = document.querySelector("#add-question")
const formContainer = document.querySelector(".hidden")
const closeBtn = document.querySelector("#close-btn")
addQuestionBtn.addEventListener("click", function addBtnToggle() {
if (formContainer.className == "hidden") {
formContainer.classList.remove("hidden")
formContainer.classList.add("form-container")
} else if (formContainer.className == "form-container") {
formContainer.classList.remove("form-container")
formContainer.classList.add("hidden")
}
})
closeBtn.addEventListener("click", function closeForm() {
if (formContainer.className == "form-container") {
formContainer.classList.remove("form-container")
formContainer.classList.add("hidden")
}
})
//Form event listener / Creating cards to populate grid
const questionInput = document.querySelector("#question-input")
const answerInput = document.querySelector("#answer-input")
const saveBtn = document.querySelector("#save-btn")
const form = document.querySelector("form")
const grid = document.querySelector(".grid-cards")
form.addEventListener("submit", function sumbit(e) {
e.preventDefault()
//Creating elements
let questionValue = questionInput.value
let answerValue = answerInput.value
let div = document.createElement("div")
div.classList.add("card")
let h3 = document.createElement("h3")
h3.setAttribute("id", "question")
showHideAnswer = document.createElement("a")
showHideAnswer.setAttribute("href", "")
showHideAnswer.innerHTML = "Show/Hide Answer"
let p = document.createElement("p")
p.classList.add("hidden")
let deleteBtn = document.createElement("button")
deleteBtn.setAttribute("id", "deleteBtn")
//Appending created elements to div
grid.appendChild(div)
div.append(h3)
div.append(showHideAnswer)
div.append(p)
div.append(deleteBtn)
h3.innerHTML = questionValue
p.innerHTML = answerValue
deleteBtn.innerHTML = "Delete"
//Show and hide answer
showHideAnswer.addEventListener("click", function showAnswer(e) {
e.preventDefault()
if (p.className == "hidden") {
p.classList.remove("hidden")
p.classList.add("answer")
} else if (p.className == "answer") {
p.classList.remove("answer")
p.classList.add("hidden")
}
})
//Delete a flashcard
deleteBtn.addEventListener("click", function deleted() {
grid.removeChild(div)
})
//Local storage
//Gathering all the inner HTML from my grid which the created flashcards sit in
localStorage.setItem("innerContent", grid.innerHTML)
const innerContent = localStorage.getItem("innerContent")
//Attempting to populate the grid with the users created cards
grid.innerHTML = inner
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
}
.container {
max-width: 1100px;
width: 100%;
}
.header {
padding: 25px 0;
}
#add-question {
margin-top: 15px;
padding: 10px 15px;
}
.innerForm-container {
background-color: rgb(219, 219, 219);
padding: 20px;
width: 500px;
border: 2px solid black;
position: relative;
}
h2 {
margin-top: 10px;
}
#question-input {
margin-top: 10px;
width: 100%;
height: 70px;
}
#answer-input {
margin-top: 10px;
width: 100%;
height: 70px;
}
#save-btn {
margin-top: 15px;
padding: 10px 100px;
}
#close-btn {
position: absolute;
top: 5px;
right: 5px;
padding: 15px 20px;
}
.hidden {
display: none;
}
.grid-cards {
display: grid;
grid-template-columns: repeat(3, 350px);
grid-template-rows: repeat(5, 200px);
grid-column-gap: 25px;
grid-row-gap: 25px;
justify-content: center;
margin-top: 20px;
}
.card {
background-color: rgb(230, 230, 230);
border: 1px solid black;
border-radius: 15px;
padding: 15px;
position: relative;
}
h3 {
font-size: 22px;
}
p {
margin-top: 15px;
}
a {
margin-top: 25px;
display: block;
}
#deleteBtn {
padding: 10px 20px;
position: absolute;
bottom: 15px;
right: 15px;
}
.hidden {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="inner-container">
<div class="header">
<h1>Flashcards</h1>
<button id="add-question">Add Question</button>
</div>
<div class="hidden">
<div class="innerForm-container">
<form action="">
<h2>Question</h2>
<textarea name="" id="question-input" cols="30" rows="10"></textarea>
<h2>Answer</h2>
<textarea name="" id="answer-input" cols="30" rows="10"></textarea>
<button id="save-btn">Save</button>
<button id="close-btn">X</button>
</form>
</div>
</div>
<div class="grid-cards">
</div>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
I am trying to get the content from and then trying to repopulate it again after refreshing the page so basically all of the users created flashcards will be saved.
You are properly saving the content of the grid. However, you are just not loading it into the grid when the page is loaded.
To do so, just add:
grid.innerHTML = localStorage.getItem('innerContent')
I am making a small project where you can make flashcards that populate a grid inside of a div that has a class of "grid-cards". At the very bottom of my Codepen Javascript code you can see I attempted to save all the created flashcards to localStorage so when the user refreshes the created flashcards will still be there.
//Add Question button toggle and close button function
const addQuestionBtn = document.querySelector("#add-question")
const formContainer = document.querySelector(".hidden")
const closeBtn = document.querySelector("#close-btn")
addQuestionBtn.addEventListener("click", function addBtnToggle() {
if (formContainer.className == "hidden") {
formContainer.classList.remove("hidden")
formContainer.classList.add("form-container")
} else if (formContainer.className == "form-container") {
formContainer.classList.remove("form-container")
formContainer.classList.add("hidden")
}
})
closeBtn.addEventListener("click", function closeForm() {
if (formContainer.className == "form-container") {
formContainer.classList.remove("form-container")
formContainer.classList.add("hidden")
}
})
//Form event listener / Creating cards to populate grid
const questionInput = document.querySelector("#question-input")
const answerInput = document.querySelector("#answer-input")
const saveBtn = document.querySelector("#save-btn")
const form = document.querySelector("form")
const grid = document.querySelector(".grid-cards")
form.addEventListener("submit", function sumbit(e) {
e.preventDefault()
//Creating elements
let questionValue = questionInput.value
let answerValue = answerInput.value
let div = document.createElement("div")
div.classList.add("card")
let h3 = document.createElement("h3")
h3.setAttribute("id", "question")
showHideAnswer = document.createElement("a")
showHideAnswer.setAttribute("href", "")
showHideAnswer.innerHTML = "Show/Hide Answer"
let p = document.createElement("p")
p.classList.add("hidden")
let deleteBtn = document.createElement("button")
deleteBtn.setAttribute("id", "deleteBtn")
//Appending created elements to div
grid.appendChild(div)
div.append(h3)
div.append(showHideAnswer)
div.append(p)
div.append(deleteBtn)
h3.innerHTML = questionValue
p.innerHTML = answerValue
deleteBtn.innerHTML = "Delete"
//Show and hide answer
showHideAnswer.addEventListener("click", function showAnswer(e) {
e.preventDefault()
if (p.className == "hidden") {
p.classList.remove("hidden")
p.classList.add("answer")
} else if (p.className == "answer") {
p.classList.remove("answer")
p.classList.add("hidden")
}
})
//Delete a flashcard
deleteBtn.addEventListener("click", function deleted() {
grid.removeChild(div)
})
//Local storage
//Gathering all the inner HTML from my grid which the created flashcards sit in
localStorage.setItem("innerContent", grid.innerHTML)
const innerContent = localStorage.getItem("innerContent")
//Attempting to populate the grid with the users created cards
grid.innerHTML = inner
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
}
.container {
max-width: 1100px;
width: 100%;
}
.header {
padding: 25px 0;
}
#add-question {
margin-top: 15px;
padding: 10px 15px;
}
.innerForm-container {
background-color: rgb(219, 219, 219);
padding: 20px;
width: 500px;
border: 2px solid black;
position: relative;
}
h2 {
margin-top: 10px;
}
#question-input {
margin-top: 10px;
width: 100%;
height: 70px;
}
#answer-input {
margin-top: 10px;
width: 100%;
height: 70px;
}
#save-btn {
margin-top: 15px;
padding: 10px 100px;
}
#close-btn {
position: absolute;
top: 5px;
right: 5px;
padding: 15px 20px;
}
.hidden {
display: none;
}
.grid-cards {
display: grid;
grid-template-columns: repeat(3, 350px);
grid-template-rows: repeat(5, 200px);
grid-column-gap: 25px;
grid-row-gap: 25px;
justify-content: center;
margin-top: 20px;
}
.card {
background-color: rgb(230, 230, 230);
border: 1px solid black;
border-radius: 15px;
padding: 15px;
position: relative;
}
h3 {
font-size: 22px;
}
p {
margin-top: 15px;
}
a {
margin-top: 25px;
display: block;
}
#deleteBtn {
padding: 10px 20px;
position: absolute;
bottom: 15px;
right: 15px;
}
.hidden {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="inner-container">
<div class="header">
<h1>Flashcards</h1>
<button id="add-question">Add Question</button>
</div>
<div class="hidden">
<div class="innerForm-container">
<form action="">
<h2>Question</h2>
<textarea name="" id="question-input" cols="30" rows="10"></textarea>
<h2>Answer</h2>
<textarea name="" id="answer-input" cols="30" rows="10"></textarea>
<button id="save-btn">Save</button>
<button id="close-btn">X</button>
</form>
</div>
</div>
<div class="grid-cards">
</div>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
I am trying to get the content from and then trying to repopulate it again after refreshing the page so basically all of the users created flashcards will be saved.
You are properly saving the content of the grid. However, you are just not loading it into the grid when the page is loaded.
To do so, just add:
grid.innerHTML = localStorage.getItem('innerContent')
Ive been studying javascript and following along on this online tutorial for a to-do list. I switched up and added a few of my own features, but I am not sure how would go about adding a feature where I can edit a individual list item?
I started off creating a function editTodo(key), I know I would have to append my new text to the old list text? If someone could give me a hint or guide me in the right direction?
//array that holds todo list items
let listItems = [];
//Function will create a new list item based on whatever the input value
//was entered in the text input
function addItem (text) {
const todo = {
text, //whatever user types in
checked: false, //boolean which lets us know if a task been marked complete
id: Date.now(), //unique identifier for item
};
//it is then pushed onto the listItems array
listItems.push(todo);
renderTodo(todo);
}
function checkDone(key) {
//findIndex is an array method that returns position of an element in array
const index = listItems.findIndex(item => item.id === Number(key));
//locates the todo item in the listItems array and set its checked property
//to opposite. 'true' will become 'false'
listItems[index].checked = !listItems[index].checked;
renderTodo(listItems[index]);
}
function deleteTodo(key) {
//find todo object in the listItems array
const index = listItems.findIndex(item => item.id === Number(key));
//create a new object with properties of the current list item
//delete property set to true
const todo = {
deleted: true,
...listItems[index]
};
//remove the list item from the array by filtering it out
listItems = listItems.filter(item => item.id !== Number(key));
renderTodo(todo);
}
//edits list item
function editTodo(key) {
//find todo object in the listItems array
const index = listItems.findIndex(item => item.id === Number(key));
}
//selects form element
const form = document.querySelector('.js-form');
const addGoal = document.getElementById('addBtn');
//adds a submit event listener
function selectForm(event) {
//prevent page refresh on form submission
event.preventDefault();
//select the text input
const input = document.querySelector('.js-todo-input');
//gets value of the input and removes whitespace beginning/end of string
//we then save that to new variable -> text
const text = input.value.trim();
//checks whether 2 operands are not equal, returning true or false (boolean)
//if input value is not equal to blank, add user input
if (text !== '') {
addItem(text);
input.value = ''; //value of text input is cleared by setting it to empty
input.focus(); //focused so user can add many items to list witout focusing the input
}
};
addGoal.addEventListener('click', selectForm, false);
form.addEventListener('submit', selectForm, false);
function renderTodo(todo) {
//saves local storage items, convert listItems array to JSON string
localStorage.setItem('listItemsRef', JSON.stringify(listItems));
//selects the first element with a class of 'js-to'list'
const list = document.querySelector('.js-todo-list');
//selects current todo (refer to top) list item in DOM
const item = document.querySelector(`[data-key='${todo.id}']`);
//refer to function deleteTodo(key)
if (todo.deleted) {
//remove item from DOM
item.remove();
return
}
//use the ternary operator to check if 'todo.checked' is true
//if true, assigns 'done' to checkMarked. if not, assigns empty string
const checkMarked = todo.checked ? 'done' : '';
//creates list 'li' item and assigns it to 'goal'
const goal = document.createElement('li');
//sets the class attribute
goal.setAttribute('class', `todo-item ${checkMarked}`);
//sets the data-key attribute to the id of the todo
goal.setAttribute('data-key', todo.id);
//sets the contents of the list item 'li'
goal.innerHTML = `
<input id="${todo.id}" type="checkbox" />
<label for="${todo.id}" class="tick js-tick"></label>
<span>${todo.text}</span>
<button class="edit-todo js-edit-todo"><i class="fa-solid fa-pencil"></i></button>
<button class="delete-todo js-delete-todo">X</button>
`;
//if item already exists in the DOM
if (item) {
//replace it
list.replaceChild(goal, item);
}else {
//otherwise if it doesnt (new list items) add at the end of the list
list.append(goal);
}
}
//selects entire list
const list = document.querySelector('.js-todo-list');
//adds click event listener to the list and its children
list.addEventListener('click', event => {
if (event.target.classList.contains('js-tick')) {
const itemKey = event.target.parentElement.dataset.key;
checkDone(itemKey);
}
//add this 'if block
if (event.target.classList.contains('js-delete-todo')) {
const itemKey = event.target.parentElement.dataset.key;
deleteTodo(itemKey);
}
})
//render any existing listItem when page is loaded
document.addEventListener('DOMContentLoaded', () => {
const ref = localStorage.getItem('listItemsRef');
if (ref) {
listItems = JSON.parse(ref);
listItems.forEach(t => {
renderTodo(t);
});
}
});
#import url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
margin: 0;
padding: 0;
}
body {
font-family: 'Montserrat', sans-serif;
line-height: 1.4;
}
.container {
width: 100%;
max-width: 500px;
margin: 0 auto;
padding-left: 10px;
padding-right: 10px;
color: rgb(43, 43, 43);
height: 90vh;
margin-top: 20vh;
margin-bottom: 5vh;
overflow-y: auto;
}
.app-title {
text-align: center;
margin-bottom: 20px;
font-size: 80px;
opacity: 0.5;
}
.todo-list {
list-style: none;
margin-top: 20px;
}
.todo-item {
margin-bottom: 10px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.todo-item span {
flex-grow: 1;
margin-left: 10px;
margin-right: 10px;
font-size: 22px;
}
.done span {
background-color:#0099e5;
color:#fff;
}
input[type="checkbox"] {
display: none;
}
#addBtn {
padding: 8px 16px;
font-size:16px;
font-weight:bold;
text-decoration: none;
background-color:#0099e5;
color:#fff;
border-radius: 3px;
border: 3px solid #333;
margin-left:10px;
cursor:pointer;
}
#addBtn:hover {
background-color:#0078b4;
}
.tick {
width: 30px;
height: 30px;
border: 3px solid #333;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.tick::before {
content: '✓';
font-size: 20px;
display: none;
}
.done .tick::before {
display: inline;
}
.delete-todo {
border: none;
font-size:16px;
background-color:red;
color:#fff;
outline: none;
cursor: pointer;
width: 28px;
height: 28px;
border-radius:20px;
}
.edit-todo {
border: none;
font-size:16px;
background-color:green;
color:#fff;
outline: none;
cursor: pointer;
width: 28px;
height: 28px;
border-radius:20px;
}
.empty-warning {
flex-direction:column;
align-items:center;
justify-content:center;
display:none;
}
.todo-list:empty {
display:none;
}
.todo-list:empty + .empty-warning {
display:flex;
}
.empty-warning-title {
margin-top:15px;
opacity: 0.8;
color: rgb(43, 43, 43);
}
form {
width: 100%;
display: flex;
justify-content: space-between;
margin-left:5px;
}
input[type="text"] {
width: 100%;
padding: 10px;
border-radius: 4px;
border: 3px solid #333;
}
<!DOCTYPE html>
<html lang="en">
<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>To-Do List</title>
<link rel = "stylesheet" href = "style.css">
<script src="https://kit.fontawesome.com/67e5409c20.js" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<h1 class="app-title">To Do List</h1>
<form class="js-form">
<input autofocus type="text" aria-label="Enter a new todo item" placeholder="Ex - Walk the dog" class="js-todo-input">
<input type="button" id="addBtn" value="Add">
</form>
<ul class="todo-list js-todo-list"></ul>
<div class="empty-warning">
<h2 class="empty-warning-title">Add your first goal</h2>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
I added the edit feature to the event handler for click events on the list:
Figure I
if (event.target.matches('.edit-todo') && event.target !== event.currentTarget) {
const text = event.target.previousElementSibling;
text.toggleAttribute('contenteditable');
if (text.contenteditable) {
text.focus();
}
}
Basically, when the user clicks an edit button the contenteditable attribute is toggled (true/false) on the <span> that sits right before the button (hence .previousElementSibling).
I also added 2 CSS rulesets as well:
Figure II
.fa-pencil { pointer-events: none }
[contenteditable] { outline: 3px inset blue }
For some reason my mouse cannot click font-awesome icons, I have no idea why. So I disabled click events on the edit icon in order to click the edit button. Others might have the same problem as I do -- I'm 99% sure there's no harm in keeping that ruleset since it just makes the edit button 100% the origin element on the event chain. The second ruleset is a visual cue to the user that the <span> is editable.
let listItems = [];
function addItem(text) {
const todo = {
text,
checked: false,
id: Date.now(),
};
listItems.push(todo);
renderTodo(todo);
}
function checkDone(key) {
const index = listItems.findIndex(item => item.id === Number(key));
listItems[index].checked = !listItems[index].checked;
renderTodo(listItems[index]);
}
function deleteTodo(key) {
const index = listItems.findIndex(item => item.id === Number(key));
const todo = {
deleted: true,
...listItems[index]
};
listItems = listItems.filter(item => item.id !== Number(key));
renderTodo(todo);
}
function editTodo(key) {
const index = listItems.findIndex(item => item.id === Number(key));
}
const form = document.querySelector('.js-form');
const addGoal = document.getElementById('addBtn');
function selectForm(event) {
event.preventDefault();
const input = document.querySelector('.js-todo-input');
const text = input.value.trim();
if (text !== '') {
addItem(text);
input.value = '';
input.focus();
}
};
addGoal.addEventListener('click', selectForm, false);
form.addEventListener('submit', selectForm, false);
function renderTodo(todo) {
// localStorage.setItem('listItemsRef', JSON.stringify(listItems));
const list = document.querySelector('.js-todo-list');
const item = document.querySelector(`[data-key='${todo.id}']`);
if (todo.deleted) {
item.remove();
return
}
const checkMarked = todo.checked ? 'done' : '';
const goal = document.createElement('li');
goal.setAttribute('class', `todo-item ${checkMarked}`);
goal.setAttribute('data-key', todo.id);
goal.innerHTML = `
<input id="${todo.id}" type="checkbox" />
<label for="${todo.id}" class="tick js-tick"></label>
<span>${todo.text}</span>
<button class="edit-todo js-edit-todo"><i class="fa-solid fa-pencil"></i></button>
<button class="delete-todo js-delete-todo">X</button>
`;
if (item) {
list.replaceChild(goal, item);
} else {
list.append(goal);
}
}
const list = document.querySelector('.js-todo-list');
list.addEventListener('click', function(event) {
if (event.target.classList.contains('js-tick')) {
const itemKey = event.target.parentElement.dataset.key;
checkDone(itemKey);
}
if (event.target.classList.contains('js-delete-todo')) {
const itemKey = event.target.parentElement.dataset.key;
deleteTodo(itemKey);
}
if (event.target.matches('.edit-todo') && event.target !== event.currentTarget) {
const text = event.target.previousElementSibling;
text.toggleAttribute('contenteditable');
if (text.contenteditable) {
text.focus();
}
}
})
/*
document.addEventListener('DOMContentLoaded', () => {
const ref = localStorage.getItem('listItemsRef');
if (ref) {
listItems = JSON.parse(ref);
listItems.forEach(t => {
renderTodo(t);
});
}
});*/
#import url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
margin: 0;
padding: 0;
}
body {
font-family: 'Montserrat', sans-serif;
line-height: 1.4;
}
.container {
width: 100%;
max-width: 500px;
margin: 0 auto;
padding-left: 10px;
padding-right: 10px;
color: rgb(43, 43, 43);
height: 90vh;
margin-top: 20vh;
margin-bottom: 5vh;
overflow-y: auto;
}
.app-title {
text-align: center;
margin-bottom: 20px;
font-size: 80px;
opacity: 0.5;
}
.todo-list {
list-style: none;
margin-top: 20px;
}
.todo-item {
margin-bottom: 10px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.todo-item span {
flex-grow: 1;
margin-left: 10px;
margin-right: 10px;
font-size: 22px;
}
.done span {
background-color: #0099e5;
color: #fff;
}
input[type="checkbox"] {
display: none;
}
#addBtn {
padding: 8px 16px;
font-size: 16px;
font-weight: bold;
text-decoration: none;
background-color: #0099e5;
color: #fff;
border-radius: 3px;
border: 3px solid #333;
margin-left: 10px;
cursor: pointer;
}
#addBtn:hover {
background-color: #0078b4;
}
.tick {
width: 30px;
height: 30px;
border: 3px solid #333;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.tick::before {
content: '✓';
font-size: 20px;
display: none;
}
.done .tick::before {
display: inline;
}
.delete-todo {
border: none;
font-size: 16px;
background-color: red;
color: #fff;
outline: none;
cursor: pointer;
width: 28px;
height: 28px;
border-radius: 20px;
}
.edit-todo {
border: none;
font-size: 16px;
background-color: green;
color: #fff;
outline: none;
cursor: pointer;
width: 28px;
height: 28px;
border-radius: 20px;
}
.empty-warning {
flex-direction: column;
align-items: center;
justify-content: center;
display: none;
}
.todo-list:empty {
display: none;
}
.todo-list:empty+.empty-warning {
display: flex;
}
.empty-warning-title {
margin-top: 15px;
opacity: 0.8;
color: rgb(43, 43, 43);
}
form {
width: 100%;
display: flex;
justify-content: space-between;
margin-left: 5px;
}
input[type="text"] {
width: 100%;
padding: 10px;
border-radius: 4px;
border: 3px solid #333;
}
.fa-pencil {
pointer-events: none
}
[contenteditable] {
outline: 3px inset blue
}
<!DOCTYPE html>
<html lang="en">
<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>To-Do List</title>
<link rel="stylesheet" href="style.css">
<script src="https://kit.fontawesome.com/67e5409c20.js" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<h1 class="app-title">To Do List</h1>
<form class="js-form">
<input autofocus type="text" aria-label="Enter a new todo item" placeholder="Ex - Walk the dog" class="js-todo-input">
<input type="button" id="addBtn" value="Add">
</form>
<ul class="todo-list js-todo-list"></ul>
<div class="empty-warning">
<h2 class="empty-warning-title">Add your first goal</h2>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
I have a simple note taking web application. Each time the user clicks on the '+' button a new note is added. Once he clicks on the '⟳' button all are excluded. I want to add five new item slots in the note that the user clicked. In order to do that I need to know which note he did so. This last bit is the one confusing me. How can I know which button the user clicked if all of the buttons are generated by the user?
HTML:
<html lang="en">
<head>
<title>To Do Lists</title>
<link rel="stylesheet" href="styles.css" />
<script src="script.js"></script>
</head>
<body>
<div class="top_bar">
<button id="plus">+</button>
<button id="restart">⟳</button>
</div>
<div id="notes" class="notes">
</div>
</body>
</html>
CSS
padding: 0px;
margin: 0px;
}
body{
display: flex;
flex-direction: column;
}
.top_bar{
width: 100%;
height: 10vh;
background-color: #95E29B;
display: flex;
align-items: center;
justify-content: space-between;
}
button{
font-size: 35px;
border: none;
width: 15%;
height: 10vh;
background-color: #3BCE4B;
cursor: pointer;
}
.notes{
width: 100%;
height: 90vh;
overflow: auto;
background-color: black;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
.note{
margin-top: 20px;
margin-bottom: 20px;
margin-left: 20px;
height: 40vh;
width: 30%;
border-radius: 10px;
background-color: white;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: flex-end;
}
.note_input{
margin-top: 20px;
margin-right: 5%;
font-size: 30px;
width: 90%;
border-style: solid;
border-top: none;
border-left: none;
border-right: none;
border-color: black;
}
form{
margin-top: 10px;
margin-right: 15%;
width: 80%;
height: 49%;
overflow-y: auto;
}
li{
border: none;
width: 70%;
display: flex;
}
.li_input{
border-style: solid;
border-color: black;
border-top: none;
border-left: none;
border-right: none;
margin-left: 10px;
font-size: 20px;
}
.more_items{
width: 35px;
height: 35px;
margin-right: 2%;
border-radius: 100%;
font-size: 20px;
}
JavaScript
const add_note = () => {
// Creates a new note and its props
const new_note = document.createElement("div");
const new_input = document.createElement("input");
const new_form = document.createElement("form");
const new_ol = document.createElement("ol");
const new_button = document.createElement("button");
//Populates the new note with inputs and checkboxes
for (let i = 0; i < 5; i++) {
let new_li = document.createElement("li");
let new_checkbox = document.createElement("input");
new_checkbox.setAttribute("type", "checkbox");
let new_li_input = document.createElement("input");
new_li_input.classList.add("li_input");
new_ol.appendChild(new_li);
new_li.appendChild(new_checkbox);
new_li.appendChild(new_li_input);
}
//New note's settings
new_note.classList.add("note");
new_note.appendChild(new_input);
new_input.classList.add("note_input");
new_input.setAttribute("placeholder", "Note's title");
new_note.appendChild(new_form);
new_ol.classList.add("ols");
new_form.appendChild(new_ol);
new_note.appendChild(new_button);
new_button.classList.add("more_items");
//Inserts the new note and button
const note_block = document.getElementById("notes");
note_block.appendChild(new_note);
new_button.addEventListener("click", add_more_items);
new_button.innerHTML = "+";
};
//Adds more items
const add_more_items = () => {
//console.log(new_button.parentElement.nodeName);
//let new_ol = document.getElementsByClassName("ols")[];
for (let i = 0; i < 5; i++) {
let new_li = document.createElement("li");
let new_checkbox = document.createElement("input");
new_checkbox.setAttribute("type", "checkbox");
let new_li_input = document.createElement("input");
new_li_input.classList.add("li_input");
new_ol.appendChild(new_li);
new_li.appendChild(new_checkbox);
new_li.appendChild(new_li_input);
}
};
//Removes all notes
const remove_note = () => {
let amount_of_notes = document.getElementsByClassName("note").length;
console.log(amount_of_notes);
while (amount_of_notes != 0) {
amount_of_notes--;
document.getElementsByClassName("note")[amount_of_notes].remove();
}
alert("All notes were removed.");
};
// Loads the buttons
const load_buttons = () => {
document.getElementById("plus").addEventListener("click", add_note);
document.getElementById("restart").addEventListener("click", remove_note);
};
// Main method
document.addEventListener("DOMContentLoaded", () => {
load_buttons();
});
Given your html is fairly simple, you can do this in a rudimentary style by making use of parentNode.
Your current code is erroring because you're trying to target new_ol to add the fresh <li> elements but it doesn't exist in scope of the add_more_items function. And even if it did, it would be ambiguous - which <ol> should it refer to?
Instead, you can work out the parent <ol> from the clicked button, like so:
const add_more_items = (e) => {
const new_ol = e.target.parentNode.querySelector('ol');
// rest of your code
}
Here's a full snippet putting all that together. I've put it in a codepen as the snippet editor here struggled with some parts of your layout: https://codepen.io/29b6/pen/qBxxXqG
Bear in mind that traversing the DOM like this isn't ideal. The main problem with this approach is that if your HTML structure changes, you can end up chaining multiple parentNodes together which gets ugly fast. But it should help you understand the concept of selecting an element's parent like you asked.
Clicking on the Home button at the end of this project brings it to the beginning, but no function is reset. Level buttons are not also being enabled anew. If I enable those level buttons by writing some extra code for enabling, then the number of buttons given for each level will be doubled after selecting the level. In other words, for the first time due to selecting the basic level, there were 4 options, But when I click on the last home button and then select the medium level to play the game from the beginning, it becomes 16 options instead of 8.
//VARIABLE DECLARATION PART
let frontpage = document.querySelector(".front-page");
let playbutton = document.querySelector(".play");
let levelpage = document.querySelector(".levelpg");
let startbtn = document.querySelector(".startbtn");
let maingame = document.querySelector(".maingame");
let easybtn = document.querySelector(".easy");
let mediumbtn = document.querySelector(".medium");
let hardbtn = document.querySelector(".hard");
let nextbtn = document.querySelector(".nextbtn");
let pagecount = document.querySelector('.gamepagecount');
let getnumberdiv = document.querySelector('.numberbtn').children;
let resultpg = document.querySelector('.resultpage');
let backhome = document.querySelector('.backhome');
let finalscore = document.querySelector('.score');
let resulttext = resultpg.children[1];
let changeimg = document.querySelector('.resultpage img');
// PLAYBUTTON CLICK
playbutton.addEventListener("click", () => {
frontpage.classList.add("hidden");
levelpage.classList.remove("hidden");
levelpage.classList.add("visibility");
});
//GAME START FUNCTION
function startGame(level) {
if (level == "easy") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
easybtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 10`;
nextbtn.disabled = true
levelChange(4);
gameInterfaceChange()
mainGame(10);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(4)
pageCount(10);
mainGame(10);
})
});
}
else if (level == "medium") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
mediumbtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 15`;
nextbtn.disabled = true
levelChange(8);
gameInterfaceChange();
maingame.style.top = "20%";
mainGame(20);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(8)
pageCount(15)
mainGame(20);
})
});
}
else if (level == "hard") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
hardbtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 20`;
nextbtn.disabled = true
levelChange(12);
gameInterfaceChange();
maingame.style.top = "12%";
mainGame(30);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(12)
pageCount(20)
mainGame(30);
})
});
}
}
//PAGE SLIDING FUNCTION
function gameInterfaceChange() {
levelpage.classList.remove("hidden");
levelpage.classList.add("hidden");
maingame.classList.remove("hidden");
maingame.style.top = "25%";
maingame.classList.add("visibility");
}
// FUNCTION OF RANDOM INPUTING NUMBER IN DIV
function mainGame(maxnum) {
let numboxlen = getnumberdiv.length;
let wrongnum = Math.floor(Math.random() * maxnum) + 1;
let getnumber = [];
//DUPLICATE RANDOM NUMBER CHECKING
for (let i = 0; i < numboxlen; i++) {
let check = getnumber.includes(wrongnum);
if (check === false) {
getnumber.push(wrongnum);
}
else {
while (check === true) {
wrongnum = Math.floor(Math.random() * maxnum) + 1;
check = getnumber.includes(wrongnum);
if (check === false) {
getnumber.push(wrongnum);
}
}
}
}
// NUMBER PUTTING IN InnerHtml
for (var j = 0; j < numboxlen; j++) {
if (getnumber[j] < 10) {
getnumberdiv[j].innerHTML = '0' + getnumber[j];
}
else {
getnumberdiv[j].innerHTML = getnumber[j];
}
}
}
// BUTTON ADDING ACCORDING TO THE LEVEL
function levelChange(divnum) {
for (let index = 0; index < divnum; index++) {
let newBtn = document.createElement('button');
let newbtnNode = document.createTextNode('');
newBtn.appendChild(newbtnNode);
let gamebtn = document.getElementById('numbrbtn');
gamebtn.appendChild(newBtn);
newBtn.setAttribute("onclick", `numberClick(${index},${divnum})`);
}
}
//RIGHT - WRONG CHECKING FUNTION
var right = 0;
var wrong = 0;
function numberClick(index, divnum) {
let rightnumberindex = Math.floor(Math.random() * divnum);
if (index == rightnumberindex) {
nextbtn.disabled = false
right++;
//RIGHT AND WRONG BACKGROUND ADDING AND BUTTON DISABLE
getnumberdiv[index].classList.add("rightans");
for (let i = 0; i < divnum; i++) {
getnumberdiv[i].disabled = true;
}
}
else {
nextbtn.disabled = false
wrong++;
//RIGHT AND WRONG BACKGROUND ADDING AND BUTTON DISABLE
getnumberdiv[rightnumberindex].classList.add("rightans");
getnumberdiv[index].classList.add("wrongans");
for (let i = 0; i < divnum; i++) {
getnumberdiv[i].disabled = true;
}
}
}
// BUTTON ENABLE ON NEXT BUTTION CLICK
function enableBtn(divnum) {
for (let i = 0; i < divnum; i++) {
nextbtn.disabled = true
getnumberdiv[i].disabled = false;
getnumberdiv[i].classList.remove("wrongans");
getnumberdiv[i].classList.remove("rightans");
}
}
//PAGE COUNTING ACCORDING TO THE LEVEL
let currentpg = 1;
function pageCount(levelPg) {
currentpg++;
if (currentpg <= levelPg) {
if (currentpg == levelPg) {
nextbtn.innerHTML = 'Result'
pagecount.innerHTML = `${currentpg} of ${levelPg}`;
}
else {
pagecount.innerHTML = `${currentpg} of ${levelPg}`;
}
}
else {
result();
}
}
//FINAL RESULT FUNTION
function result() {
maingame.classList.remove("visibility");
maingame.classList.add("hidden");
resultpg.classList.remove('hidden')
resultpg.classList.add('visibility')
if (right > wrong) {
changeimg.setAttribute('src', 'trophy.png')
resulttext.innerHTML = `You Win`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
else if (right == wrong) {
changeimg.setAttribute('src', 'draw.png')
resulttext.innerHTML = `It's Draw`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
else if (right < wrong) {
changeimg.setAttribute('src', 'lose.png')
resulttext.innerHTML = `You Lose`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
}
//BACK TO THE HOME FUNCTION
backhome.addEventListener('click', () => {
frontpage.classList.add("visibility");
frontpage.classList.remove("hidden");
resultpg.classList.add('hidden')
resultpg.classList.remove('visibility')
// enable level button
mediumbtn.disabled = false;
hardbtn.disabled = false;
easybtn.disabled = false;
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
margin-top: 50px;
}
.guessing-game {
position: relative;
color: white;
text-align: center;
margin: auto;
width: 350px;
height: 600px;
border-radius: 25px;
padding: 50px 30px;
background: linear-gradient(to right, #bd3f32, #cb356b);
}
.guessing-game .front-page .front-img {
height: 160px;
text-align: center;
}
.guessing-game .front-page img {
max-height: 100%;
}
.guessing-game .front-page .front-text h1 {
margin-top: 50px;
font-size: 1.8em;
}
.guessing-game .front-page .front-text p {
margin-top: 10px;
font-size: 1em;
}
.guessing-game .front-page .front-text button,
.resultpage button ,
.levelpg .easy,
.levelpg .medium,
.levelpg .hard,
.maingame .nextbtn {
margin-top: 30px;
width: 100%;
color: white;
padding: 15px;
outline: 0;
border: 0;
border-radius: 50px;
font-size: 0.9em;
background-color: #d64d5d;
box-shadow: rgba(17, 17, 26, 0.1) 0px 1px 0px,
rgba(17, 17, 26, 0.144) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 48px;
}
.guessing-game .front-page .front-text button:hover,
.maingame .nextbtn:hover,
.resultpage button:hover {
transition: 0.5s;
background-color: #c22f40;
}
/* Level page */
.visiblepg {
position: absolute;
top: 12%;
width: 290px;
}
.levelpg h1 {
margin: 45px 0 40px 0;
font-weight: 600;
font-size: 2.4em;
border: 1px solid white;
}
.levelpg .easy,
.levelpg .medium,
.levelpg .hard {
display: block;
margin-top: 15px;
padding: 12px;
background: white;
font-size: 1em;
border-radius: 10px;
font-weight: 400;
color: #c22f40;
}
.startbtn {
background: transparent;
border: 0;
outline: 0;
}
.levelpg i {
color: white;
margin-top: 50px;
font-size: 70px;
border-radius: 50%;
border: 2px solid transparent;
}
.levelpg i:hover {
background-color: white;
border: 2px solid white;
color: #c22f40;
transition: 0.5s;
}
/* GAME PART */
.maingame .gamepagecount {
background-color: #d64d5d;
color: white;
padding: 4px;
border-radius: 6px;
font-size: 0.8em;
font-weight: 600;
}
.maingame .gametext {
margin-top: 15px;
font-size: 1.2em;
}
.maingame .numberbtn {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.maingame .numberbtn button {
margin-top: 40px;
width: 50px;
height: 50px;
background-color: white;
display: flex;
align-content: space-around;
justify-content: center;
align-items: center;
flex-wrap: wrap;
flex: 1 0 21%;
margin-left: 10px;
border: 0;
outline: 0;
border-radius: 10px;
font-size: 1em;
color: #c22f40;
font-weight: 600;
}
.maingame .numberbtn button:nth-child(1),
.maingame .numberbtn button:nth-child(5),
.maingame .numberbtn button:nth-child(9) {
margin-left: 0;
}
.resultpage h1 {
margin: 0px 0 40px 0;
}
.resultpage img {
margin-top: 45px;
width: 50%;
}
/* PRE DEFINE CSS */
.visibility {
visibility: visiible;
opacity: 2s;
transition: 0.5s;
transform: translateX(0px);
}
.hidden {
visibility: hidden;
opacity: 0;
transition: 0.5s;
transform: translateX(-30px);
}
.levelcolor {
transition: 0.5s;
color: white !important;
background-color: #c22f40 !important;
}
.rightans {
background-color: #27ae60 !important;
color: white !important;
transition: 0.5s;
}
.wrongans {
background-color: #fd4631 !important;
color: white !important;
transition: 0.5s;
}
<!DOCTYPE html>
<html lang="en">
<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" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet" />
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"
integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<title>Guessing Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="guessing-game">
<div class="front-page">
<div class="front-img">
<img src="./question.png" alt="" />
</div>
<div class="front-text">
<h1>Guessing Game</h1>
<p>
You just need to chose the right number from the option. If your
guess is right more than wrong , you will win otherwise you will
fail! Let's see how good your sixth sense is!!!
</p>
<button class="play">Let's play</button>
</div>
</div>
<div class="levelpg hidden visiblepg">
<h1>Game level</h1>
<button class="easy" onclick="startGame('easy')">Easy</button>
<button class="medium" onclick="startGame('medium')">Medium</button>
<button class="hard" onclick="startGame('hard')">Hard</button>
<button class="startbtn"><i class="fas fa-play-circle"></i></button>
</div>
<div class="maingame visiblepg hidden">
<p class="gamepagecount">1</p>
<p class="gametext">Guess the number you think is right</p>
<div class="numberbtn" id="numbrbtn"></div>
<button class="nextbtn">Next</button>
</div>
<div class="resultpage levelpg hidden visiblepg">
<img src="" alt="" />
<h1></h1>
<div class="score"></div>
<button class="backhome">Home</button>
</div>
</div>
<script src="./main.js"></script>
</body>
</html>
In short, as soon as I click on the home button, I want the game to start anew, all the functions will be reset anew, and the HTML will be reset anew also. I hope my problem is enough clear to understand.
I have solved the problem.
I just add a reload function to solve this problem.
backhome.addEventListener('click', () => {
frontpage.classList.add("visibility");
frontpage.classList.remove("hidden");
resultpg.classList.add('hidden')
resultpg.classList.remove('visibility')
//reload function
window.location.reload();
})