NewBoy NewBoy - 7 months ago 53
HTML Question

jQuery AddClass and RemoveClass function for multiple element throughout web page

I submitted my code on a code review site and it highlighted that have duplicate functions within my script which can be seen below.

$(document).ready(function () {

$('#search-btn').click(function () {
$('.search-bar-wrap').toggleClass('searchActive');
$('.more-menu').removeClass('moreMenuActive');
$('account-menu').removeClass('acMenuActive');
});

$('.more-btn').click(function () {
$('.more-menu').toggleClass('moreMenuActive');
$('.account-menu').removeClass('acMenuActive');
$('.nav-bar-wrap').removeClass('searchActive');
});

$('.ac-btn').click(function () {
$('.account-menu').toggleClass('acMenuActive');
$('.nav-bar-wrap').removeClass('searchActive');
$('.more-menu').removeClass('moreMenuActive');
});

// MOBILE

$('#mobile-menu').click(function () {
$('.mobile-menu').toggleClass('mobileMenuActive');
$('.m-accord-dwn').removeClass('accordionActive');
});

$('.active-mobile-menu').click(function () {
$('.mobile-menu').toggleClass('mobileMenuActive');
$('.m-accord-dwn').removeClass('accordionActive');
});

$('.mobile-accordion').click(function () {
$('.m-accord-dwn').toggleClass('accordionActive');
});
});


The click functions demonstrated above are adding and removing classes to show can hidden element on the web page and to also give the click but an active state etc. I am trying to follow best practices for me code. Based on my code above is there a way create a global active function? Jsfiddle

Answer

The way to eliminate redundant code is to use classes and structure in your markup. By structuring the markup, the same class should be able to be applied to multiple elements, not just one element like you currently have.

You only need one style in your CSS:

.inactive {
    visibility: hidden;
}

Then change your markup so each element to be hidden/shown has a "container" element around it and its button. The buttons that toggle the visibility should all have the "toggle-btn" class. And the elements to be hidden/shown all have the "pane" and "inactive" classes.

<header ...>

<div class="container">
    <a class="toggle-btn ...">more</a>
    <div class="pane inactive  ...">
        ...
    </div>
</div>

<div class="container">
    <a class="toggle-btn ...">account</a>
    <div class="pane inactive  ...">
        ...
    </div>
</div>

<div class="container">
    <a class="toggle-btn ...">search</a>
    <article class="pane inactive  ...">
        ...
    </article>
</div>

</header>

Now your JavaScript can be:

$(document).ready(function() {
    $('.toggle-btn').click(function() {
        var $pane = $(this).closest('.container').find('.pane');
        if ($pane.hasClass('inactive')) {
            $('.container .pane').addClass('inactive');
            $pane.removeClass('inactive');
        } else {
            $pane.addClass('inactive');
        }
    });
});

Notice how you only need one event handler registered. Inside the event handler this references the button that was clicked. The "pane" element is found by first using .closest() to get the container element and then .find().

jsfiddle