Target certain classes in an array

Hello,

I’m still very new to JS and am working my way through a learn JS book but have become stuck on an exercise.:frowning:

In the exercise I have 5 elements (lets call them input fields), 3 of which I have given a class of ‘red’ to. What I can’t figure out is how I select just the input tags with the class=‘red’ attribute on them by using the getElementsByTagName. I understand that getElementsByTagName puts all the elements into an array, but how do I target the ones just with the red class?

I’m sure there is a way of doing it using the className property but I can’t seem to get anything working?

Thanks in advance for any pointers.

You need to loop through the five elements. This is normally done with a for loop. First, create an empty array (before the loop). Then with each iteration of the loop, you check the className property. If there is a match, you put the matching elements in the new array (using the push() method).

Alternatively, you don’t need to put them in a new array and you can just do whatever you want to do to the “red” elements directly in the loop.

Give it a go and post again if you get stuck.

Hey thanks for getting back to me so quickly Raffles. I’ll give what you suggested a try and let you know how I get on.

Thanks again for the help.

Hmm, I’ve had a go at using a for loop to sort out my issue but when I think about it, I might have more inputs in the future so can not just loop through a set number. Let me try and explain the problem I’m having using examples of my code.

The exercise in the book I’m stuck on is to using javascript to replace a default checkbox with a graphic. In the example this is done by targeting the required checkbox input using getElementById but in the exercise you are asked to add more checkboxes with a class of ‘graphic’ and target them in the function to replace with a graphic. You are asked to target them using getElementsByTagName and the className property.

Below is the code from the example using getElementById:

HTML

<form name="form1">
<p>
<input type = "checkbox" name="check1" id="check1">
An ordinary checkbox.
</p>
<p>
<input type = "checkbox" name="check2" id="check2">
A graphic checkbox, created with unobtrusive JavaScript.
</p>
<p>
<input type = "checkbox" name="check3" id="check3" class="graphic">
A graphic checkbox, created with unobtrusive JavaScript.
</p>
<p>
<input type = "checkbox" name="check4" id="check4" class="graphic">
A graphic checkbox, created with unobtrusive JavaScript.
</p>
</form>

Javascript

function graphicBox(box) {
   // find the object and its parent
   obj = document.getElementById(box);
   parentobj = obj.parentNode;
   // hide the regular checkbox
   obj.style.visibility = "hidden";
   // create the image element and set its onclick event
   img = document.createElement("IMG");
   img.onclick = Toggle;
   img.src = "unchecked.gif";
   // save the checkbox id within the image ID
   img.id = "img" + box;
   // display the graphic checkbox
   parentobj.insertBefore(img,obj);
}
function Toggle(e) {
   if (!e) var e=window.event;
   // find the image ID
   img = (e.target) ? e.target : e.srcElement;
   // find the checkbox by removing "img" from the image ID
   checkid = img.id.substring(3);
   checkbox = document.getElementById(checkid);
   // "click" the checkbox
   checkbox.click();
   // display the right image for the clicked or unclicked state
   if (checkbox.checked) file = "checked.gif";
      else file="unchecked.gif";
   img.src=file;
}
//replace the second checkbox with a graphic
graphicBox("check2");

So if I am now to target the inputs via class name using getElementsByTagNames I thought the script might need to go something like this:

function graphicBox(graphic) {
   // find the object and its parent
   obj = document.getElementsByTagName(input);
   if (obj.className != 'graphic') return;
   parentobj = obj.parentNode;
   // hide the regular checkbox
   obj.style.visibility = "hidden";
   // create the image element and set its onclick event
   img = document.createElement("IMG");
   img.onclick = Toggle;
   img.src = "unchecked.gif";
   // save the checkbox id within the image ID
   img.id = "img" + graphic;
   // display the graphic checkbox
   parentobj.insertBefore(img,obj);
}
function Toggle(e) {
   if (!e) var e=window.event;
   // find the image ID
   img = (e.target) ? e.target : e.srcElement;
   // find the checkbox by removing "img" from the image ID
   checkid = img.id.substring(3);
   checkbox = document.getElementById(checkid);
   // "click" the checkbox
   checkbox.click();
   // display the right image for the clicked or unclicked state
   if (checkbox.checked) file = "checked.gif";
      else file="unchecked.gif";
   img.src=file;
}

graphicBox("graphic");

Would using a for loop still help me in this situation as what I have done above isn’t working at all!

Thanks for the help.

Here is the problem:

obj = document.getElementsByTagName(input);
if (obj.className != 'graphic') return;

obj is going to be a collection of the inputs, like an array of them. So obj.className is always going to be “undefined”. You have to access each individual input in the collection and check each of their classNames.
You need something like this:

var objs = document.getElementsByTagName(input), obj; // we define obj here as an empty variable
for (var i = 0, j = objs.length; i < j; i++) {
  obj = objs[i]; // this is the current input being operated on
  if (obj.className === 'graphic') {
    // now do the stuff you want to do to the "graphic" inputs
  }
}

Ah I see, getElementsByTagName puts all the inputs into an array.

Thanks for the help Raffles, I’m gonna have a go at putting the code together and will give you a shout if I run into problems.

Yes, but bear in mind that it isn’t an array. It’s a special type of object that seems like an array. You can often treat it like an array, but it’s worth knowing this in case you run into problems later (for instance, when a method like push() doesn’t work on your collection).