简体   繁体   中英

How to reduce repeating code in jquery?

I have the following code that is used to change the css of a div based on whether a checkbox is clicked or not, so I have multiple divs with multiple checkboxes. I also have the checkboxes set saved to a cookie, so I have additional code to update the div on pageload. Is there a more efficient way to do this besides repeating the same code every time for each individual ID?

Here is a sample of the first two blocks of both sections of my code. Both are repeated from the first one up to 100 instances depending on how many checkboxes are on the page. It's not a huge file, but it seems to me there is probably a better way to do this that I don't know about.

$('#check_1').click(function () {
    if($('#check_1').is(':checked')) {
        $('#gs_wrap1').addClass('fade');
        $('#collect1').removeClass('notcollected');
        $('#collect1').addClass('collected');           
    } else {
        $('#gs_wrap1').removeClass('fade');
        $('#collect1').removeClass('collected');
        $('#collect1').addClass('notcollected');
    }
});
$('#check_2').click(function () {
    if($('#check_2').is(':checked')) {
        $('#gs_wrap2').addClass('fade');
        $('#collect2').removeClass('notcollected');
        $('#collect2').addClass('collected');           
    } else {
        $('#gs_wrap2').removeClass('fade');
        $('#collect2').removeClass('collected');
        $('#collect2').addClass('notcollected');
    }
});

if($('#check_1').is(':checked')) {
    $('#gs_wrap1').addClass('fade');
    $('#collect1').removeClass('notcollected');
    $('#collect1').addClass('collected');
} else {
    $('#gs_wrap1').removeClass('fade');
    $('#collect1').removeClass('collected');
    $('#collect1').addClass('notcollected');
}
if($('#check_2').is(':checked')) {
    $('#gs_wrap2').addClass('fade');
    $('#collect2').removeClass('notcollected');
    $('#collect2').addClass('collected');
} else {
    $('#gs_wrap2').removeClass('fade');
    $('#collect2').removeClass('collected');
    $('#collect2').addClass('notcollected');
}

HTML Code is as followed:

<input class="inputbox" type="checkbox" name="check_1" id="check_1">
<label for="check_1">
<div class="notcollected" id="collect1"></div>
<div class="gs_wrap" id="gs_wrap1">
<div class="gs_list_headimg"></div>
<div class="gs_list_description"></div></div></label>
<input class="inputbox" type="checkbox" name="check_2" id="check_2">
<label for="check_2">
<div class="notcollected" id="collect2"></div>
<div class="gs_wrap" id="gs_wrap2">
<div class="gs_list_headimg"></div>
<div class="gs_list_description"></div></div></label>
var $check1   = $('#check_1');
var $wrap1    = $('#gs_wrap1');
var $collect1 = $('#collect1');

var $check2   = $('#check_2');
var $wrap2    = $('#gs_wrap2');
var $collect2 = $('#collect2');

$check1.click(function () {
    handleChecked($check1, $wrap1, $collect1);
});

$check2.click(function () {
    handleChecked($check2, $wrap2, $collect2);
});

handleChecked($check1, $wrap1, $collect1);
handleChecked($check2, $wrap2, $collect2);


function handleChecked($check, $wrap, $collect) {
    if ($check.is(':checked')) {
        $wrap.addClass('fade');
        $collect.removeClass('notcollected').addClass('collected');
    } else {
        $wrap.removeClass('fade');
        $collect.removeClass('collected').addClass('notcollected');
    }
}

Using classes (in general) for doing such things is a much better in terms of code reusability. It means not being tightly coupled to the strict ids.

Assuming, you only have checkboxes in question.

$('input[type="checkbox"]').on('click', function(event){
    var $this = $(this);
    if($this.is(':checked')){
        enableFade($this);
    } else {
        disableFade($this);
    }
});

function enableFade(el){
    el.closest('.gs_wrap').addClass('fade');
    el.closest('.collect').removeClass('notcollected').addClass('collected');
}

function disableFade(el){
    el.closest('.gs_wrap').removeClass('fade');
    el.closest('.collect').removeClass('collected').addClass('notcollected');
}

Since HTML structure is not provided, I am assuming it to as follows

<div>
    <div class="gs_wrap">
        <div>
            <input type="checkbox"/>
        </div>
        <div class="collect">
        </div>
    </div>
</div>
<div>
    <div class="gs_wrap">
        <div>
            <input type="checkbox"/>
        </div>
        <div class="collect">
        </div>
    </div>
</div>
<div>
    <div class="gs_wrap">
        <div>
            <input type="checkbox"/>
        </div>
        <div class="collect">
        </div>
    </div>
</div>
<!-- And so on -->

Start by analyzing your code. First, you are doing something like:

$('#check_1').click
$('#check_2').click
...
//more check clicks.

You could just select all elements that start with check_ and add a click handler to those.

$('[id^="check_"]').click(function(){

});

Now, the body of your handlers are also very similar. The only thing that changes is the id number at the end. It depends on the id number at the end of the clicked element so you could simply do:

$('[id^="check_"]').click(function(){
    var id = $(this).prop('id').match(/\d+$/)[0]; //selects numbers at the end.
    if($('#check_' + id).is(':checked')) {
        $('#gs_wrap' + id).addClass('fade');
        $('#collect' + id).removeClass('notcollected');
        $('#collect' + id).addClass('collected');           
    } else {
        $('#gs_wrap' + id).removeClass('fade');
        $('#collect' + id).removeClass('collected');
        $('#collect' + id).addClass('notcollected');
    }
});

Finally, all it's left is to set the initial state, which has the same body as our click handler. We could just abstract that out into a separate function:

function addRemoveFade(){
    var id = $(this).prop('id').match(/\d+$/)[0]; //selects numbers at the end.
    if($('#check_' + id).is(':checked')) {
        $('#gs_wrap' + id).addClass('fade');
        $('#collect' + id).removeClass('notcollected');
        $('#collect' + id).addClass('collected');           
    } else {
        $('#gs_wrap' + id).removeClass('fade');
        $('#collect' + id).removeClass('collected');
        $('#collect' + id).addClass('notcollected');
    }
}

But we just lost the context to get the id, we'd need to pass the jquery object to get the id, but since we are just interested in getting the id, we'd just pass that instead.

function addRemoveFade(id){
    if($('#check_' + id).is(':checked')) {
        $('#gs_wrap' + id).addClass('fade');
        $('#collect' + id).removeClass('notcollected');
        $('#collect' + id).addClass('collected');           
    } else {
        $('#gs_wrap' + id).removeClass('fade');
        $('#collect' + id).removeClass('collected');
        $('#collect' + id).addClass('notcollected');
    }
}

Now, we can do:

function addRemoveFade(id){
    if($('#check_' + id).is(':checked')) {
        $('#gs_wrap' + id).addClass('fade');
        $('#collect' + id).removeClass('notcollected');
        $('#collect' + id).addClass('collected');           
    } else {
        $('#gs_wrap' + id).removeClass('fade');
        $('#collect' + id).removeClass('collected');
        $('#collect' + id).addClass('notcollected');
    }
}

$('[id^="check_"]').click(function(){
    var id = $(this).prop('id').match(/\d+$/)[0]; //selects numbers at the end.
    addRemoveFade(id);    
});

addRemoveFade(1);
addRemoveFade(2);

Again we end up repeating this for every check_ element we have. We don't need to do this. You could just do:

function addRemoveFade(id){
    if($('#check_' + id).is(':checked')) {
        $('#gs_wrap' + id).addClass('fade');
        $('#collect' + id).removeClass('notcollected');
        $('#collect' + id).addClass('collected');           
    } else {
        $('#gs_wrap' + id).removeClass('fade');
        $('#collect' + id).removeClass('collected');
        $('#collect' + id).addClass('notcollected');
    }
}

$('[id^="check_"]').each(function(){
    var id = $(this).prop('id').match(/\d+$/)[0];
    addRemoveFade(id);
    $(this).click(function(){
        addRemoveFade(id);
    });
});

There are still some repeated code around in the addRemoveFade function and it's probably still best to have classes instead of all these ids, but you get the idea now (I hope).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM