javascript/jQuery中checkbox 全選反選問題解決方案

先貼一些測試目標代碼吧java

 <div class="testdiv" id='testdiv'>
     <label for="checkboxall">
     <input type="checkbox" name="checkboxall" id="checkboxall" value="all">
     反選
     </label>     
     <p>
         <input type="checkbox" name="checkbox1">A
         <input type="checkbox" name="checkbox1"> B
         <input type="checkbox" name="checkbox1">C
     </p>
     <p>
         <input type="checkbox" name="checkbox1">D
         <input type="checkbox" name="checkbox1">E
         <input type="checkbox" name="checkbox1">F
     </p>
 </div>

再來一段BUG的代碼:瀏覽器

 $("div.testdiv label input:checkbox[name=checkboxall]").bind('change,click',function(evt){
     var e = evt || window.event;
     $isChecked = $(this).attr("checked");
     $("input:checkbox[name='checkbox1']").each(function(index,element){
        $(this).attr("checked",$isChecked);
     });
 });

錯誤分析:測試

  1. 首先這段代碼寫得不夠簡練,不必使用each遍歷,效率低,選擇器越完整,查詢速度通常越快this

$("div.testdiv input:checkbox[name='checkbox1']").attr('checked',$isChecked);

2.這段代碼是有bug,在jQuery中實現添加屬性在底層顯然使用了tag.setAttrbute(attrname,attrvalue);spa

而未直接使用tag.attrname=attrvalue;或者tag[attrname]=attrvalue。緣由在於在非IE的瀏覽器內核陣營code

推薦使用的是setAttribute,由於setAttribute能夠添加非標籤屬性,因此形成片面上的屬性添加而不是原對象

生屬性的改變,特別是具備狀態的標籤,所以總成上面的切換隻能發生一次。事件


代碼改造:element

先來講說原生js對象和jQuery對象的相互轉換:rem

若element是js對象,
js轉爲jQuery對象的方式$(element)
jQuery轉爲js對象的方式$(element)[0]轉爲js對象(注意,集合對象不能這樣轉)
集合對象仍是用遍歷方式比較好

jQuery方式改造以下:

$("div.testdiv label input:checkbox[name=checkboxall]").bind('change,click',function(evt){
     var e = evt || window.event;
     //使用原生js獲得當前「選擇全部」標籤的checked狀態
     $isChecked = this.checked;
     //這裏不得不使用each遍歷出全部符合條件的chekbox原生js對象
     $("div.testdiv input:checkbox[name='checkbox1']").each(function(index,element){
       element.checked = $isChecked;//或者 element['checked']=$isChecked;
     });
 });

在js中不會出現這樣的bug,在這裏使用js實現一次吧

var $ = function(id)
{
    return document.getElementById(id);
}
//添加事件兼容的方法
function addEvent(elm, evType, fn, useCapture) {

        if (elm.addEventListener) 
        {
            elm.addEventListener(evType, fn, useCapture);//DOM2.0
            return true;
        }
        else if (elm.attachEvent) {
            var r = elm.attachEvent('on' + evType, fn);//IE5+
            return !!r;
        }
        else {
            elm['on' + evType] = fn;//DOM 0
        }
}

var checkall = $('checkboxall');
var testdiv  = $('testdiv');
var checkboxs = testdiv.getElementsByName('checkbox1');

function toggleCheckbox(evt)
{
  var e = evt || window.event;
  for(var i=0;i<checkboxs.length;i++)
  {
    checkboxs[i]['checked'] = checkall.checked; 
    //或者 checkboxs[i].checked = checkall.checked;
  }
}

addEvent(checkall,'click',toggleCheckbox,false);
//最有一個參數設置爲false,緣由一直沒明白過,望讀者自行檢索相關信息,能夠留言給我
addEvent(checkall,'change',toggleCheckbox,false);

好了,就這些了,注意測試時代碼的執行順序啊。

-----------------------------------------------------------------------------------

更新一下內容(2014-11-13)

在jQuery 1.6+版本以上,jQuery彌補了這種不足,添加了屬性 

prop(name|properties|key,value|fn)-->設置或者添加property

removeProp(name) -->移除property


$("input[type='checkbox']").prop({

  disabled: true

});

$("input[type='checkbox']").prop("disabled", false);

$("input[type='checkbox']").prop("checked", true);

所以,全選能夠改形成下面的方式

$("div.testdiv label input:checkbox[name=checkboxall]").bind('change,click',function(evt){
     var e = evt || window.event;
     //使用原生js獲得當前「選擇全部」標籤的checked狀態
     $isChecked = this.checked;
     //這裏不得不使用each遍歷出全部符合條件的chekbox原生js對象
     $("div.testdiv input:checkbox[name='checkbox1']").prop('checked',true);
 });

這裏要特別說明 property和attribute的雀斑,property指的是原生屬性(特有),而arrtibute一般是共同屬性和附加屬性,

所以改變checked除了上述方法外,還能夠使用這個。


Try doing it;

相關文章
相關標籤/搜索