Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

document.querySelector via textContent

Tags:

javascript

dom

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();
    }
});
like image 953
user8551674 Avatar asked Sep 07 '17 02:09

user8551674


People also ask

How do you document querySelector?

The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.

What can I use instead of document querySelector?

The other alternative is element. query / queryAll . These are alternative methods to querySelector and querySelectorAll that exist on DOM parent nodes. They also take selectors, except these selectors are interpreted relative to the element being queried from.

How do I get text content of an element?

To find elements by content: Use the document. querySelectorAll method to select DOM elements by tag. Use the for...of loop to iterate over the collection. On each iteration, check if the textContent of the element matches the expected content.

Can I use document querySelector in angular?

querySelector() Function in AngularJS. While the document. getElementById function targets a specific id, the document. querySelector() function targets the CSS elements in a web page, for instance the a and p tags in the HTML.


1 Answers

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 -->
like image 163
Kaiido Avatar answered Sep 30 '22 04:09

Kaiido