StackThis
StackThis

Reputation: 883

bootstrap3 - hide.bs.dropdown function firing regardless of .click definition? ..with fiddle

Have a setup where a .click event that calls a setRead() function when the dropdown-menu closes, which triggers an ajax call.

Right now, for some reason the setRead() function is being called regardless of the .click definition.. http://jsfiddle.net/N2v9S/6/

setRead() should only be called when .markRead is clicked, not .markedRead

Here's the HTML (it involves handlebars templating, where the value is a different id for each btn):

<div class="thisness">
    <div class="exterior">
      <input type="hidden" name="storyID" id="storyID" class="storyID" value="id1" />
    <div class="interior">
      <div class="btn-group dropdown markRead">
            <button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
            <span class="glyphicon glyphicon-unchecked"></span>
            </button>
        <ul class="dropdown-menu" role="menu">
          <li><a href="#">Item 1</a></li>
          <li><a href="#">Item 2</a></li>
        </ul>
      </div><!--/.btn-group(dropdown)-->
    </div></div><!--/.interior/.exterior-->
    ...
</div><!--/.thisness-->

Here's the Javascript/jQuery:

function setRead(id, markedRead, datetimeRead) {

  var AjaxReadData = {
      id : id,
      markedRead : markedRead,
      datetimeRead : datetimeRead
  };

  // make an ajax call
  alert('ajax of ' + id + ' markedRead: ' + markedRead + ' at ' + datetimeRead);

  console.log(AjaxReadData.id + " message marked read: " + AjaxReadData.markedRead);

}

$(document).ready(function(){

    $(".thisness").on("click", ".markRead", function () {

        var datetimeRead = new Date(); // setting the datetime when read

        console.log('markRead clicked');

        var $this = $(this),
            $that = $(this).closest('.exterior').find('.glyphicon-unchecked');

        markedRead = true;

        $that.removeClass('glyphicon-unchecked').addClass('glyphicon-check');
        console.log('now checked icon');

        $this.removeClass('markRead').addClass('markedRead');
        console.log('now markedRead class');

        var id = $(this).closest('.exterior').find( ".storyID" ).val();
        console.log(id);

        console.log('ready for ajax of ' + id + ' markedRead: ' + markedRead + ' at ' + datetimeRead);

        // when .markRead (now .markedRead) dropdown closes      
        $(".thisness").on("hide.bs.dropdown", $this , function () {
          console.log('ajax of ' + id + ' markedRead: ' + markedRead + ' at ' + datetimeRead);
          setRead(id, markedRead, datetimeRead);
        })

    });

}); // doc is ready

Also tested a .when and .then jQuery promise, but this actually runs before the dropdown-menu is hidden?

$.when( $(".thisness").on("hide.bs.dropdown", $this) ).then(function () {
  console.log('ajax of ' + id + ' markedRead: ' + markedRead + ' at ' + datetimeRead);
    setRead(id, markedRead, datetimeRead);
})

Upvotes: 0

Views: 533

Answers (1)

jme11
jme11

Reputation: 17374

The issue is that you are attaching an event handler. So, it's not like it goes away outside the if statement, it's been attached. Do a test, manually set one of the glyphicons to check and run the page. You'll see that even after clicking the checked icon, and selecting from it's dropdown, setRead() doesn't run.

Use the one() function instead of on().

$(".thisness").one("hide.bs.dropdown", $this , function () {
    console.log('ajax of ' + id + ' markedRead: ' + markedRead + ' at ' + datetimeRead);
    setRead(id, markedRead, datetimeRead);
})

Upvotes: 2

Related Questions