jQuery Mousehold Event

I’m working on a web application for Work and we’re working towards recreating an existing desktop application on a web page (don’t get me started on that one!).

Anyway, traditional applications have ‘spinners’ that make numbers or items go up and down (I’m working on that too). This jQuery plugin adds the missing ‘repeat’ event.

Download the mousehold plugin.

The ‘repeat’ is when you keep a key pressed down and it keeps printing the character, or you keep the mouse button pressed down and it keeps firing the click event.

The plugin works by setting a ‘mousedown’ event and keeps firing the function at the given interval until the ‘mouseup’ event or the mouse moves off the element.

This last logic is because if it wasn’t in place, the function specified would keep firing (since the mouse up event fired, but not on the element we set it on).

Here’s an example that shows a practical example.

Feedback and so on is welcome. If you’re interested in the ‘stepper’ code, feel free to ask.

24 Responses to “jQuery Mousehold Event”

  1. Very cool Remy!

  2. Hey, glad to see the error was fixed… great plugin, thanks!

  3. Hi there, if you’re after a spinner then it’s worth checking this one out. (Uses background image on a textbox to look and act like a spin box.)

  4. Awesome!!! Thanks

  5. i can tunder stand the function of it

  6. Not bad. But I think a typical spinner will also have a longer delay up front to make sure the user is intending to hold down the button, then a much shorter delay when continuing to poll and increment the value.

  7. I like the idea, but it doesn’t seem to work with the “this” I need to pass a funciton that would get executed in context of the jquery object, so I could use “this” to reference which element to work with. This is Whay I used.

    jQuery.fn.mousehold = function(timeout, f) {
      if (timeout && typeof timeout == 'function') {
        f = timeout;
        timeout = 100;
      }
      if (f && typeof f == 'function') {
        var timer = 0;
        jQuery.fireObj = 0;
        return this.each(function() {
          jQuery(this).mousedown(function() {
            jQuery(this).each(f)
            jQuery.fireObj = this;
            timer = setInterval("jQuery(jQuery.fireObj).each(" + f + ")", timeout);
          })
    
          clearMousehold = function() {
            clearInterval(timer);
            jQuery.fireObj = 0;
          }
    
          jQuery(this).mouseout(clearMousehold);
          jQuery(this).mouseup(clearMousehold);
        })
      }
    }
    
  8. @ davinci27 – I didn’t initially understand what you meant, but I think now you’re saying that the function passed in isn’t executed against the context of the element the plugin was attached to.

    If so, I’ve found the error and made the change. It was quite simple and doesn’t require setting a variable within the jQuery object (which I would generally avoid for fear of conflicts or race conditions):

    f.call(this, ctr);

    ‘this’ within the context of the setInterval is Window, rather than the element it was set against. So I’ve changed the plugin as follows:

    [snip]
    var t = this;
    timer = setInterval(function() {
      ctr++;
      f.call(t, ctr);
    [snip]

    This way, as I’m caching this in the t variable, when I execute f.call it’s against the correct element.

    This has been updated in the plugin code now.

  9. Great timing, I need one now. Thanks

    To George, the url you gave, http://www.softwareunity.com/sandbox/JQuerySpinBtn/ is also great.

    Thanks to both of you

  10. Nice one! :) Just what I needed!

  11. [...] Extra selectors for JQuery Add more selectors to jQuery. Mousewheel Mousewheel event handler. Mousehold Event Add repeating event as the user holds down the mouse. Multiple File Upload Select multiple files [...]

  12. [...] Extra selectors for JQuery Add more selectors to jQuery. Mousewheel Mousewheel event handler. Mousehold Event Add repeating event as the user holds down the mouse. Multiple File Upload Select multiple files [...]

  13. I ran into a problem with passing ‘e’, seems like e is being set to just 1 in my code and not the event info, anyone else had this problem?
    I have to grab the position of the mouse while the mouse button is held, but the vars are undefined.

    
    $("#interfaceWindow").mousehold(100, function(e) {
      var destX = e.pageX - this.offsetLeft;
      var destY = e.pageY - this.offsetTop;
    
      if(charY > destY)
        moveChar('n');
      if(charY < destY)
        moveChar('s');
      if(charX  > destX)
        moveChar('w');
      if(charX  < destX)
        moveChar('e');
    });
    
  14. hey that is nifty – the example seems to be from an app thats used to do forex trading…. now im curious which one?

  15. I solved the same problem, but I use SetTimer and various duration:

    http://plugins.jquery.com/project/repeatedclick

  16. Thank you very much! I couldn’t get things to work while using setInterval alone.

    still do not completely understand how you put that method together but I will figure that out later on

  17. Is there any way to make the interval accelerate over time?

    It would be really cool if the time between events got smaller every time.

  18. Wow, thank you very much for making this great plugin. I did have a problem with your demo though, I was able drag (mouseout) and it would still go. This was probably becuase I dragged the element with me. I would add .disableSelection() to those button to stop people from being about to select/drag them.

    I noticed that if you dragged the element around the mouse up when you are back at the original location, it would still go, and if you mousedown again… it would do it twice as fast.

    Thanks again for this fantastic plugin

  19. Hi Remy. Thanks a ton for this plugin! I developed a scrolling portfolio and want to replace the click function that drags the scrolling button with your mousehold function. I am thinking it is as simple as the following but am not getting any results. Could you please take a peak when you get a chance? Thanks!

    Here is a snippet simplified to illustrate what I am trying to do


    $(window).load(function () {

    $(document).click(function(){

    $(document).mousehold(200, function(){
    //send the variable value from here on the duration set by mousehold
    }
    });

    });//END WINDOW LOAD FUNCTION

    The URL of the type of thing I am developing is here:

    http://www.levlane.com/dev/scrolltest2/

    Thank you again!
    Rich

  20. Hi, nice work. For those wanting to get the event object back with each mousedown fire, just add the missing ‘e’ parameter to the mousedown call on line 28, then change line 34 from:

    f.call(t, ctr);

    to:

    f.call(t, e);

    This will pass back the same event object that was first fired on mousedown. Useful for when you want to get the ‘e.target’ for each call. I personally don’t need to know the amount of times it was fired, but prefer the event object.

    Cheers.

  21. Hi Adam, and Ali,

    Ali: your solution will only get the initial mousedown event “e” object, so it wont solve what Adam needs.. here is how i solved the functionality, this also still keeps ctr as well, if needed…

    
    jQuery.fn.mousehold = function(timeout, f) {
    
    	if (timeout && typeof timeout == 'function') {
    		f = timeout;
    		timeout = 100;
    	}
    	if (f && typeof f == 'function') {
    		var timer = 0;
    		var fireStep = 0;
    		return this.each(function() {
    			jQuery(this).mousedown(function() {
    				var my_e;
    				$(document).mousemove(function (e){
    					my_e = e;
    				});
    				fireStep = 1;
    				var ctr = 0;
    				var t = this;
    				timer = setInterval(function() {
    					ctr++;
    					f.call(t, ctr, my_e);
    					fireStep = 2;
    				}, timeout);
    			})
    
    			clearMousehold = function() {
                                    $(document).unbind('mousemove');
    				clearInterval(timer);
    				if (fireStep == 1) f.call(this, 1);
    				fireStep = 0;
    			}
    			
    			jQuery(this).mouseout(clearMousehold);
    			jQuery(this).mouseup(clearMousehold);
    		})
    	}
    }
    
    

    Best,
    Cem

  22. Hi Remy, thanks for providing this.

    I have modified your script to allow an optional function to be passed in which is called at the end when the user releases their mouse button or moves away. This works great.

    The one thing I’m missing is the ability for it to speed up when the user keeps their mouse button held down. Do you have something which will do this please e.g. be able to specify bands of time and speed which will automatically get applied? This would make it perfect.

    Thanks once again.

  23. Hi Remy, thanks for code.
    Get only one problem. It doesn’t work on ajax or JS generated HTML.
    Try to replace mousedown with live, but it didn’t work.

    Do you have some tips how to make it work?
    Thanks a lot.

  24. Awesome work! I just have one question though: how do you unbind this?

Leave a Reply
Not required

CODE: Please escape code and wrap in <pre><code>, doing so will automatically syntax highlight