Get subclass of document.getElementsByClassName - javascript

So, I have this html code:
<div class='class1' id='example'>
<span class='class2'>Some text</span>
<span class='class3'>Some text 2</span>
</div>
I want to get every class1 and then add an event listener (click) on class2 and class3 (and I need that id to get some info from a PHP file). I tried something like this:
var yes = document.getElementsByClassName('class1');
for (var i=0 ; i<yes.length;i++)
yes[i].getElementsByClassName('class2').addEventListener('click',redirectfunction,false);
It's not working. What can I do?!

You are probably better to use querySelectorAll as it has wider support than getElementsByClassName (IE 8+) and you can get the elements in one go:
var yes = document.querySelectorAll('.class1 > .class2, .class1 > .class3');
querySelectorAll returns a static NodeList, so iterate over the returned object to access the members.
However, be prepared to provide a fallback for older browsers.

At first getsElementsByClassName should be getElementsByClassName (if not a typo) and then yes[i].getElementsByClassName('class2') returns a HTMLCollection of found elements and you are using this:
yes[i].getElementsByClassName('class2')
.addEventListener('click',redirectfunction,false);
So, you are trying to add an event listener on a collection. You may use another loop if there are multiple elements or just use something like this:
yes[i].getElementsByClassName('class2')[0]
.addEventListener('click',redirectfunction,false);
Update: (Example)
var els = document.querySelectorAll('div.class1');
for(var i =0, l=els.length; i<l; i++) {
var cls = els[i].querySelectorAll('span[class^=class]');
for(var x =0, n=cls.length; x<n; x++) {
cls[x].addEventListener('click', function(e) {
redirectfunction.call(this, e, this.parentNode.id);
}, false);
}
}
function redirectfunction(e, id) {
alert('This is id: ' + id);
}

Related

How can access bunch of <li>?

I have a list of texts and I want to change their innerHTML. how can I do that by javascript if I have thousands of li tag (whose data come from database)?
<div>
<ul>
<li>a</li>
<li>as</li>
<li>asd</li>
<li>asds</li>
<li>asdsa</li>
<li>asdsad</li>
<li>asdsadz</li>
<li>asdsadzc</li>
....
.....
</ul>
</div>
-Thanks.
Update
JS code being used:
function a(){
var parent = document.getElementById("z");
var i = 0;
for(i = 0; i <= parent.children.length; i++){
if(parent.children[i].tagName == "LI"){
if(i%2!=0){
parent.children[i].innerHTML="ok";
}
}
}
}
document.onload=a(); // this didn't work. so I called the function in body tag instead of that.
<body onload="a();">
Have you tried using getElementsByTagName ? Sonds like it would help you find the elements you're trying to work with.
Edit
If you can give an Id to the UL element that holds the li's you're trying to process, you could do something like this:
var parent = document.getElementById("yourID");
var i = 0;
for(i = 0; i < parent.children.length; i++){
if(parent.children[i].tagName == "LI") {
//do what you want...
}
}
EDit 2
You have to change the last line on your script:
document.onload=a();
With this one: window.onload=a;
That'll get your function to execute on the onLoad event. Note that there might be some crossbrowser incompatibility, I would suggest researching a bit on how to execute functions on the onload event on a crossbrowser manner, or just adding this to your body tag:
<body onload="a();">
Given the - not so far fetched - precondition you wish to use jQuery, you can select them and iterate over them with "each".
$("li").each(
function() { $(this).html("changed content"); }
);
If you are not using jQuery, using a js-library that helps you out with the quircky dom is probably not a bad idea...
The general idea
Select nodes
Iterate and change html
is always the same.

Using Javascript, what is the method to get an element, based on the text between the opening and closing tags?

I'm a beginner, and couldn't find the answer after searching.
In my example, I'm looking for an
some text here
I'd want to find this particular element, so I can do stuff with it.
Edit: The only thing I know that's unique about the element for sure, is the text "some text here", that's why I want to find it based on that.
Put id on the element:
<a href="bla" onclick="dah" id='myEl'>some text here</a>
From javascript:
var myEl = document.getElementById('myEl') // gives the element
You can also use psuedo selector :contains, with the jQuery library.
Example 2
$('div:contains("test")').css('background-color', 'red');​
http://jsfiddle.net/9z5du/
Example 2
<script>
$("div:contains('John')").css("text-decoration", "underline");
</script>
If you know that the element is a link, you can first call getElementsByTagName [docs] to narrow down your search:
var elements = document.getElementsByTagName('a');
Then you have to iterate over the elements and test which one contains the next you are looking for:
var element = null;
for(var i = 0, l = elements.length; i < l; i++) {
if(elements[i].innerHTML === 'some text here') {
// found the element
element = elements[i];
break;
}
}
if(element) {
// found the element, lets do something awesome with it
}
There are multiple ways to get the content of an element, using Node#innerText (IE) or Node#textContent (W3C) is another option. You might have to trim the text first before you compare it.
If the HTML is as shown in your post,
if(elements[i].firstChild || elements[i].firstChild.nodeValue)
is even more elegant.
The MDN documentation about the DOM might be helpful.
If you can modify the HTML then adding an ID and using getElementById would be the better option.
Try this
function getit()
{
var elems = document.getElementsByTagName('a');
for(var i=0; i<elems.length; i++)
{
var text = elems[i].childNodes[0] != null ? elems[i].childNodes[0].nodeValue : '';
if(text == "some text here")
doSomethingWith(elems[i]);
}
}

JavaScript - innerHTML to change more then first occurrence plus random array

I have two baffling things going on,
First: Is I’m trying to use the .innerHTML to change more than just the first occurrence.
Second: Is that I’m trying to have a random word replace the .innerHTML.
I've only been able to change the first word let alone all plus the random is a complete fail, any help would be appreciated.
Hello <p id="p1">World!</p>
Hello <p id="p1">World!</p>
Hello <p id="p1">World!</p>
<script type="text/javascript">
document.getElementById("p1").innerHTML="newWorld()";
function newWorld() {
var worlds = new Array ("Pluto!", "Mars!", "Saturn!", "Earth!", "Mercury!");
var whichWorld = Math.floor(Math.random()*worlds.length);
worlds[whichWorld]();
};
</script>
IDs in HTML documents are meant to be unique. The function getElementById will only ever return 1 element, nothing more. For groups of similar elements, you want to give them all a common class and then use getElementsByClassName (notice the plural Elements vs Element) - this function won't work with IE 8 or earlier, however, so if you need to support IE you would have to do getElementsByTagName and then filter in only those that have the class you want.
As far as the second part of the code, first you are setting the innerHTML to the actual string newWorld() not to the return value of the function (which there is none, as you are not currently returning something from within newWorld) - I think you meant to do document.getElementById("p1").innerHTML = newWorld();. Secondly, the random part of the code is correct and should be choosing a random planet each time. The end of the code is a bit puzzling, however - what exactly are you trying to do there? worlds[whichWorld] is going to be a string (Earth!, etc.) not a callable function. If worlds was an array of functions then the code would work (assuming you also returned it, since you intend to set it as the innerHTML)
In short, something like this would be the "proper" way to set all <span> elements within a parent element to a random planet:
<div id="planets">
<p>Hello <span>World!</span></p>
<p>Hello <span>World!</span></p>
<p>Hello <span>World!</span></p>
</div>
And the Javascript:
var spans = document.getElementById('planets').getElementsByTagName('span');
for(var i = 0; i < spans.length; i++) {
spans[i].innerHTML = randomWorld();
}
function randomWorld() {
var worlds = ["Pluto!", "Mars!", "Saturn!", "Earth!", "Mercury!"];
var whichWorld = Math.floor(Math.random() * worlds.length);
return worlds[whichWorld];
}
And here it is in action. You are clearly new to Javascript so I encourage you to continue to try and learn the basics of it. Eventually, however, you will want to look into libraries such as jQuery which make a lot of the tediousness of writing cross-browser Javascript go away.
According to HTML standard id must be unique, thus getElementById always return 1 element (usually the first found in the HTML.
You could write:
Hello <p class="planet">World!</p>
Hello <p class="planet">World!</p>
Hello <p class="planet">World!</p>
<script type="text/javascript">
var planets = document.getElementsByClassName("planet")
for (var i=0; i < planets.length; i++) {
planets[i].innerHTML = newWorld();
}
function newWorld() {
var worlds = new Array ("Pluto!", "Mars!", "Saturn!", "Earth!", "Mercury!");
var whichWorld = Math.floor(Math.random()*worlds.length);
return worlds[whichWorld];
}
</script>
I know jQuery is out of the scope of the question, but with a library such as jQuery (and NOT using identical ids) it would be possible to change the content of several element with one statement...
Ids in HTML are supposed to be unique. As such, the getElementById method only returns the first element with the given ID. You've got all the logic right, but you can simplify your answer a bit. Change the ids to classes and use the getElementsByClassName method like so:
Hello <span class="p1">World!</span>
Hello <span class="p1">World!</span>
Hello <span class="p1">World!</span>
<script type="text/javascript">
var worlds = ["Pluto!", "Mars!", "Saturn!", "Earth!", "Mercury!"];
var pTags = document.getElementsByClassName("p1");
for (i = 0; i < pTags.length; i++)
{
pTags[i].innerHTML = worlds[Math.floor(Math.random() * worlds.length)];
}
​</script>
DEMO
Note that the getElementsByClassName method doesn't work in IE8 or earlier. So if you want it to be backwards compatible with those browsers, you'll either need to use the getElementsByTagName and filter them manually or use jQuery.
JAVASCRIPT DEMO, WORKS ON ALL BROWSERS
JQUERY DEMO
Use a function that gives you a group of elements such as querySelectorAll or getElementsByTagName or getElementsByClassName:
Hello <p class="world">World!</p>
Hello <p class="world">World!</p>
Hello <p class="world">World!</p>
<script type="text/javascript">
var newWorld = function () {
var worlds = new Array ("Pluto!", "Mars!", "Saturn!", "Earth!", "Mercury!");
var whichWorld = Math.floor(Math.random()*worlds.length);
return worlds[whichWorld];
};
var worlds = document.getElementsByClassName("world");
for (var i=0; i < worlds.length; i++) {
worlds[i].innerHMTL = newWorld();
}
</script>
To mark multiple elements, you should use class attribute.
Multiple elements in DOM can have same value of class attribute,
but the value of id attribute should be unique.
So the example may look like:
<button id="change-world-btn">Change World</button>
<hr />
<h4>Elements with target class name:</h4>
Hello <span class="world-name">World!</span><br />
Hello <span class="world-name">World!</span><br />
Hello <span class="world-name">World!</span><br />
<hr />
<h4>Element with different class name:</h4>
Hello <span class="other-class">World!</span><br />
<script type="text/javascript">
var worlds = new Array ("Pluto!", "Mars!", "Saturn!", "Earth!", "Mercury!");
function newWorld() {
return worlds[Math.floor(Math.random() * worlds.length)];
}
elements = document.getElementsByTagName('span');
document.getElementById('change-world-btn').onclick = function() {
world = newWorld();
for(var i = 0, el; el = elements[i++];) {
if(el.className == 'world-name') {
el.innerHTML = world;
}
}
};
​</script>
Try it.
Also you can use document.getElementsByClassName function to simplify the task, but this function is not supported in IE < 9.

javascript selectors

How does one select DOM elements in javascript?
Like for example:
<div class="des">
<h1>Test</h1>
<div class="desleft">
<p>Lorem Ipsum.</p>
</div>
<div class="Right">
<button>Test</button>
</div>
</div>
Now how do i select h1? This is just a part of a bigger Page, so cannot use getElementsByTagName(), since others might get selected. Also since there might be other h1's in the document later, i cannot attach the index(body's) to above.
Is there a simple way to select, say <h1> tag which is under the classname of desleft?
I cannot use jQuery or any other libraries.
You can use this to get to your H1:
var des = document.getElementsByClassName('des')
var fc = des[0].getElementsByTagName('h1')
alert(fc[0].innerHTML)
w3.org has selectors now (http://www.w3.org/TR/selectors-api/#examples). Here are 2 different ways that worked for me on Chrome. You may want to use querySelectorAll function that returns a list.
<script type="text/javascript">
//looks for <h1> tag under <div> with className "des"
showOff1 = function() {
var x = document.querySelector(".des h1");
alert(x.innerHTML);
}
//looks for <div> tag with className "desleft" and then use previousSibling to traceback <h1> tag
showOff2 = function() {
var y = document.querySelector("div.desleft");
var z = y.previousSibling.previousSibling;
alert(z.innerHTML);
}
</script>
<body onload="showOff2();">
Use querySelectorAll
You can use querySelectorAll:
// Will return a NodeList even if there is only one element found
var heading = document.querySelectorAll('.des > h1');
heading[1].style.color = 'red'; // NodeList is similar to an array
This will return a NodeList.
or
Use querySelector to return the first element found:
var first_heading = document.querySelector('.des > h1');
first_heading.style.color = 'blue';
Commonly used with an id selector #single-header-id.
Here's a demo
getElementsByTag()
Would be a function that you can start with, and then you can filter for the DOMElements that have the class.
var h1_array = document.getElementsByTag('h1');
var h1_class_array = [];
for (var i=0, len=h1_array.length; i < len; i++) {
if (h1_array[i].className.indexOf('classname') !== -1) {
h1_class_array.push(h1_array[i]);
}
}
The .indexOf function returns -1 if the needle is not found in the haystack.
Now re-reading your question, why not just give your h1's id's ?
DOM traversal is one of javascript's glaring issues (enter jQuery).
a simple getElementById() would save you a headache, and ids on all your h1's would be much cleaner in the end than trying to formulate an algorithm to select them by other means.
If you mean to select a h1 that is before the first element of class desleft, you could always do this:
document.getElementsByClassName("desleft")[0].previousSibling.previousSibling
Example: http://jsfiddle.net/Xeon06/ZMJJk/
previousSibling needs to be called twice because of the empty text node between the two. That's why using libraries to do this stuff is really the best way to go.
var h1 = document.querySelector('.desleft').previousElementSibling;
Find element with className='desleft' using selector '.desleft'
Just move back to previous element (not to previous node!)

Javascript DOM howto?

I am a javascript noob.
I would like to select the second 'p' element of the div.box.
How do I do this?
Thanks a lot!
Tom
To get second p element of div with class box you'd do this:
var paragraph = null;
var divs = document.findElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
if (div.class == 'box') {
var paragraphs = div.getElementsByTagName('p');
if (paragraphs.length > 1)
paragraph = paragraphs[1];
break;
}
}
The paragraph would then be in the paragraph variable (or null if it wasn't found).
However you can do this much easier with a library such as jQuery:
var paragraph = $('div.box p:eq(1)');
Without using jQuery, the basic method would be to attach an unique ID to your Dom element
<p id="second_p_elmt"> [...] </p>
and then accessing it through the getElementById() method:
<script ...>
var second_p_elmt = document.getElementById('second_p_elmt');
</script>
<script type="text/javascript">
var boxElem = document.getElementById('box'),
pElems = boxElem.getElementsByTagName('p'),
whatYouWant = pElems[1]; // [1] is the second element in the response from getElementsByTagName
</script>
You have several options. As stated above, you could use one of the excellent frameworks, like jQuery or prototype. Or you give the <p/> an ID, that you can use simply with document.getElementById().
Then, as reko_t pointed out, without the above, you must write a lengthy DOM traversing code (which is preferable, if you don't use JS frameworks elsewhere, over embedding them only for this task).
In the most recent browsers (namely, IE>=8, FF>=3.5, recent Opera and Safari > 3) you can also use this simple snippet:
var p = document.querySelectorAll("div.box p");

Categories

Resources