I'm having trouble getting a selector to work properly.
I have this HTML:
<div.wrapper>
<div.ui-controlgroup-controls>
<form>
<div.ui-btn></div>
</form>
<div.ui-btn></div>
<div.ui-btn></div>
<div.ui-btn></div>
<div.ui-btn></div>
</div>
</div>
and I'm trying to select the div
tags, which are children of ui-controlgroup-controls
- which means excluding whats inside the form.
This is what I'm trying:
// el is my div.wrapper element
el.children[0].getElementsByTagName("div");
However this does not work, because the div inside the form ends up in the selection.
Question:
How can I select the elements correctly when I don't want to use jQuery?
The getElementsByTagName () is a method of the document or element object. The getElementsByTagName () accepts a tag name and returns a list of elements with the matching tag name. The getElementsByTagName () returns a live HTMLCollection of elements.
The Element.getElementsByTagName () method returns a live HTMLCollection of elements with the given tag name . All descendants of the specified element are searched, but not the element itself.
Definition and Usage. The getElementsByTagName() method returns a collection of all elements in the document with the specified tag name, as a NodeList object. The NodeList object represents a collection of nodes. The nodes can be accessed by index numbers. The index starts at 0. Tip: The parametervalue "*" returns all elements in the document.
When called on an HTML element in an HTML document, getElementsByTagName lower-cases the argument before searching for it. This is undesirable when trying to match camel-cased SVG elements (such as <linearGradient> ) in an HTML document. Instead, use Element.getElementsByTagNameNS () , which preserves the capitalization of the tag name.
One way to do this is to iterate over your resulting node list and check the parent:
var nodes = el.children[0].getElementsByTagName("div");
nodes = Array.prototype.slice.call(nodes);
nodes = nodes.filter(function(v, i){
return v.parentElement === el.children[0];
});
Here is a demonstration of this approach: http://jsfiddle.net/WLhY2/
A simpler (albeit less efficient) approach is to use querySelectorAll
to retrieve the relevant nodes using a selector expression:
var divs = document.querySelectorAll('div.ui-controlgroup-controls > div')
For the browser that supports querySelectorAll:
var divs = el.children[0].querySelectorAll("div");
For the browsers that supports the usage of slice on NodeList (e.g. not IE, at least not IE < 9):
var slice = Function.call.bind(Array.prototype.slice);
var divs = slice(el.children[0].children).filter(function(node) {
return node.tagName === "DIV"
});
For the browsers that doesn't support neither:
var nodes = el.children[0].children;
var divs = [];
for (var l = nodes.length, node; node = nodes[--l];) {
if (node.tagName === "DIV")
divs.push(node);
}
In most browsers, you can do:
el.querySelectorAll(".ui-controlgroup-controls > div")
But this could give false positives if there are more deeply nested ".ui-controlgroup-controls"
that you want to avoid.
If that's the case, just iterate the .children
, and build a collection of nested divs.
var divs = [];
for (var i = 0, len = el.children.length; i < len; i++) {
if (el.children[i].classname === "ui-controlgroup-controls") {
for (var j = 0, lenj = el.children[i].children.length; j <, lenj; j++) {
if (el.children[i].children[j].nodeName === "DIV") {
divs.push(el.children[i].children[j])
}
}
}
}
If it's known that you have only one ui-controlgroup-controls
element, then you can get rid of the outer loop, and just use children[0]
.
var divs = [];
for (var j = 0, lenj = el.children[0].children.length; j <, lenj; j++)
if (el.children[0].children[j].nodeName === "DIV")
divs.push(el.children[o].children[j])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With