HTML 中的三态复选框?

Tri-state Check box in HTML?

提问人:Pekka 提问时间:11/13/2009 更新时间:12/25/2022 访问量:130828

问:

在 HTML 中没有三态检查按钮(是、否、空),对吧?

是否有任何简单的技巧或变通方法,而不必自己渲染整个事情?

HTML 表单 复选框

评论

0赞 David Thomas 11/13/2009
从功能上讲,在您的用法中,“no”和“null”有什么区别?
5赞 Franz 11/13/2009
看看下面的答案(除了我的)。“Null”的意思是“没有答案”......
2赞 Pekka 11/13/2009
完全。这是一个具有祖先的项目,“null”表示“使用父值”。
9赞 Mir 12/16/2011
三态复选框的另一种用法是在搜索/筛选时。例如,假设我有一个搜索二手车列表的界面。其中一个搜索选项可能是汽车是否有天窗。这三种状态可以按如下方式使用: 只展示带天窗的汽车 只展示没有天窗的展示车 同时显示两者 现在,当然,这可以通过多种方式处理......我们可以使用一个下拉列表,或者我们可以使用一组三个单选按钮......但是三态复选框(要么是空的,要么是绿色的,要么是红色的X)也是一个不错的解决方案。
4赞 Jason 8/8/2017
对于复选框列表来说,这将是有用的,列表顶部有一个复选框可以选中或取消选中所有剩余的框。如果全部选中,则标题复选框可以反映这一点。如果全部未选中,则标题复选框也可以反映这一点。如果列表包含选中和未选中框的组合,则在中间状态下显示标题复选框将提供视觉反馈。该标题复选框永远不会带有值 - 它只是一个视觉提示和 UI 辅助工具。能够在所有三种状态之间切换头部复选框也很方便。

答:

6赞 Franz 11/13/2009 #1

您可以使用单选按钮组来实现该功能:

<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 11/13/2009
我知道,谢谢。:)我目前正在使用选择,但表单变得有点混乱。
1赞 Franz 11/13/2009
那么,第三种状态到底会是什么样子呢?就像复选框被禁用时一样?你想如何触发它?
0赞 Dan McGrath 11/13/2009 #2

你需要使用 javascript/css 来伪造它。

请尝试此处的示例:http://www.dynamicdrive.com/forums/archive/index.php/t-26322.html

0赞 AmbroseChapel 11/13/2009 #3

可以禁用 HTML 表单元素 -- 这不是吗?您的用户将看到它处于三种状态之一,即选中、未选中和禁用,这些状态将显示为灰色且不可单击。对我来说,这似乎类似于“null”或“不适用”或您在第三种状态中寻找的任何内容。

评论

0赞 Pekka 11/13/2009
非常好的主意,但我需要用户能够再次单击它。我担心在禁用的复选框上,我无法触发事件等。
0赞 Janus Troelsen 9/29/2012
您仍然可以看到已禁用复选框的值,如果该值不重要,则用户会感到困惑。
0赞 bdsl 3/24/2016
我认为“null”表示用户没有提供问题的答案。这并不一定意味着这个问题不适用。
143赞 pau.moreno 1/18/2011 #4

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

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

请参阅 w3c 参考指南。要使复选框在视觉上不确定,请将其设置为 true:

element.indeterminate = true;

这是Janus Troelsen的小提琴。但请注意:

  • 状态不能在 HTML 标记中设置,只能通过 Javascript 完成(请参阅此 JSfiddle 测试CSS 技巧中的详细文章indeterminate)

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

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

上一个答案

另一种选择是使用复选框透明度 对于“某些选定”状态(就像 Gmail 过去所做的那样 在以前的版本中执行)。它将需要一些 javascript 和 CSS 类。在这里,我举了一个特定的例子,它处理一个列表 可检查的项目和一个允许选择所有/不选择任何项目的复选框。 此复选框显示“某些选定”状态,当某些列表 项目被选中。

给定一个带有 ID 的复选框和几个带有 一个类,#select_all.select_one

淡化“全选”复选框的 CSS 类将是 以后:

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

以及处理全选复选框的三态状态的 JS 代码 如下所示:

$('#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/

评论

13赞 Janus Troelsen 9/29/2012
修改了它以使用 HTML5 的不确定属性
1赞 rdans 6/18/2014
在 chrome v35 中测试,“全部”复选框仅在第一次单击时选中其他框。在此之后,它只能取消选中其他复选框。在此版本中修复:jsfiddle.net/CHRSb/1
3赞 Luna 7/15/2015
.prop('checked', ...)应该使用而不是 ..attr('checked', ...)
0赞 Mike DeSimone 12/2/2015
我修复了罗斯指出的错误;这里是新小提琴
0赞 Patanjali 11/5/2021
幸运的是,CSS Tricks 文章(css-tricks.com/indeterminate-checkboxes)有一个不需要 92k 的普通 js 版本!!库,完成如此几乎微不足道的任务。
49赞 Ms2ger 1/18/2011 #5

您可以在元素上使用 HTML 的不确定 IDL 属性input

评论

3赞 Ms2ger 3/4/2013
根据 Bert Bos 在 2002 年的一封电子邮件(<lists.w3.org/Archives/Public/www-dom/2002JanMar/0014.html>),IE/Win 和 IE/Mac 从第 4 版开始就支持它。Firefox 似乎已经在 3.6 版中实现了它。它似乎也在 2008 年的 Safari 中实现。我认为这不会使很多最终用户。
0赞 Hashbrown 10/4/2013
请改用此 URL (help.dottoro.com/ljuocesd.php)。它显示了谁支持它(每个人都从什么时候开始),并直观地显示它是什么。人们害怕规范页面。+1 对于这个非插件的解决方案
0赞 Peter 9/7/2011 #6

https://github.com/supernifty/tristate-checkbox 中有一个简单的 JavaScript 三态输入字段实现

0赞 Matt Frear 12/16/2011 #7

带有复选框插件的jQuery插件“jstree”可以做到这一点。

http://www.jstree.com/documentation/checkbox

-马 特

4赞 altso 9/13/2012 #8

您可以使用不确定状态:http://css-tricks.com/indeterminate-checkboxes/。浏览器支持它,开箱即用,不需要任何外部 js 库。

评论

3赞 Hashbrown 10/4/2013
已经有答案了吗?
2赞 PhoneixS 4/21/2014 #9

就像@Franz答案一样,您也可以使用选择来完成。例如:

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

有了这个,您还可以给出一个将与表单一起发送的具体值,我认为使用 javascript 不确定版本的复选框,它将发送复选框的下划线值。

至少,当 javascript 被禁用时,你可以将其用作回调。例如,给它一个 id,然后在 load 事件中将其更改为具有不确定状态的复选框的 javascript 版本。

3赞 ptvty 7/15/2014 #10

我认为最语义化的方式是使用复选框输入可以具有的属性。没有css,没有图像等;一个内置的 HTML 属性!readonly

参见 Fiddle:
http://jsfiddle.net/chriscoyier/mGg85/2/

如上一招所述:http://css-tricks.com/indeterminate-checkboxes/

评论

0赞 ViRuSTriNiTy 8/25/2015
不错的解决方案,但遗憾的是,这在 IE(使用版本 11 进行测试)中不起作用,因为不再识别更快的点击。
18赞 Wolfgang Fahl 12/23/2014 #11

我的建议是使用

  • 三个适当的 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; 
       };" />  

1赞 MFH 6/17/2015 #12

参考@BoltClock答案,这是我对更复杂的递归方法的解决方案:

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

它可能不是最漂亮的解决方案,但它对我来说效果很好,而且非常灵活。

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

data-select-all="chapter1"

以及元素本身:

data-select-some="chapter1"

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

2赞 Frank Sebastià 4/15/2016 #13

除了上面提到的所有插件之外,还有一些jQuery插件也可能有所帮助:

对于单个复选框:

对于树状行为复选框:

编辑这两个库都使用“不确定”复选框属性,因为 Html5 中的此属性仅用于样式设置(https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state),因此 null 值永远不会发送到服务器(复选框只能有两个值)。

为了能够将此值提交到服务器,我创建了隐藏的对应字段,这些字段使用一些 javascript 在表单提交时填充。当然,在服务器端,您需要选中这些对应字段,而不是原始复选框。

我使用了第一个库(独立复选框),其中重要的是:

  • 初始化选中的、未选中的、不确定的值
  • 使用 .val() 函数获取实际值
  • 无法使工作 .state(可能是我的错误)

希望能有所帮助。

5赞 gil.fernandes 11/18/2019 #14

下面是一个使用上述不确定属性的可运行示例:

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>

只需运行代码片段即可查看其外观。

1赞 Ravi Makwana 2/27/2020 #15

这里有其他带有简单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>

评论

0赞 Friedrich -- Слава Україні 5/25/2022
我在这里找到了同样的例子:css-tricks.com/indeterminate-checkboxes/...
1赞 Faeldihn 8/14/2020 #16

因为我需要这样的东西 - 没有任何插件 - 用于表格中脚本生成的复选框......我最终得到了这个解决方案:

<!DOCTYPE html>
<html>
<body>

Toto <input type="checkbox" id="myCheck1" onclick="updateChkBx(this)" /><br />
Tutu <input type="checkbox" id="myCheck2" onclick="updateChkBx(this)" /><br />
Tata <input type="checkbox" id="myCheck3" onclick="updateChkBx(this)" /><br />
Tete <input type="checkbox" id="myCheck4" onclick="updateChkBx(this)" /><br />

<script>
var chkBoxState = [];

function updateChkBx(src) {
  var idx = Number(src.id.substring(7)); // 7 to bypass the "myCheck" part in each checkbox id
  if(typeof chkBoxState[idx] == "undefined") chkBoxState[idx] = false; // make sure we can use stored state at first call
  
  // the problem comes from a click on a checkbox both toggles checked attribute and turns inderminate attribute to false
  if(chkBoxState[idx]) {
    src.indeterminate = false;
    src.checked = false;
    chkBoxState[idx] = false;
  }
  else if (!src.checked) { // passing from checked to unchecked
    src.indeterminate = true;
    src.checked = true; // force considering we are in a checked state
    chkBoxState[idx] = true;
  }
}
// to know box state, just test indeterminate, and if not indeterminate, test checked
</script>

</body>
</html>
0赞 user1664043 2/6/2021 #17

在上面使用不确定状态的答案的基础上,我想出了一点来处理单个复选框并将它们设置为三态。

无论如何,MVC razor 每个复选框使用 2 个输入(复选框和具有相同名称的隐藏复选框,以始终在提交中强制执行一个值)。MVC 使用“true”作为复选框值,使用“false”作为同名的隐藏值;使其适合在 API 调用中使用布尔值。此代码段使用第三个隐藏状态在提交后保留最后一个请求值。

使用以下命令初始化的复选框将开始不确定。选中一次将打开该复选框。选中两次将关闭该复选框(返回同名的隐藏值)。第三次检查会将其返回到不确定状态(并清除隐藏的内容,因此提交将产生空白)。

该页面还使用要启动的查询字符串上的任何值填充另一个隐藏的(例如,triBox2Orig),因此可以在提交之间初始化和保留 3 个状态。

$(document).ready(function () {
    var initCheckbox = function (chkBox)
    {
        var hidden = $('[name="' + $(chkBox).prop("name") + '"][type="hidden"]');
        var hiddenOrig = $('[name="' + $(chkBox).prop("name") + 'Orig"][type="hidden"]').prop("value");
        hidden.prop("origValue", hidden.prop("value"));
        if (!chkBox.prop("checked") && !hiddenOrig) chkBox.prop("indeterminate", true);
        if (chkBox.prop("indeterminate")) hidden.prop("value", null);
        chkBox.change(checkBoxToggleFun);
    }

    var checkBoxToggleFun = function ()
    {
        var isChecked = $(this).prop('checked');
        var hidden = $('[name="' + $(this).prop("name") + '"][type="hidden"]');
        var thirdState = isChecked && hidden.prop("value") === hidden.prop("origValue");
        if (thirdState) {   // on 3rd click of a checkbox, set it back to indeterminate
            $(this).prop("indeterminate", true);
            $(this).prop('checked', false);
        }
        hidden.prop("value", thirdState ? null : hidden.prop("origValue"));
    };

    var chkBox = $('#triBox1');
    initCheckbox(chkBox);

    chkBox = $('#triBox2');
    initCheckbox(chkBox);
});
1赞 Friedrich -- Слава Україні 5/27/2022 #18

使用辅助变量的简短片段和:indeterminate

cb1.state = 1

function toggle_tristate(cb) {
    cb.state = ++cb.state % 3   // cycle through 0,1,2
    if (cb.state == 0) {
        cb.indeterminate = true;
        cb.checked = true;   // after 'indeterminate' the state 'false' follows 
    }
}
<input id="cb1" type="checkbox" onclick="toggle_tristate(this)">

仅被捕获。其余的都是自动处理的。state==0

http://jsfiddle.net/6vyek2c5