Anthony Chung
Anthony Chung

Reputation: 1477

Implementing getElementsByClassName recursively

Trying to hand-code getElementsByClassName recursively.

While the code works in my console, I'm not passing my test case in mocha. Assuming the test case was written correctly, what can I do to make my code better (read: more correct)?

var getElementsByClassName = function(className){
  var docBody = document.body;
  var classes = [];
  var walk = function (node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
      walk(node, func);
      node = node.sibling;
    }
  }
  walk(docBody, function() { 
    if (docBody.classList.contains(className)) {
      classes.push(docBody)
    }
  });
  return classes;
};

Upvotes: 1

Views: 1542

Answers (2)

PointedEars
PointedEars

Reputation: 14980

For a start, objects implementing the Element interface have a nextSibling (and a previousSibling) property, not a sibling property, so your while loop always stops after the .firstChild as the property access evaluates to a false-value.

Next time, please debug first.

Also, I recommend implementing this based on the return value of document.getElementsByTagName("*") instead which already does the recursive traversal much more efficiently (since it uses native DOM code).

Your question sounds like a homework assignment. StackOverflow is there to help you solve real problems instead. Please read the FAQ on which questions are considered appropriate here.

Upvotes: 1

Paul Roub
Paul Roub

Reputation: 36458

Two problems, as noted above: node.sibling should be node.nextSibling, and you need to look at the node passed to walk(), not always at docBody.

Additionally, some of the nodes you encounter (e.g. text nodes) won't have a classList, so account for that:

var getElementsByClassName = function(className) {
  var docBody = document.body;
  var classes = [];

  var walk = function (node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
      walk(node, func);
      node = node.nextSibling;
    }
  }

  walk(docBody, function(node) { 
    if (node.classList && node.classList.contains(className)) {
      classes.push(node)
    }
  });

  return classes;
};

Upvotes: 4

Related Questions