I have a table that dynamically adds a row after values are inputted. How can I add a delete button at the end of the table which will delete the row and the data that is appended in an array?
I am guessing one way to go about it is using classList and appending it to the last , which in this case is where the "X" delete button is placed in the table.
let myLibrary = [];
function Book(titles, authors, pages, reads){
this.titles = titles,
this.authors = authors,
this.pages = pages,
this.reads = reads
}
function addBookToLibrary(){
let t = document.getElementById("titles").value;
let a = document.getElementById("authors").value;
let p = document.getElementById("pages").value;
let r = document.getElementById("reads").value;
let book = new Book(t, a, p, r);
myLibrary.push(book);
}
function deleteButton(){
let tds = document.querySelectorAll("td");
for (let i = 0; i < tds.length; i++){
let text = tds[i].innerText;
if (text === "x"){
tds[i].classList.add("delete-btn");
}
}
}
let subDisplay = document.getElementById("subDisplay");
subDisplay.addEventListener("click", displayDetails);
let row = 1;
function displayDetails(){
let title = document.getElementById("titles").value;
let author = document.getElementById("authors").value;
let pages = document.getElementById("pages").value;
let read = document.getElementById("reads").value;
let display = document.getElementById("display");
let newRow = display.insertRow(row);
let cell1 = newRow.insertCell(0);
let cell2 = newRow.insertCell(1);
let cell3 = newRow.insertCell(2);
let cell4 = newRow.insertCell(3);
let cell5 = newRow.insertCell(4);
cell1.innerHTML = title;
cell2.innerHTML = author;
cell3.innerHTML = pages;
cell4.innerHTML = read;
cell5.innerHTML = "x";
row++;
modalBg.classList.remove("bg-active");
}
let modalBtn = document.querySelector('.modal-btn');
let modalBg = document.querySelector('.modal-bg');
let modalClose = document.querySelector(".modal-close");
let submitBtn = document.querySelector(".submit-button");
modalBtn.addEventListener("click", function(){
modalBg.classList.add("bg-active");
});
modalClose.addEventListener("click", function(){
modalBg.classList.remove("bg-active");
});
*, *::after, *::before{
box-sizing: border-box;
}
nav {
background-color: black;
color: white;
height: 35px;
position: relative;
}
p {
position: absolute;
margin: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 35px;
}
table {
width: 100%;
}
th {
text-align: left;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 10px;
}
.modal-bg{
position: fixed;
width: 100%;
height: 100vh;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity 0.5s;
}
.bg-active{
visibility: visible;
opacity: 1;
}
.modal{
position: relative;
padding: 10px;
font-family: "montserrat", sans-serif;
background-color: white;
width: 30%;
height: 30%;
display: flex;
justify-content: space-around;
align-content: center;
flex-direction: column;
}
.modal-button{
padding: 10px 30px;
background-color: black;
color: white;
border: none;
font-family: "Montserrat", sans-serif;
cursor: pointer;
}
.modal-close{
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
.submit-button{
margin-top: 10px;
margin-bottom: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src = "script.js" defer></script>
<link rel = "stylesheet" href="styles.css">
</head>
<body>
<nav>
<p>Library</p>
</nav>
<div class = displaytable>
<table id = "display">
<tr>
<th>Title</th>
<th>Author</th>
<th>Pages</th>
<th>Read</th>
<th>Remove</th>
</tr>
</table>
</div>
<button class="modal-btn">Add Book</button>
<button class = "delete-btn">Delete Book</button>
<div class="modal-bg">
<div class ="modal">
<h2>Book</h2>
<label for="name">Title</label>
<input type="text" name="name" id = "titles">
<label for="name">Author</label>
<input type="text" name="name" id = "authors">
<label for="name">Pages</label>
<input type="text" name="name" id = "pages">
<label for="name">Read</label>
<input type="text" name="name" id = "reads">
<span class="modal-close">x</span>
<button class="submit-button" id = "subDisplay" onclick="addBookToLibrary()">Submit</button>
</div>
</div>
</body>
</html>
I would do this by keeping a track of the objects that are on the table using a structure such as an array. Create a separate array and update the same as you update the table. While doing so, do the following:
html = `<tr><td>${item}</td><td><input type="button" onclick="remove('${item}')" value="Remove"></td></tr>`;
Next, add a function that will filter the array to remove the value you clicked from the same and then, recreate the table.
function remove(input) {
arr = arr.filter((value, index, arr) => { return value != input;});
updateTable();
}
I have made a fiddle to demonstrate the same:
https://jsfiddle.net/cruciformhawk7/ozcf3md4/
Edit: After looking at your update, this code might help you.
https://jsfiddle.net/cruciformhawk7/gbuc0j8s/
Hope it helps.
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')
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>
I am new to coding, and I am trying to make a shopping list app although I ran into some problem.
I am trying to select the elements of a table, it has two columns one for the shopping item and one for buttons next to each item. I want to click the button next to the item and with that add a css style of strikethrough but only for that respective item. But now i can click any "Mark as buyed button" and will apply the styles for all the items, and after that sort the items in ascending or descending order with two other buttons. A little help/hint would be appreciated.
Thank you in advance, if my post is not that clear please do tell
Here is my code:
My code
let addItem = document.querySelector('.add-item');
let input = document.querySelector('input[type="text"]');
let table = document.querySelector('.list');
let tbody = document.querySelector('.tbody');
let ascBtn = document.querySelector('.btn-asc');
let descBtn = document.querySelector('.btn-desc');
// let itemsToSort = document.querySelector('.shopping-list-item');
// let shoppingItems = [];
addItem.addEventListener('click', addItemToList);
// ascBtn.addEventListener('click', ascend);
// descBtn.addEventListener('click', descend);
function addItemToList() {
if (input.value !== '') {
let tableRow = document.createElement('tr');
let firstTableData = document.createElement('td');
let secondTableData = document.createElement('td');
let actionBtn = document.createElement('button');
actionBtn.className = 'action-btn btn';
actionBtn.innerText = 'Mark as buyed';
firstTableData.className = 'shopping-list-item';
tbody.appendChild(tableRow);
firstTableData.innerHTML = input.value;
tableRow.appendChild(firstTableData);
secondTableData.appendChild(actionBtn)
tableRow.appendChild(secondTableData);
input.value = '';
// console.log(firstTableData, secondTableData)
// shoppingItems.push(input.value);
}
}
input.addEventListener('keydown', keyPress);
function keyPress(e) {
if (input.value !== '' && e.keyCode == 13) {
let tableRow = document.createElement('tr');
let firstTableData = document.createElement('td');
let secondTableData = document.createElement('td');
let actionBtn = document.createElement('button');
actionBtn.className = 'action-btn btn';
actionBtn.innerText = 'Mark as buyed';
firstTableData.className = 'shopping-list-item';
tbody.appendChild(tableRow);
firstTableData.innerHTML = input.value;
tableRow.appendChild(firstTableData);
secondTableData.appendChild(actionBtn)
tableRow.appendChild(secondTableData);
input.value = '';
}
}
table.addEventListener('click', function (e) {
// console.log(e.target)
// console.log('this works')
let dynamicTd = document.querySelectorAll('.shopping-list-item');
if (e.target && e.target.className == 'action-btn btn') {
// console.log('this works too');
for (let i = 0; i < dynamicTd.length; i++) {
console.log(dynamicTd[i]);
dynamicTd[i].className = 'checked';
}
}
})
// function ascend(a, b) {
// let item = shoppingItems.value;
// console.log(item);
// }
// function descend() {
// }
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: #6c757d;
}
.shopping-list {
width: 1000px;
margin: 0 auto;
background-color: #2a9d8f;
margin-top: 50px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 5px;
}
.btn {
display: inline-block;
}
.header {
text-align: center;
font-size: 60px;
font-weight: 200;
background-color: #f9f9f9;
width: 100%;
padding: 20px 0;
}
.form {
width: 500px;
padding: 30px 0;
}
.form input {
width: 60%;
padding: 10px 15px;
border-radius: 5px;
outline: none;
}
.form button {
width: 30%;
padding: 10px 10px;
margin-left: 20px;
border-radius: 5px;
outline: none;
}
.btn-container {
width: 50%;
}
.btn-container .btn {
width: 30%;
padding: 10px;
border-radius: 5px;
outline: none;
}
.list {
background-color: #a8dadc;
width: 50%;
margin-top: 20px;
border-radius: 5px;
padding: 10px 20px;
}
.list th {
padding: 10px 0;
}
.list td {
width: 60%;
}
.action-btn {
width: 100%;
padding: 10px;
border-radius: 5px;
outline: none;
}
.checked {
text-decoration: line-through;
}
<!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="style.css">
<title>Shopping List</title>
</head>
<body>
<section class="shopping-list">
<h2 class="header">Shopping List</h2>
<!-- prevent from submitting and disappearing of items add onsubmit -->
<form class="form" onsubmit="return false">
<input type="text">
<!-- prevent from submitting and disappearing of items add type='button' -->
<button type="button" class="add-item btn">Add Item</button>
</form>
<div class="btn-container">
<button class="btn-asc btn">Sort asc</button>
<button class="btn-desc btn">Sort desc</button>
</div>
<table class="list">
<thead>
<tr>
<th>Item</th>
<th>Action</th>
</tr>
</thead>
<tbody class="tbody">
</tbody>
</table>
</section>
<script src="app.js"></script>
</body>
</html>
You can traverse up the DOM using Node.parentNode before selecting the td using querySelector to apply the checked class.
table.addEventListener("click", function (e) {
if (e.target && e.target.className == "action-btn btn") {
const td = e.target.parentNode.parentNode.querySelector("td")
if (td) {
td.className = "checked";
}
}
});
Codepen
You can replace your for loop within method added to table as click listener to: e.target.parentElement.previousSibling.className = 'checked'.
But it is not the best solution. A better way to do this would be to store list items as objects in an array and add the dataset to the delete button. Then you can simply remove that array element based on dataset attribute.
I have been trying to build a simple products page where there is a product. All I wanted to do simply is when I click the "add to basket" button of a certain product, it only increments the total of this product number. Problem with my code is that simply clicking on any add to basket button will increment all products no matter what. What is wrong with my code?
$( document ).ready(function() {
var Product = function(name,price,counter) {
this.name = name;
this.price = price;
this.counter = counter;
// this.button = button;
}
Product.prototype.addToBasket = function(){
return this.counter.innerHTML++;
}
//Products, addtobasket buttons and removefrombasket buttons
var allProducts = document.querySelectorAll('.product');
var productRed = document.querySelector('.productred');
var productBlue = document.querySelector('.productblue')
var addBtn = document.querySelectorAll('.addtobasket');
var rmvBtn = document.querySelectorAll('.removefrombasket')
//Red Product
var redProductPrice = $('#red .price-tag');
var redProductCounter = document.getElementById('red-counter');
var redProductElement = document.getElementById('red');
var redProduct = new Product(redProductElement,redProductPrice.html(),redProductCounter);
//Blue Product
var blueProductPrice = $('#blue .price-tag');
var blueProductCounter = document.getElementById('blue-counter');
var blueProductElement = document.getElementById('blue');
var blueProduct = new Product(blueProductElement,blueProductPrice.html(),blueProductCounter);
var clickBtn = function(obj) {
for (var i = 0; i < allProducts.length ; i++) {
var currentBtn = addBtn[i];
if(currentBtn.parentElement.className === 'product productred') {
currentBtn.addEventListener('click', function(e){
e.preventDefault();
obj.addToBasket();
}, false)
}
else if(currentBtn.parentElement.className === 'product productblue') {
currentBtn.addEventListener('click', function(e){
e.preventDefault();
obj.addToBasket();
}, false)
}
}
}
clickBtn(redProduct);
clickBtn(blueProduct);
});
body {
width: 1060px;
margin: 10px auto;
font-family: "Arial",sans-serif;
}
.column {
margin-top: 50px;
width: 100%;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: -o-flex;
display: flex;
justify-content: center;
}
.productred,
.productblue {
/*position: absolute;*/
/*top: 50px;*/
display: block;
margin: 10px;
border: 0.5px solid;
width: 30%;
min-height: 300px;
text-align: center;
}
.productred .addtobasket,
.productred .removefrombasket,
.productblue .addtobasket,
.productblue .removefrombasket {
position: relative;
top: 105%;
}
.checkoutdiv {
margin-top: 50px;
}
.productred .price-text,
.productblue .price-text {
position: fixed;
top: 30%;
color: white;
}
.productred .counter,
.productblue .counter {
position: absolute;
top: 28%;
margin-left: 290px;
/*left: 38%;*/
color: yellow;
border: 1px solid;
padding: 5px;
}
#red {
background-color: red;
}
#blue {
background-color: blue;
}
#green {
background-color: green;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous">
</script>
<meta charset="UTF-8">
<title>Order Page</title>
</head>
<body>
<main id="container">
<div class="column">
<div class="product productred" id="red">
<p class="price-text"> Price: <span class='price-tag'>10</span></p>
<p id='red-counter' class="counter">0</p>
<button class="addtobasket red">Add to Basket</button>
</div>
<div class="product productblue" id="blue">
<p class="price-text"> Price: <span class='price-tag'>15</span> </p>
<p id='blue-counter' class="counter">0</p>
<button class="addtobasket blue">Add to Basket</button>
</div>
</main>
</body>
</html>