Три состояния флажок в HTML?

163

В HTML нет кнопки проверки трех состояний (да, нет, ноль), верно?

Есть ли какие-то простые трюки или обходные пути без необходимости визуализировать все это самостоятельно?

Пекка
источник
Функционально, в чем разница между «нет» и «ноль» в вашем использовании?
Дэвид говорит восстановить Монику
5
Посмотрите на ответы ниже (кроме моего). «Нуль» означает что-то вроде «Нет ответа» ...
Франц
2
Именно. Это элемент с предками, и «ноль» означает «использовать родительское значение».
Пекка
7
Альтернативное использование для флажка с тремя состояниями - при поиске / фильтрации. Например, предположим, у меня есть интерфейс для поиска в списке подержанных автомобилей. Один из вариантов поиска может быть, есть ли у автомобиля люк на крыше. Три состояния можно использовать следующим образом: показывать только автомобили с люком на крыше показывать только автомобили без люка на крыше показывать оба варианта Теперь, конечно, это может быть обработано несколькими способами ... мы могли бы использовать раскрывающийся список или использовать набор из трех переключателей ... но флажок с тремя состояниями (который либо пуст, либо имеет зеленую отметку, либо имеет красный крестик) также является хорошим решением.
Мир
2
Было бы полезно для списка флажков, с одним флажком в начале списка, чтобы либо отметить, либо снять все остальные флажки. Если все проверено, то флажок заголовка может отражать это. Если все не отмечено, флажок заголовка может отражать это тоже. Если список содержит комбинацию отмеченных и не отмеченных флажков, то отображение флажка заголовка в промежуточном состоянии обеспечит визуальную обратную связь. Этот флажок заголовка никогда не будет иметь значения - это всего лишь визуальная подсказка и помощь пользовательского интерфейса. Возможность переключения флажка головы между всеми тремя состояниями также была бы удобной.
Джейсон

Ответы:

119

Редактировать - благодаря комментарию Януса Троелсена я нашел лучшее решение:

HTML5 определяет свойство для флажков, называемых indeterminate

См. Справочное руководство w3c . Чтобы сделать флажок визуально неопределенным, установите для него значение true:

element.indeterminate = true;

Вот скрипка Януса Троелсена . Обратите внимание, однако, что:

  • indeterminateСостояние не может быть установлено в HTML - разметке, это может быть сделано только с помощью Javascript (см этого теста JSfiddle и этой подробной статьи в CSS трюках )

  • Это состояние не меняет значение флажка, это всего лишь визуальная подсказка, которая маскирует реальное состояние ввода.

  • Тест браузера: у меня работал в Chrome 22, Firefox 15, Opera 12 и обратно в IE7. Что касается мобильных браузеров, браузер Android 2.0 и Safari mobile на iOS 3.1 не поддерживают его.

Предыдущий ответ

Другой альтернативой было бы поиграть с прозрачностью флажка для состояния «некоторые выбраны» (как это делал Gmail в предыдущих версиях). Это потребует некоторого JavaScript и CSS-класса. Здесь я поместил конкретный пример, который обрабатывает список с проверяемыми элементами и флажок, который позволяет выбрать все / ни один из них. Этот флажок показывает состояние «некоторые выбраны» при выборе некоторых элементов списка.

Учитывая флажок с идентификатором #select_allи несколько флажков с классом .select_one,

Класс CSS, который скрывает флажок «выбрать все», будет следующим:

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

И код JS, который обрабатывает три состояния флажка select all, следующий:

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

Вы можете попробовать это здесь: http://jsfiddle.net/98BMK/

Надеюсь, это поможет!

pau.moreno
источник
1
Протестировано в Chrome v35, и флажок «все» проверяет только остальные поля при первом нажатии. После этого работает только снятие других флажков. Исправлено в этой версии: jsfiddle.net/CHRSb/1
rdans
2
.prop('checked', ...)следует использовать вместо .attr('checked', ...).
Луна
Я исправил ошибки, указанные Россом; новая скрипка здесь .
Майк ДеСимоне
48

Вы можете использовать HTML в indeterminateатрибут IDL на inputэлементы.

Ms2ger
источник
3
Согласно Берту Босу в электронном письме от 2002 года (< lists.w3.org/Archives/Public/www-dom/2002JanMar/0014.html> ), IE / Win и IE / Mac поддерживают его с версии 4. Firefox, по-видимому, реализовали его в версии 3.6. Похоже, что он был реализован в Safari в 2008 году. Я думаю, что это не так много для конечных пользователей.
Ms2ger
используйте этот URL ( help.dottoro.com/ljuocesd.php ) вместо этого. Он показывает, кто его поддерживает (каждый бар оперы), с каких пор и визуально отображает, что это такое. Люди боятся страниц спецификаций. +1 за это не плагин решение
Hashbrown
15

Мое предложение будет использовать

  • три соответствующих символа Юникода для трех состояний, например, ❓, ✅, ❌
  • поле ввода простого текста (размер = 1)
  • без границ
  • только для чтения
  • не отображать курсор
  • обработчик onclick для переключения между тремя состояниями

Смотрите примеры на:

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

Вы можете использовать радиогруппы для достижения этой функциональности:

<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
источник
1
Я знаю это, спасибо. :) В настоящее время я использую select, но форма становится немного загроможденной.
Пекка
1
Ну, тогда как именно будет выглядеть третье государство? Так же, как когда флажок отключен? Как бы вы хотели вызвать это?
Франц
3

Я думаю, что наиболее семантическим способом является использование readonlyатрибутов, которые могут иметь входные данные флажков. Нет CSS, нет изображений и т.д .; встроенное свойство HTML!

Смотрите Фиддл:
http://jsfiddle.net/chriscoyier/mGg85/2/

Как описано здесь в последнем трюке: http://css-tricks.com/indeterminate-checkboxes/

Webinan
источник
Хорошее решение, но, к сожалению, это не работает в IE (тест с версией 11), поскольку более быстрые щелчки больше не распознаются.
ВИРУСТРИНИКА
3

Вот исполняемый пример с использованием упомянутого indeterminateатрибута :

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>

Просто запустите фрагмент кода, чтобы увидеть, как он выглядит.

gil.fernandes
источник
2

Как ответ @Franz, вы также можете сделать это с помощью выбора. Например:

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

При этом вы также можете дать конкретное значение, которое будет отправлено с формой, я думаю, что с неопределенной версией чекбокс javascript, он будет отправлять значение подчеркивания чекбокс.

По крайней мере, вы можете использовать его в качестве обратного вызова, когда JavaScript отключен. Например, присвойте ему идентификатор и в событии загрузки измените его на версию флажка javascript с неопределенным статусом.

PhoneixS
источник
2

Помимо всего вышеперечисленного, могут также помочь плагины jQuery:

для отдельных флажков:

для флажков древовидного поведения:

РЕДАКТИРОВАТЬ Обе библиотеки используют атрибут флажка « неопределенный », так как этот атрибут в Html5 только для стиля ( https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state ), нулевое значение никогда не отправляется на сервер (флажки могут иметь только два значения).

Чтобы иметь возможность отправить это значение на сервер, я создал скрытые поля аналога, которые заполняются при отправке формы с использованием некоторого JavaScript. На стороне сервера, вам, конечно, нужно проверять эти поля вместо оригинальных.

Я использовал первую библиотеку (автономные флажки), где важно:

  • Инициализировать отмеченные, непроверенные, неопределенные значения
  • используйте функцию .val (), чтобы получить фактическое значение
  • Не могу заставить работать .state (возможно, моя ошибка)

Надеюсь, это поможет.

Фрэнк Себастиа
источник
2

Вот другой пример с простым jQuery и свойством 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

Ссылаясь на ответ @BoltClock , вот мое решение для более сложного рекурсивного метода:

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

Возможно, это не самое симпатичное решение, но оно отлично работает для меня и довольно гибко.

Я использую два объекта данных, определяющих контейнер:

data-select-all="chapter1"

и сами элементы:

data-select-some="chapter1"

Оба имеют одинаковое значение. Комбинация обоих объектов данных в одном флажке позволяет использовать подуровни, которые сканируются рекурсивно. Поэтому для предотвращения триггера изменения необходимы две вспомогательные функции.

MFH
источник
0

Можно отключить элементы HTML-формы - не так ли? Ваши пользователи увидят его в одном из трех состояний: проверено, не проверено и отключено, и оно будет серым и недоступным для нажатия. Мне кажется, что это похоже на «ноль» или «не применимо» или что-то, что вы ищете в этом третьем состоянии.

AmbroseChapel
источник
Очень хорошая идея, но мне нужно, чтобы пользователь мог снова щелкнуть по нему. Я боюсь, что при отключенном флажке у меня будут проблемы с запуском событий и так далее.
Пекка
Вы по-прежнему можете видеть значение отключенного флажка, который вводит пользователя в заблуждение, если значение не имеет значения.
Янус Троелсен
Я думаю, что «ноль» означает представлять пользователя, не предоставившего ответ на вопрос. Это не обязательно означает, что вопрос не применим.
BDSL