HTML中的三态复选框?

197

在HTML中,没有三态复选按钮(是、否、空值),对吗?

有没有简单的技巧或解决方法,而不必自己渲染整个按钮?


在你的使用中,“no”和“null”之间的功能上有什么区别? - David Thomas
5
请看以下答案(除了我的)。"Null" 意思类似于“无回答”... - Franz
2
没错,它是一个带有祖先的项目,“null”意味着“使用父级值”。 - Pekka
9
一种三态复选框的替代用途是在搜索/筛选时使用。例如,假设我有一个界面来搜索一系列二手车。其中一个搜索选项可能是这辆车是否有天窗。可以使用三种状态如下:仅显示拥有天窗的汽车 仅显示没有天窗的汽车 显示两者当然,这可以通过多种方式处理...我们可以使用下拉菜单,或者我们可以使用一组三个单选按钮...但是三态复选框(它可以为空、有一个绿色的勾号或者有一个红色的叉号)也是一个不错的解决方案。 - Mir
4
在一个复选框列表中,添加一个复选框在列表头部,用于勾选或取消勾选所有剩余的复选框,这样做会很有用。如果所有的复选框都被勾选了,那么列表头部的复选框也应该被勾选。如果所有的复选框都没有被勾选,那么列表头部的复选框也应该未被勾选。如果复选框列表同时包含已勾选和未勾选的选项,那么在列表头部显示复选框处于中间状态,可以提供视觉反馈。这个列表头部的复选框不会带有任何值,它只是一种视觉提示和用户界面辅助工具。另外,能够在三种状态之间切换列表头部的复选框也会非常方便。 - Jason
显示剩余2条评论
18个回答

143

编辑 — 感谢 Janus Troelsen 的评论,我找到了更好的解决方案:

HTML5 为复选框定义了一个叫做 indeterminate 的属性

请参阅w3c reference guide。要使复选框在视觉上呈现不确定状态,请将其设置为 true:

element.indeterminate = true;

这里是Janus Troelsen的fiddle。但请注意:

  • indeterminate状态无法在HTML标记中设置,只能通过Javascript来实现(参见这个JSfiddle test和这篇CSS tricks详细文章)。

  • 此状态不会改变复选框的值,它只是一个视觉提示,掩盖了输入的真实状态。

  • 浏览器测试:在Chrome 22、Firefox 15、Opera 12和IE7上测试成功。关于移动浏览器,Android 2.0浏览器和iOS 3.1上的Safari移动版不支持它。

之前的答案

Another alternative would be to play with the checkbox transparency for the "some selected" state (as Gmail does used to do in previous versions). It will require some javascript and a CSS class. Here I put a particular example that handles a list with checkable items and a checkbox that allows to select all/none of them. This checkbox shows a "some selected" state when some of the list items are selected.

Given a checkbox with an ID #select_all and several checkboxes with a class .select_one,

The CSS class that fades the "select all" checkbox would be the following:

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

And the JS code that handles the tri-state of the select all checkbox is the following:

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

You can try it here: http://jsfiddle.net/98BMK/


13
我将它改成了使用HTML5的不确定属性(indeterminate attribute)(链接:http://jsfiddle.net/ysangkok/UhQc8/)。 - Janus Troelsen
1
在Chrome v35中测试,"all"复选框只在第一次单击时检查其他框。之后,它只能用于取消选中其他复选框。在此版本中已修复:http://jsfiddle.net/CHRSb/1/ - rdans
3
应该使用.prop('checked', ...)而不是.attr('checked', ...) - Luna
我修复了Ross指出的错误; 新的fiddle在这里 - Mike DeSimone
幸运的是,CSS Tricks文章(https://css-tricks.com/indeterminate-checkboxes/)有一个纯js版本,不需要92k的库来完成这样一个几乎微不足道的任务。 - Patanjali
我恳请回答问题的人尽可能使用最少的依赖项。不要假设人们正在使用大型库。一般来说,库需要持续更新,并且会大幅增加入侵风险向量。 - Patanjali

49

3
据2002年Bert Bos在一封电子邮件中所说,自IE/Win和IE/Mac 4版本起就支持此功能。Firefox在3.6版本中似乎已经实现了它。Safari在2008年似乎也实现了它。我认为这并不涉及到很多最终用户。 - Ms2ger
请使用此网址(http://help.dottoro.com/ljuocesd.php)来查看以下与编程有关的内容的翻译。所有浏览器都支持它,除了Opera浏览器,自从什么时候开始支持它,以及视觉上展示它是什么。人们害怕规范页面。为这个非插件解决方案加1分。 - Hashbrown

18

我的建议是使用三个适当的Unicode字符来表示三种状态,例如❓、✅、❌

  • 一个普通文本输入字段(size=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; 
       };" />  


6
你可以使用单选按钮组来实现这个功能:
<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
我知道,谢谢。:) 我目前正在使用选择器,但表单有点混乱。 - Pekka
1
那么,第三种状态到底会是什么样子呢?就像复选框被禁用时一样吗?你想如何触发它? - Franz


4

3
在这个 已有答案的问题 中,讨论了如何在HTML中创建三态复选框。 - Hashbrown

3

很好的解决方案,但遗憾的是在IE(版本11)中无法工作,因为快速点击不再被识别。 - ViRuSTriNiTy

2

像@Franz的回答一样,您也可以使用


2
除了上述提到的,还有一些jQuery插件也可以帮助实现复选框功能:
对于单个复选框:
- jQuery-Tristate-Checkbox-plugin: http://vanderlee.github.io/tristate/ 对于树状结构的复选框:
- jQuery Tristate: http://jlbruno.github.io/jQuery-Tristate-Checkbox-plugin/ 注意:这两个库都使用了“indeterminate”属性,因为在Html5中,该属性仅用于样式(https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state),null值永远不会发送到服务器(复选框只能有两个值)。
为了能够将此值提交到服务器,我创建了隐藏的相应字段,在表单提交时使用一些javascript来填充这些字段。在服务器端,您需要检查这些相应字段而不是原始复选框。
我使用第一个库(独立复选框)时需要注意以下几点:
- 初始化已选、未选和不确定值 - 使用.val()函数获取实际值 - 无法使用.state(可能是我的错误)
希望这能帮到您。

1

参考@BoltClock的答案,下面是我对于一种更加复杂的递归方法的解决方案:

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

我可能不是最好的解决方案,但对我来说很有效,并且非常灵活。

我使用两个数据对象来定义容器:

data-select-all="chapter1"

以及元素本身:

data-select-some="chapter1"

两者具有相同的值。将两个数据对象组合在一个复选框中允许子级,这些子级被递归扫描。因此需要两个“辅助”函数来防止更改触发器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接