Why wont my onclick not remove any of my classes? - javascript

I have a huge problem here.
I can't get my onclick to work as I want .. So I hope someone here can help me.
#NiceToKnow
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="video"></div>
I want it to display: none; every of my class="nice", so you only can see class="video", but nothing happens at all.

You are selecting the elements of the class not the class itself. So you will have to loop through the elements as javascript can only edit what is in the DOM not the CSS classes that effect your elements. So getElementsByClassName returns an array of nodes in which we must loop through and hide each one. Click runsnippet below to see this work
function changeNice(){
//ASSIGN ELEMENTS TO ARRAY
elementsofClass=document.getElementsByClassName('nice');
for(i=0; i<elementsofClass.length; i++){
//HIDE SELECTED ELEMENT
elementsofClass[i].style.display='none';
}}
#NiceToKnow
<div id="cards1" class="nice">TEST 1</div>
<div id="cards2" class="nice">TEST 2</div>
<div id="cards3" class="nice">TEST 3</div>
<div id="cards4" class="video">I don't HIDE</div>
Also don't use duplicate ID. This will cause errors later when trying to select your elements.

The getElementsByClassName will return an array, so we need to iterate through the array and hide one by one.
So it is better to declare a function and define the logic inside that. Please see the example below.
window.hideAllniceClass = function () {
var elems = document.getElementsByClassName('nice');
for (var i = 0; i != elems.length; ++i) {
elems[i].style.display = "none"; // hidden has to be a string
}
}
#NiceToKnow
<div id="cards1" class="nice">Test Content</div>
<div id="cards2" class="nice">Test Content</div>
<div id="cards3" class="nice">Test Content</div>
<div id="cards4" class="video">Test Video Content</div>
DEMO

Change your code to something like that:
var elems = document.getElementsByClassName('nice');
for(var i = 0; i < elems.length; i++) {
elems[i].style.display = 'none'
}
You have to iterate on the results returned by getElementsByClassName.
jsfiddle

You can create a loop that will loop through all the nice elements and then display none like this: https://jsfiddle.net/7vf9pz8u/
<script>
function hide(){
for(ct=0; ct < 3; ct++){
document.getElementsByClassName('nice')[ct].style.display='none'
}
}
</script>

getElementsByClassName returns array of all the match elements so you will have to provide index or loop through all of them to change their property.
Change your code to this
document.getElementsByClassName('nice')[0].style.display='none'
//For every element
var e = document.getElementsByClassName('nice');
for (i = 0; i < e.length; i++) {
e[i].style.display = "none";
}

As your divs do not have unique names they are in an array cards[].
So to access a particular div you need to reference the the array to that particular div. The quoted solution should work.

Related

Why my "for" loop only gets the last item in html

I already read JavaScript closure inside loops – simple practical example and Why am I only getting the last item from javascript for loop? but still can't figure out, so I post my code to ask for help
function Produit(nom, prix){
this.nom = nom;
this.prix = prix;
}
// ______________ Objet ____________________
var apple = new Produit("apple", 0.30);
var banana = new Produit("banana", 0.03);
var pear = new Produit("pear", 0.35);
var kiwi = new Produit("kiwi", 0.40);
var produit = [apple,banana,pear,kiwi];
for (var i = 0; i < produit.length; i++) {
$('.test').html(produit[i].nom);
};
html
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
The for loop only gets the last item name "kiwi" in html.
I tested the loop with console.log and alert and they both get the 4 item names: "apple","banana","pear","kiwi"
Why doesn't this show up in my HTML?
The problem is you're changing the content of every single element with a test class on every loop iteration. Example:
$('.test').html('Replaced');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
If you want to change the nth .test element on every loop iteration, you can use .eq.
var list = ['a', 'b', 'c', 'd'];
var $test = $('.test');
for (var i = 0; i < list.length; i++) {
$test.eq(i).html(list[i]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
Simply change the line in your for loop to this:
$('.test').eq(i).html(produit[i].nom);
When you call $(".test").html() you're replacing the contents of all the elements with that class. You need to use .eq() to specify a particular one.
for (var i = 0; i < produit.length; i++) {
$('.test').eq(i).html(produit[i].nom);
};
Another way to do it would be to pass a function to .html(). It receives the index of the element, and can use that to index the produit array:
$('.test').html(function(i) {
return produit[i].nom;
});
From what I understand, you'd like to populate your html so that you get
<div class="test">apple</div>
<div class="test">banana</div>
<div class="test">pear</div>
<div class="test">kiwi</div>
but instead you are getting
<div class="test">kiwi</div>
<div class="test">kiwi</div>
<div class="test">kiwi</div>
<div class="test">kiwi</div>
Is that correct?
If so, it's because
$('.test').html()
selects every matching instance. you aren't looping over the divs.
The issue is that this statement:
$('.test').html(produit[i].nom);
sets the HTML for ALL .test elements on every iteration of your loop, thus they are all set to the value of produit[i].nom on every iteration of your for loop so they all end up with the value at the last iteration of your loop. You aren't iterating over the .test elements to set them one at a time.
There are many different ways to do this, but I'll suggest an alternative approach that uses jQuery's .each() to iterate over your collection and then assigns the right HTML to each element:
var produit = [apple,banana,pear,kiwi];
$(".test").each(function(index, element) {
$(element).html(produit[index].nom);
});
This is also a little more efficient that some other methods because it evaluates the selector $(".test") only once and then iterates that one list of elements rather than re-evaluate the selector every time through the loop.
jQuery has lots of tricks up its sleeve. It turns out that the .html() method can also take a callback function that will be called separately for each element in the collection. So, you can also do this:
var produit = [apple,banana,pear,kiwi];
$(".test").html(function(index) {
return produit[index].nom;
});

Getting infinity loop when I append div to existing divs?

I had took some program test online,from there I got some infinity loop error in appending new div to existing div.
<div id="one">
<div id="two"></div>
</div>
And this JS code is to add new div:
appendChildren();
function appendChildren() {
var allDivs = document.getElementsByTagName("div");
for (var i = 0; i < allDivs.length; i++) {
var newDiv = document.createElement("div");
allDivs[i].appendChild(newDiv);
console.log(allDivs[i]);
}
}
I want the HTML to look like this:
<div id="one">
<div id="two">
<div></div>
</div>
<div></div>
</div>
But at run time the program doesn't stop looping. Why? I couldn't guess! So can I run that appendChildren() only one time or is there another solution?
document.getElementsByTagName("div") is a live collection - it always reflects the actual data.
It means that when you append a div item, it is automatically appended to your collection. So, it never ends.
You can copy your collection using [].slice.call so that it doesn't change.
Here is the working demo snippet:
function appendChildren() {
var allDivs = [].slice.call(document.getElementsByTagName("div"));
for (var i = 0; i < allDivs.length; i++) {
var newDiv = document.createElement("div");
allDivs[i].appendChild(newDiv);
console.log(allDivs[i]);
}
}
appendChildren();
// For demonstration purposes only:
document.getElementById('html').innerText = document.getElementById('one').outerHTML;
<div id="one">
<div id="two">
</div>
</div>
<pre id="html"></pre>
The html element displays the HTML result - however, it looks bad. You may use developer tools to see the actual structure in a familiar way.

JavaScript - how to delete elements that do not have a specific class?

I want to delete all elements that do not have the class 'stay'
For example:
<div class="stay">Stay</div>
<div class="stay">Stay</div>
<div class="go">Go</div>
<div class="element">Stay</div>
<div class="Sel">classy</div>
I would like some javascript that would delete the elements that do not have the class stay and Sel, without having to list the classes go and element
I have used:
var els = document.querySelectorAll('#parent :not(.stay)');
for (var i = 0; i < els.length; i++) {
els[i].parentNode.removeChild(els[i])
}
from the first answer, but am unsure of how to keep the class 'Sel'.
Also, I DO NOT want any Jquery.
When you are doing such an operation should need to target a particular parent element, else it could also remove elements like html/body etc.
So assuming you have a parent node, you can use querySelectorAll in conjunction with :not() selector
<div id="parent">
<div class="stay">Stay</div>
<div class="stay">Stay</div>
<div class="go">Go</div>
<div class="element">element</div>
</div>
then
var els = document.querySelectorAll('#parent :not(.stay)');
for (var i = 0; i < els.length; i++) {
els[i].parentNode.removeChild(els[i])
}
Demo: Fiddle

getElementsByClassName get single element

I need to add an EventListener function on every div with a certain class, I tried this:
var a = document.getElementsByClassName('linkto');
for (var i = 0; i<a.length;i++) {
a[i].addEventListener('click',function(){
console.log(a);
}); }
But that gives me all the divs. My divs are generated in a foreach loop:
#foreach($faqs['My_Stay'] as $faqheading)
<div class="row lowboarder linkcolor-darkblue linkto">
{{ link_to('#div'.$faqheading->id,$faqheading->heading) }}
</div>
#endforeach
Is there a good way to determine which div was clicked on?
try like below, "this" inside your click function refer to the clicked div
for (var i = 0; i<a.length;i++) {
a[i].addEventListener('click',function(){
console.log(this.innerText);
}); }

target selected members of an array

I have a series of divs of the same class; some with title attributes set - some without:
<div class="component_wrapper cw1" title="thisTitle1">... </div>
<div class="component_wrapper cw2" title="thisTitle2">... </div>
<div class="component_wrapper cw3" title="thisTitle3">... </div>
<div class="component_wrapper cw4" title="">... </div>
<div class="component_wrapper cw5" title="">... </div>
I've constructed a javascript function that loops through these divs and displays the ones with the title attribute set by setting their css display attribute to "inline":
function checkComponent(e){
var hdrSet = document.getElementsByClassName("component_wrapper");
var titles = {};
for (var i=0; i<hdrSet.length; i++){
if ( !titles[ hdrSet[i].title ] ) {
titles[ hdrSet[i].title ] = true;
hdrSet[i].style.display = "inline";
}
}
}
checkComponent();
the problem is, when I load the page the divs that I'm trying to target display (good), but also 1 of the divs not targeted displays. In the example above, the first four divs display, when all I want is the first three. What's wrong with my code... and is there an better way to construct the function?
Your code checks for duplicate titles, not missing ones. Here's how you could fix that:
function checkComponent(){
var hdrSet = document.getElementsByClassName("component_wrapper");
for (var i = 0; i < hdrSet.length; i++){
if(hdrSet[i].title) {
hdrSet[i].style.display = "inline";
}
}
}
checkComponent();
Also, if you're open to using jQuery, it's much neater and more compatible:
function checkComponent() {
$('.component_wrapper[title]:not([title=""])').css('display', 'inline');
}
checkComponent();

Categories

Resources