Javascript.querySelector найти <div> по внутреннему ТЕКСТ</div>
Как я могу найти DIV с определенным текстом? Например:
<div>
SomeText, text continues.
</div>
Пытаясь использовать что-то вроде этого:
var text = document.querySelector('div[SomeText*]').innerTEXT;
alert(text);
Но, конечно, это не сработает. Как мне это сделать?
Ответы
Ответ 1
Вопрос OP - это простой JavaScript, а не jQuery. Хотя есть много ответов, и мне нравится @Pawan Nogariya ответ, пожалуйста, проверьте эту альтернативу.
Вы можете использовать XPATH в JavaScript. Подробнее о статье MDN здесь.
Метод document.evaluate()
оценивает запрос/выражение XPATH. Таким образом, вы можете передавать выражения XPATH, переходить в документ HTML и находить нужный элемент.
В XPATH вы можете выбрать элемент, используя текстовый узел, такой как следующий, whch получает div
, у которого есть следующий текстовый узел.
//div[text()="Hello World"]
Чтобы получить элемент, содержащий некоторый текст, используйте следующее:
//div[contains(., 'Hello')]
Метод contains()
в XPATH принимает узел как первый параметр и текст для поиска в качестве второго параметра.
Проверьте это шлепнуть здесь, это пример использования XPATH в JavaScript
Вот фрагмент кода:
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";
Как вы можете видеть, я могу захватить элемент HTML и изменить его, как мне нравится.
Ответ 2
Поскольку вы спросили об этом в javascript, чтобы у вас было что-то вроде этого
function contains(selector, text) {
var elements = document.querySelectorAll(selector);
return Array.prototype.filter.call(elements, function(element){
return RegExp(text).test(element.textContent);
});
}
И тогда назовите это так
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
Ответ 3
Вы можете использовать это довольно простое решение:
Array.from(document.querySelectorAll('div'))
.find(el => el.textContent === 'SomeText, text continues.');
-
Array.from
преобразует NodeList в массив (для этого используются несколько методов, например, оператор спреда или срез)
-
Результат, являющийся теперь массивом, позволяет использовать метод Array.find
, тогда вы можете вставить любой предикат. Вы также можете проверить textContent с регулярным выражением или любым другим, что вам нравится.
Обратите внимание, что Array.from
и Array.find
являются функциями ES2015. Те могут быть совместимы со старыми браузерами, такими как IE10 без транспилятора:
Array.prototype.slice.call(document.querySelectorAll('div'))
.filter(function (el) {
return el.textContent === 'SomeText, text continues.'
})[0];
Ответ 4
Это решение делает следующее:
-
Использует оператор распространения ES6 для преобразования NodeList всех div
в массив.
-
Предоставляет вывод, если div
содержит строку запроса, а не только если она точно равна строке запроса (что происходит для некоторых других ответов). Например, он должен предоставлять вывод не только для "SomeText", но также для "SomeText, текст продолжается".
-
Выводит все содержимое div
, а не только строку запроса. например, для "SomeText, text continue" он должен выводить целую строку, а не только "SomeText".
-
Позволяет нескольким div
содержать строку, а не только один 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>
Ответ 5
Лучше всего посмотреть, есть ли у вас родительский элемент div, который вы запрашиваете. Если так, получите родительский элемент и выполните элемент element.querySelectorAll("div")
. Как только вы получите nodeList
применить фильтр на нем по свойству innerText
. Предположим, что родительский элемент div, который мы запрашиваем, имеет id
container
. Обычно вы можете напрямую обращаться к контейнеру с идентификатора, но пусть это делает правильный путь.
var conty = document.getElementById("container"),
divs = conty.querySelectorAll("div"),
myDiv = [...divs].filter(e => e.innerText == "SomeText");
Так что это.
Ответ 6
Если вы не хотите использовать 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]
}
Когда у вас есть узлы в массиве, содержащие текст, вы можете что-то с ними делать. Как предупреждать каждого или печатать на консоль. Одно из предостережений состоит в том, что это может не обязательно захватить divs как таковое, это захватит родительский элемент текстового блока, который имеет текст, который вы ищете.
Ответ 7
В Google это лучший результат для тех, кому нужно найти узел с определенным текстом. В результате обновления ноделист теперь можно выполнять в современных браузерах без необходимости его преобразования в массив.
Решение может использовать 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
}
});
Это помогло мне найти текст поиска/замены внутри нодлиста, когда обычный селектор не мог выбрать только один узел, поэтому мне пришлось фильтровать каждый узел один за другим, чтобы проверить его на иглу.
Ответ 8
Используйте XPath и document.evaluate(), и обязательно используйте text(), а не. для аргумента contains(), иначе у вас будет весь HTML-код или внешний элемент div.
var headings = document.evaluate("//h1[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
или игнорировать начальные и конечные пробелы
var headings = document.evaluate("//h1[contains(normalize-space(text()), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
или соответствуют всем типам тегов (div, h1, p и т.д.)
var headings = document.evaluate("//*[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
Затем повторить
let thisHeading;
while(thisHeading = headings.iterateNext()){
// thisHeading contains matched node
}
Ответ 9
Здесь подход XPath, но с минимальным жаргоном XPath.
Регулярный выбор на основе значений атрибутов элемента (для сравнения):
// 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 на основе текста внутри элемента.
// 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';
}
А вот с учетом регистра, так как текст более изменчив:
// 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';
}