Search code examples
javascriptjqueryaddclassremoveclass

Having to repeat JS block for multiple locations how can I create a more practical method


I am creating kind of a dual navigation menu/map functionality where you can click on certain locations and a new panel will display, hiding the previously viewed panel. Also with a map hover effect. Here is what I'm working on JSFiddle.

I'm trying to figure out a best method to shorten my functions as there would be multiple locations. The block below is what I'm repeating over and over again for new locations. It covers the click and hover on the map. I know repeating the block below isn't practical so I'm hoping someone can guide me.

$('a#united-states').click(function(event){
    $('.list').removeClass('current');
    $('div.united-states').addClass('current');                        
    event.preventDefault();
})
$('span.us').mouseover(function(){
   $('.list').removeClass('current');
   $('div.united-states').addClass('current');
}).mouseout(function(){
   $('div.united-states').removeClass('current');
   $('.list').addClass('current');
}).css('cursor', 'pointer');

HTML

<div class="panel list current">
        <ul class="locations">
          <li><a href="#" id="united-states">United States</a></li>  
          <li><a href="#" id="canada">Canada</a></li>  
          <li><a href="#" id="africa">Africa</a></li>  
        </ul>
    </div>

    <div class="panel united-states">
        <h3>United States of America</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc nec quam tristique, ullamcorper dolor at, facilisis dui. Sed faucibus eros vel purus finibus congue. Phasellus non ante laoreet, faucibus metus vel, accumsan massa. Sed tincidunt eros sed purus interdum, id vehicula elit rhoncus. </p>
        <p><a href="#" id="list">Back to list</a></p>
    </div><!--/.panel-->

The JSFiddle link should give a better idea. If there is not better method, just let me know I'm more than happy to just live with this :) Much appreciated!


Solution

  • Give all the region/country a elements a common class, say region and all the span elements a common class, say pin. Then for each a or span element replace the id with or add a data-attribute matching the region/country. Now, it won't matter how many regions you add, as long as you stick to these simple rules, the following code should work for all the regions/countries:

    $('.region').click(function(event){
        $('.list').removeClass('current');
        var region = $(this).data('region');
        $('div.' + region).addClass('current');                        
        event.preventDefault();
    });
    $('.map > .pin').mouseover(function(){
        $('.list,.panel').removeClass('current');
        var region = $(this).data('region');
        $('div.' + region).addClass('current');
    }).mouseout(function(){
        var region = $(this).data('region');
        $('div.' + region).removeClass('current');
        $('.list').addClass('current');
    }).css('cursor', 'pointer');
    

    DEMO

    EDIT 1:

    For the back link to work -- do the following. Change:

    <p><a href="#" id="list">Back to list</a></p>
    

    To:

    <p><a href="#" class="back-list">Back to list</a></p>
    

    Then add the following code:

    $('.back-list').on('click', function(e) {
        e.preventDefault();
        $('.panel').removeClass('current');
        $('.list').addClass('current');
    });
    

    You do not want to use duplicate IDs, every ID must be unique. In fact, you may not even need IDs.

    DEMO