作为一项挑战,我正在尝试创建一个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>
如有任何帮助,请提供帮助。
答案 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)
}