web-dev-qa-db-fra.com

Javascript .querySelector trouver <div> par innerTEXT

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?

58
passwd

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.

58
gdyrrahitis

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
28
Pawan Nogariya

Vous pouvez utiliser cette solution assez simple:

Array.from(document.querySelectorAll('div'))
  .find(el => el.textContent === 'SomeText, text continues.');
  1. 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).

  2. 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];
24
Niels

Cette solution a les effets suivants:

  • Utilise l'opérateur de propagation ES6 pour convertir la liste de noeuds de tous les divs en un tableau.

  • Fournit une sortie si divcontient 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 divs 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>
10
Andrew Willems

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.

5
Redu

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.

3
Steve Botello

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.

0
Vigilante

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
}
0
Steven Spungin

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';
}
0
Jan Kyu Peblik