Comment trouver DIV avec certains textes? Par exemple:
<div>
SomeText, text continues.
</div>
Essayer d'utiliser quelque chose comme ça:
var text = document.querySelector('div[SomeText*]').innerTEXT;
alert(text);
Mais bien sûr, cela ne fonctionnera pas. Comment puis-je le faire?
La question d'OP concerne Plain JavaScript et non jQuery. Bien qu'il y ait beaucoup de réponses et que j'aime bien la réponse de @Pawan Nogariya, consultez cette alternative.
Vous pouvez utiliser XPATH en JavaScript. Plus d'infos sur l'article de MDN ici .
La méthode document.evaluate()
évalue une requête/expression XPATH. Ainsi, vous pouvez y passer des expressions XPATH, parcourir le document HTML et localiser l’élément souhaité.
Dans XPATH, vous pouvez sélectionner un élément, par le nœud de texte, comme ci-dessous, qui obtient le div
comportant le nœud de texte suivant.
//div[text()="Hello World"]
Pour obtenir un élément contenant du texte, utilisez ce qui suit:
//div[contains(., 'Hello')]
La méthode contains()
dans XPATH prend un nœud comme premier paramètre et le texte à rechercher comme deuxième paramètre.
Cochez cette case ici , ceci est un exemple d'utilisation de XPATH en JavaScript
Voici un extrait de code:
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";
Comme vous pouvez le constater, je peux récupérer l’élément HTML et le modifier à ma guise.
Puisque tu l'as demandé en javascript, tu peux avoir quelque chose comme ça
function contains(selector, text) {
var elements = document.querySelectorAll(selector);
return Array.prototype.filter.call(elements, function(element){
return RegExp(text).test(element.textContent);
});
}
Et puis appelez comme ça
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
Vous pouvez utiliser cette solution assez simple:
Array.from(document.querySelectorAll('div'))
.find(el => el.textContent === 'SomeText, text continues.');
Le Array.from
convertira la liste de noeuds en un tableau (plusieurs méthodes permettent d'effectuer cette opération, comme l'opérateur ou la tranche étendue).
Le résultat étant maintenant un tableau, vous pouvez utiliser la méthode Array.find
, vous pouvez ensuite insérer n'importe quel prédicat. Vous pouvez également consulter textContent avec une expression régulière ou celle que vous préférez.
Notez que Array.from
et Array.find
sont des fonctionnalités ES2015. Pour être compatible avec les anciens navigateurs comme IE10 sans transpiler:
Array.prototype.slice.call(document.querySelectorAll('div'))
.filter(function (el) {
return el.textContent === 'SomeText, text continues.'
})[0];
Cette solution a les effets suivants:
Utilise l'opérateur de propagation ES6 pour convertir la liste de noeuds de tous les div
s en un tableau.
Fournit une sortie si div
contient la chaîne de requête, et pas seulement si elle est exactement égale la chaîne de requête (ce qui se produit pour certaines des autres réponses). par exemple. Il devrait fournir une sortie non seulement pour 'SomeText' mais également pour 'SomeText, text continue'.
Affiche tout le contenu de div
, pas seulement la chaîne de requête. par exemple. Pour 'SomeText, text continue', il convient de générer l'ensemble de la chaîne, et pas seulement 'SomeText'.
Permet à plusieurs div
s de contenir la chaîne, pas à un seul 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>
Vous feriez mieux de voir si vous avez un élément parent de la div que vous interrogez. Si c'est le cas, récupérez l'élément parent et effectuez une element.querySelectorAll("div")
. Une fois que vous avez obtenu la nodeList
, appliquez un filtre sur la propriété innerText
. Supposons qu'un élément parent de la div que nous interrogeons ait un id
sur container
. Vous pouvez normalement accéder au conteneur directement à partir de l'id, mais procédons correctement.
var conty = document.getElementById("container"),
divs = conty.querySelectorAll("div"),
myDiv = [...divs].filter(e => e.innerText == "SomeText");
Alors c'est tout.
Si vous ne voulez pas utiliser jquery ou quelque chose comme ça, essayez ceci:
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]
}
Une fois que vous avez les nœuds dans un tableau contenant le texte, vous pouvez faire quelque chose avec eux. Comme alerte chacun ou imprimer sur console. Un inconvénient est que cela ne saisira pas nécessairement les divs en soi, mais que le parent du textnode qui contient le texte que vous recherchez sera saisi.
Google en fait l’un des meilleurs résultats pour ceux qui ont besoin de trouver un nœud avec un texte spécifique. En guise de mise à jour, une liste de nœuds est maintenant éditable dans les navigateurs modernes sans qu'il soit nécessaire de la convertir en tableau.
La solution peut utiliser forEach comme si.
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
}
});
Cela a fonctionné pour moi de faire un texte de recherche/remplacement à l'intérieur d'une liste de noeuds lorsqu'un sélecteur normal ne pouvait pas choisir un seul nœud, donc je devais filtrer chaque nœud un par un pour le vérifier pour l'aiguille.
Utilisez XPath et document.evaluate (), et assurez-vous d'utiliser text () et non. pour l'argument includes (), sinon vous aurez tout le code HTML, ou l'élément div le plus externe correspondant.
var headings = document.evaluate("//h1[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
ou ignorer les espaces de début et de fin
var headings = document.evaluate("//h1[contains(normalize-space(text()), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
ou correspondre à tous les types de balises (div, h1, p, etc.)
var headings = document.evaluate("//*[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
Puis itérer
let thisHeading;
while(thisHeading = headings.iterateNext()){
// thisHeading contains matched node
}
Voici l'approche XPath mais avec un minimum de jargon XPath.
Sélection régulière basée sur les valeurs d'attribut d'élément (pour comparaison):
// 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';
}
Sélection XPath basée sur le texte dans l'élément.
// 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';
}
Et voici avec insensible à la casse puisque le texte est plus 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';
}