小成本实现部分选中的复选框

大家都知道,HTML 里复选框(checkbox)表示选中状态的 checked 属性,只有选中和没被选中两种情况。但有时候,我们还要表示「部分选中」状态:如实现树或表格勾选时,当用户选择一部分子记录,父记录的状态就应该是部分选择。

通常的做法

有很多方案可以实现这个需求,这里列举两个有代表性的简单介绍下:

1)利用 checkbox 自身其他属性来模拟。如下图,用 disabled 的选中状态来表示部分选中。

ucren tree(来源:ucren2008 的树组件)

这种方案的好处是实现简单。坏处是占用了复选框的 disabled 状态,会导致某些需求无法实现,也不直观。更严重的是,大部分浏览器处理键盘 tab 按键时会跳过 disabled 元素,这会导致上图中表示部分选择的 checkbox 无法用键盘操作。

2)利用图片等其他元素来模拟。如下图,整个 checkbox 都是其他元素模拟出来的。

ztree(来源:zTree

这种方案使用图片模拟 checkbox,不受系统控件限制,可以实现任何想要的效果,但系统控件往往有着大量交互细节和可用性考虑,要全部模拟会比较复杂。

indeterminate 属性

实际上,checkbox 有一个叫 indeterminate 的属性,把它设为 true,就可以让 checkbox 变为「部分选中」的样子。这个属性只是改变 checkbox 的外观,不对它的 checked 属性产生影响。另外,indeterminate 属性只能通过 JavaScript 来设置。来看下实际效果:

需要注意的是,indeterminate 并不是最近才出现的,很久以前它还是 IE 的一个私有属性,IE5 就支持。后来的浏览器基本上都支持:

  • IE 5+;
  • Firefox 3.6+;
  • Chrome 全系列;
  • Opera 11+;
  • Safari Mac 和 iOS 版;

W3C 的 HTML5 文档包含了对 checkbox indeterminate 属性的定义;CSS3 文档中也有 :indeterminate 伪类选择器,用来选择「部分选中的 checkbox」,如下例:

<style>:indeterminate + span { color: red; }</style>

<input type="checkbox" id="cbTest2"> <span>这是一段文字</span>

<script>
    document.getElementById('cbTest2').indeterminate = true;
</script>

注意事项

不同浏览器和操作系统在对 indeterminate 属性展现上有些差异,这是原生表单控件的共同特点。我觉得没什么问题,但可能有些产品经理或设计师无法接受。

另外一个比较大的问题是,IE 与其他浏览器在处理点击 indeterminate 为 true 的 checkbox 时的差异。通过点击或空格键操作部分选中的 checkbox 时,在 mouseup 或者 keyup 阶段,所有浏览器都会将 indeterminate 属性改为 false,但 IE 是到此为止,其他浏览器还会改变 checkbox 的 checked 状态。也就是说对于以下代码:

<input id="chk1" type="checkbox" />
<script>
    document.getElementById('chk1').indeterminate = true;
</script>

各浏览器都会显示为部分选中的 checkbox。但点一下它,IE 下会是未选中状态,其他浏览器会变成选中状态。

这个特性可以通过创建临时元素来探测:

var tmp = document.createElement("input");
tmp.type = "checkbox";
tmp.checked = false;
tmp.indeterminate = true;

var body = document.body;
body.appendChild(tmp);
tmp.click();
body.removeChild(tmp);

alert(tmp.checked); //IE 是 false,其他浏览器是 true

结论

有时候,合理利用浏览器原生控件来实现一些功能,既简单高效,又有良好的体验和可用性,何乐而不为呢?

phpmyadmin(来源:phpmyadmin

本文链接:参与评论 »

--EOF--

提醒:本文最后更新于 1081 天前,文中所描述的信息可能已发生改变,请谨慎使用。

专题「浏览器」的其他文章 »

Comments