Puedo hacer esto:
<div id="myDiv">
<div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");
Es decir, puedo recuperar con éxito todos los hijos directos del myDiv
elemento que tienen clase .foo
.
El problema es que me molesta que deba incluir el #myDiv
en el selector, porque estoy ejecutando la consulta en el myDiv
elemento (por lo que obviamente es redundante).
Debería poder dejar la opción #myDiv
desactivada, pero entonces el selector no es una sintaxis legal ya que comienza con >
.
¿Alguien sabe cómo escribir un selector que obtenga solo los hijos directos del elemento en el que se está ejecutando el selector?
javascript
dom
css-selectors
mattsh
fuente
fuente
Respuestas:
Buena pregunta. En el momento en que se solicitó, no existía una forma implementada universalmente para realizar "consultas con raíz de combinador" (como las llamó John Resig ).
Ahora se ha introducido la pseudoclase: scope . No es compatible con las versiones [anteriores a Chrominum] de Edge o IE, pero Safari ya lo ha admitido durante algunos años. Usando eso, su código podría convertirse en:
Tenga en cuenta que, en algunos casos, también puede omitir
.querySelectorAll
y utilizar otras características de la API DOM antiguas. Por ejemplo, en lugar demyDiv.querySelectorAll(":scope > *")
simplemente escribirmyDiv.children
, por ejemplo.De lo contrario, si aún no puede confiar
:scope
, no puedo pensar en otra forma de manejar su situación sin agregar más lógica de filtro personalizada (por ejemplo, encontrar demyDiv.getElementsByClassName("foo")
quién.parentNode === myDiv
), y obviamente no es ideal si está tratando de admitir una ruta de código que realmente ¡solo quiere tomar una cadena de selección arbitraria como entrada y una lista de coincidencias como salida! Pero si, como yo, terminaste haciendo esta pregunta simplemente porque te quedaste atascado pensando "todo lo que tenías fue un martillo", no olvides que hay una variedad de otras herramientas que DOM también ofrece.fuente
myDiv.getElementsByClassName("foo")
no es lo mismo quemyDiv.querySelectorAll("> .foo")
, es más parecidomyDiv.querySelectorAll(".foo")
(que en realidad funciona, por cierto) en el sentido de que encuentra todos los descendientes.foo
en lugar de solo los hijos.<style scoped>
) no tienen nada que ver con el:scope
pseudo-selector descrito en esta respuesta.La forma correcta de escribir un selector que está "arraigado" al elemento actual es usar
:scope
.Sin embargo, la compatibilidad con el navegador es limitada y necesitará una cuña si desea utilizarla. Construí scopedQuerySelectorShim para este propósito.
fuente
:scope
especificación es actualmente un "Borrador de trabajo" y, por lo tanto, está sujeta a cambios. Es probable que siga funcionando así si / cuando se adopte, pero un poco antes de decir que esta es la "forma correcta" de hacerlo en mi opinión.Aquí hay un método flexible, escrito en vanilla JS, que le permite ejecutar una consulta de selector de CSS solo sobre los hijos directos de un elemento:
fuente
Math.random().toString(36).substr(2, 10)
producir la misma ficha más de una vez.any dupe would need to also be a child of the same parent node
,id
atributos son en todo el documento. Tienes razón, las probabilidades siguen siendo bastante insignificantes, pero gracias por tomar el camino correcto y agregar ese contador :)si sabe con certeza que el elemento es único (como su caso con el ID):
Para una solución más "global": (use un ajuste de MatchSelector )
donde
elm
está su elemento padre ysel
es su selector. También se podría utilizar totalmente como prototipo.fuente
matchesSelector
prefijo (que ni siquiera funciona en la última versión de Chrome), contamina el espacio de nombres global (no se declaró ret), no devuelve una NodeList como se espera que haga querySelectorMethods. No creo que sea una buena solución, de ahí el voto negativo.La siguiente solución es diferente a las propuestas hasta ahora y me funciona.
La razón es que primero selecciona todos los hijos coincidentes y luego filtra los que no son hijos directos. Un hijo es un hijo directo si no tiene un padre que coincida con el mismo selector.
HTH!
fuente
Creé una función para manejar esta situación, pensé en compartirla.
En esencia, lo que está haciendo es generar una cadena aleatoria (la función randomString aquí es un módulo npm importado, pero puede crear el suyo) y luego usar esa cadena aleatoria para garantizar que obtiene el elemento que espera en el selector. Entonces eres libre de usar el
>
después de eso.La razón por la que no estoy usando el atributo id es que es posible que el atributo id ya esté en uso y no quiero anularlo.
fuente
Bueno, podemos obtener fácilmente todos los hijos directos de un elemento usando
childNodes
y podemos seleccionar ancestros con una clase específica conquerySelectorAll
, por lo que no es difícil imaginar que podríamos crear una nueva función que obtenga ambos y los compare.Nota: Esto devolverá una matriz de nodos, no una NodeList.
Uso
fuente
Me gustaría agregar que puede extender la compatibilidad de : scope simplemente asignando un atributo temporal al nodo actual.
fuente
Me hubiera ido con
fuente
Estoy haciendo esto sin siquiera intentarlo. ¿Funcionaría esto?
Pruébelo, tal vez funcione, tal vez no. Disculpas, pero ahora no estoy en una computadora para probarlo (respondiendo desde mi iPhone).
fuente