Noor
Noor

Reputation: 45

jquery plugin function overriding execute function many times

I created a small jQuery plugin that shows and hides a div when the user clicks on the button .show and the button .hide, respectively. I want to pass a function as a plugin option to do some specific processing for onhide. But the onhide function executes as many times as the show and hide buttons are clicked.

Here is the jsfiddle.

When you click show/hide buttons more then once then the alert will show the same number of times.

I think it should alert only once for the hide button.

$.fn.showhide = function(options){ 

    var popup = this;
          defaultOptions = {
                 onHide : function() { },
           onShow : function() { }
         };
      var Options = $.extend({},defaultOptions, options); 
          this.each(function() {         
       $(this).on('click',function(e){ 
         var id = $(this).data('id');
         $('#'+id).show();
         $('.hide').on('click',function(){
           var id = $(this).data('id');
           $('#'+id).hide();
           if (Options.onHide.call() === false) {
                    return;
              }

         });

          });
      });
}

$('.show').showhide({
 onHide :function() {
  alert('hide');
 }

}
);

Upvotes: 0

Views: 45

Answers (2)

Mosh Feu
Mosh Feu

Reputation: 29277

Just replace

$('.hide').on('click',function(){

To

$('.hide').one('click',function(){

Explanation:

With your code, each time the user clicks on .show you attach one more delegation .click to the button. one will do it just once.

$.fn.showhide = function(options){ 

  var popup = this;
  defaultOptions = {
    onHide : function() { },
    onShow : function() { }
  };
  var Options = $.extend({},defaultOptions, options); 
  this.each(function() { 		 
    $(this).on('click',function(e){ 
      var id = $(this).data('id');
      $('#'+id).show();
      $('.hide').unbind('click').one('click',function(){
        var id = $(this).data('id');
        $('#'+id).hide();
        if (Options.onHide.call() === false) {
          return;
        }

      });

    });
  });
};

$('.show').showhide({
  onHide :function() {
    alert('hide');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="show" data-id="123">
Show 
</button>
<button class="hide" data-id="123">
 Hide
</button>
<div class="showhide" id="123" style="display:none;">
This is div with id 123
</div>

Update

I was added unbind('click') before the one to unbind the older listeners.

Upvotes: 1

chrisv
chrisv

Reputation: 725

It's because you're implementing your onHide method inside a loop.

Move this bit:

$('.hide').on('click',function(){
       var id = $(this).data('id');
       $('#'+id).hide();
       if (Options.onHide.call() === false) {
                return;
          }

     });

to right before your closing bracket of your method and everything works fine!

Edit: Fiddle here: https://jsfiddle.net/ka9gw09t/10/

Upvotes: 1

Related Questions