Aust
Aust

Reputation: 11622

Passing parameters using .call() inside a setInterval function

What I am trying to do is make a function that calls another function continuously as long as the mouse button is being held. I am doing this just so I can get a better understanding of .call() and callbacks. Here is my code:

jQuery.fn.contmousedown = function(mousedownCallback){
  var interval, self = this;
  jQuery(this).mousedown(function(event){
    interval = setInterval(function(self, event){
      mousedownCallback.call(self, event);
      console.log('on');
    },0);
  });
  jQuery(this).mouseup(function(event){
    clearInterval(interval);
  });
}

$(document).contmousedown(function(e){
  $('#run').html(e.pageX+', '+e.pageY);
});

And the error I receive is:

Uncaught TypeError: Cannot read property 'pageX' of undefined

And of course I am receiving that about 300x a second. :) If i change my interval declaration line to interval = setInterval(function(self){ then I get 'on' logged to my console at about 300x a second but I lose the event. So my question is how can I make it so I can callback the function and pass it the event parameter?

Example - http://jsfiddle.net/ZxKxD/


Thinking about this on my commute home, I decided that it would be nice to keep both events. So here is my final code:

jQuery.fn.mousehold = function(mousedownCallback){
  var interval, self = this, move_event;
  jQuery(this).mousemove(function(e){
    move_event = e;
  });
  jQuery(this).mousedown(function(click_event){
    interval = setInterval(function(){
      mousedownCallback.call(self, click_event, move_event);
    },0);
  });
  jQuery(this).mouseup(function(){
     clearInterval(interval);
  });
  jQuery(this).mouseout(function(){
     clearInterval(interval);
  });
}

$(document).mousehold(function(click_event, move_event){
  $('#run').html(click_event.pageX+':'+move_event.pageX+', '
                +click_event.pageY+':'+move_event.pageY);
});

Upvotes: 0

Views: 1155

Answers (1)

Matt Ball
Matt Ball

Reputation: 359966

setInterval does not pass arguments to the callback, so remove the self and event arguments. You don't "lose" the event in doing so.

$.fn.contmousedown = function(mousedownCallback)
{
    var interval,
        self = this;

    $(this).mousedown(function(event)
    {
        interval = setInterval(function()
        {
            mousedownCallback.call(self, event);
            console.log('on');
        }, 0);
    });

    $(this).mouseup(function()
    {
        clearInterval(interval);
    });
}

Demo: http://jsfiddle.net/mattball/9veUQ


So how can I get a continuous update on the cursor position?

Use mousemove to capture the event.

$.fn.contmousedown = function(mousedownCallback)
{
    var interval,
        self = this,
        event;

    $(this).mousemove(function(e)
    {
        event = e;
    });

    $(this).mousedown(function ()
    {
        interval = setInterval(function()
        {
            mousedownCallback.call(self, event);
        }, 0);
    });

    $(this).mouseup(function()
    {
        clearInterval(interval);
    });
};

Demo: http://jsfiddle.net/mattball/dVaWS/

Upvotes: 4

Related Questions