2

I am trying to bind the click events of div elements to show their respective modals.

I pass through the IDs of each element, and the function reports it is binding the correct ID.

When I actually click on a div though, the click event is always triggered for the final ID.

I have inspected the HTML of the DIVs, and they all have the right IDs.

<div id="e800" data-target="#event800" class="event" data-eid="800">
  <p>Click Me</p>
  <div id="event800" style="display: none;" role="dialog" tabindex="1" class="modal">
     <p>I am another DIV</p>
  </div>
</div>

<div id="e801" data-target="#event801" class="event" data-eid="801">
  <p>Click Me</p>
  <div id="event801" style="display: none;" role="dialog" tabindex="1" class="modal">
     <p>I am another DIV</p>
  </div>
</div>

<div id="e802" data-target="#event802" class="event" data-eid="802">
  <p>Click Me</p>
  <div id="event802" style="display: none;" role="dialog" tabindex="1" class="modal">
     <p>I am another DIV</p>
  </div>
</div>


function BindEvents(ids) {

  for(var i = 0, l = ids.length; i < l; i++) {
    /* ID of element - ex: #e800 */
    var e = "#e" + ids[i];

    /* ID of element I want to show - ex: #event800 */
    var id = $(e).data('target');

    /*
       This console.log outputs the correct e and id. Ex:
       "Binding click of #e800 to show #event800"
    */
    console.log("Binding click of " + e + " to show " + id);

    $(e).on('click', function(ev) {
      /*
        This console.log outputs the e and id of the very last div.
        I click #e800 and the output for this is :
        "Click event of #e802 now showing #event802"
      */
      console.log("Click event of " + e + " now showing " + id);
      $(id).show();
      $('#backdrop').show();
    });

    /*
      $(id) element is a child of the $(e) element.
      If we do not call ev.stopPropagation() then
      the click will also be triggered in $(e).
      This would cause the modal to reshow directly
      after being hidden.
      Which means once clicked, it would never hide.
    */

    $(id).on('click', function(ev) {
      ev.stopPropagation();
      $(id).hide();
      $('#backdrop').hide();
    });
  }
}

The solution to my problem was in the Duplicate question.

Although I have changed my code to the accepted answer and removed the loop.

function BindEvents(ids) {

  $(document).on('click', '.event-bind', function() {
    var id = $(this).data('target');

    $(id).show();
    $('#backdrop').show();

    $(id).one('click', function(ev) {
      ev.stopPropagation();
      $(id).hide();
      $('#backdrop').hide();
    });

  });
}
Dobz
  • 1,213
  • 1
  • 14
  • 36
  • You may want to include those divs as well. – nicael Jun 17 '16 at 15:08
  • I've added the DIVs now. Note: I've removed all of the paragraphs from inside to make them smaller. – Dobz Jun 17 '16 at 15:15
  • If the element you want to show it's always inside that one you click ... why you need ID's ? will be more easier on click `.event` show this child `.modal` – DaniP Jun 17 '16 at 15:22
  • When adding DIVs dynamically I would have had to rebind all events. – Dobz Jun 17 '16 at 15:23
  • No just need to delegate the event ... some like `$('body').on("click",".event", function ()...` – DaniP Jun 17 '16 at 15:23

1 Answers1

1

I would recommend putting a using the class on all of them (i.e. class="showModalOnClick") "edit" -- possibly change it to suit your needs better.

Then, use a single bind event :

    // bind to document instead of directly to the class in case you have 
    // some of the items to click being added after the document is loaded.
    $(document).on('click','.edit',function(){
        var $this = $(this);
        var e = $this.attr('id');
        var id = $this.data('target');

        // This console.log outputs the e and id of the very last div.
        // I click #e800 and the output for this is :
        // "Click event of #e805 now showing #event805"
        console.log("Click event of " + e + " now showing " + id);
        $(id).show();
        $('#backdrop').show();

        // $(id) element is a child of the $(e) element.
        // If we do not call ev.stopPropagation() then
        // the click will also be triggered in $(e).
        // This would cause the modal to reshow directly
        // after being hidden.
        // Which means once clicked, it would never hide.
        // .one will run this event once and unbind after
        $(id).one('click', function(ev) {
            ev.stopPropagation();
            $(id).hide();
            $('#backdrop').hide();
        });
    });
  • I had this before, but extra DIVs are added dynamically, this means rebinding every DIV when a new one comes along. – Dobz Jun 17 '16 at 15:17
  • @Dobz https://learn.jquery.com/events/event-delegation/ – billyonecan Jun 17 '16 at 15:19
  • you would have to if you did $('.edit').on('click', function(){...}) But by binding to the document, and filtering on the class, that fixes the problem : $(document).on('click', '.edit', function(){...}); – David Lance Jun 17 '16 at 15:19