0

I have a menu with multiple links (a HTML tags).

Clicking a menu entry add the 'active' class which change the menu entry look & feeling. The menu entries has the data-remove="true" in order to Ajaxify the link.

What I want to do is to prevent calling the server when the user click 2 times the same link.

My idea was to say if the menu entry has the 'active' class, then prevent the call to the server otherwise let it go.

I gave some tries to preventDefault, stopPropagation, and return false ... but it's not working as expected. The best I got was when combining both preventDefault and stopPropagation but then the controller were never call anymore.

How can do to avoid calling the controller when clicking a link having the 'active' CSS class ?

ZedTuX
  • 2,859
  • 3
  • 28
  • 58
  • 1
    Me thinks that logic is best suited for the function that actually does the ajax fetching, and just do a `if ( !$(this).hasClass('active') ) {...` in front of the ajax function. – adeneo Jan 13 '15 at 21:43
  • 1
    provide your markup and js that youve got so far – Alex Jan 13 '15 at 21:44
  • @adeneo there is no Javascript function (the one I'm mentioning is a function I tried to write to block the ajax call). Adding the `data-remove="true"` to the link is doing the magic thanks to the Rails framework. (I've noticed I've forgotten the Rails tag) – ZedTuX Jan 13 '15 at 21:49
  • Note: It's not the Rails framework which is providing this but jQuery-ujs (https://github.com/rails/jquery-ujs/wiki/ajax) – ZedTuX Jan 13 '15 at 21:51
  • Well, preventDefault prevents the default behaviour, it doesn't stop other event handlers added by javascript, which is something you generally can't do, or at least not easily. – adeneo Jan 13 '15 at 21:59

2 Answers2

0

Sounds like you are losing the event delegation. Since the class is removed, the event is also gone. Try using the selector of the closes parent in the dom tree that doesn't lose it's id or changes classes.

Example

$("#wrapper").on("click", ".active", function(e){
    e.preventDefault();
    e.stopPropagation();
    //other code you wanted handled.
});

this will delegate the click to the parent container. then when the "active" class is removed, the event can still work if it is added back.

read this thoroughly http://api.jquery.com/on/

eg_dac
  • 701
  • 4
  • 14
  • But I don't think I can do this as I need the user to click the a tag where the classes are managed. If I delegate the event to the parent, the link is not going to be executed right? (Well I guess it's still possible with Javascript) – ZedTuX Jan 13 '15 at 22:43
  • that is incorrect. when you delegate the event, the event is delegated to the parent, but it fires on the class. – eg_dac Jan 13 '15 at 22:45
  • If you agree with my answer, can you mark it correct please. ty. – eg_dac Jan 14 '15 at 15:18
  • Well as I don't have tried it I can't confirm this is working. :( – ZedTuX Jan 14 '15 at 16:37
0

The issue was that first click on first link was firing the on click once, then click another link was firing 2 times and so on.

I have fixed it adding a boolean on the event in order to execute my code only one time. With this I have implemented a 'previous' class which shows which was the previous menu entry clicked.

As jQuery-ujs is handling the data-remote=true using .ajax (link_to and remote => true + jquery : How? Help?), I have hooked on the 'beforeSend' event and here I'm looking for the 'previous' class instead of the 'active' class.

Here is my code Javascript code:

$('a.list-group-item').bind('ajax:beforeSend', function(jqXHR, settings) {
  if ($(jqXHR.target).hasClass('previous'))
    return false;
});

$('a.list-group-item').on('click', function() {
  if (event.handled !== true)
  {
    $('a.list-group-item.previous').removeClass('previous');
    $('a.list-group-item.active').addClass('previous').removeClass('active');
    $(this).addClass('active');
    event.handled = true;
  }
});
Community
  • 1
  • 1
ZedTuX
  • 2,859
  • 3
  • 28
  • 58