jquerytoggle

jQuery toggle hide/show div; how to prevent to hide div when click again on the same anchor


I have 2 divs which toggle when click on anchor. Click on anchor 1; div 1 is shown, div 2 is hide. When clicking second time on anchor 1; div 1 also hides. This should not be! How can i prevent that?

I tried this with if( !$(this).closest('li').hasClass('.active') ) { but this does not work

$('.showSingle').click(function() {

  if (!$(this).closest('li').hasClass('.active')) {

    $('.active').closest('li').removeClass('active');
    $(this).closest('li').addClass('active');
    $('.targetDiv').not('#div' + $(this).attr('target')).hide();
    $('#div' + $(this).attr('target')).toggle();

  }

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<li class="active">
  <a class="showSingle" target="1">Show div 1</a>
</li>
<li>
  <a class="showSingle" target="2">Show div 2</a>
</li>

<br /><br />

<section id="div1" class="targetDiv">
  Content div 1
</section>

<section id="div2" class="targetDiv" style="display:none;">
  Content div 2
</section>

Fiddle


Solution

  • Almost.

    This is simpler and works

    $(function() {
      $('.showSingle').on('click', function() {
        const target = $(this).attr('target');
        const $li = $(this).closest('li');
        $('li.active').removeClass('active'); // remove all active 
        $li.addClass('active');
        $('.targetDiv').hide(); // hide all
        $(`#div${target}`).show();
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <li class="active">
      <a class="showSingle" target="1">Show div 1</a>
    </li>
    <li>
      <a class="showSingle" target="2">Show div 2</a>
    </li>
    
    <br /><br />
    
    <section id="div1" class="targetDiv">
      Content div 1
    </section>
    
    <section id="div2" class="targetDiv" style="display:none;">
      Content div 2
    </section>

    However as comments say, do not use target, instead use data-attributes or in my opinion better, href

    $(function() {
      $nav = $('#nav').on('click', '.showSingle', function() {
        const target = $(this).attr('href');
        const $li = $(this).closest('li');
        $('li.active', $nav).removeClass('active'); // remove all active 
        $li.addClass('active');
        $('.targetDiv').hide(); // hide all
        console.log(target)
        $(target).show();
      });
    });
    a {
      text-decoration: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <ul id="nav">
      <li class="active">
        <a class="showSingle" href="#div1">Show div 1</a>
      </li>
      <li>
        <a class="showSingle" href="#div2">Show div 2</a>
      </li>
    </ul>
    
    <br /><br />
    
    <section id="div1" class="targetDiv">
      Content div 1
    </section>
    
    <section id="div2" class="targetDiv" hidden>
      Content div 2
    </section>

    Here is a CSS improvement since it will show the target div if linked from outside

    $(function() {
      const $nav = $('#nav').on('click', '.showSingle', function() {
        const target = $(this).attr('href');
        const $li = $(this).closest('li');
        $('li.active', $nav).removeClass('active'); // remove all active 
        $li.addClass('active');
      });
      const hash = location.hash || $('.showSingle').first().attr('href');
      if (hash && hash.startsWith('#div')) {
        $activate = $nav.find(`[href="${hash}"]`);
        if ($activate.length ===1) $activate.closest('li').addClass('active');
      }  
    });
    a {
        text-decoration: none;
    }
    
    .active { background-color: green }
    .targetDiv {
        display: none; /* Hide all targetDiv elements by default */
    }
    
    .targetDiv:target {
        display: block; /* Show the targetDiv if it's the target of the URL fragment */
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <ul id="nav">
      <li>
        <a class="showSingle" href="#div1">Show div 1</a>
      </li>
      <li>
        <a class="showSingle" href="#div2">Show div 2</a>
      </li>
    </ul>
    
    <br /><br />
    
    <section id="div1" class="targetDiv">
      Content div 1
    </section>
    
    <section id="div2" class="targetDiv">
      Content div 2
    </section>