Javascript .querySelector 通过innerTEXT查找<div>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37098405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript .querySelector find <div> by innerTEXT
提问by passwd
How can I find DIV with certain text? For example:
如何找到带有特定文本的 DIV?例如:
<div>
SomeText, text continues.
</div>
Trying to use something like this:
尝试使用这样的东西:
var text = document.querySelector('div[SomeText*]').innerTEXT;
alert(text);
But ofcourse it will not work. How can I do it?
但当然它不会工作。我该怎么做?
采纳答案by gdyrrahitis
OP's question is about plain JavaScriptand not jQuery. Although there are plenty of answers and I like @Pawan Nogariya answer, please check this alternative out.
OP 的问题是关于纯JavaScript而不是jQuery。尽管有很多答案并且我喜欢@Pawan Nogariya 的答案,但请查看此替代方案。
You can use XPATHin JavaScript. More info on the MDN article here.
您可以在 JavaScript 中使用XPATH。有关 MDN 文章的更多信息,请访问此处。
The document.evaluate()
method evaluates an XPATH query/expression. So you can pass XPATH expressions there, traverse into the HTML document and locate the desired element.
该document.evaluate()
方法评估 XPATH 查询/表达式。因此,您可以在那里传递 XPATH 表达式,遍历 HTML 文档并找到所需的元素。
In XPATH you can select an element, by the text node like the following, whch gets the div
that has the following text node.
在 XPATH 中,您可以通过如下所示的文本节点选择一个元素,获取div
具有以下文本节点的元素。
//div[text()="Hello World"]
To get an element that contains some text use the following:
要获取包含一些文本的元素,请使用以下命令:
//div[contains(., 'Hello')]
The contains()
method in XPATH takes a node as first parameter and the text to search for as second parameter.
contains()
XPATH 中的方法将节点作为第一个参数,将要搜索的文本作为第二个参数。
Check this plunk here, this is an example use of XPATH in JavaScript
在此处检查此 plunk ,这是在 JavaScript 中使用 XPATH 的示例
Here is a code snippet:
这是一个代码片段:
var headings = document.evaluate("//h1[contains(., 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
var thisHeading = headings.iterateNext();
console.log(thisHeading); // Prints the html element in console
console.log(thisHeading.textContent); // prints the text content in console
thisHeading.innerHTML += "<br />Modified contents";
As you can see, I can grab the HTML element and modify it as I like.
如您所见,我可以抓取 HTML 元素并根据需要对其进行修改。
回答by Niels
You could use this pretty simple solution:
您可以使用这个非常简单的解决方案:
Array.from(document.querySelectorAll('div'))
.find(el => el.textContent === 'SomeText, text continues.');
The
Array.from
will convert the NodeList to an array (there are multiple methods to do this like the spread operator or slice)The result now being an array allows for using the
Array.find
method, you can then put in any predicate. You could also check the textContent with a regex or whatever you like.
在
Array.from
将节点列表转换为数组(有多种方法来做到这一点,如传播经营者或切片)结果现在是一个数组,允许使用该
Array.find
方法,然后您可以放入任何谓词。您还可以使用正则表达式或您喜欢的任何内容检查 textContent。
Note that Array.from
and Array.find
are ES2015 features. Te be compatible with older browsers like IE10 without a transpiler:
请注意,Array.from
和Array.find
是 ES2015 的特性。无需转译器即可与较旧的浏览器(如 IE10)兼容:
Array.prototype.slice.call(document.querySelectorAll('div'))
.filter(function (el) {
return el.textContent === 'SomeText, text continues.'
})[0];
回答by Pawan Nogariya
Since you have asked it in javascript so you can have something like this
既然你已经在 javascript 中问过了,所以你可以有这样的东西
function contains(selector, text) {
var elements = document.querySelectorAll(selector);
return Array.prototype.filter.call(elements, function(element){
return RegExp(text).test(element.textContent);
});
}
And then call it like this
然后这样称呼
contains('div', 'sometext'); // find "div" that contain "sometext"
contains('div', /^sometext/); // find "div" that start with "sometext"
contains('div', /sometext$/i); // find "div" that end with "sometext", case-insensitive
回答by Andrew Willems
This solution does the following:
此解决方案执行以下操作:
Uses the ES6 spread operator to convert the NodeList of all
div
s to an array.Provides output if the
div
containsthe query string, not just if it exactly equalsthe query string (which happens for some of the other answers). e.g. It should provide output not just for 'SomeText' but also for 'SomeText, text continues'.Outputs the entire
div
contents, not just the query string. e.g. For 'SomeText, text continues' it should output that whole string, not just 'SomeText'.Allows for multiple
div
s to contain the string, not just a singlediv
.
使用 ES6 扩展运算符将所有
div
s的 NodeList 转换为数组。如果
div
包含查询字符串,而不仅仅是它完全等于查询字符串(其他一些答案会发生这种情况),则提供输出。例如,它不仅应该为“SomeText”提供输出,还应该为“SomeText,文本继续”提供输出。输出全部
div
内容,而不仅仅是查询字符串。例如,对于“SomeText,文本继续”,它应该输出整个字符串,而不仅仅是“SomeText”。允许多个
div
s 包含字符串,而不仅仅是单个div
.
[...document.querySelectorAll('div')] // get all the divs in an array
.map(div => div.innerHTML) // get their contents
.filter(txt => txt.includes('SomeText')) // keep only those containing the query
.forEach(txt => console.log(txt)); // output the entire contents of those
<div>SomeText, text continues.</div>
<div>Not in this div.</div>
<div>Here is more SomeText.</div>
回答by Redu
You best see if you have a parent element of the div you are querying. If so get the parent element and perform an element.querySelectorAll("div")
. Once you get the nodeList
apply a filter on it over the innerText
property. Assume that a parent element of the div that we are querying has an id
of container
. You can normally access container directly from the id but let's do it the proper way.
您最好查看是否有要查询的 div 的父元素。如果是这样,获取父元素并执行element.querySelectorAll("div")
. 一旦你nodeList
在innerText
属性上应用了一个过滤器。假设我们正在查询的 div 的父元素有一个id
of container
。您通常可以直接从 id 访问容器,但让我们以正确的方式进行。
var conty = document.getElementById("container"),
divs = conty.querySelectorAll("div"),
myDiv = [...divs].filter(e => e.innerText == "SomeText");
So that's it.
就是这样了。
回答by Steve Botello
If you don't want to use jquery or something like that then you can try this:
如果你不想使用 jquery 或类似的东西,那么你可以试试这个:
function findByText(rootElement, text){
var filter = {
acceptNode: function(node){
// look for nodes that are text_nodes and include the following string.
if(node.nodeType === document.TEXT_NODE && node.nodeValue.includes(text)){
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_REJECT;
}
}
var nodes = [];
var walker = document.createTreeWalker(rootElement, NodeFilter.SHOW_TEXT, filter, false);
while(walker.nextNode()){
//give me the element containing the node
nodes.push(walker.currentNode.parentNode);
}
return nodes;
}
//call it like
var nodes = findByText(document.body,'SomeText');
//then do what you will with nodes[];
for(var i = 0; i < nodes.length; i++){
//do something with nodes[i]
}
Once you have the nodes in an array that contain the text you can do something with them. Like alert each one or print to console. One caveat is that this may not necessarily grab divs per se, this will grab the parent of the textnode that has the text you are looking for.
一旦您在包含文本的数组中拥有节点,您就可以对它们做一些事情。就像提醒每个人或打印到控制台一样。一个警告是,这本身可能不一定会抓取 div,这将抓取具有您正在查找的文本的 textnode 的父级。
回答by Vigilante
Google has this as a top result for For those who need to find a node with certain text. By way of update, a nodelist is now iterable in modern browsers without having to convert it to an array.
对于需要查找具有特定文本的节点的人,Google 将此作为最佳结果。通过更新,节点列表现在可以在现代浏览器中迭代,而无需将其转换为数组。
The solution can use forEach like so.
解决方案可以像这样使用 forEach 。
var elList = document.querySelectorAll(".some .selector");
elList.forEach(function(el) {
if (el.innerHTML.indexOf("needle") !== -1) {
// Do what you like with el
// The needle is case sensitive
}
});
This worked for me to do a find/replace text inside a nodelist when a normal selector could not choose just one node so I had to filter each node one by one to check it for the needle.
当普通选择器无法仅选择一个节点时,这对我在节点列表中执行查找/替换文本很有用,因此我必须逐个过滤每个节点以检查它是否有针。
回答by Steven Spungin
Use XPath and document.evaluate(), and make sure to use text() and not . for the contains() argument, or else you will have the entire HTML, or outermost div element matched.
使用 XPath 和 document.evaluate(),并确保使用 text() 而不是 。对于 contains() 参数,否则您将匹配整个 HTML 或最外面的 div 元素。
var headings = document.evaluate("//h1[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
or ignore leading and trailing whitespace
或忽略前导和尾随空格
var headings = document.evaluate("//h1[contains(normalize-space(text()), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
or match all tag types (div, h1, p, etc.)
或匹配所有标签类型(div、h1、p 等)
var headings = document.evaluate("//*[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
Then iterate
然后迭代
let thisHeading;
while(thisHeading = headings.iterateNext()){
// thisHeading contains matched node
}
回答by Jan Kyu Peblik
Here's the XPath approach but with a minimum of XPath jargon.
这是 XPath 方法,但使用了最少的 XPath 术语。
Regular selection based on element attribute values (for comparison):
基于元素属性值的常规选择(用于比较):
// for matching <element class="foo bar baz">...</element> by 'bar'
var things = document.querySelectorAll('[class*="bar"]');
for (var i = 0; i < things.length; i++) {
things[i].style.outline = '1px solid red';
}
XPath selection based on text within element.
基于元素内文本的 XPath 选择。
// for matching <element>foo bar baz</element> by 'bar'
var things = document.evaluate('//*[contains(text(),"bar")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < things.snapshotLength; i++) {
things.snapshotItem(i).style.outline = '1px solid red';
}
And here's with case-insensitivity since text is more volatile:
这里不区分大小写,因为文本更不稳定:
// for matching <element>foo bar baz</element> by 'bar' case-insensitively
var things = document.evaluate('//*[contains(translate(text(),"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz"),"bar")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < things.snapshotLength; i++) {
things.snapshotItem(i).style.outline = '1px solid red';
}
回答by Pawe? Zieliński
I had similar problem.
我有类似的问题。
Function that return all element which include text from arg.
返回包含来自 arg 的文本的所有元素的函数。
This works for me:
这对我有用:
function getElementsByText(document, str, tag = '*') {
return [...document.querySelectorAll(tag)]
.filter(
el => (el.text && el.text.includes(str))
|| (el.children.length === 0 && el.outerText && el.outerText.includes(str)))
}
}