HervéRenault.fr

Logo non-officiel de JavaScript

Exemple de XPath en JavaScript

J'ai un vieux tableau dans lequel j'aimerais cocher les cases de toutes les lignes qui ont un lien qui commence par 2021 :

Illustration du vieux tableau

Ce n'est pas possible simplement avec document.querySelectorAll. Voici le code JS simplifié qui utilise XPath en partant du principe que rien d'autre ne va modifier la page pendant son exécution :

var iterateur = document.evaluate("//td/a[starts-with(., '2021')]/../preceding-sibling::td/input", document);

var nœud = iterateur.iterateNext();

while (nœud) {
  nœud.checked = true;

  nœud = iterateur.iterateNext();
}

Mais si je veux aussi au passage mettre sur fond vert tous les liens qui commencent par 2021, je modifie le document et ça lance une exception :
DOMException: XPathResult.iterateNext: The document has been mutated since the result was returned

var iterateur = document.evaluate("//td/a[starts-with(., '2021')]", document);

var nœud = iterateur.iterateNext();

while (nœud) {
  nœud.style = 'background: limegreen';

  var ite2 = document.evaluate("../preceding-sibling::td/input", nœud);
  var n2 = ite2.iterateNext();

  n2.checked = true;

  nœud = iterateur.iterateNext();
}
            

Dans ce cas, il faut que je demande un cliché (snapshot) du DOM :

var cliché = document.evaluate("//td/a[starts-with(., '2021')]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);

for (var i = 0; i < cliché.snapshotLength; i++) {
  var nœud = cliché.snapshotItem(i);

  nœud.style = 'background: limegreen';

  var itérateur = document.evaluate("../preceding-sibling::td/input", nœud);
  var n2 = itérateur.iterateNext();

  n2.checked = true;
}
MDN