Vendetta
Vendetta

Reputation: 63

Hardcoded getElementsByClassName Recursive (element.className vs. element.classList.contains)

After several attempts of hardcoding a recursive getElementsByClassName method, I settled with the following:

var getElementsByClassName = function(className) {
  var result = [];

  function inspect(element) {
    var children = element.children;
    for(var i = 0; i < children.length; i++) {
      if(children[i].classList.contains(className)) {
        result.push(children[i]);
      }
      if(children[i].hasChildNodes) {
        inspect(children[i]);
      }
    }
  }

  inspect(document);
  return result;
};

However, I can't figure why this solution doesn't work, considering className returns the value we can test against:

var getElementsByClassName = function(className) {
  var result = [];

  function inspect(element) {
    if (element.className === className) result.push(element);

    var children = element.children;
    for(var i = 0; i < children.length; i++) {
      inspect(children[i]);
    }
  }

  inspect(document);
  return result;
};

Thanks for the help, in advance, and if you have any other suggestions for improving my code, please let me know.

Upvotes: 0

Views: 1643

Answers (1)

Shams Ali
Shams Ali

Reputation: 11

  1. your if statement needs to be updated because there are certain cases in which an element can have more than one class to it. Currently your just testing for if there is only one class. You can either use contains method to check it using indexOf as i did below to see if the required classname is in the list.
  2. when calling your recursive call you are using document. I am not too sure but i do believe you want to be calling document.body... That means you are trying to assign var children to document.children when invoking the function for the first time, however you want to call document.body.children as well as for the if statement document.body.classname...so when calling the recursive call it should be inspect(document.body).if you want to use document then you would have to use document.childNodes....however it is better to use document.body.children because document.childNodes adds spaces in your result between each element. So if there are 3 children then document.body.children will have a length of 3, but document.childNodes will have a length of 5. You can do this same function using childnodes instead of childen however you the contain method inside the if block would be better to use in that case.

heres a solution for u that sort of uses your algorithm, but there are better ways to implement and you can also do this without an inner function.

var getElementsByClassName = function(className) {
  var result = [];

  function inspect(element, result) {
    var children = element.children;
    var parts = element.className.split(' ');
    if(parts.indexOf(className) >= 0){
      result.push(element);
    }
    for(var i = 0; i < children.length; i++) {
      inspect(children[i], result);
    }
  }

  inspect(document.body, result);
  return result;
};

Upvotes: 1

Related Questions