Casella di controllo tri-state in HTML?


163

Non c'è modo di avere un pulsante di controllo in tre stati (sì, no, null) in HTML, giusto?

Ci sono semplici trucchi o soluzioni alternative senza dover rendere il tutto da soli?


Funzionalmente, qual è la differenza tra 'no' e 'null' nel tuo utilizzo?
David dice di ripristinare Monica il

5
Guarda le risposte di seguito (tranne la mia). "Null" significa qualcosa come "Nessuna risposta" ...
Franz,

2
Esattamente. È un elemento con antenati e "null" significa "usa il valore principale".
Pekka

7
Un utilizzo alternativo per una casella di controllo a tre stati è durante la ricerca / il filtro. Ad esempio, supponiamo che io abbia un'interfaccia per cercare un elenco di auto usate. Una delle opzioni di ricerca potrebbe essere se l'auto ha un tetto apribile. I tre stati potrebbero essere usati come segue: Mostra solo le auto CON un tetto apribile Mostra solo le auto WIHTOUT un tetto apribile Mostra entrambi di tre pulsanti di opzione ... ma anche una casella di controllo a tre stati (vuota o con un segno di spunta verde o con una x rossa) è una buona soluzione.
Mir,

2
Sarebbe utile per un elenco di caselle di controllo, con una casella in cima all'elenco per selezionare o deselezionare tutte le caselle rimanenti. Se tutti sono selezionati, la casella di controllo dell'intestazione può riflettere questo. Se tutti sono deselezionati, anche la casella di spunta dell'intestazione può riflettere questo. Se l'elenco contiene una combinazione di caselle selezionate e deselezionate, la visualizzazione della casella di controllo dell'intestazione in uno stato intermedio fornirebbe un feedback visivo. Quella casella di controllo dell'intestazione non avrebbe mai un valore: è solo un segnale visivo e un aiuto all'interfaccia utente. Sarebbe anche utile poter selezionare la casella di controllo head tra tutti e tre gli stati.
Jason,

Risposte:


119

Modifica - Grazie al commento di Janus Troelsen, ho trovato una soluzione migliore:

HTML5 definisce una proprietà per le caselle di controllo chiamate indeterminate

Vedi la guida di riferimento di w3c . Per rendere la casella di controllo visivamente indeterminata, impostala su true:

element.indeterminate = true;

Ecco il violino di Janus Troelsen . Si noti, tuttavia, che:

  • Lo indeterminatestato non può essere impostato nel markup HTML, può essere eseguito solo tramite Javascript (vedere questo test JSfiddle e questo articolo dettagliato nei trucchi CSS )

  • Questo stato non modifica il valore della casella di controllo, è solo un segnale visivo che maschera lo stato reale dell'input.

  • Test del browser: ha funzionato per me in Chrome 22, Firefox 15, Opera 12 e ritorno a IE7. Per quanto riguarda i browser mobili, il browser Android 2.0 e Safari mobile su iOS 3.1 non ne hanno il supporto.

Risposta precedente

Un'altra alternativa sarebbe quella di giocare con la trasparenza della casella di controllo per lo stato "alcuni selezionati" (come fa Gmail consente di fare nelle versioni precedenti). Richiederà un po 'di javascript e una classe CSS. Qui metto un esempio particolare che gestisce un elenco con elementi selezionabili e una casella di controllo che consente di selezionarli tutti / nessuno. Questa casella di controllo mostra uno stato "alcuni selezionati" quando alcuni degli elementi dell'elenco sono selezionati.

Data una casella con un ID #select_alle diverse caselle con una classe.select_one ,

La classe CSS che sfuma la casella "seleziona tutto" sarebbe la seguente:

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

E il codice JS che gestisce il tri-stato della casella di controllo Seleziona tutto è il seguente:

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

Puoi provarlo qui: http://jsfiddle.net/98BMK/

Spero che aiuti!



1
Testato in Chrome v35 e la casella di controllo "tutto" seleziona solo le altre caselle al primo clic. Dopodiché funziona solo per deselezionare le altre caselle di controllo. Risolto in questa versione: jsfiddle.net/CHRSb/1
rdans,

2
.prop('checked', ...)dovrebbe essere usato al posto di .attr('checked', ...).
Luna,

Ho risolto i bug segnalati da Ross; nuovo violino qui .
Mike DeSimone,

48

È possibile utilizzare l' indeterminateattributo IDL HTML sugli inputelementi.


3
Secondo Bert Bos in un'e-mail del 2002 (< lists.w3.org/Archives/Public/www-dom/2002JanMar/0014.html> ), IE / Win e IE / Mac lo hanno supportato dalla versione 4. Firefox sembra l'ho implementato nella versione 3.6. Sembra anche essere stato implementato in Safari nel 2008. Penso che non faccia molti utenti finali.
Ms2ger,

utilizzare invece questo URL ( help.dottoro.com/ljuocesd.php ). Mostra chi lo supporta (tutti bar opera), da quando, e visualizza visivamente di cosa si tratta. Le persone hanno paura delle pagine delle specifiche. +1 per questa soluzione non plug-in
Hashbrown,

15

La mia proposta sarebbe in uso

  • tre caratteri Unicode appropriati per i tre stati, ad esempio ❓, ✅, ❌
  • un campo di input di testo semplice (dimensione = 1)
  • nessun confine
  • sola lettura
  • non visualizza alcun cursore
  • gestore di clic per passare da uno stato all'altro

Vedi esempi su:

/**
 *  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

È possibile utilizzare i gruppi radio per ottenere tale funzionalità:

<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
Lo so grazie. :) Attualmente sto usando selects, ma il modulo si sta un po 'ingombra.
Pekka,

1
Bene, allora che aspetto avrebbe esattamente il terzo stato? Proprio come quando la casella di controllo è disabilitata? Come vorresti attivarlo?
Franz,

3

Penso che il modo più semantico sia usare l' readonlyattributo che gli input della casella di controllo possono avere. Nessun CSS, nessuna immagine, ecc .; una proprietà HTML integrata!

Vedi violino:
http://jsfiddle.net/chriscoyier/mGg85/2/

Come descritto qui nell'ultimo trucco: http://css-tricks.com/indeterminate-checkboxes/


Bella soluzione, ma purtroppo non funziona in IE (test con la versione 11) poiché i clic più veloci non vengono più riconosciuti.
ViRuSTriNiTy

3

Ecco un esempio eseguibile usando l' indeterminateattributo citato :

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 eseguire lo snippet di codice per vedere come appare.


2

Come la risposta di @Franz, puoi farlo anche con una selezione. Per esempio:

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

Con questo puoi anche dare un valore concreto che verrà inviato con il modulo, penso che con la versione indeterminata della casella di controllo JavaScript, invierà il valore sottolineato della casella di controllo.

Almeno, puoi usarlo come callback quando javascript è disabilitato. Ad esempio, assegnagli un ID e, in caso di caricamento, modificalo nella versione javascript della casella di controllo con stato indeterminato.


2

Oltre a tutti quelli citati sopra, ci sono plugin jQuery che possono aiutare anche:

per singole caselle di controllo:

per le caselle di controllo del comportamento ad albero:

EDIT Entrambe le librerie utilizzano l' attributo checkbox " indeterminato ", poiché questo attributo in HTML5 è solo per lo styling ( https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state ), il valore null non viene mai inviato al server (le caselle di controllo possono avere solo due valori).

Per poter inviare questo valore al server, ho creato campi di controparte nascosti che vengono compilati al momento dell'invio del modulo utilizzando javascript. Sul lato server, ovviamente, dovrai selezionare i campi di contropartita anziché le caselle di controllo originali.

Ho usato la prima libreria (caselle di controllo indipendenti) in cui è importante:

  • Inizializza i valori controllati, non selezionati, indeterminati
  • utilizzare la funzione .val () per ottenere il valore effettivo
  • Impossibile far funzionare .state (probabilmente il mio errore)

Spero che aiuti.


2

Ecco altri esempi con jQuery e proprietà semplici 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

Facendo riferimento alla risposta di @BoltClock , ecco la mia soluzione per un metodo ricorsivo più complesso:

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

Potrebbe non essere la soluzione più carina ma funziona bene per me ed è abbastanza flessibile.

Uso due oggetti dati che definiscono il contenitore:

data-select-all="chapter1"

e gli elementi stessi:

data-select-some="chapter1"

Entrambi hanno lo stesso valore. La combinazione di entrambi gli oggetti dati all'interno di una casella di controllo consente i livelli secondari, che vengono scansionati in modo ricorsivo. Pertanto sono necessarie due funzioni "helper" per impedire il trigger di modifica.



0

È possibile avere gli elementi del modulo HTML disabilitati - non sarebbe così? I tuoi utenti lo vedrebbero in uno dei tre stati, ovvero selezionato, deselezionato e disabilitato, che sarebbe disattivato e non selezionabile. A me sembra simile a "null" o "non applicabile" o qualunque cosa tu stia cercando in quel terzo stato.


Ottima idea, ma ho bisogno che l'utente sia in grado di fare nuovamente clic. Temo che su una casella di controllo disabilitata, avrò problemi a sparare eventi e così via.
Pekka,

puoi comunque vedere il valore di una casella di spunta disabilitata, il che confonde l'utente se il valore non è importante.
Janus Troelsen,

Penso che "null" significhi rappresentare l'utente che non fornisce una risposta alla domanda. Ciò non significa necessariamente che la domanda non sia applicabile.
bdsl


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.