Obter elemento dentro do elemento por classe e ID - JavaScript

136

Tudo bem, eu já me envolvi com JavaScript antes, mas a coisa mais útil que escrevi é um alternador de estilos CSS. Então, sou um pouco novo nisso. Digamos que eu tenha código HTML como este:

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

Como eu mudaria "Olá, mundo!" para "adeus mundo!" ? Eu sei como document.getElementByClass e document.getElementById funcionam, mas gostaria de ser mais específico. Desculpe se isso foi perguntado antes.

Tanner Babcock
fonte

Respostas:

232

Bem, primeiro você precisa selecionar os elementos com uma função como getElementById.

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

getElementByIdretorna apenas um nó, mas getElementsByClassNameretorna uma lista de nós. Como existe apenas um elemento com esse nome de classe (até onde eu sei), você pode obter o primeiro ( [0]é para isso que serve - é como uma matriz).

Em seguida, você pode alterar o html com .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
fonte
1
Obter o pai por ID não é necessário neste caso. document.getElementsByClassNamefuncionaria bem.
rvighne
7
@rvighne os requisitos exatos do OP eram que ele "gostaria de ser mais específico". A pessoa que estava fazendo a pergunta estava perguntando como poderia ser mais específico em sua travessia na árvore DOM. O uso de getElementByClassName não foi um ponto de confusão, mas posso ver como alguém pode facilmente pensar que eu estava indicando os dois como necessário. Eles não são. Se você deseja direcionar apenas elementos de uma determinada classe que estejam sob um nó específico de um determinado ID, em vez de elementos dessa mesma classe em um nó diferente, é isso que você usaria.
Joseph Marikle
1
Pode ser bom para editar esta resposta e mudança .innerHtmlpara .textContentpara o benefício de cópia de segurança / colar codificadores.
codescribblr
14

Você pode fazer assim:

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

ou, se você quiser fazer isso com menos verificação de erro e mais brevidade, isso pode ser feito em uma linha como esta:

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

Na explicação:

  1. Você pega o elemento id="foo".
  2. Você encontra os objetos que estão contidos nesse objeto class="bar".
  3. Isso retorna um nodeList do tipo matriz, para que você faça referência ao primeiro item nesse nodeList
  4. Em seguida, você pode definir o innerHTMLitem para alterar seu conteúdo.

Advertências: alguns navegadores mais antigos não suportam getElementsByClassName(por exemplo, versões mais antigas do IE). Essa função pode ser ajustada no lugar, se estiver faltando.


É aqui que eu recomendo o uso de uma biblioteca que tenha suporte ao seletor CSS3 embutido, em vez de se preocupar com a compatibilidade do navegador (deixe outra pessoa fazer todo o trabalho). Se você quiser apenas uma biblioteca para fazer isso, o Sizzle funcionará muito bem. No Sizzle, isso seria feito assim:

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

O jQuery possui a biblioteca Sizzle integrada e no jQuery, seria:

$("#foo .bar").html("Goodbye world!");
jfriend00
fonte
Obrigado, eu estava tendo problemas com document.getElementBy *. O jQuery facilita muito as coisas.
Tanner Babcock
7

Se isso funcionar no IE 7 ou inferior, lembre-se de que getElementsByClassName não existe em todos os navegadores. Por isso, você pode criar seu próprio getElementsByClassName ou pode tentar isso.

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
fonte
getElementsByClassNametambém não funciona no IE8, mas você pode usá-lo querySelectorAllem seu lugar (praticamente de qualquer maneira).
user113716
@ Ӫ _._ Ӫ ... lol ... você está correto, mas você acabou de provar minha resposta ainda mais. Você não pode confiar em getElementsByClassName se sua página precisar funcionar em vários navegadores. O jQuery seria definitivamente uma opção, mas também o código acima.
John Hartsock
Sim, eu quis dizer esse comentário em apoio à sua resposta, mas também ressalte que é possível usar qSAum shim para que você ainda possa usar código nativo no IE8. Embora dê uma olhada mais de perto na sua solução, você precisa corrigir algumas coisas.
user113716
@ Ӫ _._ Ӫ ... curioso o que você vê ... porque eu não estou vendo.
John Hartsock
var i = 0, var child = fooDiv.childNodes[i]é inválido. i <= fooDiv.childNodesrealmente não faz sentido. childNode.className.test("bar")Não há childNodevariável e uma string não possui um test()método.
user113716
4

Função 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
fonte
Há um pequeno erro na amostra acima. Em vez de retornar instantaneamente no caminho else, você deve verificar se algo foi encontrado primeiro. Caso contrário, os outros nós filhos não serão repetidos. Algo assim: if (elementToReturn) {return elementToReturn; }
Jannik
3

A maneira mais fácil de fazer isso é:

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

ou melhor legível:

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

Você não deve usar document.getElementByID porque seu trabalho apenas para o lado do cliente controla quais IDs são corrigidos. Você deve usar o jquery como no exemplo abaixo.

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

usa isto :

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

// do not forget to add script tags as above

se você quiser remover, editar qualquer operação, basta adicionar "." por trás e fazer as operações

hardik akbari
fonte
10
Usar uma arma termonuclear para matar um cervo funcionará, mas é um leve exagero. O uso de uma biblioteca jQuery de vários kb para selecionar um elemento quando o Javascript oferece essa funcionalidade em seu código base é um pouco mais exagerado.
Danejir 25/07/16