Reputation: 313
I have a nodelist like this:
[text, div.post, comment, text, div.post, comment, text, div.post, comment, text, div.post, comment, text, div.post, comment, text]
This nodelist is a result of an ajax call, div.post
is my posts and I want to select it to add new classname.
How do I select div.post
from this nodelist by using vanilla javascript?
Upvotes: 1
Views: 7672
Reputation: 48733
You can write a selector finder. This is not too specific, but it definitely needs improvement. You can find a selector by class
id
and tagName
. It will return the first one from the NodeList
.
var children = document.getElementById('foo').childNodes;
findAndPrint('#bar', children);
findAndPrint('div#baz', children);
function findAndPrint(selector, nodeList) {
print('>> Found?: ' + JSON.stringify(toEl(getNodeBySelector(nodeList, selector))));
}
function print(str) {
document.getElementById('out').innerHTML += str + '<br />';
}
function getNodeBySelector(nodeList, selector) {
var parts = selector.split(/(?=[#\.])/g);
for (var i = 0; i < nodeList.length; i++) {
var node = nodeList[i];
if (node !== undefined && isElement(node)) {
var el = toEl(node);
if (isMatch(el, parts)) {
return node;
}
}
};
return undefined;
}
function isElement(node) {
try {
return node instanceof HTMLElement;
} catch (e) {
return (typeof node === "object") &&
(node.nodeType === 1) && (typeof node.style === "object") &&
(typeof node.ownerDocument === "object");
}
}
function toEl(node) {
if (node) {
return {
'name': node.tagName.toLowerCase(),
'id': node.getAttribute('id'),
'class': node.getAttribute('class')
};
}
return undefined;
}
function isMatch(el, parts) {
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
if (part.indexOf('.') == 0) {
if (el.class != null && el.class.indexOf(part.substr(1)) === -1) {
return false;
}
} else if (part.indexOf('#') == 0) {
if (el.id != null && el.id !== part.substr(1)) {
return false;
}
} else {
if (el.name != null && el.name !== part) {
return false;
}
}
}
return true;
}
<div id="out"></div>
<div id="foo">
<div id="bar"></div>
<div id="baz"></div>
</div>
You can modify each node in the NodeList
instead of returing the first element by using:
function applyToNode(nodeList, selector, callback) {
var parts = selector.split(/(?=[#\.])/g);
for (var i = 0; i < nodeList.length; i++) {
var node = nodeList[i];
if (node !== undefined && isElement(node)) {
if (isMatch(toEl(node), parts)) {
callback(node, i, nodeList);
}
}
};
}
Where callback is:
function callback(node, index, nodeList) {
// ...
}
Upvotes: 0
Reputation: 448
Like itmars and Amit Jokis answer in a for loop
nodelist = [text, div.post, comment, text, div.post, comment, text, div.post, comment, text, div.post, comment, text, div.post, comment, text];
for(var i=0; i< nodelist.length;i++){
var nodeItem = nodelist.item(i);
if(nodeItem.nodeName=="div" && (nodeItem.className.indexOf("post") > -1)){
//do your stuff
}
}
Upvotes: 0
Reputation: 59292
Just a matter of then iterating through it and adding the class. Since you cannot loop as is, you can make use of Array.forEach
and Function.call
[].forEach.call(nodelist, function(elm){
if(elm.className.indexOf("post") > -1 && elm.nodeName == "DIV")
elm.className += ' classNameHere';
});
Upvotes: 1
Reputation: 3967
Here: https://developer.mozilla.org/en-US/docs/Web/API/NodeList.item
nodelist = [text, div.post, comment, text, div.post, comment, text, div.post, comment, text, div.post, comment, text, div.post, comment, text];
youritem = nodelist.item(1);
To go through and find all that match criteria you'll have to do a loop like Amit's answer. Otherwise the solution above will work for cherry-picking it.
Upvotes: 0