Ying Yi
Ying Yi

Reputation: 782

Use loop to bind events

//I hava this tool function to bind event
var bindEvent = function($dom,events,data,_this){
  for(var key in events){
    $dom.bind(key,function(){
      events[key].apply(_this,[data]);
    });
  }
};

//and use like this
var events = {
  click:function(){
    alert("click");
  },
  dblclick:function(){
    alert("dblclick");
  }
};

var $btn = $("#btn");
bindEvent($btn,events,"mydata",$btn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

when i click on the button, dblclick event is always being triggered.
I know, the reason of this problem.
There is a closure when bind event which is used in "for" loop. Upon termination of loop, the last object in memory (there is dbclick callback function).
so, when trigger click event, it run alert("dblclick").
I want to know if had a good way to solve this problem. Or have a good way to implement tool function for bind event.
Thank you very much.

Upvotes: 2

Views: 680

Answers (5)

eisbehr
eisbehr

Reputation: 12452

I don't know why you would need data, but in general you don't need a loop for adding more than one event. You can just pass the object to bind or on. And because in an event this is always the element, you don't need to set the context.

$("#btn").on({
    click: function() {
        console.log("click");
    },
    dblclick: function() {
        console.log("dblclick");
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Or as long version with your wrapper function:

var bindEvent = function($dom, events) {
    $dom.bind(events);
};

var events = {
    click: function(){
        console.log("click");
    },
    dblclick: function(){
        console.log("dblclick");
    }
};

var $btn = $("#btn");
bindEvent($btn, events);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Upvotes: 3

Einsamer
Einsamer

Reputation: 1087

I dont know the exact answer, but I tried:

var bindEvent = function(dom,events,data,_this){
    dom.bind(events,function(){
    for(var key in events){
      events[key].apply(_this,[data]);
    }
  });
}

Upvotes: 0

Rayon
Rayon

Reputation: 36609

Create a closure inside for-in loop(while attaching event) where inner-function will remember the environment in which it is created!

var bindEvent = function($dom, events, data, _this) {
  for (var key in events) {
    $dom.bind(key, (function(key) {
      return function() {
        events[key].apply(_this, [data]);
      }
    })(key));
  }
};
var events = {
  click: function() {
    console.log("click");
  },
  dblclick: function() {
    console.log("dblclick");
  }
};

var $btn = $("#btn");
bindEvent($btn, events, "mydata", $btn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Note: As alert is being invoked on click event, dblclick event is prevented, use console.log instead of alert and test!

Upvotes: 3

Fadhly Permata
Fadhly Permata

Reputation: 1686

Try this:

var eventBinder = function(obj, events) {
  $.each(events, function(key, value) {
    obj.on(key, function(e) {
      events[key]();
    });
  });
}

var eventsData = {
  click: function(e) {
    console.log("click");
  },
  dblclick: function(e) {
    console.log("dblclick");
  }
};

eventBinder($("#btn"), eventsData);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Upvotes: 1

Haresh Vidja
Haresh Vidja

Reputation: 8496

Both event always contradict but you can achiev this by counter number of clicks between small time interval.

//I hava this tool function to bind event
var bindEvent = function($dom,events,data,_this){
    $dom.on(events);
  
};
var dblckickinterval = 500, clicks = 0, timer = null;
//and use like this
var events = {
  click:function(e){
   clicks++;  //count clicks

        if(clicks === 1) {
            timer = setTimeout(function() {
                alert("click");  //perform single-click action    
                clicks = 0; //after action performed, reset counter
            }, dblckickinterval);
        } else {

            clearTimeout(timer);    //prevent single-click action
            alert("dblclick");  //perform double-click action
            clicks = 0;             //after action performed, reset counter
        }
    
  },
  dblclick:function(e){
    e.preventDefault();
    
  }
};

var $btn = $("#btn");
bindEvent($btn,events,"mydata",$btn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">MYBtn</button>

Upvotes: 2

Related Questions