console
function nextNode(node, rootNode) {
if (node.children.length) {
return node.children[0]
}
if (node === rootNode) {
return null
}
while (node.parentNode) {
if (node.parentNode.nextElementSibling) {
return node.parentNode.nextElementSibling
}
node = node.parentNode
}
return null
}
function nextSelectorNode(node, selector, rootNode) {
return {
'child': {value: nextNode(node, rootNode), hasNext: false},
'descendant': {value: nextNode(node, rootNode), hasNext: true},
'subSelector': {value: nextNode(node, rootNode), hasNext: true},
}[selector.relation]
}
function match(node, selector) {
return {
'class': node.className.trim().split(/ +/).indexOf(selector.value) >= 0,
'tag': node.tagName.toLowerCase() === selector.value.toLowerCase(),
}[selector.matchType]
}
function querySelector(node, selectors) {
var rootNode = node
node = {value: node, hasNext: true}
let i = 0
for (i; i < selectors.length; i++) {
node = nextSelectorNode(node.value, selectors[i], rootNode)
do {
if (match(node.value, selectors[i])) {
break
}
node = nextSelectorNode(node.value, selectors[i], rootNode)
} while (node.value && node.hasNext)
}
if (i === selectors.length) {
return node
}
return null
}
var selectors = [
{relation: 'subSelector', matchType: 'class', value: 'mls-info'},
{relation: 'child', matchType: 'tag', value: 'div'},
{relation: 'descendant', matchType: 'class', value: 'copyright-content'},
]
console.log(querySelector(document, selectors))
<div class="mls-info">
<div>
<div class="copyright-content"></div>
</div>
</div>