返回基于数组的DOM元素

时间:2017-12-03 23:47:07

标签: javascript html arrays object dom

作为一项挑战,我正在尝试创建一个JavaScript选择引擎,即一个JavaScript函数,它将返回给定CSS选择器的DOM元素。

我无法使用document.querySelector / document.querySelectorAll。

我目前正在创建参数的对象,但现在卡住了。我现在需要遍历页面上的每个元素,如果它匹配我的标签或类/ id,则将该元素推送到数组。

$("div") //Should return 2 DIVs

$("img.some_class") //Should return 1 IMG

$("#some_id") //Should return 1 DIV 

$(".some_class") //Should return 1 DIV and 1 IMG

function $ (selector) { 

	var elements =[];

	var pageTags =[];

	var all = document.getElementsByTagName("*");

	//splits selector
	var arg = parse(selector);

	function parse(subselector) {
		 var obj = {tags:[], classes:[], ids:[], attrs:[]};
		 subselector.split(/(?=\.)|(?=#)|(?=\[)/).forEach(function(token){
		    switch (token[0]) {
		      case '#':
		         obj.ids.push(token.slice(1));
		        break;
		      case '.':
		         obj.classes.push(token.slice(1));
		        break;
		      case '[':
		         obj.attrs.push(token.slice(1,-1).split('='));
		        break;
		      default :
		         obj.tags.push(token);
		        break;
		    }
		  });
		  return obj;
	}

	console.log(arg);


	for (var item of all) {

		//gets tagname of all page elements
		var element = item.tagName.toLowerCase();

		console.log(element);
		//if argument contains DOM element
		if (arg.indexOf(element) !== -1) {

			var x = document.getElementsByTagName(element);
			
			for (var test of x) {
				elements.push(test);
			}

		}

	}

	return elements;

}
<html>
  <head>
    <script src="Answer.js"></script>
    <script src="Test.js"></script>
  </head>
  <body onload="test$()">
    <div></div>
    <div id="some_id" class="some_class some_other_class"></div>
    <img id="some_other_id" class="some_class some_other_class"></img>
    <input type="text">
  </body>
</html>

如有任何帮助,请提供帮助。

1 个答案:

答案 0 :(得分:1)

检查此jsfiddle。 当然会有更多的组合...

我将测试用例限制为您提供的html示例。

function _select(attrValues, tagFilter, cssSel) {

  var results = [];
  //var value = selector.slice(1);
  var all = document.getElementsByTagName(tagFilter);
  //look for an id attribute
  if (cssSel === '#') {
    for (var i = 0; i < all.length; i++) {
      if (all[i].id === attrValues) {
        results.push(all[i]);
      }
    }
  } else {
    if (typeof attrValues === 'string') {
      for (var i = 0; i < all.length; i++) {
        if (all[i].classList.contains(attrValues)) {
            results.push(all[i]);
        }
      }
    } else {
        //multiple selector classes
      var found = 0;
      for (var i = 0; i < all.length; i++) {
        for (var j = 0; j < attrValues.length; j++) {
          if (all[i].classList.contains(attrValues[j])) {
            found += 1;
            if (found === attrValues.length) {
              results.push(all[i]);
            }
          }
        }
      }
    }
  }
  return results;
}

function $(selector) {

  var cssSel = selector.charAt(0);
  var cssSelectors = ['.', '#'];

  if (cssSel === cssSelectors[0] || cssSel === cssSelectors[1]) {
    //direct selector
    var attrValue = selector.slice(1),
      tagFilter = '*';
    return _select(attrValue, tagFilter, cssSel)
  } else {
    for (var i = 0; i < cssSelectors.length; i++) {
      var tokens = selector.split(cssSelectors[i]);
      if (tokens.length > 1 && tokens[0] !== "") {
        //nested selector
        var tagFilter = tokens[0], //the first of the array should be the tagname ,because the case of the cssSelector at charAt(0) should have been caught in the if at the beginning.
          attrValue = tokens.slice(1); //the rest of the array are selector values
        return _select(attrValue, tagFilter, cssSel)
      }
    }
  }
  return document.getElementsByTagName(selector);
}

//TEST cases

var results = $("div")
console.log('Should return 2 DIVs')
for ( var e of results){
    console.log(e)
}

var results = $(".some_class")
console.log('Should return 1 DIV and 1 IMG')
for ( var e of results){
    console.log(e)
}

var results = $("#some_id")
console.log('Should return 1 DIV ')
for ( var e of results){
    console.log(e)
}

var results = $("img.some_class")
console.log('Should return 1 IMG')
for ( var e of results){
    console.log(e)
}

var results = $("div.some_class.some_other_class")
console.log('Should return 1 div')
for ( var e of results){
    console.log(e)
}