Can't set styles to elements with a specified class javascript - 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..

Related

Using querySelectorAll inside a for-in-loop

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";
}

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));
}

Javascript Getting specific element (of parent) by name

I'm using custom tags to define sections in an application, so I have something like this:
<mysection>
<form>
<input name="myfield">
</form>
</mysection>
I'm using the following and able to get the tag (printed to console, everything is groovy)
var parent = document.getElementsByTagName('mysection');
The issue I'm having is finding the child field by name:
var myfield = parent.getElementsByName("myfield");
...as I don't want to pick up on any other 'sections' that might have an input with the name 'myfield'.
EDIT:
var parent = document.getElementsByTagName('mysection')[0];
was suggested and returns to console the section contents, however, getElementsByName throws an error:
Uncaught TypeError: Object #<NodeList> has no method 'getElementsByName'
Using getElementsByTagName() and getElementsByName() will return a NodeList, you need to get the first element of the list like this:
var parent = document.getElementsByTagName('mysection')[0];
var myfield = parent.getElementsByName("myfield")[0];
Edit
You were correct, getElementsByName is not valid for an element. I am unsure how to localize the functionality of it as you are trying to do. It seems that it will only work for document. You may have to write your own implementation of getElementsByName if you want to use it in a localized scope.
Second Edit
To be nice, I made that implementation for you :D Here it is in all its "glory".
Element.prototype.getElementsByName = function (arg) {
var returnList = [];
(function BuildReturn(startPoint) {
for (var child in startPoint) {
if (startPoint[child].nodeType != 1) continue; //not an element
if (startPoint[child].getAttribute("name") == arg) returnList.push(startPoint[child]);
if (startPoint[child].childNodes.length > 0) {
BuildReturn(startPoint[child].childNodes);
}
}
})(this.childNodes);
return returnList;
};
var parent = document.getElementsByTagName('mysection')[0];
var myfield = parent.getElementsByName("myfield")[0];
Small fix
I was incorrectly passing the element and not its children into the recursion. The code above has been edited with the proper argument passed now. See working fiddle: http://jsfiddle.net/js6NP/5/
I actually found a much more simple way to handle this:
document.querySelectorAll('mysection [name="myfield"]');
Here you can see an example where it only modifies the field inside the section specified: http://jsfiddle.net/fluidbyte/kph6H/
qSA supports modern browsers and is compatible down to IE8, Here's a polyfill to support back to IE7: https://gist.github.com/2724353
getElementsByName won't work on a DOM element reference. Use querySelector or querySelectorAll instead. In example:
var parent = document.getElementsByTagName('mysection')[0];
var myfield = parent.querySelector("[name='myfield']");
Just use an ID instead:
<mysection>
<form>
<input name="myfield" id="fieldName">
</form>
</mysection>
var myfield = document.getElementById("fieldName");
ID's are supposed to be unique on a page. So you shouldn't have trouble accessing the right element.
If you really have to use name/tagname, getElementsByTagName and getElementsByName both always return a array (A empty one if no element was found). you can access the right element, just like you'd access elements in arrays:
document.getElementsByTagName('mysection')[0]; For the first element with tagname mysection.

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