使用jQuery

时间:2016-09-28 17:06:48

标签: javascript jquery

我有this个复选框,我无法找到有效的解决方案。我知道答案非常简短,但我无法解决这个问题,这就是为什么我需要一些帮助。

在我的代码中,我有一个类添加了一个假复选框(我没有隐藏输入用于测试目的)和一个jQuery .click()事件,该函数用于在被点击时将已检查的状态类添加到伪复选框,反之亦然。

CSS

.fake-checkbox { /*...*/ }
.fake-checkbox.checked-state { /*...*/ }

JS

(function($) {
  $('.fake-checkbox').click(function() {
    // ...
  });
});

问题在于标签中包含的复选框在点击时存在冲突(请参阅我的代码以了解正在进行的操作)。

感谢。

3 个答案:

答案 0 :(得分:2)

您应该使用.change()方法而不是click来获取复选框输入。复选框更改后,您需要确定是否已选中复选框。如果 ,则删除checked-state类。如果不是,请添加该类。

$(function(){
    $('.fake-checkbox').change(function() {
        if( this.checked ){
            $(this).removeClass('checked-state');
        }else{
            $(this).addClass('checked-state');
        }
    });
});

如果您要更改父标签的类,请使用.parent()方法:

$(this).parent('label').addClass('checked-state'); $(this).parent('label').removeClass('checked-state');

根据您的评论,如果您有一些实例,其中复选框是/不在标签内,您可以进行更多的条件检查。请参阅下面的示例,其中查找具有类is-label的父标签:

$(function(){
    $('.fake-checkbox').change(function() {
        if( this.checked ){
            $(this).removeClass('checked-state');
        }else{
            $(this).addClass('checked-state');
        }

        if( $(this).parent('label').hasClass('is-label') ){
            if( this.checked ){
                $(this).parent('label').removeClass('checked-state');
            }else{
                $(this).parent('label').addClass('checked-state');
            }
        }
    });
});

答案 1 :(得分:1)

没有理由在该布局中使用任何JavaScript。基本CSS可以根据复选框的状态进行样式设置。

.cb {
  display: none;
}
.fake-checkbox {
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: white;
  border-radius: 5px;
  border: 1px solid black;
}
.cb:checked + .fake-checkbox {
  background-color: blue;
}
<label>
  <input class="cb" type="checkbox">
  <span class="fake-checkbox"> </span>
</label>

<label>
  <input class="cb" type="checkbox" checked="checked">
  <span class="fake-checkbox"> </span>
</label>

那么当它没有包裹在标签中时该怎么办?那么你可以将它们包装在标签中并完成,或者你可以在它上面插入大量的JavaScript。所以我要做的是将点击事件添加到未包含在标签中的跨度。这样标签的工作正常。所有JavaScript都会切换复选框状态。过滤/选择可以任何方式完成,这是一个快速的解决方案。

$(".fake-checkbox").filter( function() {
  return !$(this).parent().is("label");
}).on("click", function() {
  $(this).prev("input").click();
});
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"],
.input-group input[type="checkbox"]
{
  display: none;
}
.fake-checkbox {
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: white;
  border-radius: 5px;
  border: 1px solid black;
}
input:checked + .fake-checkbox {
  background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
  <div class="checkbox">
    <label>
      <input type="checkbox">
      <span class="fake-checkbox"></span>
    </label>
  </div>
  <div class="checkbox">
    <label>
      <input type="checkbox" checked>
      <span class="fake-checkbox"></span>
    </label>
  </div>
  <hr>
  <label class="checkbox-inline">
    <input type="checkbox">
    <span class="fake-checkbox"></span>
  </label>
  <label class="checkbox-inline">
    <input type="checkbox" checked>
    <span class="fake-checkbox"></span>
  </label>
  <hr>
  <div class="form-group">
    <div class="input-group">
      <div class="input-group-addon" style="position: relative;">
        <input type="checkbox">
        <span class="fake-checkbox"></span>
      </div>
      <input type="text" class="form-control">
    </div>
  </div>
  <div class="input-group">
    <div class="input-group-addon" style="position: relative;">
      <input type="checkbox" checked>
      <span class="fake-checkbox"></span>
    </div>
    <input type="text" class="form-control">
  </div>
</div>

答案 2 :(得分:0)

当您开始通过JavaScript / jQuery应用自定义类和委托事件时,默认的复选框行为绝不容易配置。执行此操作的最安全,最准确的方法(跨浏览器)是缓存目标元素的集合,然后使用onInterceptTouch / .bind() jQuery方法触发验证,以确定您要执行的操作。然后,禁用默认复选框行为并添加您自己的侦听器和行为。更新后的示例考虑了未包含在标签内的复选框。

Updated Working Example

<强>参考文献:

jQuery .on()

jQuery .bind()

jQuery event.preventDefault()

因此,这类问题暗示了重新发明轮子。有一些强大的库可以更轻松,更准确地执行此任务。

icheck对于这类事物来说是一个很棒的库。

.on()
//Alexander Dixon - 09/28/2016

//Determine scope of your target inputs by isolating the DOM parent containers.
var masterContainer = $('div.checkbox, label.checkbox-inline, div.form-group, div.input-group, div.input-group-addon');
var allInputs = [];

//Cache all target inputs into an array collection.
masterContainer.each(function() {
    var inputs = $(this).find($('input[type="checkbox"]'));
    for (i = 0, z = inputs.length; i < z; i++) {
        allInputs.push(inputs[i]);
    }
});

//Confirm you targeted them all.
console.log(allInputs);

//Custom function to handle add class validation
function applyClasses(a) {
    $(a).each(function(i) {
        var spanToStyle = $(a[i]).closest($('label, div')).find('span.fake-checkbox') || $(a[i]).siblings('span.fake-checkbox');
        if ($(a[i]).is(':checked')) {
            spanToStyle.addClass('checked-state');
        } else {
            spanToStyle.removeClass('checked-state');
        }
    });
}

//Add new event to circumvent default labeled checkbox functionality and determines whether to add or remove a class
$('label').not($('.fake-checkbox')).on('keypress click', function(e) {
    e.preventDefault();
    console.log('i clicked it');
    if (e.isDefaultPrevented()) {
        console.log(e.target);
        var elementClicked = ($(e.target).attr('class')) ? $(e.target).attr('class') : "label";
        //var elementClickedLabel = $(e.target).context.toString();
        console.log("element clicked: " + elementClicked);
        if ((elementClicked.match(/fake-checkbox/)) || (elementClicked.match(/label/))) {
            console.log('fake clicked');
            var closestCheckBox = ($(e.target).siblings('input[type="checkbox"]').length === 1) ? $(e.target).siblings('input[type="checkbox"]') : $(e.target).find('input[type="checkbox"]');
            console.log(closestCheckBox);
            if (closestCheckBox.is(':checked')) {
                closestCheckBox.prop('checked', false);
            } else {
                closestCheckBox.prop('checked', true);
            }
        }
        applyClasses($(allInputs));
    }
});

//Cache non-labeled checkboxes for precise control and DOM targeting/Event triggering.
var nonLabeledCheckboxes = $('div.input-group-addon').find('span.fake-checkbox');

$(nonLabeledCheckboxes).on('keypress click', function(e) {
    e.preventDefault();
    console.log('i clicked it');
    if (e.isDefaultPrevented()) {
        console.log(e.target);
        var elementClicked = $(e.target).attr('class');
        var elementClickedLabel = $(e.target).context.toString();
        if (elementClicked.match(/fake-checkbox/)) {
            console.log('fake clicked');
            console.log($(e.target).siblings('input[type="checkbox"]'));
            var closestCheckBox = $(e.target).siblings('input[type="checkbox"]');
            if (closestCheckBox.is(':checked')) {
                closestCheckBox.prop('checked', false);
            } else {
                closestCheckBox.prop('checked', true);
            }
        }
        applyClasses($(allInputs));
    }
});

//Initialize on page load.
applyClasses($(allInputs));
.fake-checkbox {
    position: absolute;
    top: 1px;
    left: -3px;
    width: 18px;
    height: 18px;
    border: 2px solid #333;
    border-radius: 3px;
    z-index: 5;
    cursor: pointor;
}

.input-group-addon .fake-checkbox {
    top: 5px;
    left: 9px;
    cursor: pointer;
}

.fake-checkbox.checked-state {
    border-color: blue;
    cursor: pointor;
}