HTML 中的三状态复选框 Tri-state 复选框? ?

在 HTML 中不可能有一个三状态检查按钮(是,否,null) ,对吗?

有没有什么简单的技巧或变通方法,而不需要自己完成整件事情?

121653 次浏览

您可以使用无线电群组来实现这一功能:

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

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

这里举个例子: http://www.dynamicdrive.com/forums/archive/index.php/t-26322.html

可以使用 HTML 表单元素 残疾人——这样不就行了吗?您的用户将看到它处于三种状态之一,即选中、未选中和禁用状态,这些状态将变成灰色且不可点击。对我来说,这似乎类似于“无效”或“不适用”或任何你正在寻找的第三种状态。

多亏了 Janus Troelsen 的评论,我找到了一个更好的解决方案:

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

为了使复选框在视觉上看起来不确定,将它设置为 true:

element.indeterminate = true;

这里是 Janus Troelsen 的小提琴。不过,请注意:

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

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

  • 浏览器测试: 在 Chrome22,Firefox15,Opera 12和 IE7中都可以。在移动浏览器方面,Android 2.0浏览器和 iOS 3.1上的 Safari 移动浏览器都不支持。

前一个答案

另一种选择是使用复选框透明性 为“一些选定”的状态(如 Gmail 是的用来 这需要一些 javascript 和 CSS 这里我放了一个特殊的例子来处理一个带有 可选项和一个允许选择所有/不选项的复选框。 此复选框显示当某些列表 项目被选中。

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

淡出“ select all”复选框的 CSS 类将是 以下内容:

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

以及处理 select all 复选框的三态的 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/

希望能帮上忙!

您可以在 input元素上使用 HTML 的 indeterminate IDL 属性

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

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

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

马特

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

像@Franz 这样的回答,你也可以通过选择来完成,例如:

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

通过这种方式,您还可以给出一个具体的值,这个值将随表单一起发送,我认为对于 javascript 不确定版本的复选框,它将发送该复选框的下划线值。

至少,您可以在禁用 javascript 时使用它作为回调。例如,给它一个 id,并在加载事件中将其更改为具有不确定状态的复选框的 javascript 版本。

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

看小提琴:
Http://jsfiddle.net/chriscoyier/mgg85/2/

正如最后一个技巧所描述的: Http://css-tricks.com/indeterminate-checkboxes/

我的提案将使用

  • 三种状态的三个适当的 Unicode 字符,例如 & # x2753; ,& # x2705; ,& # x274C;
  • 纯文本输入字段(size = 1)
  • 没有边界
  • 只读
  • 不显示光标
  • 单击处理程序来切换这三种状态

请参考以下例子:

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

关于@BoltClock 回答,下面是我对更复杂的递归方法的解决方案:

Http://jsfiddle.net/gx7so2tq/2/

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

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

data-select-all="chapter1"

以及元素本身:

data-select-some="chapter1"

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

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

对于单个复选框:

树状行为复选框:

剪辑 这两个库都使用‘ 不确定’复选框属性,因为 Html5中的这个属性只是用于样式(https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state) ,所以空值从不发送到服务器(复选框只能有两个值)。

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

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

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

希望能帮上忙。

下面是一个使用上述 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>

只要运行代码片段就可以看到它的外观。

这里还有一个带有简单 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>

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

<!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>

基于上述使用不确定状态的答案,我想出了一些处理单个复选框并使其成为三态的方法。

MVC 剃须刀每个复选框使用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);
});

使用辅助变量和 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)">

Only state==0 is captured. The rest is handle automatically.

http://jsfiddle.net/6vyek2c5