1. 程式人生 > >小成本實現部分選中的複選框

小成本實現部分選中的複選框

提醒:本文最後更新於 1795 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

大家都知道,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

結論

有時候,合理利用瀏覽器原生控制元件來實現一些功能,既簡單高效,又有良好的體驗和可用性,何樂而不為呢?

--EOF--

提醒:本文最後更新於 1795 天前,文中所描述的資訊可能已發生改變,請謹慎使用。