Deleting class from an element - javascript

I'm making a task board project.
Must say I'm using only HTML, CSS, JS, and nothing else right now.
I'm making a fade-in effect to the newly added note (ul element), and I would like to delete the fade-in class from the previously added note.
this is a chunk of my code that displays the note inside the div.
function displayAllTasks(allTasks){
taskNotesDiv.innerHTML = "";
for(const task of allTasks){
const index = allTasks.indexOf(task);
const note = `
<div class"noteDiv">
<ul class="fadeInNote">
<button type="button" onclick="deleteTask(${index})">
<i class="fa-solid fa-trash deleteButton"></i>
</button>
<li>Task: ${task.task}</li>
<li>Description: ${task.textArea}</li>
<li>Date: ${task.date}</li>
<li>Time: ${task.time}</li>
</ul>
</div>
`
taskNotesDiv.innerHTML += note;
}
}
I tried already another function to delete it but with no success.
any help would be appreciated!

There can be multiple approaches, but my approach is to create element using document.createElement . The modified JS will become:
function displayAllTasks(allTasks) {
last_ul = null; // store the last ul element added
taskNotesDiv.innerHTML = "";
for (const task of allTasks) {
const index = allTasks.indexOf(task);
let noteDiv = document.createElement('div');
noteDiv.classList.add('noteDiv');
note_ul = document.createElement('ul');
note_ul.classList.add('fadeInNote');
note_ul.innerHTML = `
<button type="button" onclick="deleteTask(${index})">
<i class="fa-solid fa-trash deleteButton"></i>
</button>
<li>Task: ${task.task}</li>
<li>Description: ${task.textArea}</li>
<li>Date: ${task.date}</li>
<li>Time: ${task.time}</li>`
noteDiv.appendChild(note_ul);
// if it is not the first element, then remove the class from previous
if (last_ul != null) {
last_ul.classList.remove('fadeInNote');
}
last_ul = note_ul; // this becomes previous for next iteration
taskNotesDiv.appendChild(noteDiv);
}
// remove class of the last element
if (last_ul != null) {
last_ul.classList.remove('fadeInNote');
}
}

Related

JavaScript removing list elements by class name

I am having an issue with my javascript function in regards to removing elements. What I have below is two lists inside a div menu with each <li> marked by a class according to the category of drink and the drinks themselves. I also have a button that opens a modal box where the user would type in a drink category to remove. I decided to approach this by naming <li> with classes by the drink category and then taking a js function to get the elements by class name from the input text node and to remove those elements with what the user typed.
<div class = "menu">
<ul>
<li class = "coffee">french press</li>
<li class = "tea"><a href="#">english breakfast/a></li>
<li class = "milk">whole</li>
</ul>
<ul>
<li class = "coffee">dark roast</li>
<li class = "tea">green tea</li>
<li class = "milk">two percent</li>
</ul>
</div>
<button type="button" id ="openmodal">Click Me!</button>
<div id="myDeleteModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<h1 class="modal-title">
<b>Type the drink category you want to remove </b>
</h1>
<input id="deletedrinktext" type="text" />
<button id="delete">Remove</button>
<button type="button" class="btn btn-defaultdeletedrink" id="closedbtn" data-dismiss="modal" onclick="">Close</button>
</div>
</div>
<script>
var modal = document.getElementById("myDeleteModal");
// Get the button that opens the modal
var btn = document.getElementById("openmodal");
var closebtn = document.getElementById("closedbtn");
// When the user clicks the button, open the modal
btn.onclick = function () {
modal.style.display = "block";
}
closebtn.onclick = function (event) {
modal.style.display = "none";
}
</script>
<script>
(function () {
document.querySelector('#delete').addEventListener('click', function () {
let inputRemover = document.querySelector('#deletedrinktext');
let itemRemover = document.createTextNode(inputRemover.value);
let listRemover = document.getElementsByClassName(itemRemover);
for (var i = 0; i < listRemover.length; i++) {
if (document.contains(listRemover)) {
listRemover[i].remove();
}
}
inputRemover.value = ""; // clear input
});
})();
</script>
So what I want to replicate is a user would open the modal box, type in coffee and click remove. This would remove from the document the following two elements:
<li class = "coffee">french press</li>
<li class = "coffee">dark roast</li>
This function isn't working so far and I am not sure if there is an error in my JS in getting each element or if going with the class approach is not the way to go about it? When I type in the name of the category just like written in my HTML, the element in the list still displays.
remove() is not a function of Array in javascript. I think your best approach would be to just not display the elements you want to remove. To do just change your handler function to this:
let inputRemover = document.querySelector('#deletedrinktext');
let listRemover = document.getElementsByClassName(inputRemover.value);
for (let i = 0; i < listRemover.length; i++) {
if (document.contains(listRemover[i])) {
listRemover[i].style.display = 'none';
}
}
JSFiddle to try it out without modal functionality.
This also helps you if you maybe want to reset the list. To do so, just set the display property on every element to block.
Also, I don't knwo if it is a copy paste issue but the a at english breakfast is missing a < in the closing tag.

Is there a way to uniquely identity a dynamically added element?

I am trying to dynamically load a bunch of posts from a API and then implement a like button for each of them.
function load_allposts(){
fetch("/posts")
.then(response => response.json())
.then(posts => {
var enc = document.createElement('div');
enc.className = "post-enc";
let s = ``;
posts.forEach(element => {
s += `<div class="p-container">
<div>
<button type="button" class="btn btn-link" class="profile-btn" data-id=${element[0].author_id}> ${element[0].author_name} </button>
</div>
<div class="post-body">
${element[0].body}
</div>
<div class="p1">
<span class="like-status">${element[0].likes}</span> people like this
<button class="like-btn">${element[1]}</button>
</div>
<div class="post-time">
${element[0].timestamp}
</div>
</div>`;
});
enc.innerHTML = s;
document.querySelector('#all-posts').appendChild(enc);
});
}
I would to like to modify the <span class="like-status"> element when I click the <button class="like-btn">. The only way that I can think of to get a reference to <span class="like-status"> is by adding a ID to it by implementing some kind of counter, which I feel is more like a hack rather than real solution.
I tried googling but almost all solutions involved JQuery, which I am not familiar with. Any help would be appreciated.
You can use delegate event binding document.addEventListener('click', function(event) { to trigger click event for dynamically added button.
It will raise click on every element inside document you need to find if it is one which you expect with event.target.matches('button.like-btn').
Then you can find your span with getting parent and then finding span.like-status using querySelector.
Try it below. For demo modified load_allposts. You do not need to do any change in it.
load_allposts();
document.addEventListener('click', function(event) {
if (event.target.matches('button.like-btn')) {
let span = event.target.parentElement.querySelector('span.like-status');
span.innerText = 'Modified';
}
});
function load_allposts() {
let posts = [1]
var enc = document.createElement('div');
enc.className = "post-enc";
let s = ``;
posts.forEach(element => {
s += `<div class="p-container">
<div>
<button type="button" class="btn btn-link" class="profile-btn" data-id=element[0].author_id> element[0].author_name </button>
</div>
<div class="post-body">
element[0].body
</div>
<div class="p1">
<span class="like-status">element[0].likes</span> people like this
<button class="like-btn">element[1]</button>
</div>
<div class="post-time">
element[0].timestamp
</div>
</div>`;
});
enc.innerHTML = s;
document.querySelector('#all-posts').appendChild(enc);
}
<div id='all-posts'>
</div>
Note event delegation have extra overhead so alternatively you can use below code.
Here added two functions added as below and added one line bindClickEvent(enc); at end of load_allposts function.
likeClick - perform custom logic to update span.like-status
bindClickEvent - bind click event to all button.like-btn inside div
Call bindClickEvent(enc); at end of load_allposts function.
Try it below.
load_allposts();
// perform custom logic to update span.like-status
function likeClick(event) {
// querySelector will return first matching element
let span = event.target.parentElement.querySelector('span.like-status');
span.innerText = 'Modified';
}
// bind click event to all button.like-btn inside div
function bindClickEvent(enc) {
// querySelectorAll will return array of all matching elements
let buttons = enc.querySelectorAll('button.like-btn');
// loop over each button and assign click function
for (let i = 0; i < buttons.length; i++) {
buttons[i].onclick = likeClick;
}
}
function load_allposts() {
let posts = [1]
var enc = document.createElement('div');
enc.className = "post-enc";
let s = ``;
posts.forEach(element => {
s += `<div class="p-container">
<div>
<button type="button" class="btn btn-link" class="profile-btn" data-id=element[0].author_id> element[0].author_name </button>
</div>
<div class="post-body">
element[0].body
</div>
<div class="p1">
<span class="like-status">element[0].likes</span> people like this
<button class="like-btn">element[1]</button>
</div>
<div class="post-time">
element[0].timestamp
</div>
</div>`;
});
enc.innerHTML = s;
document.querySelector('#all-posts').appendChild(enc);
// assign click event to buttons inside enc div.
bindClickEvent(enc);
}
<div id='all-posts'>
</div>

How do I remove an element from a user created list (shopping cart)

const cartContent = document.querySelector(".cart_content");
.
.
.
addCartItem(item) {
const div = document.createElement('div');
div.classList.add('cart_item');
div.innerHTML = `
<div class="shop_cart_items_wrapper">
<span class="remove_item" data-id=${item.id}><i class="fas fa-times"></i></span>
<div class="shop_cart_items">
<p class="item_amount">${item.amount}</p>
<span class="cart_title_text_wrapper"><h4 class="cart_title_text">${item.title}</h4></span>
<span class="cart_price_amount_wrapper"><h5 class="cart_price_amount">$${item.price}</h5></span>
</div>
<div>
<div class="inc_dec_amounts_cart">
<i class="fas fa-chevron-up" data-id=${item.id}></i>
<i class="fas fa-chevron-down" data-id=${item.id}></i>
</div>
</div>
</div>`;
cartContent.appendChild(div);
}
.
.
.
cartContent.addEventListener("click", event => {
if (event.target.classList.contains("remove_item")) {
let removeItem = event.target;
let id = removeItem.dataset.id;
cartContent.removeChild.firstElementChild(removeItem.parentElement.parentElement);
this.removeItem(id);
}
So I have everything that's needed for the code to work. I want the entire product item removed from the cart as I press the 'times' icon. I think the removeItem.parentElement.parentElement is not targetting the times icon. What do I have to do to make it target the times icon and close the cart_item div?
It sounds like you're trying to remove the item relative to where the class remove_item is defined (which I assume is maybe the X icon or something. A better way of going about is just defining an id on the parent item itself, finding that element via document.querySelector, and then removing it.
So instead of having something like this
const div = document.createElement('div');
div.classList.add('cart_item');
div.setAttribute('data-item-id', item.id); // <-- now the cart_item has an id associated to it
div.innerHTML = `
<div class="shop_cart_items_wrapper">
<span class="remove_item" data-id=${item.id}><i class="fas fa-times"></i></span>
<div class="shop_cart_items">
And then your remove function becomes
cartContent.addEventListener("click", event => {
if (event.target.classList.contains("remove_item")) {
let removeItem = event.target;
let id = removeItem.dataset.id;
cartContent.removeChild(document.querySelector(`[data-item-id=${id}`));
this.removeItem(id);
}
Or something of the sort. If you're looking for a specific answer on how to get this relatively via your method, that's possible but just giving you another way of going about the solution.

sessionStorage return null

Im trying to achieve this piece of code but in my console it says thing is null which is weird because when I look in the console, sessionStorage isn't empty...
$(".btn-alert").click(function(){
var identifierOfSpan = $(this > "span").text();
for(var prop in sessionStorage){
var thing = JSON.parse(sessionStorage.getItem(prop))
if(thing.id == identifierOfSpan){
sessionStorage.removeItem(prop);
}
}
$(this).closest(".voyages").remove();
if(sessionStorage.length == 0){
alert("Message!");
location.href="reservation.html"
}
});
the button is supposed to delete the div and the sessionStorage item which looks like this
Html :
<div class="voyages">
<button class="btn btn-alert btn-md mr-2" tabindex="-1">delete the flight</button>
<span>ID : 4224762</span>
<div class="infos">
<img src="img/angleterre.jpg" alt="maroc">
<div>
<ul>
<li><h5>Angleterre, Londres (LON)</h5></li>
<li><h5>2 adulte(s)</h5></li>
<li><h5> Aucun enfants </h5></li>
<li><h5>Type : Couple</h5></li>
</ul>
</div>
</div>
<hr>
<h3>Options</h3>
<ul>
<li>voiture : 0</li>
<li>Hotel : 0 </li>
</ul>
<hr>
<h3>Prix :3713$</h3>
If I'm reading your question correctly, you want to...
Click on a button
Find the first sibling <span> element and parse a number out of its text content
Remove all sessionStorage items (JSON serialized objects) with matching id properties
For the ID, I highly recommend adding some data directly to the <button> to help you identify the right record. If you can, try something like
<button class="btn btn-alert btn-md mr-2" data-voyage="4224762"...
Try something like this
$('.btn-alert').on('click', function() {
const btn = $(this)
const id = btn.data('voyage')
// or, if you cannot add the "data-voyage" attribute
const id = btn.next('span').text().match(/\d+$/)[0]
// for index-based removal, start at the end and work backwards
for (let i = sessionStorage.length -1; i >= 0; i--) {
let key = sessionStorage.key(i)
let thing = JSON.parse(sessionStorage.getItem(key))
if (thing.id == id) {
sessionStorage.removeItem(key)
}
}
// and the rest of your code
btn.closest(".voyages").remove();
if(sessionStorage.length === 0) {
alert("Message!");
location.href = 'reservation.html'
}
})
The problem with using a for..in loop on sessionStorage is that you not only get any item keys added but also
length
key
getItem
setItem
removeItem
clear

How to remove element from array

I have little problem with my code. I push the value of an input in an empty array, and i display the value in a html list with a remove button.
But when i remove the value in html, the array still holds the value. I used arr.splice(0, 1) but it doesn't remove the specific value. Example:
My html list looks like:
v1
v2
v3
My array after the list is filled:
array = [v1, v2, v3]
When i remove v2 in html my array doesn't changes. I'm new to JavaScript.
My code in JSBin or JSFiddle.
im sorry my english is not very nice
https://jsfiddle.net/15mdjdpa/
var taches = [];
var saisie;
var ecran;
var liste;
var organiz;
var j= 0;
function run(){
saisie= document.getElementById('champ').value;
taches.push(saisie);
ecran = document.getElementById('afficheur');
var liste = document.getElementById('listes');
console.log("taches :", taches);
var li = document.createElement('li');
li.setAttribute("id", "lisupr");
var btn = document.createElement('Button');
btn.textContent="X";
btn.addEventListener("click",function supr (){
liste.removeChild(li);
taches.splice(0,1);
console.log("tableau taches: "+ taches);
} );
li.innerText= saisie + " "+" ";
console.log("saisie "+saisie);
li.appendChild(btn);
liste.appendChild(li);
}
<input type ="text" id="champ" onfocus="javascript:this.value=''" class="form-control ">
<button type="button" onclick ="run()" class="btn btn-primary" >send</button>
<div id="afficheur"><h4> list : </h4>
<ul id="listes"> </ul>
</div>
If you want to remove v2 from array, do like this.
var index = array.indexOf(v2);
if(index != -1) array.splice(index,1);
I'd rewrite this code using jQuery. I'd remove all the ids - you can make the edits relative to the button being clicked. Which would let you have more than one of these on a page, among other things.
HTML:
<div class="module">
<input class="item" />
<button type="button" class="btn btn-primary js-add">add</button>
<ul class="list"></ul>
</div>
Here's the script:
var list = [],
addToList = function(target,item){
list.push(item);
target
.append(
$('<li>')
.html(item)
.append(
$('<button>')
.addClass('js-delete m-l')
.html('X')
)
)
}
$('.js-add').click( function(){
var parent = $(this).parent(),
item = parent.find('input.item');
addToList(parent.find('ul.list'),item.val());
item.val('');
})
$('.module').on( 'click', '.js-delete', function(){
var parent = $(this).parent(),
index = $('li').index( parent );
list.splice(index,1);
parent.remove();
console.log(list);
})
Actually, if you want to make it so you can add multiple lists, you actually need to nest the 'list' array in an object or array, and have something reference it, probably inside the module div.
Your issue is what Angular does automatically - without all the management. It binds the html content to the json array so all you need to do is change the array value, or delete it. The HTML would immediately reflect the change.
Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/yducyt83/

Categories