javascript selectors - javascript

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!)

Related

how to select tags that are inside certain other tags

I want to select all the <"a"> tags on a page that are inside all the <"code"> tags on the page so I can count them, and I want to do this using JavaScript.. how can I do this?
I tried using document.getElementsByTagName("code").getElementsByTagName("a"); and document.getElementsByTagName("code").querySelectorAll("a"); but it doesn t seem to work
document.getElementsByTagName("code").getElementsByTagName("a");
VM1278:1 Uncaught TypeError: document.getElementsByTagName(...).getElementsByTagName is not a function
at :1:39
You can use .querySelectorAll(selectors).
const matches = document.querySelectorAll('code a');
console.log(matches);
<code>
<a>Test</a>
<p>Other tag</p>
<a>Example</a>
</code>
You need to loop through the initial element search, since it returns an HTMLCollection of elements:
var elements = document.getElementsByTagName("code");
var all = [];
for(var i = 0; i < elements.length; i++){
var tempElements = elements[i].getElementsByTagName("a");
all = [...tempElements, ...all];
}
Try this instead:
document.querySelectorAll('code a').length
The querySelector and querySelectorAll functions accept CSS-like DOM selectors and return a node or NodeList, respectively.
See:
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
You can use
document.querySelector("code > a");
you can do it like this:
var anchors = document.getElementById("thediv").getElementsByTagName("a");
alert("The Div has " + anchors.length + " links in it");
<div id="thediv">
link 1
link 2
link 3
</div>

getElementById from ancestor element to remove child's class

I want to use a parent element with getElementById.
For example: I want to use ancestor id "test" to remove class "myClass".
HTML
<div id="test">
<div id="test-child-one">
...
</div>
<div id="test-child-two">
...
</div>
<div id="test-child-three">
<div class="myClass"></div>
</div>
</div>
Javascript
var element = document.getElementById("test");
element.className = element.className.replace(/\bmyClass\b/g, "");
It won't work. Please help! Thanks.
You could do this:
//If you want to remove the class from all decendants
//Get all decendants with class "myClass"
const childEles = document.getElementById('test').querySelectorAll('.myClass');
//Or per David
const childEles = document.querySelectorAll('#test .myClass');
//Iterate the collection and remove "myClass" from all decendants
for(let x = 0; x < childEles.length; x++){
childEles[x].classList.remove("myClass");
}
//If you only want to remove the first decendant
document.getElementById('test').querySelectorAll('.myClass')[0].classList.remove("myClass");
//Or per David
document.querySelectorAll('#test .myClass')[0].classList.remove("myClass);
Do like Ryan Wilson specified it or simple one-liner:
document.getElementById("test").querySelectorAll('.myClass').forEach(function (el) { el.classList.remove("myClass"); });
Or a beautiful way, if you have transpiler between your code and browser:
removeChildrenClass = (parentId, childClass) => document.querySelectorAll(`#${parentId} .${childClass}`).forEach(el => el.classList.remove(childClass));
removeChildrenClass("test", "myClass");
Expanding on the other answers provided, it seems as though you are looking for querySelectorAll. Given that you already have some ancestor element element, querySelectorAll can be used to find all children with the specified class. To build on your example:
Using querySelectorAll
// Example constant element IDs/classes
var parentId = "test";
var targetClass = "myClass";
// The given parent element
var element = document.getElementById(parentId);
// Iterate over all children `elem`s with the target class
element.querySelectorAll(targetClass).forEach(function (elem) {
elem.classList.remove(targetClass);
});
This is just an example to demonstrate how querySelectorAll can be used on specific elements to solve exactly such a problem. Note that querySelectorAll will match multiple classes containing myClass if they exist, if you want to specifically remove the first such class, you might use querySelector instead.

how browser find collection elements when we are using css selector

I want to know how browsers find html collection elements when we use css selector.for example.
<div>
<p class="color">I'm p1</p>
</div>
<div>
<div>
<p class="color">I'm p2</p>
</div>
</div>
<p class="color">I'm p3</p>
when we use $("p") or $(".color") we will get three p elements.
so,my question is the order of finding those elements.
(p1,p2,p3) or (p3,p1,p2) or others
because html is a dom tree,the browser may use tree traversal algorithms,which have 5 kinds of(depth-first,pre,in,post,breadth).So,which algorithm is the browser taken.
In that specific use case you will get:
I'm p1
I'm p2
I'm p3
even without to use jQuery.
var p = $(".color");
for(var i=0; i<p.length; i++) {
var el = p.eq(i);
console.log(el.text());
}
console.log("test");
var p2 = document.querySelectorAll(".color");
for(var i=0; i<p2.length; i++) {
var el = p2[i];
console.log(el.innerHTML);
}
JSFiddle -> http://jsfiddle.net/RSEyf/3/
So, it looks like the browser gets the elements in their order in the html.
It is the same even if you use just p instead of .color.

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 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