Obtener elemento dentro de elemento por clase e ID - JavaScript

136

Muy bien, he incursionado en JavaScript antes, pero lo más útil que he escrito es un conmutador de estilo CSS. Así que soy algo nuevo en esto. Digamos que tengo un código HTML como este:

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

¿Cómo cambiaría "Hola mundo!" a "¡Adiós mundo!" ? Sé cómo funcionan document.getElementByClass y document.getElementById, pero me gustaría ser más específico. Lo siento si esto se ha preguntado antes.

Tanner Babcock
fuente

Respuestas:

232

Bueno, primero debes seleccionar los elementos con una función como getElementById.

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

getElementByIdsolo devuelve un nodo, pero getElementsByClassNamedevuelve una lista de nodos. Dado que solo hay un elemento con ese nombre de clase (por lo que puedo decir), puede obtener el primero ( [0]para eso es, es como una matriz).

Luego, puede cambiar el html con .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
fuente
1
Obtener el padre por ID no es necesario en este caso. document.getElementsByClassNamefuncionaría bien
rvighne
77
@rvighne los requisitos exactos de OP era que "le gustaría ser más específico". La persona que hizo la pregunta preguntaba cómo podría ser más específico en su recorrido del árbol DOM. El uso de getElementByClassName no fue un punto de confusión, pero puedo ver cómo alguien podría pensar fácilmente que estaba indicando ambos, según sea necesario. Ellos no son. Si desea apuntar solo a elementos de una determinada clase que se encuentran bajo un nodo particular de una ID determinada en lugar de elementos de esa misma clase bajo un nodo diferente, esto es lo que usaría.
Joseph Marikle
1
Puede ser bueno para editar esta respuesta y el cambio .innerHtmlde .textContentla prestación de la seguridad de copiar / pegar codificadores.
codescribblr
14

Puedes hacerlo así:

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

o, si desea hacerlo con menos verificación de errores y más brevedad, puede hacerlo en una línea como esta:

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

En explicación:

  1. Obtienes el elemento con id="foo".
  2. Luego encontrará los objetos que están contenidos dentro de ese objeto que tienen class="bar".
  3. Eso devuelve una lista de nodos similar a una matriz, por lo que hace referencia al primer elemento en esa lista de nodos
  4. Luego puede configurar el innerHTMLelemento de ese elemento para cambiar su contenido.

Advertencias: algunos navegadores antiguos no son compatibles getElementsByClassName(por ejemplo, versiones anteriores de IE). Esa función puede ajustarse en su lugar si falta.


Aquí es donde recomiendo usar una biblioteca que tenga compatibilidad con el selector CSS3 incorporado en lugar de preocuparse por la compatibilidad del navegador (deje que alguien más haga todo el trabajo). Si desea que solo una biblioteca haga eso, Sizzle funcionará de maravilla. En Sizzle, esto se haría así:

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

jQuery tiene la biblioteca Sizzle incorporada y en jQuery, esto sería:

$("#foo .bar").html("Goodbye world!");
jfriend00
fuente
Gracias, estaba teniendo problemas con document.getElementBy *. jQuery hace las cosas mucho más fáciles.
Tanner Babcock
7

Si esto necesita funcionar en IE 7 o inferior, debe recordar que getElementsByClassName no existe en todos los navegadores. Debido a esto, puede crear su propio getElementsByClassName o puede probar esto.

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
fuente
getElementsByClassNametampoco funciona en IE8, pero puede usarlo querySelectorAllen su lugar (más o menos de todos modos).
usuario113716
@ Ӫ _._ Ӫ ... jajaja ... estás en lo correcto pero solo pruebas mi respuesta aún más. No puede confiar en getElementsByClassName si su página necesita funcionar en varios navegadores. jQuery definitivamente sería una opción, pero también lo debería ser el código anterior.
John Hartsock
Sí, quise decir ese comentario en apoyo de su respuesta, pero también para señalar que es posible usarlo qSAen una cuña para que aún pueda usar código nativo en IE8. Si bien echa un vistazo más de cerca a su solución, tiene algunas cosas que deben corregirse.
user113716
@ Ӫ _._ Ӫ ... curioso qué ves ... porque no lo estoy viendo.
John Hartsock
var i = 0, var child = fooDiv.childNodes[i]no es válido. i <= fooDiv.childNodesRealmente no tiene sentido. childNode.className.test("bar")No hay childNodevariable, y una cadena no tiene un test()método.
user113716
4

Función recursiva :

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
fuente
Hay un error menor en el ejemplo anterior. En lugar de regresar instantáneamente en la ruta else, debe verificar si se encontró algo primero. De lo contrario, los otros nodos secundarios no se enlazarán. Algo como esto: if (elementToReturn) {return elementToReturn; }
Jannik
3

La forma más fácil de hacerlo es:

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

o mejor legible:

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

No debe usar document.getElementByID porque solo funciona para el lado del cliente que controla qué identificadores son fijos. Debería usar jquery en su lugar como el siguiente ejemplo.

<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>

utilizar este :

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

// do not forget to add script tags as above

si desea eliminar, editar cualquier operación, simplemente agregue "." detrás y hacer las operaciones

hardik akbari
fuente
10
Usar un arma termonuclear para matar un venado funcionará, pero es una exageración leve. Usar una biblioteca jQuery de varios kb para seleccionar un elemento cuando Javascript ofrece esa funcionalidad en su código base es un poco más exagerado.
Danejir