Using querySelectorAll inside a for-in-loop - javascript

I'm feeling a little stupid to ask this because it should be so simple, but I'm getting pretty frustrated.
I have a few divs that I want to show only one at a time, so I want to hide the rest. My approach:
var elements = document.querySelectorAll("div");
for (i in elements) {
elements[i].style.setProperty("display", "none");
}
Firefox always says elements[i].style.setProperty(); is undefined.
I've made a workaround using a normal for-loop without using in, but I'd still like to know why this doesn't work.
Thanks in advance!

Replace
elements[i].style.setProperty("display", "none");
with
elements[i].style.display = "none";
As the HTMLElement.style property returns a CSSStyleDeclaration object that represents the element's inline styles as properties, i.e. style.property = 'value'
And use a regular for loop when iterating over array-like objects that has a length, like nodeLists
var elements = document.querySelectorAll("div");
for ( var i=0; i<elements.length; i++) {
elements[i].style.display = "none";
}

Related

Why can't I make "onclick" event handler in my javascript code? [duplicate]

I am using getElementById when I need to clone the div element.
Code:
printHTML( document.getElementById("div_name").cloneNode(true));
Now I need to use getElementsByClassName
CloneNode is not working when using getElementsByClassName.
How can I put class name in here?
Thank's
EDIT:
When I try to use this:
printHTML( $('.dataTables_scroll').clone(true) );
You can see my function:
function printHTML(clonedDive){
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.contentWindow.onunload = function(){
$(".DTTT_container").show("fast");
$("#header_outer").show("fast");
$(".ColVis.TableTools").show("fast");
$("#footer").show("fast");
};
iframe.contentWindow.document.body.appendChild(clonedDive);
iframe.contentWindow.print();
document.body.removeChild(iframe);
}
I am getting an error in this line:
iframe.contentWindow.document.body.appendChild(clonedDive);
This is an error description:
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
getElementsByClassName gets a nodelist, or an array-like object containing elements if you will, as there can be more than one element with the same class.
getElementsByClassName does this even if only one element matches the class.
You can generally recognize methods like that be the s in getElements, which means it gets multiple elements, i.e. a nodeList.
getElementById only gets one element as ID's are unique.
To get the first element in the nodelist, use bracket notation, like so:
document.getElementsByClassName("div_name")[0].cloneNode(true);
or one could use querySelector, which gets the first matching element only
document.querySelector(".div_name").cloneNode(true);
The jQuery solution would be:
$('.div_name').clone(true);
and to iterate over elements with a certain classname you'd use a loop
var elems = document.getElementsByClassName("div_name");
for ( var i=0; i<elems.length; i++ ) {
printHTML( elems[i].cloneNode(true) );
}
Due to getElementsByClassName returns an object's array, so you have to use for loop to iterates among them, as follows:
for (i = 0; i < document.getElementsByClassName("div_name").length; i++){
printHTML( document.getElementsByClassName("div_name")[i].cloneNode(true));
}
otherwise, if you know the index of the element you have let we say 1
printHTML( document.getElementsByClassName("div_name")[1].cloneNode(true));
This does not work? :
printHTML( document.getElementsByClassName("class_name")[0].cloneNode(true));
You can loop through the elements and clone one by one...
var e = document.getElementsByClassName('div');
for (var i = 0; i < e.length; i += 1) {
// Clone e[i] here
console.log(e[i].cloneNode(true));
}

Can't set styles to elements with a specified class javascript

This is my javascript code:
document.getElementsByClassName('loader').style.opacity = "0";
this code will give an error in my console displayed below:
TypeError: 'undefined' is not an object (evaluating 'document.getElementsByClassName('loader').style.opacity = "0"')
I have already tried these, but these also do not work:
document.document.querySelectorAll('.loader').style.opacity = '0';
document.document.querySelector('.loader').style.opacity = '0';
My html code:
<div class="loader">Some Text</div>
The .getElementsByClassName() function returns a list of elements. You have to iterate over that list with your own code.
var loaders = document.getElementsByClassName('loader');
for (var i = 0; i < loaders.length; ++i)
loaders[i].style.opacity = '0';
If you just want to operate on particular members of the list, you can (if you're careful) treat it like an array. I mention being careful because .getElementsByClassName() returns a "live" NodeList. If you remove the class "loader" from one or more of the elements, the list will change. (That's not the case for the lists returned from .querySelectorAll().)
If you select elements by classes you most will most likely end up with an array of elements. You need to set the parameters for each one. Pure JS doesn't behave as jQuery regarding this.
First make your selection by
var elements = document.getElementsByClassName('loader');
then cycle through them
for(var i=0; i<elements.length; i++){
elements[i].style.opacity = "0";
}
See if this helps..

Click object by classname

I am trying document.getElementsByClassName('classname').click();, but it doesn't fire the click on the class. Why is that?
Why is that?
Because the getElementsByClassName method returns an array of DOM elements. And calling a click method on an array hardly makes sense. If you want to call this click method you could do that on some particular element of the array. For example if you wanted to call it on the first element (assuming the array is not empty of course):
document.getElementsByClassName('classname')[0].click();
But since you have tagged your question with jQuery you probably just wanted to write:
$('.classname').click();
document.getElementsByClassName('classname') returns an array of DOM nodes.
Try:
var nodes = document.getElementsByClassName('classname');
for(var i = 0; i < nodes.length; i++) {
nodes[i].click();
}
Also remember that getElementsByClassName is not supported by every browser.
try this:
$(function() {
$('.classname').click();
});
Your code will work with
document.getElementsByClassName('classname')[0].click();
But, if you use jquery then
$(document).ready( function(){
$('.classname').on('click',function(event){});
});
OR simply $('.classname').click();
Because that will return a set of elements, which is usually an HTMLCollection. You have to then iterate through it:
https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByClassName
Pure Javascript:
var elements = document.getElementsByClassName('xxx');
for(var i = 0; i < elements.length; i++)
{
elements[i].addEventListener('click',function(){window.alert('Class name is xxx');},false);
}
JQuery:
$(document).ready(function(){
$('.xxx').on('click',function(){window.alert('Class name is xxx');});
});

Javascript - Putting element in a var but can't change style

I have a function that is called when an element is clicked.
function showHide(elem){
var clickedText = elem.getElementsByTagName("p");
clickedText.style.color = "green";
}
When I run this code I get an Uncaught TypeError: Cannot set property 'color' of undefined. However, if I do console.log(clickedText) it logs the appropriate tag. Can't for the life of me figure out why this isn't working, have I missed something totally obvious?
The getElementsByTagName method returns a collection of elements (in a NodeList, which is like an array).
You will need to specify an index. For example:
clickedText[0].style.color = "green";
Currently, you're trying to access the style property of the NodeList itself, rather than an element contained within it.
getElementsByTagName returns a list of elements, so you need to loop through the results:
var clickedTexts = elem.getElementsByTagName("p");
for (var i = 0; i < clickedTexts.length; i++) {
clickedTexts[i].style.color = "green";
}

JavaScript - Manipulation HTMLElements inside JS object

In my current project, I've encountered a somewhat strange behavior (from my point of view) when I'm trying to alter the properties af a html element.
In my code, a have defined a javascript object - This object has a 'this.element' property, containing a html element, that gets passed through the constructor. Within this object, I have a couple of functions. In one of theese functions I'm trying to alter some styling of that object, by doing:
this.element.style.visibility = "hidden";
I get no errors when trying to do this, but the style remains unchanged. After some time, I discovered a workaround:
document.getElementById(this.element.id).style.visibility = "hidden";
Which is basically the same. This works, and I can set the style of my element. Though this workaround works, it requires my elements to have ID. While this is not a problem, my coding could get a whole lot easier, if I could get around this.
I'm testing this with Chrome, which is the same browser we'll use once the project is ready for deployment, so using a different browser is not really an option for me.
I would greatly appreciate if anybody can help me understand/solve this situation :)
- Thanks in advance
EDIT: Some more code.
This example I threw together illustrates what I'm doing. However when I run this on it's own, I can't achieve the behavior I was describing.
I don't know if this is of importance, but in my case the function representing "changeAllStyles" works fine when getting called just after the constructor. All subsequence calls of this function, is due to an invocation of the "onMessage" event, coming from websockets.
var myObjArray = [];
function init(){
//Using jQuery to select all elements containing the "data-whatever" attribute:
var elements = $('*[data-whatever]');
//Create a myObj object for each of theese elements:
for (var i = 0; i < elements.length; i++) {
var params = elements[i].getAttribute("data-whatever");
myObjArray.push(new myObj(elements[i], params));
myObjArray[i].changeStyle();
}
}
function myObj(element, params){
this.element = element;
this.params = params;
this.changeStyle = function(){
this.element.style.visibility = "hidden";
};
}
function changeAllStyles(){
for (var i = 0; i < myObjArray.length; i++) {
myObjArray[i].changeStyle();
}
}
It sounds as though elsewhere in the code you're removing the DOM element after having initialized this.element and then recreating it, like this:
HTML:
<div id='bar'><span id='foo'>This is foo</span> inside 'bar'</div>
JavaScript:
var foo = document.getElementById('foo');
var bar = document.getElementById('bar');
bar.innerHTML = "<span id='foo'>This is a new foo</span> inside 'bar'";
foo.style.visibility = "hidden"; // <== No effect, wrong element
As you can see, we're getting the "foo" element, and getting the "bar" element, and then replacing the contents of "bar" with brand-new stuff. That means all of the elements inside "bar" are removed, and then new elements are created. It happens that one of the new elements has the ID "foo" and so
document.getElementById(foo.id).style.visibility = "hidden";
...would work even though foo.style.visibility = "hidden"; doesn't work, because it's a completely different element that happens to have the same ID.
There is nothing wrong with the code you show, except its complexity maybe.
My gut feeling is that unholy things are occuring behind the scene. I cannot debug the code I can't see, but I can propose a cheap workaround.
You could as well collect the elements with document.querySelectorAll('[data-whatever]'), get back your individual parameters with getAttribute() and fiddle with style directly, like so :
function changeAllStyles()
{
var elements = document.querySelectorAll ('[data-whatever]');
for (var i = 0; i < elements.length; i++)
{
var elt = elements[i];
my_parameters = elt.getAttribute ('data-whatever');
play_with (my_parameters);
elt.style.color = a_nice_shade_of_pinkish_brown;
}
}
I concur with T.J. Crowder.
My bet is, someone is destroying and recreating the DOM elements behind your back. If they are recreated by copy, you can still access their clones by Id or class or attributes, but the references to the original DOM elements are dead.
To track this down, you could try something like:
this.changeStyle = function()
{
this.element.__check = "booh!";
var possible_clone = document.getElementById (this.element.id);
if (possible_clone.__check != "booh!")
{
report_to_boss ("something fishy there");
}
};

Categories