Caixa de seleção Tri-state em HTML?


163

Não há como ter um botão de verificação de três estados (sim, não, nulo) em HTML, certo?

Existem truques simples ou soluções alternativas sem ter que renderizar tudo por si mesmo?


Funcionalmente, qual é a diferença entre 'não' e 'nulo' no seu uso?
David diz que restabelece Monica

5
Veja as respostas abaixo (exceto as minhas). Meios "nulo" algo como "Sem resposta" ...
Franz

2
Exatamente. É um item com ancestrais e "nulo" significa "usar valor pai".
586 Pekka

7
Um uso alternativo para uma caixa de seleção de três estados é ao pesquisar / filtrar. Por exemplo, vamos supor que eu tenho uma interface para pesquisar uma lista de carros usados. Uma das opções de pesquisa pode ser se o carro tem ou não teto solar. Os três estados podem ser usados ​​da seguinte maneira: Mostrar apenas carros COM teto solar Mostrar apenas carros SEM teto solar Mostrar ambos Agora, certamente, isso pode ser tratado de várias maneiras ... podemos fazer uma lista suspensa ou usar um conjunto de três botões de opção ... mas uma caixa de seleção de três estados (que está vazia, tem uma verificação verde ou tem um x vermelho) também é uma boa solução.
Mir

2
Seria útil para uma lista de caixas de seleção, com uma caixa de seleção no início da lista, para marcar ou desmarcar todas as caixas restantes. Se todos estiverem marcados, a caixa de seleção do cabeçalho poderá refletir isso. Se todos estiverem desmarcados, a caixa de seleção do cabeçalho também poderá refletir isso. Se a lista contiver uma combinação de caixas marcadas e desmarcadas, a exibição da caixa de seleção do cabeçalho em um estado intermediário fornecerá feedback visual. Essa caixa de seleção do cabeçalho nunca carregaria um valor - é apenas uma sugestão visual e um auxílio à interface do usuário. Ser capaz de alternar a caixa de seleção principal entre os três estados também seria útil.
Jason

Respostas:


119

Editar - Graças ao comentário de Janus Troelsen, encontrei uma solução melhor:

HTML5 define uma propriedade para caixas de seleção chamadas indeterminate

Consulte o guia de referência do w3c . Para fazer com que a caixa de seleção apareça visualmente indeterminada, defina-a como true:

element.indeterminate = true;

Aqui está o violino de Janus Troelsen . Observe, no entanto, que:

  • O indeterminateestado não pode ser definido na marcação HTML, apenas pode ser feito via Javascript (consulte este teste JSfiddle e este artigo detalhado em truques CSS )

  • Esse estado não altera o valor da caixa de seleção, é apenas uma sugestão visual que mascara o estado real da entrada.

  • Teste do navegador: funcionou para mim no Chrome 22, Firefox 15, Opera 12 e de volta ao IE7. Em relação aos navegadores móveis, o navegador Android 2.0 e o Safari mobile no iOS 3.1 não têm suporte para ele.

Resposta anterior

Outra alternativa seria a de jogar com a transparência caixa de seleção para o "alguns selecionados" estado (como Gmail não costumava fazer nas versões anteriores). Exigirá algum javascript e uma classe CSS. Aqui, coloquei um exemplo específico que lida com uma lista com itens verificáveis ​​e uma caixa de seleção que permite selecionar todos / nenhum deles. Esta caixa de seleção mostra o estado "alguns selecionados" quando alguns dos itens da lista são selecionados.

Dada uma caixa de seleção com um ID #select_alle várias caixas de seleção com uma classe .select_one,

A classe CSS que desaparece da caixa de seleção "selecionar tudo" seria a seguinte:

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

E o código JS que lida com o tri-estado da caixa de seleção selecionar tudo é o seguinte:

$('#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);
});

Você pode experimentá-lo aqui: http://jsfiddle.net/98BMK/

Espero que ajude!



1
Testado no chrome v35 e a caixa de seleção "all" somente marca as outras caixas na primeira vez que clicamos. Após isso, só funciona para desmarcar as outras caixas de seleção. Corrigido nesta versão: jsfiddle.net/CHRSb/1
rdans

2
.prop('checked', ...)deve ser usado em vez de .attr('checked', ...).
Luna

Corrigi os bugs que Ross apontou; novo violino aqui .
Mike DeSimone

48

Você pode usar o indeterminateatributo IDL do HTML em inputelementos.


3
De acordo com Bert Bos em um email de 2002 (< lists.w3.org/Archives/Public/www-dom/2002JanMar/0014.html> ), o IE / Win e o IE / Mac o suportam desde a versão 4. O Firefox parece implementou na versão 3.6. Também parece ter sido implementado no Safari em 2008. Eu acho que isso não faz muitos usuários finais.
Ms2ger # 03

use este URL ( help.dottoro.com/ljuocesd.php ). Mostra quem a apoia (todos bar ópera), desde quando, e visualmente exibe o que é. As pessoas têm medo das páginas de especificações. +1 para esta solução não-a-plugin
Hashbrown

15

Minha proposta seria usando

  • três caracteres unicode apropriados para os três estados, por exemplo, ❓, ✅, ❌
  • um campo de entrada de texto sem formatação (tamanho = 1)
  • sem borda
  • somente leitura
  • não exibe cursor
  • manipulador onclick para alternar entre os três estados

Veja exemplos em:

/**
 *  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; 
       };" />  



3

Você pode usar grupos de rádio para alcançar essa funcionalidade:

<input type="radio" name="choice" value="yes" />Yes
<input type="radio" name="choice" value="No" />No
<input type="radio" name="choice" value="null" />null

1
Eu sei disso, obrigado. :) No momento, estou usando selects, mas o formulário está ficando um pouco confuso.
586 Pekka

1
Bem, então como seria exatamente o terceiro estado? Assim como quando a caixa de seleção está desativada? Como você gostaria de desencadear isso?
Franz

3

Eu acho que a maneira mais semântica é usar o readonlyatributo que as entradas da caixa de seleção podem ter. Sem css, sem imagens, etc; uma propriedade HTML incorporada!

Veja o Fiddle:
http://jsfiddle.net/chriscoyier/mGg85/2/

Conforme descrito aqui no último truque: http://css-tricks.com/indeterminate-checkboxes/


Solução agradável, mas infelizmente isso não funciona no IE (teste com a versão 11), pois os cliques mais rápidos não são mais reconhecidos.
ViRuSTriNiTy

3

Aqui está um exemplo executável usando o 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>

Basta executar o snippet de código para ver como ele se parece.


2

Como a resposta @Franz, você também pode fazer isso com uma seleção. Por exemplo:

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

Com isso, você também pode dar um valor concreto que será enviado com o formulário, acho que com a versão indeterminada da caixa de seleção em javascript, ele enviará o valor sublinhado da caixa de seleção.

Pelo menos, você pode usá-lo como retorno de chamada quando o javascript estiver desativado. Por exemplo, forneça um ID e, no evento load, altere-o para a versão javascript da caixa de seleção com status indeterminado.


2

Além de todos os citados acima, existem plugins jQuery que também podem ajudar:

para caixas de seleção individuais:

para caixas de seleção de comportamento semelhante a uma árvore:

EDITAR Ambas as bibliotecas usam o atributo ' indeterminado ' da caixa de seleção, pois esse atributo no Html5 é apenas para estilizar ( https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state ), o valor nulo nunca é enviado ao servidor (as caixas de seleção podem ter apenas dois valores).

Para poder enviar esse valor ao servidor, criei campos ocultos de contrapartida que são preenchidos no envio de formulários usando algum javascript. No lado do servidor, é necessário marcar esses campos de contrapartida em vez das caixas de seleção originais, é claro.

Usei a primeira biblioteca (caixas de seleção independentes) em que é importante:

  • Inicialize os valores verificados, não verificados e indeterminados
  • use a função .val () para obter o valor real
  • Não é possível fazer o trabalho .state (provavelmente meu erro)

Espero que ajude.


2

Aqui outro exemplo com jQuery e propriedade simples 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>


1

Referindo-se à resposta do @BoltClock , aqui está minha solução para um método recursivo mais complexo:

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

Pode não ser a solução mais bonita, mas funciona bem para mim e é bastante flexível.

Eu uso dois objetos de dados que definem o contêiner:

data-select-all="chapter1"

e os próprios elementos:

data-select-some="chapter1"

Ambos com o mesmo valor. A combinação dos dois objetos de dados em uma caixa de seleção permite subníveis, que são verificados recursivamente. Portanto, são necessárias duas funções "auxiliares" para impedir o acionamento da mudança.



0

É possível ter os elementos do formulário HTML desativados - não seria? Seus usuários o veriam em um dos três estados, ou seja, marcado, desmarcado e desativado, que seriam acinzentados e não clicáveis. Para mim, isso parece semelhante a "nulo" ou "não aplicável" ou o que você estiver procurando nesse terceiro estado.


Muito boa ideia, mas preciso que o usuário possa clicar novamente. Receio que, em uma caixa de seleção desativada, tenha problemas para disparar eventos e assim por diante.
586 Pekka

você ainda pode ver o valor de uma caixa de seleção desabilitada, o que é confuso para o usuário se o valor não for importante.
Janus Troelsen

Eu acho que 'nulo' significa representar o usuário que não está fornecendo uma resposta para a pergunta. Isso não significa necessariamente que a pergunta não é aplicável.
bdsl


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.