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>
Related
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
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)
var divs = document.getElementsByClassName('clsItemBlock');
for (var i = 0; i < divs.length; i++) {
var iDiv = document.createElement('div');
iDiv.id = 'detail_button';
document.getElementsByClassName('clsItemPublished')[i].appendChild(iDiv);
iDiv.innerHTML = 'View Details';
}
The code above works and adds a 'View Detail' button to every product on a category page. What I'm need to now do with this is get the URL from another element and swap out what is currently ### in the example above.
It is essentially the first href inside of the class "clsItemMoreDetails". I've found chunks of code to do some pieces, but can't seem to piece it all together.
EDIT
Here is the HTML:
<div class="clsItemMoreDetails">
<a title="Strapless Ruffle Dress" class="onlineUser" href="http://www.runwaycrush.com/women/dresses/strapless-ruffle-dress.html">
<p class="clsItemHead">Strapless Ruffle Dress</p>
</a>
<div class="clsCategorydateBlock clsOverflow">
<p class="clsItemCategory">
<a href="http://www.runwaycrush.com/shop/ocean-avenue.html" title="Check out OceanAvenue's store">
<span>OceanAvenue</span>
</a>
</p>
<p class="clsItemPublished">$68.24
<span>USD</span>
</p>
</div>
</div>
Theoretically you should do something like this:
var url = document.getElementById("#id_of_some_element").href;
iDiv.innerHTML = 'View Details';
Presuming that other element has href property.
Truly a quirk of Javascript that goes above my head
I read into this and it seemed to do with cases in Javascript. \
Either way, I have multiple class div boxs and data filling each box. The code below outputs what the user chooses into console.
All good and well, however i am trying to extract the users choice and put it into a variable so what the user chose from the drop down can be used to inform other parts of my code. I dont know how to extract that information?
//Global variables
classText = document.getElementsByClassName("searchText");
classBox = document.getElementsByClassName("searchBoxModule");
//HTML
<div id="searchBox">
<div class="searchBoxModule" onclick="firstBox()">
<a class='searchText'></a>
</div>
<div class="searchBoxModule">
<a class='searchText'></a>
</div>
<div class="searchBoxModule">
<a class='searchText'></a>
</div>
<div class="searchBoxModule">
<a class='searchText'></a>
</div>
<div class="searchBoxModule">
<a class='searchText'></a>
</div>
</div>
//Javascript
for(var i = 0; i < classText.length; i++) {
classText[i].innerHTML = arrFiltered[i] || "";
console.log(i + arrFiltered[i]);
classBox[i].onclick = function (value) {
//if a search box is click do:
return function(){
console.log(value);
};
//The below outputs the choice of the user... but how do i put this into a variable?
}(i + 1 + " " + arrFiltered[i]);
}
Thanks,
Ewan
I think your problem is with this
(classText[i].innerHTML = arrFiltered[i] || "";)
not being able to get the innerHTML.
So do something like this in the HTML.
<div id="searchBox">
<div class="searchBoxModule" onclick="firstBox()">
<a class='searchText' id="searchText1"></a>
</div>
then you can easily do:
foo = document.getElementById('searchText1');
I have a number of <li> items, which call the same onmouseover javascript function.
The function needs to extract some data from the element that calls it, to fill some name and tel variables. This data is typed in capitals in the html code below.
Any idea on how to do this is really appreciated.
My HTML:
<li id="item1" onmouseover= "onmouseoveragent(this)" >
<a href="some link">
<span class="hideme">name</span>
</a>
<p class="hideme"> NAME TO BE PASSED TO JS
<strong class="tel">NUMBER TO BE PASSED TO JS</strong>
</p>
</li>
MY javascript:
<script language="javascript" type="text/javascript">
function onmouseoveragent(e) {
var name = e.?????;
var tel = e.?????;
};
</script>
yes you do something like this
JAVASCRIPT:
var elements = document.getElementsByClassName('data-item');
var mouseoverHandler = function() {
var name = this.getElementsByClassName('name')[0].textContent,
tel = this.getElementsByClassName('tel')[0].textContent;
alert('Name - ' + name + "\nTel - " + tel);
}
for( var i = 0; i < elements.length; i++ ) {
var current = elements[i];
current.addEventListener('mouseover', mouseoverHandler);
}
HTML MARKUP:
<li id="item1" class="data-item">
<a href="some link">
<span class="hideme">name</span>
</a>
<p class="hideme">
<span class="name">John Smith</span>
<strong class="tel">555-666-777</strong>
</p>
</li>
<li id="item1" class="data-item">
<a href="some link">
<span class="hideme">name</span>
</a>
<p class="hideme">
<span class="name">Caprica Smith</span>
<strong class="tel">545-334-641</strong>
</p>
</li>
MDN - document.getElementsByClassName();
MDN - element.textContent
It won't be e.something because e is referring to the event that just happened, that has nothing to do the other elements in the DOM
Demo
Well, there is an easier way to do it, just traverse the childNodes of your current hovered element and parse the results. Here is a working JSFiddle of the snippet below(yes, it works with all the LIs matching that structure):
function onmouseoveragent(e) {
var children = this.childNodes,
name = null,
tel = null;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.tagName === 'P') {
name = child.firstChild.nodeValue; // the first node is the text node
tel = child.childNodes[1].firstChild.nodeValue; // the strong's text node
break; // let's stop the iteration, we've got what we needed and the loop has no reason to go on
}
}
console.log(name, tel); // "NAME TO BE PASSED TO JS " "NUMBER TO BE PASSED TO JS"
}
The only difference in HTML is that you need to pass your handler this way:
<li id="item1" onmouseover="onmouseoveragent.call(this, event)">
So this inside the handler will refer to the element and not to the global object.
I suggest you two thing one change the structure of you li tag i.e; make the tag as shown
<li id="item1" class="someClass" >
<a href="some link">
<span class="hideme">name</span>
</a>
<p class="hideme">NAME TO BE PASSED TO JS </p>
<strong class="tel">NUMBER TO BE PASSED TO JS</strong>
</li>
remove strong from p because when you try to fetch p(data to be passed the strong tag will come along with it so better change it)
and also try jquery it will give you more flexibility and ease of use(what i feel)
$(".someClass").mouseover(function(e){
var name = $(e.target).find("p:first").html()
var tel = $(e.target).find("strong:first").html()
})
try this
function onmouseoveragent(e) {
var text = e.getElementsByClassName('hideme')[1].textContent;
var name = text.split("\n")[0]; var num = text.split("\n")[1]; alert(name); alert(num); }