Toggle innerHTML to a different value onclick() - javascript

I'm trying to change an existing element on click but I'm struggling to find the logic (very new to this)
I'm trying to switch the below span innerHTM on click. I have "minus" when the filter is not click and I want to add a plus when it is active, see below:
<section class="section-center" id="products-filter">
<div class="products">
<h1>SHOP THE <br />FLAVOURS</h1>
</div>
<button class="toggle-filter" id="toggle-category-filters">
filter
<span id="filter-btn-span"><i class="far fa-minus-square"></i></span>
</button>
</section>
JS:
const toggleFilterBt = document.getElementById('toggle-category-filters');
const categoriesHolder = document.getElementById('categories-holder');
const filterText = document.getElementById('filter-btn-span');
toggleFilterBt.addEventListener('click', () => {
categoriesHolder.classList.toggle('categories-show');
filterText.innerHTML = '<i class="far fa-plus-square"></i>';
});
When clicked the button does change to the plus sign, but how do I make it go back to minus when the button is clicked again?

You can check element classList
toggleFilterBt.addEventListener('click', () => {
categoriesHolder.classList.toggle('categories-show');
filterText.innerHTML = categoriesHolder.classList.contains('categories-show') ? '<i class="far fa-plus-square"></i>' : '<i class="far fa-minus-square"></i>';
});

$(".filter-btn-span").html('<i class="...."></i>');
is how i did it with jQuery (you put it in your event listener) and fill the i class with the one you want)

Add an id to your icon.
Get the icon element by id.
Add and remove between icon classes by checking that icon's class.
Here is the working example:
const toggleFilterBt = document.getElementById('toggle-category-filters');
const toggleIcon = document.getElementById('toggleIcon');
toggleFilterBt.addEventListener('click', () => {
if (toggleIcon.classList.contains('fa-minus-square')) {
toggleIcon.classList.remove('fa-minus-square');
toggleIcon.classList.add('fa-plus-square');
} else {
toggleIcon.classList.remove('fa-plus-square');
toggleIcon.classList.add('fa-minus-square');
}
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"
integrity="sha512-+4zCK9k+qNFUR5X+cKL9EIR+ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA=="
crossorigin="anonymous" />
<section class="section-center" id="products-filter">
<div class="products">
<h1>SHOP THE <br />FLAVOURS</h1>
</div>
<button class="toggle-filter" id="toggle-category-filters">
filter
<span id="filter-btn-span"><i class="far fa-minus-square" id="toggleIcon"></i></span>
</button>
</section>

Related

here i want to change play button into pause

this is html
i'm a complete beginner as i started learning js since last two month,
please help me to solve this problem
<h1>Best Song Collection</h1>
<div class="songItem">
<span class="songName">love you zindagi</span>
<span class="btn"><i class="far fa-play-circle playbtn"></i></span>
<span class="btn"><i class="far fa-pause-circle pausebtn"></i></span>
</div>
<div class="songItem">
<span class="songName">love you zindagi</span>
<span class="btn"><i class="far fa-play-circle playbtn"></i></span>
<span class="btn"><i class="far fa-pause-circle pausebtn"></i></span>
</div>
</div>
</div>
js
let pausebtn = document.querySelector(".pausebtn");
let playbtn = document.querySelector(".playbtn")
let btn = document.querySelectorAll(".btn");
function change(element){
if(element.classList==="fa-play-circle"){
element.classList.remove("fa-play-circle");
element.classList.add("fa-pause-circle");
}
}
btn.addEventListner('click',change());
First of all, if you pass a callback function, do not call it. There you need to do it as so btn.addEventListner('click', change);. (Also, there is a typo in addEventListener)
Second of all, I would change the logic of both your HTML and JS. There is no need to keep two spans inside each .songItem div, you can keep only one and just change the class that is responsible for the icon when a user clicks on the button. You will have less code and it will be more readable. Also, you don't need to put a i tag inside a span, you can pass the icons class directly to the span. What is more, it is more convenient to use const instead of let, because you do not intend to change the value of the variables.
You can achieve it by the code written below, I also attach a codepen with a working example.
const pauseIconClassName = 'fa-pause-circle'
const playIconClassName = 'fa-play-circle'
const btns = document.querySelectorAll('.btn')
function onChange (event) {
// get the button elememt from the event
const buttonElement = event.currentTarget
// check if play button class is present on our button
const isPlayButton = buttonElement.classList.contains(playIconClassName)
// if a play button, remove the play button class and add pause button class
if (isPlayButton) {
buttonElement.classList.remove(playIconClassName)
buttonElement.classList.add(pauseIconClassName)
// if a pause button, remove pause button class and add play button class
} else {
buttonElement.classList.remove(pauseIconClassName)
buttonElement.classList.add(playIconClassName)
}
// You can also use .toggle function on classList as mentioned by the person in other answer
}
// query selector all returns a list of nodes, therefore we need to iterate over it and attach an event listener to each button seperatly
btns.forEach(btn => {
btn.addEventListener('click', onChange)
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"/>
<h1>Best Song Collection</h1>
<div class="songItem">
<span class="songName">love you zindagi</span>
<span class="btn far fa-play-circle"></span>
</div>
<div class="songItem">
<span class="songName">love you zindagi</span>
<span class="btn far fa-play-circle"></span>
</div>
You probably want to toggle the button so I made an example for that. When you press the play button it will show the pause and when you press the pause button it shows play.
When the button is clicked both fa-play-circle and fa-pause-circle are toggled to alter the button icon when clicked.
You made a few mistakes in your code.
The addEventListner() contains a typo. It should be addEventListener()
You store the result of the change() function (which does not exist since it does not return anything) instead of attaching the function as an event handler. So dont call the function.
Your element variable does not contain an element but the event object so you need to call the target or currentTarget property first.
document.querySelectorAll(".btn").forEach(element => element.addEventListener('click', (event) => {
let iElement = event.currentTarget.querySelector('i');
iElement.classList.toggle("fa-play-circle");
iElement.classList.toggle("fa-pause-circle");
}));
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"/>
<div class="songItem">
<span class="songName">love you zindagi</span>
<span class="btn"><i class="far fa-play-circle playbtn"></i></span>
</div>
<div class="songItem">
<span class="songName">love you zindagi</span>
<span class="btn"><i class="far fa-play-circle playbtn"></i></span>
</div>
pass change to click listener, don't call change function.
btn.addEventListner('click', change);
const pausebtn = document.querySelector(".pausebtn");
const playbtn = document.querySelector(".playbtn");
const btn = document.querySelectorAll(".btn");
function change(element) {
if (element.classList === "fa-play-circle") {
element.classList.remove("fa-play-circle");
element.classList.add("fa-pause-circle");
}
}
btn.addEventListner("click", change);
At first glance, it looks like a syntax issue.
Try to not invoke a function and as args, you should receive an event.
So it will look something like this:
let pausebtn = document.querySelector(".pausebtn");
let playbtn = document.querySelector(".playbtn")
let btn = document.querySelectorAll(".btn");
function change(event){
if(event.target.classList==="fa-play-circle"){
event.target.classList.remove("fa-play-circle");
event.target.classList.add("fa-pause-circle");
}
}
btn.addEventListner('click', change);
EDIT: In HTML you have both buttons for play and pause, you should have just one and change the icon with js toggle.
Semantic tip, use button tag for buttons.

Items in an array disappear mysteriously

So I'm currently doing a Calorie Counter project that consists on giving the user the option to firstly, add items with the respective name and number of calories, remove items or update them when clicking on an edit icon next to the item, and finally removing all items at once.
The UI will basically display all the items that the user has added (including the name and the number of calories), where each item will have an edit icon next to it, and if the icon is clicked, it will give the user the option to edit them and delete them.
I still haven't gotten to the edit part because I'm currently stuck in the delete part.
Let's say I have 3 items in the list, when I click on the edit button and then delete, everything works out fine, the html element is deleted and it looks good. If I repeat the process one more time it still works, but when I repeat the process one last time, the problem happens.
For some reason, when I hit the edit button nothing happens, I've checked and apparently the item array is completely empty, even though I only deleted 2 out of the 3 items.
I've tried everything and I've been completely stuck for 3 days straight.
// Item Controller
const ItemController = function() {
// Hard coded items
data = [{
name: "Hamburguer",
id: 0,
calories: 1000
},
{
name: "Pasta",
id: 1,
calories: 700
},
{
name: "Apple",
id: 2,
calories: 70
}
]
return {
getItems: function() {
return data;
},
deleteAllItems: function() {
data.items = [];
UIController().clearItems();
},
getTotalCalories: function() {
totalCalories = 0;
this.getItems().forEach(item => {
totalCalories += parseInt(item.calories)
});
UIController().changeToTotalCalories(totalCalories);
},
removeSingleItem: function(item, li) {
// Getting the index of the item
indexItem = items.getItems().indexOf(item);
// Deleting item from array
items.getItems().splice(indexItem, 1);
// Deleting li item from UI
li.remove();
console.log(items.getItems());
}
}
};
const items = ItemController();
// UI controller
const UIController = function() {
return {
displayItems: function(itemsPresented) {
itemsPresented.forEach(function(item) {
itemList = document.getElementById("item-list");
itemList.innerHTML += `
<li class="collection-item" id="${item.id}">
<strong>${item.name}: </strong><em>${item.calories} calories</em>
<a href="#" class="secondary-content">
<i class="edit-item fa fa-pencil">
</i>
</a>
</li>
`;
})
},
clearItems: function() {
itemList = document.getElementById("item-list");
itemList.innerHTML = "";
items.getTotalCalories();
},
changeToTotalCalories: function(totalCalories) {
document.querySelector(".total-calories").textContent = totalCalories;
},
}
}
const uiCtrl = UIController();
// So when the page loads, the hard coded items can be represented
uiCtrl.displayItems(items.getItems());
// To delete all the items at once
clearAllBtn = document.querySelector(".clear-btn");
clearAllBtn.addEventListener("click", (e) => {
items.deleteItems();
e.preventDefault();
})
// Getting the li element (The one that has all the hard-coded items)
itemList = document.getElementById("item-list");
itemList.addEventListener("click", e => {
// Checking if the user is clicking the Edit Icon
if (e.target.classList.contains("edit-item")) {
items.getItems().forEach(item => {
li = e.target.parentElement.parentElement;
// Getting the item that has the edit icon that the user clicked
if (item.id === parseInt(e.target.parentElement.parentElement.id)) {
// Putting the name and the calories of the item that is being edited in the input fields
document.getElementById("item-name").value = item.name;
document.getElementById("item-calories").value = item.calories;
// Changing the buttons so when the user edits an item, they have the options Update and Delete
document.querySelector(".add-btn").style.display = "none";
document.querySelector(".update-btn").style.display = "block";
document.querySelector(".delete-btn").style.display = "block";
document.querySelector(".back-btn").style.display = "none";
// If the user clicks the delete button
document.querySelector(".delete-btn").addEventListener("click", e => {
// Changing all the buttons back to normal
document.querySelector(".add-btn").style.display = "block";
document.querySelector(".update-btn").style.display = "none";
document.querySelector(".delete-btn").style.display = "none";
document.querySelector(".back-btn").style.display = "block";
// Clearing out the input fields
document.getElementById("item-name").value = "";
document.getElementById("item-calories").value = "";
// Deleting item
items.removeSingleItem(item, li);
// Updating the calories
items.getTotalCalories();
e.preventDefault();
});
}
});
}
})
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<nav>
<div class="nav-wrapper blue">
<div class="container">
<a href="#" class="brand-logo center">
Tracalorie
</a>
<ul class="right">
<li>
<a href="#" class="clear-btn btn blue lighten-3">
Clear All
</a>
</li>
</ul>
</div>
</div>
</nav>
<br>
<div class="container">
<!-- Form Card -->
<div class="card">
<div class="card-content">
<span class="card-title">
Add Meal / Food Item
</span>
<form class="col">
<div class="row">
<div class="input-field col s6">
<input type="text" id="item-name" placeholder="Add item">
<label for="item-name">Meal</label>
</div>
<div class="input-field col s6">
<input type="text" id="item-calories" placeholder="Add calories">
<label for="item-calories">Calories</label>
</div>
<button class="add-btn btn blue darken-3"><i class="fa fa-plus"></i>
Add Meal</button>
<button style="display: none;" class="update-btn btn orange" display=><i class="fa fa-pencil-square-o"></i>
Update Meal</button>
<button style="display: none;" class="delete-btn btn red"><i class="fa fa-remove"></i>
Delete Meal</button>
<button class="back-btn btn grey pull-right"><i class="fa fa-chevron-circle-left"></i>
Back</button>
</div>
</form>
</div>
</div>
<!-- Calorie Count -->
<h3 class="center-align">Total Calories: <span class="total-calories">
0
</span></h3>
<!-- Item list -->
<ul id="item-list" class="collection">
</ul>
</div>
It seems like you add an eventListener to the delete button every single time a user clicks on the edit pencil. You never remove these eventListeners. So when the first edit is done, there is one delete event and one items gets deleted. The next time a user clicks on the edit button, a second event gets added to the same html element, thus two items gets deleted (both events will trigger one after the other). This becomes apparent when your hardcoded list would contain 10 items, you would see 1,2,3 and lastly 4 items disappear. I suggest you look into resetting/removing eventlisteners.

Why is my <i> tag being appended multiple times for each click as I click the add button?

I am making a Todo list using HTML, CSS and jQuery. So basically when the person types an activity and presses the '+' button it gets added to the list along with a 'Delete'(Font Awesome Recycle Bin) icon so that the user can delete the activity. I have implemented this using the .append() function. However, when a user adds the first item there is one delete button. However for every other list the number of delete buttons multiply. (Eg. when the user adds the second item there are two delete buttons for that item, and when they add the third item there are three delete buttons for that item). I can't understand why this is happening and what is the best way to fix this?
I have used .append() on the .listInput and appended the .newItem.
I have then used .append() on the .newItem and appended the can icon.
$(".enter").click(function() {
var $item = $('input[name=add]').val();
if ($item.length > 0) {
$(".listInput").append('<li class="newItem animated fadeIn">' + $item + '</li>');
$('.newItem').append('<i class="animated fadeIn far fa-trash-alt fa-1x"></i>');
} else {
alert("Enter an acitvity to add");
}
})
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="takeInput">
<input type="text" name="add" value="Add Your Item Here">
<i class="enter fas fa-plus fa-3x"></i>
</div>
<ul class="listInput">
</ul>
I want only one trash icon for each list item.
$('.newItem').append() will append something to all elements with the class newItem, not just the one you just added. To fix that just use a single append:
$(".enter").click(function() {
var $item = $('input[name=add]').val();
if ($item.length > 0) {
$(".listInput").append('<li class="newItem animated fadeIn">' + $item + '<i class="animated fadeIn far fa-trash-alt fa-1x"></i></li>');
} else {
alert("Enter an acitvity to add");
}
})
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="takeInput">
<input type="text" name="add" value="Add Your Item Here">
<i class="enter fas fa-plus fa-3x"></i>
</div>
<ul class="listInput">
</ul>
Please try this
var $item = $('input[name="add"]').val();
The problem is that $('.newItem') refers to any element that has that class. For example, if you have five items on the list they will all have the class new item. If you were to add another item (that makes six items), then you are adding a bin icon to each element with class 'newItem'
$(".enter").click(function() {
var $item = $('input[name=add]').val();
if ($item.length > 0) {
$(".listInput").append('<li class="newItem animated fadeIn">' + $item + '</li>' + '<i class="animated fadeIn far fa-trash-alt fa-1x"></i>');
} else {
alert("Enter an acitvity to add");
}
})
$(".enter").click(function() {
let item = $('input[name=add]').val();
let li = $('<li class="newItem animated fadeIn"/>');
let iconTrash = $('<i style="margin-left:1em;" class="animated fadeIn far fa-trash-alt fa-1x"/>')
if (item.length >= 0) {
li.append(item,iconTrash)
$(".listInput").append(li);
} else {
alert("Enter an acitvity to add");
}
})
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="takeInput">
<input type="text" name="add" value="Add Your Item Here">
<i class="enter fas fa-plus fa-3x"></i>
</div>
<ul class="listInput">
</ul>
The problem is the trash icon is added to all the elements that have the class 'newItem'. So you have to create a li(list item) element and append it to the ul(unordered list) element. Then create the icon and append it to the created list item element. You can create element using the document.createElement(tagName) function. and append it using javascript or jquery

Using jQuery to display each content of a button when clicked on

Am working on practice work to improve myself
I created a sidebar using jquery. Inside my sidebars I have 3 buttons.
Am trying to do something like when I click on the first button I want it to show me the contents inside the first button clicked
<div>
<li Id = ‘list-1’ class = ‘btn btn-outline-success’> </li>
<li Id = ‘list-2’ class = ‘btn btn-outline-success’> </li>
<li Id = ‘list-3’ class = ‘btn btn-outline-success’> </li>
</div>
I want each button to display its contents
Simple version (seeing as your code doesn't offer much direction)
<div>
<button id= "list-1" class="click-button btn btn-outline-success" value="Bicycle 1">Button</button>
<button id="list-2" class="click-button btn btn-outline-success" value="Bicycle 2">Button</button>
<button id="list-3" class="click-button btn btn-outline-success" value="Bicycle 3">Button</button>
</div>
<script>
$(document).ready(function () {
$('body').on('click', '.click-button', function () {
alert(this.value)
})
})
</script>

On dropdown element click its icon disappears

This code will replace what is shown inside <button></button> with selected icon from dropdown list.
This works good, only problem is that after clicking on selected element, icon inside that element will for some reason disappear? Why does this happen? I want <li> to be unchanged
http://codepen.io/filaret/pen/PGJEAL
HTML:
<div class="input-group-btn">
<button type="button" class="btn" data-toggle="dropdown">
<i class="fa fa-book"></i>
</button>
<ul class="dropdown-menu">
<li><i class="fa fa-book"></i> Something 111</li>
<li><i class="fa fa-newspaper-o"></i> Something 2222</li>
</ul>
</div>
jQuery:
var $selectWrapper = $('.input-group-btn');
$selectWrapper.find(".dropdown-menu li").click(function() {
// Get <i class="fa"></i>
var $selectedIcon = $(this).find('.fa');
// Put it inside <button></button>
$selectWrapper.find(".btn").html($selectedIcon);
});
You need to clone the icon using clone() like following
var $selectedIcon = $(this).find('.fa').clone();
instead of
var $selectedIcon = $(this).find('.fa');
UPDATED CODEPEN
Otherwise since you have i tag in dropdown and button tag and that only class change, why don't you just copy the class, it's more efficient, faster and easy to understand in your code.
jQuery(document).ready(function($) {
"use strict";
var $selectWrapper = $('.input-group-btn');
var $buttonIcon = $('.btn i');
$selectWrapper.find(".dropdown-menu li").click(function() {
// Get <i class="fa"></i>
var $selectedIcon = $(this).find('.fa');
// get icon classes
var classes = $selectedIcon.attr("class");
// Put the class in the button i tag
$buttonIcon.attr('class', classes);
});
});
See code pen: http://codepen.io/anon/pen/ORxQPZ

Categories

Resources