1

I have a simple page with 2 buttons which each populate the content of a modal remotely using the following method code

  $("button").click( function(e) {
      e.preventDefault();
      var remoteLoc = $(this).attr('data-loc');
      $("#myModal .modal-content").load(remoteLoc, function() { 
        $("#myModal").modal("show"); 
      });
  });
  $('#myModal').on('hidden.bs.modal', function (e) {
    $("#myModal .modal-content").empty();
  });

A simple example of the content being loaded is this:

<div class="modal-body">
  <a id="tomtest" href="#">Test link</a>
  <p>dfghdfgh dfgh dfgh dfgh dfgh dfgh dfgh dfg h</p>
</div>
<script type="text/javascript">
  $(document).on("click", "a#tomtest", function(e) {
    e.preventDefault();
    alert(123);
  });
</script>

The problem is that the alert fires as many times as I've opened the modal since the page loaded.

What can I do to stop this happening?

EDIT!!!

Based on the answer from @paulitto I've amended the code to add a dynamically created link in the modal content.

<div class="modal-body">
  <a id="tomAdder" href="#">Add alert link</a>
  <p>dfghdfgh dfgh dfgh dfgh dfgh dfgh dfgh dfg h</p>
</div>
<script type="text/javascript">
  $("a#tomAdder").on("click", function(e) {
    e.preventDefault();
    $('<a class="tomtest" href="#">Test link</a>').prependTo(".modal-body");
  });
  $(document).on("click","a.tomtest", function(e) {
    e.preventDefault();
    alert(123);
  });
</script>

Any ideas in this case?

Tom
  • 12,776
  • 48
  • 145
  • 240

2 Answers2

5

By using delegated events aproach like $(document).on("click", "a#tomtest", function(e) {...}); you are binding handlers to elements that do not exist yet, this way you append new handlers to same link each time opening new modal.

Attaching event in usual way whould do it for only existing link:

$("a#tomtest").on("click", function(e) {
e.preventDefault();
alert(123);

});

Update:

if you still need to use delegated events aproach, you should be able to unbind all delegated click handlers like this, before binding new click handler:

$(document).off("click", "a#tomtest" );
paulitto
  • 4,585
  • 2
  • 22
  • 28
  • I see your point, and that does solve the problem is this case, but what if the link #tomtest is added to the modal dynamically after it is loaded. Then this solution would not work again, right? – Tom Apr 09 '14 at 15:29
  • you are right, this won't work if link will be inserted dynamically afterwards – paulitto Apr 09 '14 at 15:34
  • @Tom: `$("a#tomtest").off("click", "**" );` should unbind all delegated event handlers, give it a try – paulitto Apr 09 '14 at 15:43
  • right before ` $(document).on("click","a.tomtest", function(){...}` – paulitto Apr 09 '14 at 15:46
  • Nope... still fires the alert as many times as the modal has been opened. – Tom Apr 09 '14 at 15:49
  • are you using same selectors for link? I noticed in original post you used a#tomtest, and then in updated you used class a.tomtest – paulitto Apr 09 '14 at 15:53
  • I did that because there could in theory be more than one a.tomtest at a time. But anyway, it's still not working... I think that's to do with my implementation of it though. Please stick with it - I think we're getting close! – Tom Apr 09 '14 at 15:59
  • you should be able to unbind it this way for sure `$("document").off("click", "a#tomtest" );` updated answer again :) – paulitto Apr 09 '14 at 16:00
  • Got it! Would you say it's best to unbind in the modal or call the unbind when the modal is hidden? Both work, but not sure which is the best solution. – Tom Apr 09 '14 at 16:04
  • As for me, there's no need to put both bind and unbind inside html that you load at all, as you're using delegated events you can keep all js in same place where its more convenient for you, no matter its hidden or not – paulitto Apr 09 '14 at 16:09
1

Updated to include paulitto's well put point:

Try placing this in your javascript:

$(this).off("click");

after the alert. It should then remove it after the first fire.

Fewster
  • 100
  • 1
  • 1
  • 10