Eu sou capaz de fazer isso:
<div id="myDiv">
<div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");
Ou seja, posso recuperar com êxito todos os filhos diretos do myDiv
elemento que possuem classe .foo
.
O problema é que me incomoda que eu deva incluir o #myDiv
no seletor, porque estou executando a consulta no myDiv
elemento (por isso é obviamente redundante).
Eu deveria ser capaz de deixar o #myDiv
desligado, mas o seletor não é uma sintaxe válida, pois começa com a >
.
Alguém sabe escrever um seletor que obtém apenas os filhos diretos do elemento em que o seletor está sendo executado?
javascript
dom
css-selectors
Mattsh
fonte
fonte
Respostas:
Boa pergunta. Na época em que foi perguntado, não existia uma maneira universalmente implementada de fazer "consultas com raiz de combinador" (como John Resig as chamou ).
Agora a pseudoclasse: scope foi introduzida. Não é compatível com versões [pré-Chrominum] do Edge ou IE, mas já é compatível com o Safari há alguns anos. Usando isso, seu código pode se tornar:
Observe que, em alguns casos, você também pode ignorar
.querySelectorAll
e usar outros bons e antigos recursos da API DOM. Por exemplo, em vez demyDiv.querySelectorAll(":scope > *")
você pode apenas escrevermyDiv.children
, por exemplo.Caso contrário, se você ainda não pode confiar em
:scope
, não consigo pensar em outra maneira de lidar com sua situação sem adicionar mais lógica de filtro personalizado (por exemplo, encontrar demyDiv.getElementsByClassName("foo")
quem.parentNode === myDiv
), e obviamente não é ideal se você está tentando oferecer suporte a um caminho de código que realmente só quer pegar uma string de seletor arbitrário como entrada e uma lista de correspondências como saída! Mas se, como eu, você acabou fazendo essa pergunta simplesmente porque parou pensando "tudo o que você tinha era um martelo", não se esqueça de que há uma variedade de outras ferramentas que o DOM oferece também.fonte
myDiv.getElementsByClassName("foo")
não é o mesmo quemyDiv.querySelectorAll("> .foo")
, é mais parecido commyDiv.querySelectorAll(".foo")
(o que na verdade funciona) no sentido de que encontra todos os descendentes.foo
s em vez de apenas filhos.<style scoped>
) não tem nada a ver com o:scope
pseudo-seletor descrito nesta resposta.A maneira correta de escrever um seletor "enraizado" no elemento atual é usar
:scope
.No entanto, o suporte do navegador é limitado e você precisará de um calço se quiser usá-lo. Eu construí scopedQuerySelectorShim para esta finalidade.
fonte
:scope
especificação é atualmente um "Rascunho de Trabalho" e, portanto, sujeita a alterações. É provável que ainda funcione assim se / quando for adotado, mas um pouco cedo para dizer que esta é a "maneira correta" de fazê-lo na minha opinião.Este é um método flexível, escrito em vanilla JS, que permite executar uma consulta de seletor CSS apenas nos filhos diretos de um elemento:
fonte
Math.random().toString(36).substr(2, 10)
de produzir o mesmo token mais de uma vez.any dupe would need to also be a child of the same parent node
,id
atributos são-wide documento. Você está certo, as chances ainda são mínimas, mas obrigado por seguir o caminho certo e adicionar aquele contador :)se você tiver certeza de que o elemento é único (como seu caso com o ID):
Para uma solução mais "global": (use um shim MatchSelector )
onde
elm
está o seu elemento pai esel
é o seu seletor. Pode ser totalmente usado como protótipo também.fonte
matchesSelector
prefixado (que nem funciona na versão mais recente do Chrome), polui o namespace global (ret não foi declarado), não retorna um NodeList como o querySelectorMethods deve. Não acho que seja uma boa solução, daí o downvote.A solução a seguir é diferente das propostas até agora e funciona para mim.
A lógica é que você selecione primeiro todos os filhos correspondentes e, em seguida, filtre aqueles que não são filhos diretos. Um filho é um filho direto se não tiver um pai correspondente com o mesmo seletor.
HTH!
fonte
Criei uma função para lidar com essa situação, pensei em compartilhá-la.
Em essência, o que você está fazendo é gerar uma string aleatória (a função randomString aqui é um módulo npm importado, mas você pode fazer o seu próprio.) E usar essa string aleatória para garantir que você obtenha o elemento que está esperando no seletor. Então você está livre para usar o
>
depois disso.O motivo pelo qual não estou usando o atributo id é que o atributo id já pode ser usado e não quero substituí-lo.
fonte
Bem, podemos facilmente obter todos os filhos diretos de um elemento usando
childNodes
e podemos selecionar ancestrais com uma classe específica comquerySelectorAll
, portanto, não é difícil imaginar que poderíamos criar uma nova função que obtenha ambos e compare os dois.Nota: Isso retornará um Array of Nodes, não um NodeList.
Uso
fonte
Eu gostaria de acrescentar que você pode estender a compatibilidade de : scope apenas atribuindo um atributo temporário ao nó atual.
fonte
Eu teria ido com
fonte
Estou apenas fazendo isso, mesmo sem tentar. Isso funcionaria?
Experimente, talvez funcione, talvez não. Apolovies, mas não estou no computador agora para experimentar (respondendo do meu iPhone).
fonte