2009-01-27 14 views
8

Ok, tengo un conjunto de casillas de verificación para seleccionar los criterios. Por razones de argumento, diremos que los datos son así:HTML/CSS: ¿cuál es una mejor opción para el diseño de un árbol de elementos anidados que las tablas anidadas?

[] Vehicles 
    [] Unpowered 
     [] Bicycle 
     [] Skateboard 
    [] Powered 
     [] Two-wheeled 
     [] Motorcycle 
     [] Scooter 
     [] Four-wheeled 
etc 

Las [] s representan casillas de verificación.

Haciendo caso omiso de la naturaleza obviamente artificial de este ejemplo, la idea es la siguiente:

  • Para empezar, sólo la casilla de verificación del vehículo es visible;
  • Si el usuario hace clic en el Vehículo, la casilla de verificación se activa al siguiente nivel (Encendido, Sin alimentación);
  • Si el usuario selecciona Alimentado, abre el siguiente nivel (Dos ruedas, Cuatro ruedas);
  • Si el usuario luego deshabilita el encendido, ese nivel desaparece.

Ahora, esto es relativamente fácil de configurar al hacer clic en alternar el atributo CSS de visualización entre bloque y ninguno.

Esto está actualmente estructurado en la página como:

<table> 
<tr> 
    <td><input type="checkbox" onclick="toggle('__Vehicles');"></td> 
    <td>Vehicles 
    <table id="__Vehicles"> 
    <tr> 
     <td><input type="checkbox"></td> 
     <td>Unpowered 
etc 

Debo señalar antes de que alguien le pregunta: la razón por la casilla de verificación se puso en celda de tabla era controlar el formato. Facilitó la sangría de forma efectiva, ya que todo en la siguiente celda de la tabla se alinearía.

Todo funciona bien, pero la anidación de la tabla es bastante profunda. Sigo pensando que tiene que haber una mejor manera que esto. Tiene que poder construirse fácilmente de forma dinámica y tener un buen soporte entre navegadores para el formateo del "árbol".

También debería mencionar que jQuery está disponible. Lo estoy usando para otras cosas.

Sugerencias?

Editar: Sí, el estilo de la casilla de verificación es importante ya que un par de comentarios han notado. Además, he publicado una solución para esto, basada en las respuestas que he recibido, como respuesta a continuación (demasiado grande para agregar aquí), solo para aquellos curiosos que quieran ver un ejemplo.

Respuesta

21
<ul> 
    <li><input type="checkbox" />Vehicles <ul> 
     <li><input type="checkbox" />Unpowered</li> 
     <li><input type="checkbox" />Bicycle</li> 
     <li><input type="checkbox" />Skateboard</li> 
    </ul></li> 
    <li><input type="checkbox" />Powered <ul> 
     <li><input type="checkbox" />Two-wheeled <ul> 
      <li><input type="checkbox" />Motorcycle</li> 
      <li><input type="checkbox" />Scooter</li> 
     </ul></li> 
     <li><input type="checkbox" />Four-wheeled</li> 
    </ul></li> 
</ul> 

Editar: un poco de css js & & para mostrar elementos de ocultar anidado (no hay casillas de verificación)

li.opened ul { 
display: block; 
} 

li.closed ul { 
    display: none; 
} 

y JS ...

$(document).ready(function() { 

$('li input:checkbox').click(function() { 
    $(this).parent().toggleClass('opened'); 
    $(this).parent().toggleClass('closed'); 
}); 

$('li').addClass('closed'); 
}); 

de edición, de nuevo, porque Sparr quiere algunos estilos mejores (suponiendo que las casillas de verificación tengan un estilo de "casilla de verificación"

li input.checkbox { /* input:checkbox is not 100% compatible */ 
    width: 6px; 
    margin: 0 2px; 
    /* This makes 10px be the total "width" ofh the checkbox */ 
} 

ul { 
    margin: 0 0 0 10px; /* Or whatever your total checkbox width is */ 
    padding: 0; 
} 

li { 
    padding: 0; 
} 
+0

Yup también mi idea. –

+0

El punto clave de la pregunta que omite es que el uso de tablas anidadas hace que la casilla de verificación en un nivel se alinee debajo de la etiqueta del nivel principal. Se necesita un estilo más elegante para duplicar este comportamiento con listas, y ese estilo es la parte "difícil" de esta pregunta. – Sparr

+0

también, -1 para el – Sparr

1

Las tablas son para datos tabulares. Use listas anidadas en su lugar y CSS para formatear.


Si usted está buscando una solución completa, aquí está uno usando CSS puro para los navegadores modernos y JavaScript para IE:

<style> 
ul.tree, ul.tree ul { 
    position: relative; 
    list-style: none; 
    margin: 0 0 0 20px; 
    padding: 0; 
} 
ul.tree input { 
    position: absolute; 
    margin-left: -20px; 
} 
ul.tree ul { 
    display: none; 
} 
ul.tree input:checked ~ ul { 
    display: block; 
} 
ul.tree label:hover { 
    text-decoration: underline; 
} 
</style> 
<ul class="tree"> 
    <li> 
    <input type="checkbox" id="option1"> 
    <label for="option1">Option 1</label> 
    <ul> 
     <li> 
     <input type="checkbox" id="option1a"> 
     <label for="option1a">Option 1 Sub Option A</label> 
     </li> 
     <li> 
     <input type="checkbox" id="option1b"> 
     <label for="option1b">Option 1 Sub Option B</label> 
     </li> 
    </ul> 
    </li> 
    <li> 
    <input type="checkbox" id="option2"> 
    <label for="option2">Option 2</label> 
    </li> 
</ul> 
<!--[if lte IE 7]> 
<script> 
var tree = document.getElementsByTagName('ul')[0]; 
tree.attachEvent('onclick', function() { 
    var src = event.srcElement; 

    if(src.nodeName.toLowerCase() === 'label') 
     var box = document.getElementById(src.htmlFor); 
    else if(src.nodeName.toLowerCase() === 'input') 
     var box = src; 
    else return; 

    for(var current = src.nextSibling; 
     current && current.nodeName.toLowerCase() !== 'ul'; 
     current = current.nextSibling); 

    if(current) 
     current.style.display = box.checked ? 'block' : 'none'; 
}); 
</script> 
<![endif]--> 

asume que una casilla de verificación no sea más ancho que 20px.

+0

No creo que su suposición sea válida. El diseño de la tabla funciona sin esa suposición. – Sparr

+0

Mi suposición era válida en cada navegador que comprobé. Si quiere asegurarse de que no se rompa, agregue una entrada 'ul.tree [type = checkbox] {max-width: 20px; } ' – Christoph

4

Las listas desordenadas anidadas son la mejor práctica para este tipo de cosas.

<ul> 
    <li>Item 1</li> 
    <li>Item 2 
     <ul> 
     <li>Sub Item 1</li> 
     <li>Sub Item 2</li> 
     <li>Sub Item 3</li> 
     </ul> 
    </li> 
    <li>Item 3</li> 
    <li>Item 4 
     <ul> 
     <li>Sub Item 1</li> 
     <li>Sub Item 2</li> 
     <li>Sub Item 3</li> 
     </ul> 
    </li> 
</ul> 
+0

El punto clave de la pregunta que omite es que el uso de tablas anidadas hace que la casilla de verificación en un nivel se alinee debajo de la etiqueta del nivel principal. Se necesita un estilo más elegante para duplicar este comportamiento con listas, y ese estilo es la parte "difícil" de esta pregunta. – Sparr

+0

Sí, pero una lista anidada es la forma correcta de hacerlo :) – Birk

10

Usted puede hacer esto:

<ul> 
    <li> 
    <input type="checkbox" /> Option 1 
    <ul> 
     <li><input type="checkbox" /> Option 1 Sub Option A</li> 
    </ul> 
    </li> 
</ul> 

Se podría entonces establecer el relleno/margen de la UL a 0 y 0. A continuación, establezca el padding-left de la LI a 10px.

ul { 
    margin:0; 
    padding:0; 
} 

li { 
    margin:0; 
    padding:0 0 0 20px; /* Each nested li will be padded incrementally */ 
} 

Para el javascript, adjuntar un evento para cada casilla de verificación que determina si el hermano UL (si es que existe) debe ser visible. Si la casilla está marcada, muéstrela, de lo contrario, ocúltela.

+0

+1 para recordar las casillas de verificación (y no solo publicar una lista anidada arbitrariamente) – cletus

+0

-1 para sangrar 10px en lugar del ancho de una casilla de verificación, un punto clave de la pregunta original – Sparr

+0

@Sparr, aunque creo que es una razón pobre para rechazar una respuesta, la actualicé a 20px. TIENE el poder de editar el código usted mismo una vez que lo usa. – Sampson

0

al crear cb a darles una clase CSS en función del nivel

<input class="LevelXcb" type="checkbox" /> 

CSS:

.Level0cb{left:4px;} 
.Level1cb{left:16px;} 
.Level2cb{left:28px;} 

si "izquierda" no funciona, intente configurar "margen izquierda".

+0

Pero recuerde que todos los artículos que los siguen deben alinearse también. – cletus

+0

Usted establece la clase de CSS correcta para ellos y lo hacen, ¿no? – Spikolynn

2

Tengo que decir que debe extraer el JavaScript de su marcado, además de las sugerencias anteriores. Usando una biblioteca como lowpro (una de mis favoritas), puedes crear 1 objeto para manejar el comportamiento anidado de la casilla de verificación, y haz que se aplique automáticamente, discretamente. Empacar su código de esta manera hace que su marcado sea más fácil de mantener y su código sea más fácil y rápido de escribir, más potente y más fácil de mantener.

0

Sé que esto no está muy relacionado con la pregunta, por lo que los pls no votan es solo una sugestión.

En este ejemplo de davethegr8:

<ul> 
    <li>Vehicles <ul> 
     <li>Unpowered</li> 
     <li>Bicycle</li> 
     <li>Skateboard</li> 
    </ul></li> 
    <li>Powered <ul> 
     <li>Two-wheeled <ul> 
      <li>Motorcycle</li> 
      <li>Scooter</li> 
     </ul></li> 
     <li>Four-wheeled</li> 
    </ul></li> 
</ul> 

Si das cada paso una clase, puede utilizar jQuery para hacer alguna gota de enfriamiento efects con el clic:

Como

$("li.Two-wheeled").click(function(event){ 
    $("div.main_wrapper ul.Moto_or_scooter:hidden").slideDown("slow"); 
} 

Sin embargo, una pequeña sugestión :)

1

Mientras que el complemento jQuery mcDropdown aborda el problema de la lista anidada de una manera diferente (sin casillas de verificación), puede ser adecuado para sus necesidades.

+0

Gracias por el enlace a mcDropdown. Bonito plug-in Podría usar eso para otra cosa. – cletus

3

¿Quieres ver algo de magia jQuery profunda?

<ul class="tree"> 
    <li><input type="checkbox" name="Vehicles" checked>Vehicles 
    <ul> 
     <li<input type="checkbox" name="Unpowered">Unpowered 
     <ul> 
      <li><input type="checkbox" name="Bicycle">Bicycle</li> 
      <li><input type="checkbox" name="Skateboard">Skateboard</li> 
     </ul> 
     </li> 
     <li><input type="checkbox" name="Powered" checked>Powered 
     <ul> 
      <li><input type="checkbox" name="Two-wheeled">Two-wheeled 
      <ul> 
       <li><input type="checkbox" name="Motorcycle" checked>Motorcycle</li> 
       <li><input type="checkbox" name="Scooter">Scooter</li> 
      </ul> 
      </li> 
      <li><input type="checkbox" name="Two-Wheeled">Four-wheeled</li> 
     </ul> 
    </ul> 
    </li> 
</ul> 

Nota: la única decoración aquí es el árbol de la clase.

ul.tree { 
    list-style-type: none; 
    margin: 0 0 0 -22px; 
    padding: 0; 
} 

ul.tree ul { 
    list-style-type: none; 
    margin: 0; 
    padding: 0; 
} 

ul.tree input { 
    margin-right: 6px; 
} 

ul.tree li { 
    padding: 0 0 0 22px; 
    margin: 1px; 
} 

.closed ul { 
    display: none; 
} 

y la magia:

$(function() { 
    $("ul.tree li:has(ul) > :checkbox").click(function() { 
     jQuery(this).parent().toggleClass('closed'); 
    }).not(":checked").parent().addClass("closed"); 
}); 

que convierte toda la cosa en una abertura de trabajo y el árbol de cierre cuando haz clic en las casillas de verificación. Increíble.

Gracias a davethegr8, Jonathon Sampson y otros por su asesoramiento.

+0

Agradable. Se me ocurrió casi lo mismo. – davethegr8

0

Si la anchura de las casillas de verificación sigue siendo un problema (después de todas las respuestas anteriores ...) puede:

  • Poner todas las casillas en un fijo con la caja para saber exactamente donde el texto está comenzando (y la siguiente casilla de verificación de nivel)
  • utilizar un poco de jQuery cálculos para obtener el ancho y establecer los márgenes de los otros elementos de forma dinámica (parece un poco mucho aunque ...)

Usando la estructura de lista anidada sugerido, obviamente, .

Cuestiones relacionadas