Code Lover
Code Lover

Reputation: 8348

jQuery Toggle only one div with the same class on click and toggle class

I am trying to toggle the only div respected to the menu icon and want to keep rest of divs hidden. If any of them is opened than hide them all but the clicked one.

Also, want to toggle rotate class on the menu icon so when the respective div is opened it shows rotated and when hidden that it will have a normal state.

I am having trouble achieving the result with below code. Can someone help me to fix this?

Code:

$('.more-buttons').each(function() {
  $(this).on('click', function() {

    if ($(this).hasClass('rotate')) {
      $(this).removeClass('rotate');
    }

    var id = $(this).attr('id');
    $('#' + id).toggleClass('rotate');
    $('#' + id).next('.additional-buttons-model').slideToggle('fast');
  });
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="more-buttons" id="551">
  <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="551">
  <div class="view-buttons">
    <input class="light-button" name="doedit" type="submit" value="edit">
    <input class="light-button" name="doclose" type="submit" value="close">
    <input class="light-button" name="dohide" type="submit" value="hide">
  </div>
</div>

Upvotes: 1

Views: 3098

Answers (3)

Code Lღver
Code Lღver

Reputation: 15603

Before showing the content of the clicked button you have to hide the other content. I have done that. Check out the code below:

$('.more-buttons').each(function () {
    $(this).on('click', function () {
        var clickbtn = $(this);
        $('.more-buttons').not(clickbtn).each(function(){
          $(this).removeClass('rotate');
        });
        var id = clickbtn.attr('id');
        $('#' + id).toggleClass('rotate');
        var content = $('#' + id).next('.additional-buttons-model');
        $('.additional-buttons-model').not(content).each(function(){
           $(this).css('display','none');
        });
        content.slideToggle('fast');
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="more-buttons" id="551">
    <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="551">
    <div class="view-buttons">
        <input class="light-button" name="doedit" type="submit" value="edit">
        <input class="light-button" name="doclose" type="submit" value="close">
        <input class="light-button" name="dohide" type="submit" value="hide">
    </div>
</div>
<div class="more-buttons" id="552">
    <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="552">
    <div class="view-buttons">
        <input class="light-button" name="doedit" type="submit" value="edit">
        <input class="light-button" name="doclose" type="submit" value="close">
        <input class="light-button" name="dohide" type="submit" value="hide">
    </div>
</div>
<div class="more-buttons" id="553">
    <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="553">
    <div class="view-buttons">
        <input class="light-button" name="doedit" type="submit" value="edit">
        <input class="light-button" name="doclose" type="submit" value="close">
        <input class="light-button" name="dohide" type="submit" value="hide">
    </div>
</div>
<div class="more-buttons" id="554">
    <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="554">
    <div class="view-buttons">
        <input class="light-button" name="doedit" type="submit" value="edit">
        <input class="light-button" name="doclose" type="submit" value="close">
        <input class="light-button" name="dohide" type="submit" value="hide">
    </div>
</div>

As per the comment I am adding the following code:

$('body').not('.more-buttons').click(function () {
    var clickbtn = $('.more-buttons');
    $(clickbtn).each(function(){
        $(this).removeClass('rotate');
    });
});

$('body').not('.additional-buttons-model').click(function () {
    var content = $('.additional-buttons-model');
    $(content).each(function(){
       $(this).css('display','none');
    });
});

Add the above code in your script.

Upvotes: 1

Angel Politis
Angel Politis

Reputation: 11313

In order to achieve the desired effect you can use the following code:

/* Cache the buttons. */
var btns = $('.more-buttons');

/* When a button is clicked... */
btns.on('click', function(e) {
   var
      /* Cache the clicked button. */
      btn = $(this),

      /* Cache the corresponding div. */
      div = btn.next('.additional-buttons-model');

   /* Toggle the 'rotate' class. */
   btn.toggleClass('rotate');

   /* Remove the rotate class from every button except the one clicked. */
   btns.not(btn).removeClass('rotate');

   /* Slide Up all divs but the one following the button. */
   btn.siblings('.additional-buttons-model').not(div).slideUp('fast');

   /* Slide the div following the button. */
   div.slideToggle('fast');

   /* Prevent the propagation of the event to the body. */
   e.stopPropagation();
});

/* When the user clicks on the body of the document... */
$("body").on("click", function () {
   /* Cache the buttons. */
   var btns = $(".more-buttons");

   /* Remove the 'rotate' class from all buttons. */
   btns.removeClass("rotate");

   /* Hide all divs of additional buttons. */
   btns.siblings('.additional-buttons-model').slideUp('fast');
});

In simple terms, the above code does three things regarding the div elements:

  1. First, it slides all div elements not following the clicked button up.
  2. Then, it slides the div corresponding to the clicked button up or down.
  3. When the body is clicked, all div elements are slid up and all icons lose the 'rotate' class.

Notes: (about your code 😊)

  1. Instead of using each you can simply say $('.more-buttons').on('click', ...) to take advantage of the loop jQuery does internally.
  2. Instead of using $(this) over and over, just cache it once and use the variable. This way, only a single jQuery object will be created each time instead of 4.
  3. There is no reason to cache and use the id of the clicked button (at least in the code you provided in the question).

Snippet:

/* Cache the buttons. */
var btns = $('.more-buttons');

/* When a button is clicked... */
btns.on('click', function(e) {
   var
      /* Cache the clicked button. */
      btn = $(this),

      /* Cache the corresponding div. */
      div = btn.next('.additional-buttons-model');

   /* Toggle the 'rotate' class. */
   btn.toggleClass('rotate');

   /* Remove the rotate class from every button except the one clicked. */
   btns.not(btn).removeClass('rotate');

   /* Slide Up all divs but the one following the button. */
   btn.siblings('.additional-buttons-model').not(div).slideUp('fast');

   /* Slide the div following the button. */
   div.slideToggle('fast');

   /* Prevent the propagation of the event to the body. */
   e.stopPropagation();
});

/* When the user clicks on the body of the document... */
$("body").on("click", function () {
   /* Cache the buttons. */
   var btns = $(".more-buttons");

   /* Remove the 'rotate' class from all buttons. */
   btns.removeClass("rotate");

   /* Hide all divs of additional buttons. */
   btns.siblings('.additional-buttons-model').slideUp('fast');
});
/* Used to allow you to test the click on the body in the snippet. */
html, body {
   height: 100%;
}
<!-- jQuery Script -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="more-buttons" id="551">
  <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="551">
  <div class="view-buttons">
    <input class="light-button" name="doedit" type="submit" value="edit">
    <input class="light-button" name="doclose" type="submit" value="close">
    <input class="light-button" name="dohide" type="submit" value="hide">
  </div>
</div>

<div class="more-buttons" id="552">
  <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="552">
  <div class="view-buttons">
    <input class="light-button" name="doedit" type="submit" value="edit">
    <input class="light-button" name="doclose" type="submit" value="close">
    <input class="light-button" name="dohide" type="submit" value="hide">
  </div>
</div>

<div class="more-buttons" id="553">
  <i class="material-icons">more_horiz</i>
</div>

<div class="additional-buttons-model" data-id="553">
  <div class="view-buttons">
    <input class="light-button" name="doedit" type="submit" value="edit">
    <input class="light-button" name="doclose" type="submit" value="close">
    <input class="light-button" name="dohide" type="submit" value="hide">
  </div>
</div>

Upvotes: 1

jkythc
jkythc

Reputation: 430

Please see the jsfiddle demo.

$('.more-buttons').on('click', function () {
  if($(this).hasClass('rotate')) {
    return false;
  }

  $(this).parent().find('.additional-buttons-model').slideUp('fast');
  $(this).parent().find('.more-buttons').removeClass('rotate');

  $(this).addClass('rotate');
  $(this).next('.additional-buttons-model').slideDown('fast');
});

Upvotes: -1

Related Questions