getElementByID works, getElementsByClassName does not work [duplicate] - javascript

This question already has an answer here:
getElementByID works, getElementsByClassName does not [duplicate]
(1 answer)
Closed 7 years ago.
I'm working on a solution where the javascript changes div1 instead of div2.
This code works with getElementbyId but does not work with getElementbyClassName. Why does this not work?
function refer(Div1, Div2) {
if (document.getElementByClassName('Div1')) {
if (document.getElementByClassName('Div1').style.display == 'block') {
var elems = document.getElementsByClassName('Div2');
for(var i = 0; i < elems.length; i++) {
elems[i].style.display = 'block';
}
var elem = document.getElementsByClassName('Div1');
for(var i = 0; i < elem.length; i++) {
elem[i].style.display = 'none';
}
}
}
}

Here is an example how to use getElementsByClassName: Fiddle
Is this working for you?
array = document.getElementsByClassName('div1');
for (i = 0; i < array.length; i++) {
array[i].style.backgroundColor = "red";
}
In Chrome and Edge works with no issue.

You are using a array as an object, the difference between getElementbyId and
getElementsByClassName is that:
getElementbyId will return you an object.
getElementsByClassName will return you an array.
getElementsByClassName
The getElementsByClassName(classNames) method takes a string that
contains an unordered set of unique space-separated tokens
representing classes. When called, the method must return a live
NodeList object containing all the elements in the document that
have all the classes specified in that argument, having obtained the
classes by splitting a string on spaces. If there are no tokens
specified in the argument, then the method must return an empty
NodeList.
https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname
getElementById
The getElementById() method accesses the first element with the specified id.
http://www.w3schools.com/jsref/met_doc_getelementbyid.asp
in your code the lines:
1 if (document.getElementByClassName('Div1')) {
2 if (document.getElementByClassName('Div1').style.display == 'block') {
will NOT work as expected: specially the second(2) line, cos the getElementByClassName will return an array, and the array will NOT have the style property, you gonna access each element by iterating them.
That's why the function getElementById was working for you, this function will return you the direct object , and so you will be able to access the style property.
One working code:
function refer(Div1,Div2) {
var elem = document.getElementsByClassName('Div1');
var elems = document.getElementsByClassName('Div2');
for(var i = 0; i < elem.length; i++) {
if (elem[i]) {
if (elem[i].style.display == 'block') {
elem[i].style.display = 'none';
for(var i = 0; i < elems.length; i++) {
elems[i].style.display = 'block';
}
}
}
}
}

Related

Javascript .getElementsByClassName isn't working [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 6 years ago.
This code has no errors in console.log, but it doesn't display class name as it should.
document.getElementsByClassName("abc").onmouseover = function(){mouseOver()};
function mouseOver(){
abc.innerHTML = "Class name " + abc.className;
}
The .getElementsByClassName() routine returns a list of elements. You cannot directly add event handlers to all elements via the list as you're attempting to do. You have to iterate explicitly:
var abc = document.getElementsByClassName("abc");
for (var i = 0; i < abc.length; ++i) {
// ...
}
For your purposes, doing that with the Array.prototype.forEach method makes a little more sense, though it looks odd:
var abc = document.getElementsByClassName("abc");
[].forEach.call(abc, function(element) {
element.onmouseover = function() {
element.innerHTML = "Class name: " + element.className;
};
});
Using .forEach ensures that the event handler works properly using a local variable (element) private to each invocation of the loop callback.
document.getElementsByClassName Returns an array-like object of all child elements which have all of the given class names. So you will have to bind the onmousever event with each child object.
https://developer.mozilla.org/en/docs/Web/API/Document/getElementsByClassName
You can try like this.
var elements = document.getElementsByClassName("abc")
for (var i=0; i < elements.length; i++) {
elements[i].onmouseover = function(){mouseOver(i)};
}
function mouseOver(index){
document.getElementsByClassName("abc")[index -1].innerHTML = "Class name " + document.getElementsByClassName("abc")[index -1].className;
}
<div class="abc">
mouse over me
</div>
Edited Answer based on the provided html in comment
<html> <head> </head> <body> <h1 class="abc">Hello everyone</div>
<script type="text/javascript"> var elements = document.getElementsByClassName("abc"); for (var i=0; i < elements.length; i++) { elements[i].onmouseover = function(){mouseOver(i)}; } function mouseOver(index){ document.getElementsByClassName("abc")[index -1].innerHTML = "Class name " + document.getElementsByClassName("abc")[index -1].className; } </script> </body> </html>

How to write Javascript to search nodes - without getElementsByClassName

I'm very new at recursion, and have been tasked with writing getElementsByClassName in JavaScript without libraries or the DOM API.
There are two matching classes, one of which is in the body tag itself, the other is in a p tag.
The code I wrote isn't working, and there must be a better way to do this. Your insight would be greatly appreciated.
var elemByClass = function(className) {
var result = [];
var nodes = document.body; //<body> is a node w/className, it needs to check itself.
var childNodes = document.body.childNodes; //then there's a <p> w/className
var goFetchClass = function(nodes) {
for (var i = 0; i <= nodes; i++) { // check the parent
if (nodes.classList == className) {
result.push(i);
console.log(result);
}
for (var j = 0; j <= childNodes; j++) { // check the children
if (childNodes.classList == className) {
result.push(j);
console.log(result);
}
goFetchClass(nodes); // recursion for childNodes
}
goFetchClass(nodes); // recursion for nodes (body)
}
return result;
};
};
There are some errors, mostly logical, in your code, here's what it should have looked like
var elemByClass = function(className) {
var result = [];
var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
(function goFetchClass(nodes) {
for (var i = 0; i < nodes.length; i++) {
if ( pattern.test(nodes[i].className) ) {
result.push(nodes[i]);
}
goFetchClass(nodes[i].children);
}
})([document.body]);
return result;
};
Note the use of a regex instead of classList, as it makes no sense to use classList which is IE10+ to polyfill getElementsByClassName
Firstly, you'd start with the body, and check it's className property.
Then you'd get the children, not the childNodes as the latter includes text-nodes and comments, which can't have classes.
To recursively call the function, you'd pass the children in, and do the same with them, check for a class, get the children of the children, and call the function again, until there are no more children.
Here are some reasons:
goFetchClass needs an initial call after you've defined it - for example, you need a return goFetchClass(nodes) statement at the end of elemByClass function
the line for (var i = 0; i <= nodes; i++) { will not enter the for loop - did you mean i <= nodes.length ?
nodes.classList will return an array of classNames, so a direct equality such as nodes.classList == className will not work. A contains method is better.
Lastly, you may want to reconsider having 2 for loops for the parent and children. Why not have 1 for loop and then call goFetchClass on the children? such as, goFetchClass(nodes[i])?
Hope this helps.

Event for multiple elements with the same class name [duplicate]

This question already has answers here:
getElementsByClassName onclick issue [duplicate]
(5 answers)
Closed 9 years ago.
I have the following code:
var abbrs = document.getElementsByClassName("hover");
abbrs.onmouseover=function() {
console.log(this);
};
It should trigger when I hover over an element with the class "hover", but it is not working.
What am i doing wrong?
As its name suggests document.getElementsByClassName returns a list of elements, with the hover as their className, so you can do it like:
var i=0,
len = abbrs.length,
abbrs = document.getElementsByClassName("hover");
for( ; i < len ; i++){
abbrs[i].addEventListener("mouseover", function(event){
//...
});
}
Although it answers the question but in terms of a better coding practice we better avoid from creating functions in loops. So the better practice could be something like this:
var i=0,
len = abbrs.length,
abbrs = document.getElementsByClassName("hover");
fnction addEvent(abbr){
abbr.addEventListener("mouseover", function(event){
//...
});
}
for( ; i < len ; i++){
addEvent(abbrs[i]);
}
document.getElementsByClassName returns either a NodeList or HTMLCollection depending on your current browser and version.
To add event listeners to all of the items in the "abbrs" collection/list you would need to do:
for(i=0; i< abbrs.length; i++) {
abbrs[i].onmouseover=function() {...};
}
Alternately, using jQuery:
$(".hover").on("mouseover", function() {...});
See the code below (I assume you are not using jquery)
var abbrs = document.getElementsByClassName("hover");
var index,l=abbrs.length;
for (index = 0; index < l; ++index) {
console.log(abbrs[index]);
abbrs[index].onmouseover = function() {
console.log(this);
}
}

use remove() on multiple elements

this: document.getElementsByClassName('warningmessage').remove(); doesn't work if you have multiple warningmessage elements on the page.
How can I just delete all elements with that class? do I have to use a for each? isn't there a command to deleteall()?
thanks for your tips!
With plain JavaScript you can do this:
var nodes = document.getElementsByClassName('warningmessage');
for(var i = 0; i < nodes.length; i++){
nodes[i].parentNode.removeChild(nodes[i]);
}
So you would first of all get the nodes you are interested in and afterwards iterate over them and remove them from their parents.
Sadly there is no forEach method on NodeList. However, you could this:
var nodes = document.getElementsByClassName('warningmessage');
[].forEach.call(nodes, function (node) {
node.parentNode.removeChild(node);
});
You need to use a loop. The below code shows how you write in "normal" javascript.
var elements = document.getElementsByClassName('warningmessage'),
element;
while (element = elements[0]) {
element.parentNode.removeChild(element);
}
The working demo.
​
This would be super easier using JQuery:
$('.warningmessage').remove();
But it's not that hard when you do it without. getElementsByClassName can return a nodelist of items. So you'll just have to loop through the list and remove each item:
var list = document.getElementsByClassName("warningmessage");
for(var i = list.length - 1; i >= 0; i--)
{
var n = list[i];
n.parentNode.removeChild(n);
}
You can try this
var elms= document.getElementsByClassName('warningmessage');
while(elms.length>0){
for(var i = 0; i < elms.length; i++){
elms[i].parentNode.removeChild(elms[i]);
}
}​
http://jsfiddle.net/gBwjA/
I have this problem before and I end up in this algorithm.
function removeElement(target) {
if(target.hasOwnProperty('length')) {
for(i=0; i<target.length; i++) {
removeElement(target[i]);
}
} else {
target.parentNode.removeChild(target);
}
}
and then you call the function like this:
removeElement(document.getElementById('the-id'));
or if you want to remove an HTML collection of elements then you call the function in this way:
removeElement(document.getElementsByTagName('tag-name'));

How to hide all elements of class?

I found this function:
document.getElementsByClassName = function(c){
for(var i=0,a=[],o;o=document.body.getElementsByTagName('*')[i++];){
if(RegExp('\\b'+c+'\\b','gi').test(o.className)){
a.push(o);
}
}
return a;
}
How can I hide all elements by class?
I tried:
var array = document.getElementsByClassName("hide");
for(var i = 0; i < array.length; i++)
{
$(array[i]).hide();
}
But I got error:
Could not convert JavaScript argument arg 0 [nsIDOMWindow.getComputedStyle]
jQuery allows CSS selectors to be used, doing away with the need for hand-built loops and regular expressions. To hide an element with class fooey, just do
$('.fooey').hide();
If you're using vanilla JavaScript, then:
var array = document.getElementsByClassName("hide");
for(var i = 0; i < array.length; i++)
{
array[i].style.display = 'none';
array[i].onclick = function(){
// do stuff
};
/* or:
array[i].addEventListener('click',functionToCall);
*/
}
But, given that you're using jQuery, I don't understand why you're complicating things for yourself, just use:
$('.hide').hide();
Further to the above, given your comment:
Because I must add event "click" for each element.
Simply use:
$(elementSelector).click(
function(){
// do stuff
});
Assuming you want to hide, and bind a click-event to, the same elements:
$('.hide').hide().click(
function(){
// do stuff
});
What you get from getElementsByClassName is NOT an array, but a NodeList, hence the error when trying to loop.
However, you can still loop over a NodeList using the following:
var nodeList = document.getElementsByClassName("hide");
for(var x in nodeList){}

Categories

Resources