同事今天提的需求,ASP.NET CheckBoxList裡放了一個全選Checkbox,希望做到以下效果:
1) 勾選"全選"Checkbox時,清除所有其他Checkbox的選取
2) 勾選任一非全選Checkbox時,清除"全選"Checkbox的選取

順手寫了以下的Code,裡面有些有趣的JavaScript技巧,所以拿出來 炫耀 分享一下。(看起來有點偏長,不過我暫時想不出更精簡的寫法了,如果大家有好點子,也歡迎提出來切磋一下。)

   1:  <span id="selMarket" >
   2:  <input id="selMarket_0" type="checkbox" name="selMarket:0" />
   3:      <label for="selMarket_0">全部</label>
   4:  <input id="selMarket_1" type="checkbox" name="selMarket:1" />
   5:      <label for="selMarket_1">上市</label>
   6:  <input id="selMarket_2" type="checkbox" name="selMarket:2" />
   7:      <label for="selMarket_2">上櫃</label>
   8:  <input id="selMarket_3" type="checkbox" name="selMarket:3" />
   9:      <label for="selMarket_3">興櫃</label>
  10:  </span>
  11:  <script type="text/javascript">
  12:  function afa_CBL_SelAll_Hook(CBLId, selAllCbxIdx) {
  13:      //用Checkboxlist ID找到外層的span Element
  14:      var spnCBL = document.getElementById(CBLId);
  15:      //取得其中的Checkbox陣列
  16:      var objInp = spnCBL.getElementsByTagName("input");
  17:      //將資訊偷藏在span的Attribute中
  18:      spnCBL.setAttribute("ItemsCount", objInp.length);
  19:      spnCBL.setAttribute("SelAllIdx", selAllCbxIdx);
  20:      //在每一個Checkbox都掛上onclick事件
  21:      for (var i=0; i<objInp.length; i++)
  22:          objInp[i].onclick = afa_CBL_SelAll_Click;
  23:  }
  24:  function afa_CBL_SelAll_Click(evt) {
  25:      //設法找出觸發onclick的Checkbox是哪一個,方法IE/FF有別
  26:      var inp = null;
  27:      if (window.event) inp = event.srcElement;  //IE
  28:      if (evt) inp = evt.target; //Firefox
  29:      if (inp == null) return;
  30:      //去掉ID尾端的'_n',算出span的名字
  31:      var spnName = inp.id.substring(0, inp.id.lastIndexOf("_"));
  32:      //找到span Element,取出藏在Attribute的資訊
  33:      var spnCBL = document.getElementById(spnName);
  34:      var selAllIdx = spnCBL.getAttribute("SelAllIdx");
  35:      var itemsCount = spnCBL.getAttribute("ItemsCount");
  36:      //看看是否為全選
  37:      var isSelAllCbx = (inp.id == (spnName + "_" + selAllIdx));
  38:      //當全選被選取時,其他選項全清
  39:      if (isSelAllCbx && inp.checked)
  40:          for (var i=0; i<itemsCount; i++) 
  41:          {
  42:              if (i == selAllIdx) continue;
  43:              var inpX = document.getElementById(spnName + "_" + i);
  44:              inpX.checked = false;
  45:          }         
  46:      else if (inp.checked) //其他選項被選取時,清除全選的設定
  47:          document.getElementById(spnName + "_" + selAllIdx).checked = false;
  48:  }
  49:  //傳入Checkboxlist名稱及全選Checkbox的Index即可用
  50:  afa_CBL_SelAll_Hook("selMarket", 0);
  51:  </script>

【說明】
Line 16: 利用getElementsByTagName("input")一口氣取出span下的所有INPUT成為陣列。
Line 18/19: 利用span.setAttribute("...");將相關的資訊藏在Element本身,最大的好處是要用同樣的Code要處理多個Element時,從Element本身就可以取得必要的資訊,不必另找地方放(我以前會傻傻地建類似Hashtable的結構來放多個Element的相關參數)。也可以直接寫成span.attributeName="...",但我覺得用setAttribute與內建的member有所區隔比較易讀。
Line 26-28: IE與FireFox取得觸發事件苦主的寫法不同,在不引用AJAX Framework的前題下,自己處理這段挺累的。


Comments

# by 路人甲

善用 javascript library 會更精簡...

Post a comment