Obtenir l'élément à l'intérieur de l'élément par classe et ID - JavaScript

136

D'accord, j'ai déjà essayé JavaScript, mais la chose la plus utile que j'ai écrite est un sélecteur de style CSS. Je suis donc un peu nouveau dans ce domaine. Disons que j'ai un code HTML comme celui-ci:

<div id="foo">
    <div class="bar">
        Hello world!
    </div>
</div>

Comment changerais-je "Hello world!" à "Au revoir monde!" ? Je sais comment document.getElementByClass et document.getElementById fonctionnent, mais j'aimerais être plus précis. Désolé si cela a été demandé avant.

Tanner Babcock
la source

Réponses:

232

Eh bien, vous devez d'abord sélectionner les éléments avec une fonction comme getElementById.

var targetDiv = document.getElementById("foo").getElementsByClassName("bar")[0];

getElementByIdne renvoie qu'un seul nœud, mais getElementsByClassNamerenvoie une liste de nœuds. Puisqu'il n'y a qu'un seul élément avec ce nom de classe (pour autant que je sache), vous pouvez simplement obtenir le premier (c'est à cela que [0]sert - c'est comme un tableau).

Ensuite, vous pouvez changer le code HTML avec .textContent.

targetDiv.textContent = "Goodbye world!";

var targetDiv = document.getElementById("foo").getElementsByClassName("bar")[0];
targetDiv.textContent = "Goodbye world!";
<div id="foo">
    <div class="bar">
        Hello world!
    </div>
</div>

Joseph Marikle
la source
1
Obtenir le parent par ID n'est pas nécessaire dans ce cas. document.getElementsByClassNamefonctionnerait très bien.
rvighne
7
@rvighne les exigences exactes d'OP était qu'il "aimerait être plus précis". La personne qui posait la question demandait comment il pouvait être plus précis dans son parcours d'arborescence DOM. L'utilisation de getElementByClassName n'était pas un point de confusion, mais je peux voir comment quelqu'un pourrait facilement penser que j'indiquais les deux comme nécessaires. Ils ne sont pas. Si vous souhaitez cibler uniquement les éléments d'une certaine classe qui se trouvent sous un nœud particulier d'un ID donné par opposition aux éléments de cette même classe sous un nœud différent, c'est ce que vous utiliseriez.
Joseph Marikle
1
Peut - être bon de modifier cette réponse et le changement .innerHtmlà .textContentla prestation de sécurité de copier / coller les codeurs.
codescribblr
14

Vous pouvez le faire comme ceci:

var list = document.getElementById("foo").getElementsByClassName("bar");
if (list && list.length > 0) {
    list[0].innerHTML = "Goodbye world!";
}

ou, si vous voulez le faire avec moins de vérification des erreurs et plus de brièveté, cela peut être fait en une seule ligne comme ceci:

document.getElementById("foo").getElementsByClassName("bar")[0].innerHTML = "Goodbye world!";

En explication:

  1. Vous obtenez l'élément avec id="foo".
  2. Vous trouvez ensuite les objets contenus dans cet objet qui ont class="bar".
  3. Cela renvoie une liste de nœuds de type tableau, vous référencez donc le premier élément de cette liste de nœuds
  4. Vous pouvez ensuite définir le innerHTMLde cet élément pour modifier son contenu.

Avertissements: certains navigateurs plus anciens ne prennent pas en charge getElementsByClassName(par exemple, les anciennes versions d'IE). Cette fonction peut être mise en place en cas d'absence.


C'est là que je recommande d'utiliser une bibliothèque qui prend en charge le sélecteur CSS3 intégré plutôt que de vous soucier de la compatibilité du navigateur vous-même (laissez quelqu'un d'autre faire tout le travail). Si vous voulez juste une bibliothèque pour le faire, alors Sizzle fonctionnera très bien. Dans Sizzle, cela se ferait comme ceci:

Sizzle("#foo .bar")[0].innerHTML = "Goodbye world!";

jQuery a la bibliothèque Sizzle intégrée et dans jQuery, ce serait:

$("#foo .bar").html("Goodbye world!");
jfriend00
la source
Merci, j'avais des problèmes avec document.getElementBy *. jQuery rend les choses tellement plus faciles.
Tanner Babcock
7

Si cela doit fonctionner dans IE 7 ou une version antérieure, vous devez vous rappeler que getElementsByClassName n'existe pas dans tous les navigateurs. Pour cette raison, vous pouvez créer votre propre getElementsByClassName ou vous pouvez essayer ceci.

var fooDiv = document.getElementById("foo");

for (var i = 0, childNode; i <= fooDiv.childNodes.length; i ++) {
    childNode = fooDiv.childNodes[i];
    if (/bar/.test(childNode.className)) {
        childNode.innerHTML = "Goodbye world!";
    }
}
John Hartsock
la source
getElementsByClassNamene fonctionne pas non plus dans IE8, mais vous pouvez l'utiliser querySelectorAllà sa place (à peu près de toute façon).
user113716
@ Ӫ _._ Ӫ ... lol ... vous avez raison, mais vous prouvez encore plus ma réponse. Vous ne pouvez pas compter sur getElementsByClassName si votre page doit fonctionner sur plusieurs navigateurs. jQuery serait certainement une option, mais le code ci-dessus le serait aussi.
John Hartsock
Oui, je voulais dire ce commentaire à l'appui de votre réponse, mais aussi pour souligner qu'il est possible de l'utiliser qSAdans un shim afin que vous puissiez toujours utiliser du code natif dans IE8. Bien que vous examiniez de plus près votre solution, vous avez quelques éléments à corriger.
user113716
@ Ӫ _._ Ӫ ... curieux de savoir ce que vous voyez ... parce que je ne le vois pas.
John Hartsock
var i = 0, var child = fooDiv.childNodes[i]est invalide. i <= fooDiv.childNodesn'a pas vraiment de sens. childNode.className.test("bar")Il n'y a pas de childNodevariable et une chaîne n'a pas de test()méthode.
user113716
4

Fonction récursive:

function getElementInsideElement(baseElement, wantedElementID) {
    var elementToReturn;
    for (var i = 0; i < baseElement.childNodes.length; i++) {
        elementToReturn = baseElement.childNodes[i];
        if (elementToReturn.id == wantedElementID) {
            return elementToReturn;
        } else {
            return getElementInsideElement(elementToReturn, wantedElementID);
        }
    }
}
Avi Shimshilashvili
la source
Il y a un bogue mineur dans l'exemple ci-dessus. Au lieu de retourner instantanément dans le chemin else, vous devez d'abord vérifier si quelque chose a été trouvé. Sinon, les autres nœuds enfants ne seront pas bouclés. Quelque chose comme ceci: if (elementToReturn) {return elementToReturn; }
Jannik
3

La façon la plus simple de le faire est:

function findChild(idOfElement, idOfChild){
  let element = document.getElementById(idOfElement);
  return element.querySelector('[id=' + idOfChild + ']');
}

ou mieux lisible:

findChild = (idOfElement, idOfChild) => {
    let element = document.getElementById(idOfElement);
    return element.querySelector(`[id=${idOfChild}]`);
}
Benjamin Werner
la source
-4

Vous ne devez pas utiliser document.getElementByID car il fonctionne uniquement pour les contrôles côté client dont les identifiants sont corrigés. Vous devriez utiliser jquery à la place comme dans l'exemple ci-dessous.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>                                                                                                             
<div id="foo">
   <div class="bar"> 
          Hello world!
     </div>
</div>

utilisez ceci :

$("[id^='foo']").find("[class^='bar']")

// do not forget to add script tags as above

si vous voulez une opération de suppression de modification, ajoutez simplement "." derrière et faire les opérations

hardik akbari
la source
10
Utiliser une arme thermonucléaire pour tuer un cerf fonctionnera, mais c'est une légère exagération. Utiliser une bibliothèque jQuery multi-kb pour sélectionner un élément lorsque Javascript offre cette fonctionnalité dans son code de base est légèrement plus exagéré.
Danejir