2011-12-25 14 views
16

Tengo un elemento DOM (#installations) con un número de hijos, solo uno de ellos tiene una clase .selected. Necesito seleccionar esta clase y los primeros 3 del resto (: no (.selected)) y mostrarlos - el objetivo es tener solo 4 elementos mostrados, independientemente de qué elemento tenga seleccionada la clase.Seleccionar una clase y los 3 primeros del resto; nth-child y nth-of-type inútil

El problema es, en la expresión:

#installations > *:not(.selected):nth-of-type(-n+3), .selected 

: n-ésimo de tipo() no tiene en cuenta la: selector no() y simplemente selecciona las 3 primeras hijos de #installation. Por ejemplo, si tengo este código HTML:

<div id="installations"> 
    <div id="one"/> 
    <div id="two"/> 
    <div id="three" class="selected"/> 
    <div id="four"/> 
    <div id="five"/> 
</div> 

Solo tendré seleccionado uno, dos, tres y no los primeros cuatro. La implicación lógica es que: nth-of-type() tendrá solo (uno, dos, cuatro, cinco) para seleccionar, ya que: not() ya excluyó el seleccionado, seleccionando (uno, dos, cuatro), y luego la otra parte del selector , .selected agregará el elemento seleccionado.

Si .selected no está en los primeros cuatro elementos, digamos que es el sexto, vamos a tener los primeros tres + sextos elementos seleccionados.

Para aclarar: la selección .selected más 3 elementos adyacentes también está bien. Sin embargo, esto también es difícil en caso de que .selected esté en los últimos 3 (si seleccionamos los 3 elementos adyacentes siguientes)

+2

pseudo-clases no son procesado secuencialmente; todos son evaluados juntos en todos y cada uno de sus elementos. Ver [esta respuesta] (http: // stackoverflow.com/a/5217102/106224) para más detalles (también cubre ': not()'). En su caso, ': not (.selected): nth-of-type (-n + 3)' toma los primeros dos elementos (el tercero es '.selected'), y' .selected' toma el tercero. – BoltClock

+0

Ese es el problema. Si solo pudiera excluir .selected en la primera parte del selector (antes de la primera pseudo-clase). Alternativamente, puedo poner una clase ".unselected" en todos los demás elementos, pero esperaba una solución más limpia. – Ivo

Respuesta

32

Como mencioné en mi comentario, las pseudo-clases no se procesan secuencialmente; todos son evaluados juntos en todos y cada uno de sus elementos. Vea this answer para más detalles.

Después de un poco de bricolaje alrededor, dada su HTML y las condiciones por las cuales para seleccionar elementos, se me ocurrió lo siguiente, largo lista de selectores:

/* The first three children will always be selected at minimum */ 
#installations > div:nth-child(-n+3), 
/* Select .selected if it's not among the first three children */ 
#installations > div.selected, 
/* If .selected is among the first three children, select the fourth */ 
#installations > div.selected:nth-child(-n+3) ~ div:nth-child(4) 

Para que esto funcione, uno se debe hacer una suposición simple: la clase selected solo aparecerá en un elemento a la vez.

Deberá combinar los tres selectores en la misma regla para que coincidan los cuatro elementos que está buscando. Observe las comas en mi código.

Interactive jsFiddle demo (para probar el selector con la clase en diferentes elementos secundarios)


Por lo que vale la pena, es más fácil si se puede caer de nuevo a JavaScript. A modo de ejemplo, si se utiliza jQuery, su :lt() selector hace las cosas un poco más simple:

// Apply styles using this selector instead: #installations > div.with-jquery 
$('#installations') 
    .children('div.selected, div:not(.selected):lt(3)') 
    .addClass('with-jquery'); 

Interactive jsFiddle demo (ignorar el código JS en esta demostración, que sólo existe para que sea interactivo)

+0

Sí, exactamente lo que estaba buscando. Gracias. – Ivo

+0

@Ivo: No hay problema. Digamos que necesitaba un rompecabezas para romperme la cabeza :) – BoltClock

0

Lo que necesita usar son los selectores de hermanos adyacentes. Aquí hay un ejemplo que cociné que está funcionando en Safari (no probado en otro lugar). Solo se muestran los elementos 'Dos', 'Tres' y 'Cuatro'.

<!DOCTYPE html> 
<html> 
    <head> 
    <style> 
     .the-list li {display:none;} 
     .the-list li.selected {display:block;} 
     .the-list li.selected + li {display:block;} 
     .the-list li.selected + li + li {display:block;} 
    </style> 
    </head> 
    <body> 
    <ol class='the-list'> 
     <li>One</li> 
     <li class='selected'>Two</li> 
     <li>Three</li> 
     <li>Four</li> 
     <li>Five</li> 
     <li>Six</li> 
    </ol> 
    </body> 
</html> 
+0

Los selectores de hermanos adyacentes son compatibles con todos los navegadores, sin perjuicio de los requisitos comerciales (léase: excepto IE6). – BoltClock

+0

Espera de espera, el OP quiere que se seleccionen los primeros tres +, a menos que esté seleccionado en los primeros tres, en cuyo caso se salta y selecciona los otros tres elementos que lo rodean. – Purag

+0

Y si el último elemento tiene la clase ".selected", solo se mostrará. No funciona tan bien – Ivo

Cuestiones relacionadas