admin管理员组

文章数量:1289876

Is it possible in JS to select the first element whatsoever with document.querySelector solely by a given textDocument, if the that textDocument is available on viewport when the code is executed?


I am looking for a way without the following code because it brings out all relevant tagNames and filters them via textContent, but I want to select them by text content, not to filter.

document.querySelectorAll('tagName').forEach( (e)=>{
    if (e.textContent.includes('Delete')) {
        e.click();
    }
});

Is it possible in JS to select the first element whatsoever with document.querySelector solely by a given textDocument, if the that textDocument is available on viewport when the code is executed?


I am looking for a way without the following code because it brings out all relevant tagNames and filters them via textContent, but I want to select them by text content, not to filter.

document.querySelectorAll('tagName').forEach( (e)=>{
    if (e.textContent.includes('Delete')) {
        e.click();
    }
});
Share Improve this question edited Sep 7, 2017 at 2:53 user8551674 asked Sep 7, 2017 at 2:25 user8551674user8551674 1831 gold badge2 silver badges14 bronze badges 2
  • Are you just wanting to write shorter code, like $("tagName:contains(Delete)").click() in jQuery, or are you concerned about performance when filtering by content yourself? (I would think even if .querySelectorAll() directly supported this behind the scenes it would still need to iterate over all the elements of the specified type.) – nnnnnn Commented Sep 7, 2017 at 2:57
  • Hmm, I just want JS to make a search like I do with CTRL+F and use the first element with the exact textContent it supplied, and then work with it... If it is being done, I couldn't care less from code longevity or performance. :) – user8551674 Commented Sep 7, 2017 at 3:10
Add a ment  | 

2 Answers 2

Reset to default 5

There is no CSS selector targeting on textContent.

Also, as your code is currently written, it's quite easy to grab the first element which textContent includes this string, it will always be document.documentElement or null.

You should make your query a bit more strict.

You could probably build an XPath query to this very extent, but that would end up slower than iterating over all the nodes by yourself.

So if performance is an issue, a TreeWalker is the way to go.

Here is a function that will grab elements by textContent.
It has different optional arguments which will allow you to tell

  • if the query should be strict ("string === textContent" which is the default),
  • a node to start the search from (defaults to document.documentElement)
  • if you are only interested in the elements without children

function getElementByTextContent(str, partial, parentNode, onlyLast) {
  var filter = function(elem) {
    var isLast = onlyLast ? !elem.children.length : true;
    var contains = partial ? elem.textContent.indexOf(str) > -1 :
      elem.textContent === str;
    if (isLast && contains)
      return NodeFilter.FILTER_ACCEPT;
  };
  filter.acceptNode = filter; // for IE
  var treeWalker = document.createTreeWalker(
    parentNode || document.documentElement,
    NodeFilter.SHOW_ELEMENT, {
      acceptNode: filter
    },
    false
  );
  var nodeList = [];
  while (treeWalker.nextNode()) nodeList.push(treeWalker.currentNode);
  return nodeList;
}
// only the elements whose textContent is exactly the string
console.log('strict', getElementByTextContent('This should be found'))
// all elements whose textContent contain the string (your code)
console.log('partial', getElementByTextContent('This should', true))
// only the elements whose textContent is exactly the string and which are the last Element of the tree
console.log('strict onlyLast', getElementByTextContent('This should be found', false, null, true))
<p><span>This should be found</span></p>
<span>This should only in partial mode</span><br>
<span>This must not be found</span>
<!-- p should not be found in onlyLast mode -->

No, there is not. document.querySelector can only accept a string argument that describes one or more CSS selectors separated by mas. You cannot provide document.querySelector a textDocument.

You will have to check the content of a node different, with one way being the way you've described in the question.

本文标签: javascriptdocumentquerySelector via textContentStack Overflow