1

I have a webpage with a link to make an AJAX request. When the following .js comes back the toggleClass function does not work.

$(document).ready(function(){
  $("td").click(function(){
    $(this).toggleClass("br");
  });
});

If I replace toggleClass("br") with something like addClass("br") then that does work.

Furthermore, toggleClass works fine if I put the .js into the html page or if I run it from the console. It seems that something about both toggleClass and AJAX requests together stops this code from working but I have no Earthly idea as to why that might be.

UPDATE

I've figured out the problem. I had accidentally included jQuery two times and so javascript from AJAX requests was being run twice. Hence why only toggleClass was "not working" while addClass and removeClass were.

The only mystery left is why this was only the case when the .js came from an AJAX request as opposed to when it was in the HTML itself.

Martin
  • 41
  • 4
  • td is dynamic element ? You bind it in success function ? – 4b0 May 04 '17 at 04:30
  • No, the entire `table` element comes straight from the server. – Martin May 04 '17 at 04:56
  • Have you checked the developer console to see if there's any Javascript execution failing, such that this Javascript is not being hit? – e_i_pi May 04 '17 at 04:59
  • I have, yes. And no errors are raised. As mentioned in the OP if I enter the javascript into the console it works fine. Furthermore, if put something like `console.log("x");` right below `$(this).toggleClass("br");` then "x" does get output to the console. – Martin May 04 '17 at 05:01
  • Actually, I think I have a lead! When I do what I mentioned just above I notice that I get back 2 "x"s with each click -- meaning that somehow the browser is picking up two clicks -- and so is toggling on and then off again. This seems very bizarre given that this double clicking does not occur when I pass the .js to the browser by other means (in the html or via the console). – Martin May 04 '17 at 05:04
  • I see the problem -- I required jQuery twice :) – Martin May 04 '17 at 05:12

2 Answers2

0

Assuming you want the click handler to be on an element that is populated by the AJAX query, you have to late bind the event to a DOM element that exists before the AJAX query fires. Let's say you have the following HTML:

<html>
  <body>
    <table id="populatedByAjax"></table>
  </body>
</html>

...and you know you're going to populate the table via AJAX. Then we need to declare our jQuery selector like this:

$("#populatedByAjax").on("click", "td", function(){
  $(this).toggleClass("br");
});

That makes sure that the click event is bound to any current or future td elements in the selector #populatedByAjax

e_i_pi
  • 4,590
  • 4
  • 27
  • 45
  • No, the AJAX request consists entirely of the code I posted in the OP. The table is there from the start. Furthermore, I attempted what Mayank Pandeyz suggested (very similar to what you suggest) and it still did not work with `toggleClass`. I don't think it's an issue with the selector since other functions like `addClass` and `removeClass` work fine. – Martin May 04 '17 at 04:54
0

Use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.

$(document).on('click', '#td', function() {
  $(this).toggleClass("br");
});
4b0
  • 21,981
  • 30
  • 95
  • 142