I want to change icon with every click. This code is worked But just first click. With every click after the first click, nothing happens. If i delete the if & else the click is work with every click. What is the problem ?
#foreach (var item in Model)
{
<div class="item col-lg-4 col-md-6 col-xs-12 landscapes sale" style="padding-right:15px;padding-left:15px;" data-id="#item.Id">
<div class="project-single" data-aos="fade-up">
<div class="project-inner project-head">
<div class="homes">
<!-- homes img -->
<div href="single-property-1.html" class="homes-img">
<div class="add-favorite">
<i class="far fa-heart"></i>
</div>
#if (item.Document == true)
{
<div class="homes-tag button alt featured">Document</div>
}
<div class="homes-price">$ #String.Format(new CultureInfo("hr-HR"), "{0:# ##0}", item.Price)</div>
<img src="~/EstateImages/#item.MainImage" alt="home-1" class="img-responsive">
</div>
</div>
</div>
<!-- homes content -->
</div>
</div>
}
<script type="text/javascript">
let announcements = document.querySelectorAll(".item")
let favoriteAnnouncementsText = localStorage.getItem("favorites")
let favoriteAnnouncements;
if (favoriteAnnouncementsText != null){
favoriteAnnouncements = favoriteAnnouncementsText.split("-");
}
for (let i = 0; i < announcements.length; i++) {
announcements[i].querySelector(".add-favorite i").addEventListener('click', function(e){
if (this.getAttribute("class") == "fas fa-heart"){
announcements[i].querySelector(".add-favorite").innerHTML = '<i class="far fa-heart"></i>'
}
else if (this.getAttribute("class") == "far fa-heart"){
announcements[i].querySelector(".add-favorite").innerHTML = '<i class="fas fa-heart"></i>'
}
})
}
</script>
In your event handler, you replace the element for which the click handler is defined by setting the .innerHtml property of the parent element. The html fragment is parsed and integrated into the DOM but that does not preserve the event handler definitions associated with the original element.
Change your event handler to
this.classList.toggle("fas");
this.classList.toggle("far");
This toggles both classes on the i element with each click which is equivalent to switching between those classes on each click. Other classes (ie. fa-heart) are not affected. No modification of the DOM structure is necessary.
Ref:
MDN: Web API - classList
MDN: Web API - DOMTokenList
Related
Hi im working on animating an arrow in an accordion but it only animates the first row no matter which one i pick. I know its a target issue but can make this work. some help would be great!!
code pen here https://codepen.io/al-web-dev/pen/bGRXdyL
<div class="myDiv">
<div class="row">
<div class="col-4">Test</div>
<div class="col-4 cheese">test 1</div>
<div class="col-4">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</div>
</div>
<div class="row">
<div class="col-4">Test</div>
<div class="col-4 cheese">test 2</div>
<div class="col-4">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</div>
</div>
</div>
var myDiv = document.getElementsByClassName("row");
for (var i = 0; i < myDiv.length; i++) {
myDiv[i].addEventListener("click", function (event) {
let toggleAble = document.querySelector(".fa-arrow-up");
let cheese = document.querySelector(".cheese");
event.target.classList.toggle("yello");
event.target.classList.toggle("arrow-down");
});
}
The code in your codepen and your example given here is different. I suggest settling on one version of the code if you're gonna ask for help.
The problem you were facing in your codepen example had to do with var toggleAble. You were query-selecting by a classname. .querySelector will only pick the first element from a list of elements it finds. That is why you've had only the first arrow react. Change document before your query selector method to myDiv[i] - the element you're looking for the arrow in. Like so:
for (let i = 0; i < myDiv.length; i++) {
myDiv[i].addEventListener("click", function (event) {
var toggleAble = myDiv[i].querySelector(".fa-arrow-up");
toggleAble.classList.toggle("arrow-down");
});
}
Oh and for some reason you've renamed the function parameter to myDiv, an already declared array of elements. I've changed it back to event for you.
I am writing a jquery function to filter products by type. It works perfectly fine but when I filter by type more than once. Html Element of product-box named addToWishlist stop working.
otherwise all products are displayed perfectly fine.
Cant figure out where is the problem.
Here is the code
//load products data in array
var productArray = [];
$("#product-items .col-4").each (function (){
productArray.push($(this)) })
$(".filter-btn").click(function(e) {
var btnId = e.target.id;
var tempArray = [];
for(var i = 0;i < productArray.length; i++){
var type = $(productArray[i]).find('.addToWishlist').data("type");
if(btnId == "fairness-soaps" && type == "Fairness")
tempArray.push(productArray[i])
if(btnId == "deep-clean-soaps" && type == "Deep-Clean")
tempArray.push(productArray[i])
if(btnId == "skin-whitening-soaps" && type == "Skin-Whitening")
tempArray.push(productArray[i])
}
$("#product-items").html(tempArray);
});
<div class="row" id="product-items">
<div class="col-4">
<a href="#">
<div class="product-box">
<div class="product-img">
<img src="images/product-img13.png" alt="">
<a type="button" class="addToWishlist" data-id="13" data-image="images/product-img13.png" data-price="$30"
data-name="Aloe Vera Soap" data-quantity="1" data-weight="50g" data-availability="In Stock" data-type="Fairness">
<i class="wishlist-icon fa fa-heart-o"></i></a>
</div>
<p class="product-name">Aloe Vera Soap</p>
<p class="product-price">$30</p>
</div>
</a>
</div>
and so on....
You're not reordering the product Elements, you're rewriting them. Even though the HTML of the products is the same, the events you attach to them is lost when you call $("#product-items").html(tempArray);. You either need to reapply the events to the "addToWishList" buttons or reorder the elements instead of writing directly to the html.
Here's a contrived example that shows how just because the HTML is the same doesn't mean the event stays:
<div id="container">
<button id="special-button">Click me</button>
</div>
<script>
$("#special-button").on("click", function(){
alert("I've Been clicked!");
});
$("#container").html(`<button id="special-button">Click me</button>`);
</script>
The problem is that getelementbyclass is resetting when the add to cart button is clicked its only storing one at a time i want it to store multiple i had similar problem with grand total but fixed it but i cannot use the same logic to it since it will get me nan any help ?
var addtocartbuttons = document.getElementsByClassName(`cart`)
for (let i = 0; i < addtocartbuttons.length; i++) {
var button = addtocartbuttons[i]
button.addEventListener(`click`, lang1)
}
function lang1(event) {
var target = event.srcElement;
var button = event.target
var shopitem = button.parentElement.parentElement.parentElement
var title = shopitem.getElementsByClassName(`title`)[0].innerText;
console.log(title)
res2 = document.getElementsByClassName(`result2`)
res2.textContent = title
console.log(res2)
}
<div class="product-categorie-box">
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade show active" id="grid-view">
<div class="row">
<div class="col-sm-6 col-md-6 col-lg-4 col-xl-4">
<div class="products-single fix">
<div class="box-img-hover">
<img src="../../petuta/pizza/margerita.jpg" class="img-fluid" alt="Image">
<div class="mask-icon">
<ul>
<li><i class="fas fa-eye"></i></li>
<li><i class="fas fa-sync-alt"></i></li>
<li><i class="far fa-heart"></i></li>
</ul>
<a class="cart" href="#">Add to Cart</a> </div>
</div>
<div class="why-text">
<h4 class="title" id="title1"> Kids</h4>
<h5 class = "price"> €6.00</h5>
</div>
</div>
</div>
but when button is pressed the text content in res2 despairs and put the new data any ideas?
Here is the console.log:
(HTMLCollection [div.result2, textContent: "Olives"]
0: div.result2
length: 1
textContent: "Olives")
The array only stays of the length of 1 I want it to keep storing how can I do that? I want to store the text content in res2 even when the button is clicked.
I'm making a website which sends email with an order, and when I send email only the first one get sends and even in the console it appears the length of 1 then gets reset when add to cart button is clicked.
ps.
i have 33 of these product-categorie-box so I would need some fix
I didnt use get element by id i used get element by class yet i still get one only can
ps i tried
for(var i = 0; i < elems.length; i++) {
var elems = elems[i];
element2= elems.getElementsByClassName(`result2`)[0]
console.log(element2)
}
but still same problem
I manged to get a fix with the help of barmar
function lang1(event) {
var target = event.srcElement;
var button =event.target
var shopitem = button.parentElement.parentElement.parentElement
var title = shopitem.getElementsByClassName(`title`)[0].innerText;
var node =document.createElement("LI"); // Create a <li> node
var textnode =(`${title}`)
node.innerHTML=textnode
// Create a text node // Append the text to <li>
var cnode=document.getElementsByClassName("result2")[0]
cnode.prepend(node)
console.log(cnode.textContent)
I'm having trouble adding a link to a button inside a card. the card is wrapped in a div element which when clicked automatically expands and closes.
Is there anyway to remove this functionality just when clicking on the details button? So it acts as a normal link?
Here is the code:
https://codepen.io/candroo/pen/wKEwRL
Card HTML:
<div class="card">
<div class="card__image-holder">
<img
class="card__image"
src="https://source.unsplash.com/300x225/?wave"
alt="wave"
/>
</div>
<div class="card-title">
<a href="#" class="toggle-info btn">
<span class="left"></span>
<span class="right"></span>
</a>
<h2>
Card title
<small>Image from unsplash.com</small>
</h2>
</div>
<div class="card-flap flap1">
<div class="card-description">
This grid is an attempt to make something nice that works on touch
devices. Ignoring hover states when they're not available etc.
</div>
<div class="card-flap flap2">
<div class="card-actions">
Read more
</div>
</div>
</div>
</div>
JS:
$(document).ready(function () {
var zindex = 10;
$("div.card").click(function (e) {
e.preventDefault();
var isShowing = false;
if ($(this).hasClass("show")) {
isShowing = true;
}
if ($("div.cards").hasClass("showing")) {
// a card is already in view
$("div.card.show").removeClass("show");
if (isShowing) {
// this card was showing - reset the grid
$("div.cards").removeClass("showing");
} else {
// this card isn't showing - get in with it
$(this).css({ zIndex: zindex }).addClass("show");
}
zindex++;
} else {
// no cards in view
$("div.cards").addClass("showing");
$(this).css({ zIndex: zindex }).addClass("show");
zindex++;
}
});
});
You can check the target of the event and see if it is an <a> using is()
Something like:
$("div.card").click(function (e) {
// only run when not an `<a>`
if(!$(e.target).is('a')){
e.preventDefault();
//the rest of your code
....
}
});
I don't know Jquery but with javascript you can do this inside your code:
const links = document.querySelectorAll('.btn');
links.forEach(link => link.addEventListener('click', (e)=>e.stopPropagation()))
I want to be able to modify/output to the content of particular header tag with the id attribute value of whichever anchor/link is clicked.
Currently, i am able to only change the text "City" with the value of the first id ("New York", in the below example) - because the text is outside of the nested div tags, but still within the anchor tags. so the first link works, but the 2nd and 3rd links pass empty strings/give no output. i want to the text/content to remain within the div tags as in the 2nd and 3rd links.
<base target=splash>
<H3 id=myTitle onclick="myFunction()">City</H3>
<a class="clickable" href="myPage.htm?id=108" id="New+York">New York
<div class=cityWrap>
<DIV class=cityNo>108</DIV>
<DIV class=cityName>New York</DIV>
<DIV class=country>USA</DIV>
</div>
</a>
<a class="clickable" href="myPage.htm?id=110" id="Shanghai">
<div class=cityWrap>
<DIV class=cityNo>110</DIV>
<DIV class=cityName>Shanghai</DIV>
<DIV class=country>China</DIV>
</div>
</a>
<a class="clickable" href="myPage.htm?id=112" id="Damascus">
<div class=cityWrap>
<DIV class=cityNo>112</DIV>
<DIV class=cityName>Damascus</DIV>
<DIV class=country>Syria</DIV>
</div>
</a>
<IFRAME src="myPage.htm" name=splash></IFRAME>
<script>
window.addEventListener('load', () => {
let myFunction = event => {
let clickedElem = event.target;
document.getElementById('myTitle').innerHTML = clickedElem.id;
};
for (let elem of document.getElementsByClassName('clickable')) elem.addEventListener('click', myFunction);
});
</script>
Step 1: Add listeners to all required elements
You have a couple of options.
You could exhaustively list all clickable ids in your javascript:
let ids = [ 'New York', 'Shanghai', 'Damascus' /* ... */ ];
for (let id of ids) document.getElementById(id).addEventListener('click', myFunction);
You could target the clickable elements by the fact that they are all a elements:
for (let elem of document.getElementsByTagName('a')) elem.addEventListener('click', myFunction);
You could attach a common class for all desired a elements, and use document.getElementsByClassName:
html:
<a class="clickable" href="myPage.htm?id=New York" id="New York">New York</A>
<a class="clickable" href="myPage.htm?id=Shanghai" id="Shanghai">Shanghai</A>
<a class="clickable" href="myPage.htm?id=Damascus" id="Damascus">Damascus</A>
js:
for (let elem of document.getElementsByClassName('clickable')) elem.addEventListener('click', myFunction);
Step 2: Determine which element was clicked inside of myFunction:
Now the same function, myFunction, gets called no matter which element is clicked. We have to figure out which specific element was clicked, to determine which id to display.
Fortunately Event.target does this for us. We can rewrite myFunction to look like this:
let myFunction = event => {
// Get the <a> element that was clicked
let clickedElem = event.target;
// Apply that element's id as the innerHTML of the #myTitle element
document.getElementById('myTitle').innerHTML = clickedElem.id;
};
Final code
Could look something like this:
window.addEventListener('load', () => {
let myFunction = event => {
let clickedElem = event.target;
document.getElementById('myTitle').innerHTML = clickedElem.id;
event.preventDefault(); // Important to prevent page navigation
};
for (let elem of document.getElementsByTagName('a')) elem.addEventListener('click', myFunction);
});
[href$="=108"], [href$="=108"] * { background-color: #ffa0a0; }
[href$="=110"], [href$="=110"] * { background-color: #a0ffa0; }
[href$="=112"], [href$="=112"] * { background-color: #a0a0ff; }
a > div { pointer-events: none; }
<h3 id=myTitle>City</H3>
<a href="myPage.htm?id=108" id="New+York">New York
<div class=cityWrap>
<DIV class=cityNo>108</DIV>
<DIV class=cityName>New York</DIV>
<DIV class=country>USA</DIV>
</div>
</a>
<a href="myPage.htm?id=110" id="Shanghai">
<div class=cityWrap>
<DIV class=cityNo>110</DIV>
<DIV class=cityName>Shanghai</DIV>
<DIV class=country>China</DIV>
</div>
</a>
<a href="myPage.htm?id=112" id="Damascus">
<div class=cityWrap>
<DIV class=cityNo>112</DIV>
<DIV class=cityName>Damascus</DIV>
<DIV class=country>Syria</DIV>
</div>
</a>
you can try something like this for each of the links
<a onclick="getElementById('myTitle').innerHTML = your title here">your value here</a>
else try searching for w3schools onclick event
hope this helps :>