1

My menu aims at navigating within the same long page. Only one menu item (corresponding to the section of the page being viewed currently) is visible by default. A click on that visible menu item reveals the whole menu.

Here's the trick: once the menu is revealed, another click (not talking abut double click here) on a menu item should trigger something else, namely scrolling to the area associated with the item (off topic here). Is it achievable with jQuery alone?

Somehow I need to make the alert() part execute only on the second click, not the first.

Here's my code so far: https://jsfiddle.net/v6rLs1rg/

jQuery(document).ready(function($) {
  $('.current').click(function() {
    $('.menu_item').fadeIn();
  });
  $('.menu_item').click(function() {
    alert('test');
  });
});
.menu_item {
  display: none;
}

.current {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="menu_item">
    Item 1
  </div>
  <div class="menu_item current">
    Item 2
  </div>
  <div class="menu_item">
    Item 3
  </div>
</div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
drake035
  • 3,955
  • 41
  • 119
  • 229
  • You can use `.one("click", function() )`. This will make that code execute only once. – Red Jun 22 '17 at 15:01
  • you can add a counter to your script to count the second click - e.g. `var count = 0;` and then inside your `click` function do: `count++` – treyBake Jun 22 '17 at 15:05
  • Why this does not work as expected beats me: https://jsfiddle.net/mplungjan/m921p4ou/ – mplungjan Jun 22 '17 at 15:22
  • @mplungjan, `$('.menu_item').not(".current").on` is not dynamic enough: the `current` class will be moved around, but this is only executed once, and thus static. – trincot Jun 23 '17 at 13:13
  • @trincot any suggestions ? I do not get why it would not work - no delegation expected – mplungjan Jun 23 '17 at 13:17
  • @ThisGuyHasTwoThumbs could you create an answer so I can accept it please? Your solution is the simplest and works perfectly! – drake035 Jun 23 '17 at 15:10
  • @drake035 sure will do now :) – treyBake Jun 23 '17 at 15:11
  • @mplungjan, well, you just hinted at it: you could use delegation, so that you dynamically know which is the current element, and which not (a changing fact). – trincot Jun 23 '17 at 15:11

4 Answers4

2

The easiest way you can count a click (or anything for that matter) is by using a counter variable:

<script>
    $(document).ready(function()
    {
        var counter = 0,        //its traditional to set this to 0 - but can be whatever you want
            example = [1, 2, 3] //overall count is 3

        $.each('.class', function()
        {
            counter++;
        });

        alert(counter); //should alert 2 (as counter started on 0)
    });
</script>

and that's a basic example of a counter - in your case for counting when it's the second click (or any more after that) you can do an if statement (or a switch statement if it's more than one) like so:

<script>
    $(document).ready(function()
    {
        var counter = 0;

        $('#someBtn').on('click', function()
        {
            counter++;

            switch (counter)
            {
                case 1:
                    actionOne();            
                    break;
                case 2:
                    actionTwo();
                    break;
            }
        });
    });
</script>

this should be what you're looking for.

NOTE: counter-- can be used to count down

treyBake
  • 6,440
  • 6
  • 26
  • 57
0

Place the second click function inside the .current click function. The second click function will now get triggered because it only runs after you clicked .current.

After doing this you will notice that alert() will run twice. You can fix this by replacing $('.menu_item').click() to $('.menu_item').on('click')

Fiddle

jQuery(document).ready(function($) {
  $('.current').click(function() {
    $('.menu_item').fadeIn();
    

  $('.menu_item').on("click", function() {
    alert('test');
  });
  });
});
.menu_item {
  display: none;
}

.current {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="menu_item">
    Item 1
  </div>
  <div class="menu_item current">
    Item 2
  </div>
  <div class="menu_item">
    Item 3
  </div>
</div>
Red
  • 6,599
  • 9
  • 43
  • 85
0

Using custom function chaining, you can assign the click events right after you do your jquery's fade in.

jQuery(document).ready(function($) {

  //https://stackoverflow.com/questions/37992651/jquery-chaining-custom-functions

  $.fn.activateClicks = function() {
    isFadedIn = true;
    $('.menu_item').click(function() {
      alert('test');
    });
    return this; //The magic statement
  }
  var isFadedIn = false;
  $('.current').click(function() {
    if(!isFadedIn){
      $('.menu_item').fadeIn().activateClicks();
    }
  });

});
Vasily Hall
  • 891
  • 10
  • 22
0

You could just use one click handler and let it determine in which state it is being called.

I would suggest not to detach/re-attach event handlers, as in practice you don't really need to worry about clicks being made on hidden elements.

jQuery(document).ready(function($) {
  $('.menu_item').click(function() {
    $siblings = $(this).siblings(".menu_item");
    if ($siblings.filter(":visible").length) { // more items visible
      $siblings.fadeOut().removeClass("current");
    } else { // it's the only visible one
      $siblings.fadeIn();
    }
    // Always select the clicked element
    $(this).addClass("current");
  });
});
.menu_item {
  display: none;
}

.current {
  display: block;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="menu_item">
    Item 1
  </div>
  <div class="menu_item current">
    Item 2
  </div>
  <div class="menu_item">
    Item 3
  </div>
</div>
trincot
  • 317,000
  • 35
  • 244
  • 286