¿Casilla de verificación de tres estados en HTML?

163

No hay forma de tener un botón de verificación de tres estados (sí, no, nulo) en HTML, ¿verdad?

¿Hay algún truco o solución simple sin tener que renderizar todo solo?

Pekka
fuente
Funcionalmente, ¿cuál es la diferencia entre 'no' y 'nulo' en su uso?
David dice que reinstale a Mónica el
55
Mira las respuestas a continuación (excepto la mía). "Nulo" significa algo así como "Sin respuesta" ...
Franz
2
Exactamente. Es un elemento con antepasados ​​y "nulo" significa "usar valor primario".
Pekka
77
Un uso alternativo para una casilla de verificación de tres estados es al buscar / filtrar. Por ejemplo, supongamos que tengo una interfaz para buscar una lista de autos usados. Una de las opciones de búsqueda puede ser si el automóvil tiene techo solar o no. Los tres estados se pueden usar de la siguiente manera: Mostrar solo los automóviles CON un techo solar Mostrar solo los automóviles SIN un techo solar Mostrar ambos Ahora, ciertamente, esto se puede manejar de varias maneras ... podríamos usar un menú desplegable, o podríamos usar un conjunto de tres botones de opción ... pero una casilla de verificación de tres estados (que está vacía, tiene una marca verde o tiene una x roja) también es una buena solución.
Mir
2
Sería útil para una lista de casillas de verificación, con una casilla de verificación en la parte superior de la lista para marcar o desmarcar todas las casillas restantes. Si todos están marcados, la casilla de verificación del encabezado puede reflejar eso. Si todos están desmarcados, la casilla de verificación del encabezado también puede reflejar eso. Si la lista contiene una combinación de casillas marcadas y no marcadas, mostrar la casilla de verificación del encabezado en un estado intermedio proporcionaría comentarios visuales. Esa casilla de verificación de encabezado nunca llevaría un valor: es solo una señal visual y una ayuda de interfaz de usuario. Ser capaz de cambiar la casilla de verificación de la cabeza entre los tres estados también sería útil.
Jason

Respuestas:

119

Editar - Gracias al comentario de Janus Troelsen, encontré una mejor solución:

HTML5 define una propiedad para casillas de verificación llamada indeterminate

Consulte la guía de referencia de w3c . Para que la casilla de verificación aparezca visualmente indeterminada, configúrela como verdadera:

element.indeterminate = true;

Aquí está el violín de Janus Troelsen . Tenga en cuenta, sin embargo, que:

  • El indeterminateestado no se puede establecer en el marcado HTML, solo se puede hacer a través de Javascript (consulte esta prueba JSfiddle y este artículo detallado en trucos CSS )

  • Este estado no cambia el valor de la casilla de verificación, es solo una señal visual que enmascara el estado real de la entrada.

  • Prueba del navegador: funcionó para mí en Chrome 22, Firefox 15, Opera 12 y de regreso a IE7. Con respecto a los navegadores móviles, el navegador Android 2.0 y Safari mobile en iOS 3.1 no son compatibles.

Respuesta anterior

Otra alternativa sería jugar con la transparencia de la casilla de verificación para el estado "algunos seleccionados" (como lo hace Gmail solía hacer en las versiones anteriores). Requerirá JavaScript y una clase CSS. Aquí pongo un ejemplo particular que maneja una lista con elementos marcables y una casilla de verificación que permite seleccionar todos / ninguno de ellos. Esta casilla de verificación muestra un estado "algunos seleccionados" cuando se seleccionan algunos de los elementos de la lista.

Dada una casilla de verificación con una ID #select_ally varias casillas de verificación con una clase .select_one,

La clase CSS que desvanece la casilla de verificación "seleccionar todo" sería la siguiente:

.some_selected {
    opacity: 0.5;
    filter: alpha(opacity=50);
}

Y el código JS que maneja el tri-estado de la casilla de verificación seleccionar todo es el siguiente:

$('#select_all').change (function ()
{
    //Check/uncheck all the list's checkboxes
    $('.select_one').attr('checked', $(this).is(':checked'));
    //Remove the faded state
    $(this).removeClass('some_selected');
});

$('.select_one').change (function ()
{
  if ($('.select_one:checked').length == 0)
      $('#select_all').removeClass('some_selected').attr('checked', false);
  else if ($('.select_one:not(:checked)').length == 0)
      $('#select_all').removeClass('some_selected').attr('checked', true);
  else
      $('#select_all').addClass('some_selected').attr('checked', true);
});

Puedes probarlo aquí: http://jsfiddle.net/98BMK/

¡Espero que ayude!

pau.moreno
fuente
1
Probado en Chrome v35 y la casilla de verificación "todos" solo marca las otras casillas la primera vez que se hace clic. Después de esto, solo funciona para desmarcar las otras casillas de verificación. Corregido en esta versión: jsfiddle.net/CHRSb/1
rdans
2
.prop('checked', ...)se debe utilizar en lugar de .attr('checked', ...).
Luna
Arreglé los errores que Ross señaló; nuevo violín aquí .
Mike DeSimone
48

Puede usar el indeterminateatributo IDL de HTML en los inputelementos.

Ms2ger
fuente
3
Según Bert Bos en un correo electrónico de 2002 (< lists.w3.org/Archives/Public/www-dom/2002JanMar/0014.html> ), IE / Win e IE / Mac lo han respaldado desde la versión 4. Firefox parece lo he implementado en la versión 3.6. También parece haberse implementado en Safari en 2008. Creo que eso no hace muchos usuarios finales.
Ms2ger
use esta url ( help.dottoro.com/ljuocesd.php ) en su lugar. Muestra quién lo apoya (todos menos la ópera), desde cuándo, y visualmente muestra de qué se trata. La gente tiene miedo de las páginas de especificaciones. +1 para esta solución que no es un complemento
Hashbrown
15

Mi propuesta estaría usando

  • tres caracteres unicode apropiados para los tres estados, por ejemplo, ❓, ✅, ❌
  • un campo de entrada de texto sin formato (tamaño = 1)
  • Sin bordes
  • solo lectura
  • no mostrar cursor
  • controlador onclick para alternar entre los tres estados

Ver ejemplos en:

/**
 *  loops thru the given 3 values for the given control
 */
function tristate(control, value1, value2, value3) {
  switch (control.value.charAt(0)) {
    case value1:
      control.value = value2;
    break;
    case value2:
      control.value = value3;
    break;
    case value3:
      control.value = value1;
    break;
    default:
      // display the current value if it's unexpected
      alert(control.value);
  }
}
function tristate_Marks(control) {
  tristate(control,'\u2753', '\u2705', '\u274C');
}
function tristate_Circles(control) {
  tristate(control,'\u25EF', '\u25CE', '\u25C9');
}
function tristate_Ballot(control) {
  tristate(control,'\u2610', '\u2611', '\u2612');
}
function tristate_Check(control) {
  tristate(control,'\u25A1', '\u2754', '\u2714');
}
<input type='text' 
       style='border: none;' 
       onfocus='this.blur()' 
       readonly='true' 
       size='1' 
       value='&#x2753;' onclick='tristate_Marks(this)' />

<input style="border: none;"
       id="tristate" 
       type="text"  
       readonly="true" 
       size="1" 
       value="&#x2753;"  
       onclick="switch(this.form.tristate.value.charAt(0)) { 
     case '&#x2753': this.form.tristate.value='&#x2705;'; break;  
     case '&#x2705': this.form.tristate.value='&#x274C;'; break; 
     case '&#x274C': this.form.tristate.value='&#x2753;'; break; 
       };" />  

Wolfgang Fahl
fuente
3

Puede usar grupos de radio para lograr esa funcionalidad:

<input type="radio" name="choice" value="yes" />Yes
<input type="radio" name="choice" value="No" />No
<input type="radio" name="choice" value="null" />null
Franz
fuente
1
Lo se, gracias. :) Actualmente estoy usando selects, pero el formulario se está abarrotando un poco.
Pekka el
1
Bueno, entonces, ¿cómo sería exactamente el tercer estado? ¿Como cuando la casilla de verificación está desactivada? ¿Cómo te gustaría activar eso?
Franz
3

Creo que la forma más semántica es usar el readonlyatributo que pueden tener las entradas de casilla de verificación. Sin CSS, sin imágenes, etc. ¡Una propiedad HTML incorporada!

Ver violín:
http://jsfiddle.net/chriscoyier/mGg85/2/

Como se describe aquí en el último truco: http://css-tricks.com/indeterminate-checkboxes/

Webinan
fuente
Buena solución, pero lamentablemente esto no funciona en IE (prueba con la versión 11) ya que los clics más rápidos ya no se reconocen.
ViRuSTriNiTy
3

Aquí hay un ejemplo ejecutable que usa el indeterminateatributo mencionado :

const indeterminates = document.getElementsByClassName('indeterminate');
indeterminates['0'].indeterminate  = true;
<form>
  <div>
    <input type="checkbox" checked="checked" />True
  </div>
  <div>
    <input type="checkbox" />False
  </div>
  <div>
    <input type="checkbox" class="indeterminate" />Indeterminate
  </div>
</form>

Simplemente ejecute el fragmento de código para ver cómo se ve.

gil.fernandes
fuente
2

Al igual que la respuesta de @Franz, también puede hacerlo con una selección. Por ejemplo:

<select>
  <option></option>
  <option value="Yes">Yes</option>
  <option value="No">No</option>
</select>

Con esto también puede dar un valor concreto que se enviará con el formulario, creo que con la versión de javascript de la casilla de verificación indeterminada, enviará el valor subrayado de la casilla de verificación.

Al menos, puede usarlo como devolución de llamada cuando javascript está deshabilitado. Por ejemplo, dele una identificación y, en el evento de carga, cámbiela a la versión javascript de la casilla de verificación con estado indeterminado.

PhoneixS
fuente
2

Además de todo lo mencionado anteriormente, hay complementos de jQuery que también pueden ayudar:

para casillas de verificación individuales:

para casillas de verificación de comportamiento similar a un árbol:

EDITAR Ambas bibliotecas utilizan el atributo de casilla de verificación ' indeterminado ', ya que este atributo en Html5 es solo para estilo ( https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state ), el valor nulo nunca se envía al servidor (las casillas de verificación solo pueden tener dos valores).

Para poder enviar este valor al servidor, he creado campos de contraparte ocultos que se rellenan en el envío del formulario utilizando algunos javascript. En el lado del servidor, por supuesto, deberá marcar esos campos equivalentes en lugar de las casillas de verificación originales.

He usado la primera biblioteca (casillas de verificación independientes) donde es importante:

  • Inicialice los valores marcados, no verificados, indeterminados
  • use la función .val () para obtener el valor real
  • No se puede hacer el trabajo .state (probablemente mi error)

Espero que ayude.

Frank Sebastià
fuente
2

Aquí otro ejemplo con jQuery simple y propiedad data-checked:

 $("#checkbox")
  .click(function(e) {
    var el = $(this);

    switch (el.data('checked')) {

      // unchecked, going indeterminate
      case 0:
        el.data('checked', 1);
        el.prop('indeterminate', true);
        break;

        // indeterminate, going checked
      case 1:
        el.data('checked', 2);
        el.prop('indeterminate', false);
        el.prop('checked', true);
        break;

        // checked, going unchecked
      default:
        el.data('checked', 0);
        el.prop('indeterminate', false);
        el.prop('checked', false);

    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label><input type="checkbox" name="checkbox" value="" checked id="checkbox"> Tri-State Checkbox </label>

Ravi Makwana
fuente
1

Refiriéndose a la respuesta @BoltClock , aquí está mi solución para un método recursivo más complejo:

http://jsfiddle.net/gx7so2tq/2/

Puede que no sea la solución más bonita, pero funciona bien para mí y es bastante flexible.

Yo uso dos objetos de datos que definen el contenedor:

data-select-all="chapter1"

y los elementos en sí:

data-select-some="chapter1"

Ambos tienen el mismo valor. La combinación de ambos objetos de datos dentro de una casilla de verificación permite subniveles, que se escanean de forma recursiva. Por lo tanto, se necesitan dos funciones "auxiliares" para evitar el cambio de activación.

MFH
fuente
0

Es posible tener elementos de formulario HTML deshabilitados , ¿no sería eso? Sus usuarios lo verían en uno de los tres estados, es decir, marcado, desmarcado e inhabilitado, que estaría atenuado y no se podría hacer clic en él. Para mí, eso parece similar a "nulo" o "no aplicable" o lo que sea que esté buscando en ese tercer estado.

AmbroseChapel
fuente
Muy buena idea, pero necesito que el usuario pueda hacer clic nuevamente. Me temo que en una casilla deshabilitada, tendré problemas para disparar eventos, etc.
Pekka el
aún puede ver el valor de una casilla de verificación deshabilitada, lo cual es confuso para el usuario si el valor no es importante.
Janus Troelsen
Creo que 'nulo' significa representar al usuario que no proporciona una respuesta a la pregunta. No significa necesariamente que la pregunta no sea aplicable.
bdsl