crezc3nt
crezc3nt

Reputation: 313

Find nodes in nodelist

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

Answers (4)

Mr. Polywhirl
Mr. Polywhirl

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.

Demo

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>

Also...

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

Stefan
Stefan

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

Amit Joki
Amit Joki

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

itamar
itamar

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

Related Questions