Q:

Tabbed navigation to hide and show pages

I'm new to jQuery and trying to learn how to refactor my bloated code to make it nicer and better maintainable.
I have a tabbed navigation which I'm using jQuery to hide and show pages depending on the selector that is clicked.
  $('#search_distributors').on 'click', (e) =>
    e.preventDefault()
    $('#distributor_location_search_filter_form').show()
    $('#distributor_location_search_container').show()
    $('#international_distributors_location_container').hide()
    $('#all_distributors_location_container').hide()
    $('li.search_locations').addClass('active')
    $('li.international').removeClass('active')
    $('li.all_distributors').removeClass('active')

  $('#international_distributors').on 'click', (e) =>
    e.preventDefault()
    $('#international_distributors_location_container').show()
    $('#distributor_location_search_container, 
      #distributor_location_search_filter_form, 
      #all_distributors_location_container').hide()
    $('li.search_locations').removeClass('active')
    $('li.all_distributors').removeClass('active')
    $('li.international').addClass('active')

    $('#all_distributors').on 'click', (e) =>
      e.preventDefault()
      $('#all_distributors_location_container').show()
      $('#international_distributors_location_container, 
        #distributor_location_search_container, 
        #distributor_location_search_filter_form, ').hide()
      $('li.search_locations').removeClass('active')
      $('li.international').removeClass('active')
      $('li.all_distributors').addClass('active')

I'm familiar with using functions and stuff but unsure how to DRY this up.  If anyone can shed some light on this and help me learn that would be wonderful.

A:

It's hard to give an exact answer without knowing your HTML structure, but if we assume that:

Your tab headers (apparently li-elements with classes like .search_locations and ids like #search_distributors) have some common class, such as .tabheader.
Each of your tabs is wrapped in an element with a common class, such as .tab.
You can add a HTML5 data- attribute on your tab headers to designate the tab whiches header it is.

Assumptions 1. and 2. are necessary so that you can use a common function for all the tabs without writing what is essentially the same code thrice.
Number 3. could be implemented like this:
<li class="tabheader search_locations" id="search_distributors" data-tab-id="search_distributors_tab">Search locations</li>

Then you can reduce your CoffeeScript to
$('.tabheader').on 'click', (e) =>
    e.preventDefault()
    tabId = $(e.currentTarget).data('tabId')
    $('.tab').hide()
    $('#' + tabId).show()
    $('.tabheader').removeClass('active')
    $(e.currentTarget).addClass('active')

See my jsFiddle.
If you, some strange reason, would not be able to alter your HTML in any way, your code would still be easier to maintain if you wrote a common function for displaying a tab, then called it for each of the click events:
showTab = (e, tab, header) ->
    e.preventDefault()
    allTabs = [
        '#distributor_location_search_filter_form', 
        '#distributor_location_search_container', 
        '#international_distributors_location_container', 
        '#all_distributors_location_container'
    ]
    $(allTabs.join(',')).hide()
    if tab instanceof Array
        tab = tab.join(',')
    $(tab).show()
    allHeaders = [
        'li.search_locations',
        'li.international',
        'li.all_distributors'
    ]
    $(allHeaders.join(',')).removeClass('active')
    $(header).addClass('active')

$('#search_distributors').on 'click', (e) =>
    showTab(e, ['#distributor_location_search_filter_form', '#distributor_location_search_container'], 'li.search_locations')

$('#international_distributors').on 'click', (e) =>
    showTab(e, '#international_distributors_location_container', 'li.international')

$('#all_distributors').on 'click', (e) =>
    showTab(e, '#all_distributors_location_container', 'li.all_distributors')

See my other jsFiddle.
Note that there are also multiple jQuery plugins for tab behavior, such as one in Bootstrap and jQuery UI.

