3
\$\begingroup\$

I'm trying to clean up my JQuery code for my tabs. I have 3 different styles. How do I make the following shorter?

$(document).ready(function () {
    $('.tabs-style1 li').click(function () {
        var tab_id = $(this).attr('data-tab');
        $('.tabs-style1 li').removeClass('current');
        $('.tab-content-style1').removeClass('current');
        $(this).addClass('current');
        $("#" + tab_id).addClass('current');
    })
})

$(document).ready(function () {
    $('.tabs-style2 li').click(function () {
        var tab_id = $(this).attr('data-tab');
        $('.tabs-style2 li').removeClass('current');
        $('.tab-content-style2').removeClass('current');
        $(this).addClass('current');
        $("#" + tab_id).addClass('current');
    })
})

$(document).ready(function () {
    $('.tabs-style3 li').click(function () {
        var tab_id = $(this).attr('data-tab');
        $('.tabs-style3 li').removeClass('current');
        $('.tab-content-style3').removeClass('current');
        $(this).addClass('current');
        $("#" + tab_id).addClass('current');
    })
})

Your help will be appreciated! http://michellecantin.ca/test/features/tabs/

| improve this question | | | | |
\$\endgroup\$
4
\$\begingroup\$

The visual style of your tabs is actually independent of their functionality. That is, they all behave as tabs, regardless of how they look.

So, while you could make your code more generic by making the selector strings on the fly ($(".tab-content-" + styleName) etc.), I'd recommend something different.

I'd start by separating the classes that describe style from the ones that describe function. Then I'd use the structure of the markup to figure out the rest; not everything needs a class name.

I.e. given this markup, which is slightly changed/simplified from yours

<div class="tabs tabs-style1">
  <ul class="tabs-list">
    <li class="current" data-tab="tab-1">Tab One</li>
    <li data-tab="tab-2">Tab Two</li>
    <li data-tab="tab-3">Tab Three</li>
    <li data-tab="tab-4">Tab Four</li>
  </ul>

  <div id="tab-1" class="current">
    <p>Lorem ipsum...</p>
  </div>

  <div id="tab-2">
    <p>Duis aute...</p>
  </div>

  <div id="tab-3">
    <p>Ut enim...</p>
  </div>

  <div id="tab-4">
    <p>Sed do eiusmod...</p>
  </div>
</div>

The code can be shortened to

$(".tabs").each(function () {
  var container = $(this);
  container.find(".tabs-list li").on("click", function () {
    var tab = $(this),
        target = tab.data("tab");
    tab.addClass("current")
      .siblings().removeClass("current");
    container.children("#" + target).addClass("current")
      .siblings("div").removeClass("current");
  });
});

for any and all "tab areas" on the page. It'll also work if you add new styles later, or remove any of ones you have. I.e. the visual style is decoupled from the behavior. Also, you only need to change the class name in one place to re-style an entire tab area.

CSS-wise, simply scope your rules to .style1, .style2 etc. and perhaps use the direct-descendant operator, while keeping the base styling common for all styles

.tabs-style1 .tabs-list { ... }
.tabs-style1 .tabs-list li { ... }
.tabs-style1 > div { /* tab content styling */ }

Here's a demo (it's ugly - just demonstrating the functionality)

| improve this answer | | | | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.