这是一个把radio修饰后的按钮组,实现按下一个按钮,颜色变深,再按另一个按钮,之前变深的按钮恢复,此刻被按的按钮变深色。
绑定事件中的alert(value);会提示2次?请问是怎么回事?
CSS部分可忽略,直接看最后jquery。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>toggle radio</title>
<script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
<style>
body {
font-family:sans-serif;
}
.toggle {
margin:4px;
background-color:#EFEFEF;
border-radius:4px;
border:1px solid #D0D0D0;
overflow:auto;
float:left;
}
.toggle label {
/*float:left;*/
width:4.0em;
}
.toggle label span {
text-align:center;
padding:3px;
display:block;
cursor: pointer;
}
.toggle label input {
position:absolute;
top:-20px;
}
.toggle .input-checked /*, .bounds input:checked + span works for firefox and ie9 but breaks js for ie8(ONLY) */ {
background-color:#404040;
color:#F7F7F7;
}
.toggle input:checked + span {
background-color:#404040;
color:#F7F7F7;
}
</style>
</head>
<body>
<div class="toggle">
<label><input type="radio" name="toggle" value="s01e01"><span>s01e01</span></label>
</div>
<div class="toggle">
<label><input type="radio" name="toggle" value="s01e02"><span>s01e02</span></label>
</div>
<div class="toggle">
<label><input type="radio" name="toggle" value="s01e03"><span>s01e03</span></label>
</div>
</body>
</html>
<script>
$('label').click(function(){
$(this).children('span').addClass('input-checked');
var value = $(this).children('input').val();
$(this).parent('.toggle').siblings('.toggle').children('label').children('span').removeClass('input-checked');
alert(value);
});
</script>
看了一下别人的评论,综合了一下,我觉得,这个问题的产生不是由于事件冒泡,而是由于label标签的使用(而且我觉得楼主这段代码$(this).parent('.toggle').siblings('.toggle').children('label').children('span').removeClass('input-checked');
可以不用写呀。)。可以通过以下方式证明:
1.证明不是事件冒泡,使用 jQuery中的stopPropagation() 方法可以只阻止一个事件起泡。
js代码如下修改:
$('label').click(function(event){
//$(this).children('span').addClass('input-checked');
console.log(event.target);
var value = $(this).children('input').val();
//$(this).children('span').removeClass('input-checked');
//alert(value);
//console.log(value);
//alert(value);
//return false;
event.stopPropagation();
});
会发现输出的结果是:<span>s01e01</span><input type="radio" value="s01e01" name="toggle">
不加该段代码也是这样的,因此不是事件冒泡行为。至于有的层主说用return false,它是阻止了默认的行为(在这里叫做关联行为吧哈哈,是由于label把span和input关联在一起,用return false是取消了关联行为吧)。
2.证明是由于label的关联效果。
我将楼主的代码修改为如下:
<body>
<div class="toggle">
<div class="div"><input type="radio" name="toggle" value="s01e01"><span>s01e01</span></div>
</div>
<div class="toggle">
<label><input type="radio" name="toggle" value="s01e02"><span>s01e02</span></label>
</div>
<div class="toggle">
<label><input type="radio" name="toggle" value="s01e03"><span>s01e03</span></label>
</div>
</body>
</html>
<script>
$('.div').click(function(){
//$(this).children('span').addClass('input-checked');
console.log(event.target);
});
</script>
测试一下就会发现点不同的地方就会展示三个不同的结果:
<span>s01e01</span>、
<input type="radio" name="toggle" class="radio" value="s01e01">、
<div class="div"><input type="radio" name="toggle" class="radio" value="s01e01"><span>s01e01</span></div>。
成功解除了由于label的绑定。
其中有一层只是加了class属性把label标签换成.radio,这种做法是比较好的解决办法
为什么执行两次上面已经有解释了。不过建议将click
事件换成change
事件
后面加上return false就好了。应该是label标签上面点击事件冒泡了,奇怪的是,换成span或者input就没有这个问题。
js 没问题,是你css的问题
.toggle label {
/*float:left;*/
width:4.0em;
position: relative;
}
.toggle label input {
position:absolute;
top:0px;
left: 0px;
width:50px;
height: 20px;
z-index: 9999;
opacity: 0;
}
这俩个换了就好了
只需要在click事件里面的额最后面添加return false;就行了,这句话的意思是阻止冒泡和默认行为
这样写
<script>
$('input[type="radio"]').click(function(e){
$(this).parents('div').siblings().find('span').removeClass('input-checked');
$(this).parent().find('span').addClass('input-checked');
var value = $(this).val();
console.log(value);
});
</script>
label嵌套input会把两个标签关联
点击label之后,label和input都会执行方法
我的解决方案是直接将点击事件加到input上
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>toggle radio</title>
<script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
<style>
body {
font-family:sans-serif;
}
.toggle {
margin:4px;
background-color:#EFEFEF;
border-radius:4px;
border:1px solid #D0D0D0;
overflow:auto;
float:left;
}
.toggle label {
/*float:left;*/
width:4.0em;
cursor: pointer;
}
.toggle label span {
text-align:center;
padding:3px;
display:block;
cursor: pointer;
}
.toggle label input {
position:absolute;
top:-20px;
opacity: 0;filter: alpha(opacity=0);
}
.toggle .input-checked /*, .bounds input:checked + span works for firefox and ie9 but breaks js for ie8(ONLY) */ {
background-color:#404040;
color:#F7F7F7;
}
.toggle input:checked + span {
background-color:#404040;
color:#F7F7F7;
}
</style>
</head>
<body>
<div class="toggle">
<label><input type="radio" name="toggle" class="radio" value="s01e01"><span>s01e01</span></label>
</div>
<div class="toggle">
<label><input type="radio" name="toggle" class="radio" value="s01e02"><span>s01e02</span></label>
</div>
<div class="toggle">
<label><input type="radio" name="toggle" class="radio" value="s01e03"><span>s01e03</span></label>
</div>
</body>
</html>
<script>
$('.radio').click(function(e){
// e.stopPragation();
$(this).children('span').addClass('input-checked');
var value = $(this).val();
$(this).parent('.toggle').siblings('.toggle').children('label').children('span').removeClass('input-checked');
alert(value);
});
</script>
参考链接1
参考链接2
相当于函数执行了两次
去掉input
标签后者把input
标签放在label
外面后表现正常,只执行一次。
或者在后面加上return false
或者$('label').click(function(event){
event.stopPropagation();
});
我猜可能还是事件冒泡引起的,当你点击的时候,首先点击的是input
标签,因为这个标签要获得焦点,然后才冒泡到label
标签上。 所以执行了两次click
事件
这个原因很有意思,我开始以为是事件冒泡。但是想想不对。然后代码改为:
$('label').click(function(event){
console.log(event.target.type);
$(this).children('span').addClass('input-checked');
var value = $(this).children('input').val();
$(this).parent('.toggle').siblings('.toggle').children('label').children('span').removeClass('input-checked');
console.log(value);
});
event.target.type
主要是这个会触发两个一个是undefined
一个是radio
。因为label关联的radio也被有一个关联操作。当label被点击时,默认radio也被点击了一次。
解决方法你可以
<div class="label">
<input type="radio" name="toggle" value="s01e03">
<span>s01e03</span>
</div>
$('.label').click(function(){});
其实也可以这样写,因为你本身就是要控制span
,所以直接绑定到span
上。
$('span').click(function () {
var i = $('span').index($(this));
$(this).addClass('input-checked');
var value = $('input').eq(i).val();
$('span').not($(this)).removeClass('input-checked');
console.log(value);
})
然后DOM结构不需要改。
试试这段代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>toggle radio</title>
<script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<div class="toggle">
<label class="label"><input type="radio" name="toggle" value="s01e01"><span>s01e01</span></label>
</div>
<div class="toggle">
<div class="label"><input type="radio" name="toggle" value="s01e01"><span>s01e01</span></label>
</div>
<script>
// 如果点击的是span,则是第一次点击,之后冒泡到label,而label里面包含了input,则相当于点击了input.
// 如果把label换成其他标签就好了
$('.label').click(function(event){
console.log(event.target);
});
</script>
</body>
</html>
楼上说的对,labal 和 input 的关系很特殊。