题目
题目来自廖雪峰的官方网站
对如下的Form表单:
<form id="test-form" action="test">
<legend>请选择想要学习的编程语言:</legend>
<fieldset>
<p><label class="selectAll"><input type="checkbox"> <span class="selectAll">全选</span><span class="deselectAll">全不选</span></label> <a href="#0" class="invertSelect">反选</a></p>
<p><label><input type="checkbox" name="lang" value="javascript"> JavaScript</label></p>
<p><label><input type="checkbox" name="lang" value="python"> Python</label></p>
<p><label><input type="checkbox" name="lang" value="ruby"> Ruby</label></p>
<p><label><input type="checkbox" name="lang" value="haskell"> Haskell</label></p>
<p><label><input type="checkbox" name="lang" value="scheme"> Scheme</label></p>
<p><button type="submit">Submit</button></p>
</fieldset>
</form>
绑定合适的事件处理函数,实现以下逻辑:
当用户勾上“全选”时,自动选中所有语言,并把“全选”变成“全不选”;
当用户去掉“全不选”时,自动不选中所有语言;
当用户点击“反选”时,自动把所有语言状态反转(选中的变为未选,未选的变为选中);
当用户把所有语言都手动勾上时,“全选”被自动勾上,并变为“全不选”;
当用户手动去掉选中至少一种语言时,“全不选”自动被去掉选中,并变为“全选”。
由于廖雪峰老师的题目中全选全不选按钮使用的是checkbox多选框,我的逻辑有点混乱,因此这里我把题目改成了使用单选按钮。
下面是改为i单选按钮之后的表单html文件:
<form id="test-form" action="test">
<legend>请选择想要学习的编程语言:</legend>
<fieldset>
<p><a href="#0" class="invertSelect">反选</a></p>
<p><label><input name="1" type="radio" class="selectAll" />全选</label><label><input name="1" type="radio" class="deselectAll" />全不选</label></p>
<!-- <p><label><input name="1" type="radio" class="deselectAll" />全不选</label></p> -->
<p><label><input type="checkbox" name="lang" value="javascript"> JavaScript</label></p>
<p><label><input type="checkbox" name="lang" value="python"> Python</label></p>
<p><label><input type="checkbox" name="lang" value="ruby"> Ruby</label></p>
<p><label><input type="checkbox" name="lang" value="haskell"> Haskell</label></p>
<p><label><input type="checkbox" name="lang" value="scheme"> Scheme</label></p>
<p><button type="submit">Submit</button></p>
</fieldset>
</form>
在一个p里面,放置了两个label,分别是“全选”和“全不选”,并把他们的“name”属性设置为一样的值,这样才能实现只选择一个的单选情况。
解答
下面是JS部分的代码:
<script>
'use strict';
var
form = $('#test-form'),
langs = form.find('[name=lang]'), //返回的是一个数组,如果查找的东西不存在,他就返回一个[]。!!!!!!!
selectAllLabel = form.find('input.selectAll'),
deselectAllLabel = form.find('input.deselectAll'),
invertSelect = form.find('a.invertSelect');
// 重置初始化状态:
form.find('*').show().off();
form.find(':checkbox').prop('checked', false).off();
//拦截form提交事件:
form.off().submit(function (e) {
e.preventDefault();
alert(form.serialize());
});
selectAllLabel.show();
deselectAllLabel.show();
selectAllLabel.click(function(){
langs.prop('checked',true);
});
deselectAllLabel.click(function(){
langs.prop('checked',false);
});
invertSelect.click(function() {
langs.map(function(){
this.checked = !this.checked;
if (langs.not(":checked").length == 5){
deselectAllLabel.prop('checked',true);
}
else if (langs.not(":checked").length >= 1){
deselectAllLabel.prop('checked',false);
}
else{
selectAllLabel.prop('checked',true);
}
})
});
langs.change(function(){
if (langs.not(":checked").length == 5){
deselectAllLabel.prop('checked',true);
selectAllLabel.prop('checked',false);
}
else if (langs.not(":checked").length >= 1){
deselectAllLabel.prop('checked',false);
selectAllLabel.prop('checked',false);
}
else{
selectAllLabel.prop('checked',true);
}
});
</script>
实现效果:
代码分析
'use strict';
这里是统一标准。
form = $('#test-form'),
langs = form.find('[name=lang]'), //返回的是一个对象数组,如果查找的东西不存在,他就返回一个[]。!!!!!!!
selectAllLabel = form.find('input.selectAll'),
deselectAllLabel = form.find('input.deselectAll'),
invertSelect = form.find('a.invertSelect');
这里使用了jQyery中的find()方法,返回一个jquery对象数组。对象数组:var k = [ { },{ }];d的形式。
form.find('*').show().off();
form.find(':checkbox').prop('checked', false).off();
这里是重置初始化状态。使用find方法,*代表所有的区域。第二行中的冒号代表type类型,即找到所有的type类型为checkbox的分支,也就是那物种语言,然后使用prop方法把他们恩德checked属性设置为false,即为没被选中的状态。
prop()函数的用法:
prop(property)是用来返回属性的值的,比如prop(“checked”);将会返回true或者false。prop(property,value)是用来设置值的,比如prop(“checked”,true);会将checked属性设置为true。
//拦截form提交事件:
form.off().submit(function (e) {
e.preventDefault();
alert(form.serialize());
});
这部分不懂,嘻嘻嘻。
selectAllLabel.show();
deselectAllLabel.show();
这里是设置“全选”和“全不选”这两个按钮为可见状态。不写好像也没啥事。。
selectAllLabel.click(function(){
langs.prop('checked',true);
});
这里设置点击全选事件,点击全选按钮之后,将会执行函数,函数里使用prop方法将langs(就是使用jquery查找的五种语言)的checked属性设置为true(勾选状态)。
deselectAllLabel.click(function(){
langs.prop('checked',false);
});
原理和上面的一样。
invertSelect.click(function() {
langs.map(function(){
this.checked = !this.checked;
if (langs.not(":checked").length == 5){
deselectAllLabel.prop('checked',true);
}
else if (langs.not(":checked").length >= 1){
deselectAllLabel.prop('checked',false);
}
else{
selectAllLabel.prop('checked',true);
}
})
});
这里是设置反选,反选代码块要放在langs.change上面,不然就有问题。使用了map高阶函数,直接修改this.checked。这里的this指的是langs。this的用法简单易懂:JavaScript 的 this 原理
下面是一个if else语句,判断lang的未被选中状态的长度,因find为返回值为对象数组,所以可以使用.length来获得长度(反正我是这么理解的)。
如果都没被选,则把全不选按钮打开;如果有1~4个复选框没有被选,就把全不选按钮关闭(全选按钮一直关着呢);如果全都被选择了,即没被选的按钮为0个,就把全选按钮打开。
langs.change(function(){
if (langs.not(":checked").length == 5){
deselectAllLabel.prop('checked',true);
selectAllLabel.prop('checked',false);
}
else if (langs.not(":checked").length >= 1){
deselectAllLabel.prop('checked',false);
selectAllLabel.prop('checked',false);
}
else{
selectAllLabel.prop('checked',true);
}
});
这里是点击五个复选框时的事件处理,逻辑同上。
后记
欢迎大家指出错误和理解不当点的地方!
本文介绍了如何使用JavaScript和jQuery实现一个表单的全选、反选逻辑,以及单选按钮的互斥功能。通过监听事件和修改checkbox的checked属性,实现了当用户操作时,按钮状态和语言选择状态的自动更新。
1516

被折叠的 条评论
为什么被折叠?



