AS3: MouseIdleMonitor

View Example
View Documentation
Download Class & Example Files

I recently had the need to track if the user has stopped using their mouse (if the mouse was idle) in an application I was building. It actually turned out to be a lot easier than I had imagined with the use of a timer and the built in mouse events in Flash.

This led to the birth of the MouseIdleMonitor which is a simple little utility class that dispatches two events depending on if the mouse is idle or not. For more information, please refer to the documentation.

Here is the class:

Actionscript:
  1. package com.reintroducing.mouse
  2. {
  3.     import flash.display.Stage;
  4.     import flash.events.EventDispatcher;
  5.     import flash.events.MouseEvent;
  6.     import flash.events.TimerEvent;
  7.     import flash.utils.Timer;
  8.     import flash.utils.getQualifiedClassName;
  9.    
  10.     import com.reintroducing.events.MouseIdleMonitorEvent
  11.  
  12.     /**
  13.      * A small utility class that allows you to see if a user has been inactive with the mouse.  The class will dispatch a custom MouseIdleMonitorEvent
  14.      * with a params object that contains the time the user has been idle, in milliseconds.
  15.      *
  16.      * @author Matt Przybylski [http://www.reintroducing.com]
  17.      * @version 1.0
  18.      */
  19.     public class MouseIdleMonitor extends EventDispatcher
  20.     {
  21. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  22.  
  23.         private var _stage:Stage;
  24.         private var _inactiveTime:int;
  25.         private var _timer:Timer;
  26.         private var _idleTime:int;
  27.         private var _isMouseActive:Boolean;
  28.        
  29. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  30.        
  31.        
  32.        
  33. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  34.        
  35.         /**
  36.          * Creates an instance of hte MouseIdleMonitor class. 
  37.          *
  38.          * <p>
  39.          * The class will dispatch two events:
  40.          * <ul>
  41.          * <li>MouseIdleMonitorEvent.MOUSE_ACTIVE: Dispatched when the mouse becomes active, repeatedly on MOUSE_MOVE</li>
  42.          * <li>MouseIdleMonitorEvent.MOUSE_IDLE: Dispatched when the mouse becomes inactive, params object holds idle time ("time")</li>
  43.          * </ul>
  44.          * </p>
  45.          *
  46.          * @param $stage The stage object to use for the mouse tracking
  47.          * @param $inactiveTime The time, in milliseconds, to check if the user is active or not (default: 1000)
  48.          *
  49.          * @return void
  50.          */
  51.         public function MouseIdleMonitor($stage:Stage, $inactiveTime:int = 1000):void
  52.         {
  53.             super();
  54.            
  55.             this._stage = $stage;
  56.             this._inactiveTime = $inactiveTime;
  57.             this._timer = new Timer(this._inactiveTime);
  58.         }
  59.        
  60. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  61.        
  62.        
  63.        
  64. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  65.        
  66.         /**
  67.          * Starts the MouseIdleMonitor and allows it to check for mouse inactivity.
  68.          *
  69.          * @return void
  70.          */
  71.         public function start():void
  72.         {
  73.             this._stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
  74.             this._timer.addEventListener(TimerEvent.TIMER, onTimer);
  75.            
  76.             this._timer.start();
  77.         }
  78.        
  79.         /**
  80.          * Stops the MouseIdleMonitor from checking for mouse inactivity.
  81.          *
  82.          * @return void
  83.          */
  84.         public function stop():void
  85.         {
  86.             this._idleTime = 0;
  87.             this._timer.reset();
  88.            
  89.             this._stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
  90.             this._timer.removeEventListener(TimerEvent.TIMER, onTimer);
  91.         }
  92.    
  93. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  94.    
  95.         /**
  96.          * Reset the timer if the mouse moves, user is active.
  97.          */
  98.         private function onMouseMove($evt:MouseEvent):void
  99.         {
  100.             this._isMouseActive = true;
  101.             this._idleTime = 0;
  102.             this._timer.reset();
  103.             this._timer.start();
  104.            
  105.             this.dispatchEvent(new MouseIdleMonitorEvent(MouseIdleMonitorEvent.MOUSE_ACTIVE, {}));
  106.         }
  107.        
  108.         /**
  109.          * Runs if the user is inactive, sets the idle time.
  110.          */
  111.         private function onTimer($evt:TimerEvent):void
  112.         {
  113.             this._isMouseActive = false;
  114.             this._idleTime += this._inactiveTime;
  115.            
  116.             this.dispatchEvent(new MouseIdleMonitorEvent(MouseIdleMonitorEvent.MOUSE_IDLE, {time: this._idleTime}));
  117.         }
  118.    
  119. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  120.        
  121.         /**
  122.          * Returns a boolean value that specifies if the mouse is active or not.
  123.          *
  124.          * @return Boolean
  125.          */
  126.         public function get isMouseActive():Boolean
  127.         {
  128.             return this._isMouseActive;
  129.         }
  130.        
  131.         /**
  132.          * Returns an integer representing the amount of time the user's mouse has been inactive, in milliseconds
  133.          *
  134.          * @return int
  135.          */
  136.         public function get idleTime():int
  137.         {
  138.             return this._idleTime;
  139.         }
  140.    
  141. //- HELPERS -----------------------------------------------------------------------------------------------
  142.    
  143.         override public function toString():String
  144.         {
  145.             return getQualifiedClassName(this);
  146.         }
  147.    
  148. //- END CLASS ---------------------------------------------------------------------------------------------
  149.     }
  150. }

If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.

20 Comments

Great job!
(y)

thanks rafael!

Nice work and interesting approach Matt!

I've written similar util some time ago, the only difference is that it fires the idle event after specified "idle" time. You can pause the timer i.e. when you hover over an element. It also uses singleton model so different classes can gain start/stop control over it.

Tomek

Tomek,
Sounds pretty good, I think i contemplated on using a Singleton but decided not to although I can't remember now why 😛

Wow nice code.. you happen to have something like this that works in AS2?
I have a situation where I need to check if the site is idle, not necessarily the mouse, to let the background change colors. Although it would be a good substitute. Thanks for any help.

Or maybe a point in the right direction.

Here you go, that the old AS2 version of my class:

Actionscript:
  1. /*--------------------------------------------------------------------------
  2.     [AS2] MouseMoveTimeout
  3.     ========================================================================   
  4.     var mouseMoveTimeout:MouseMoveTimeout = new MouseMoveTimeout(this, 5, action);
  5.     //after 5 seconds of not moving the mouse action() method is called
  6. --------------------------------------------------------------------------*/
  7.  
  8. import mx.utils.utils.Delegate;
  9.  
  10. class net.blog2t.util.MouseMoveTimeout extends MovieClip
  11. {
  12.     var MOUSE_MOVE_CHECK_INTERVAL:Number = 1;
  13.    
  14.     var mouseCountdownTime:Number;
  15.     var tickerInterval:Number;
  16.     var _timeout:Number;
  17.     var _callback:Function;
  18.     var _this:MovieClip;
  19.    
  20.     /*
  21.     * Constructor
  22.     */
  23.     public function MouseMoveTimeout(targetObject:MovieClip, timeout:Number, callback:Function)
  24.     {
  25.         _timeout = timeout;
  26.         _callback = callback;
  27.         _this = targetObject;
  28.        
  29.         debug(_this + ": Mouse move timeout set to: " + _timeout + "s. Use start() method to start ticking.");
  30.     }
  31.  
  32.     /*
  33.     * Starts ticking
  34.     */
  35.     public function start():Void
  36.     {
  37.         debug("Mouse move timeout started.");
  38.        
  39.         setMoveTimeout(MOUSE_MOVE_CHECK_INTERVAL);
  40.         _this.onMouseMove = Delegate.create(this, reset);
  41.     }
  42.  
  43.     /*
  44.     * Reset countdown time when user moves mouse
  45.     */
  46.     public function reset():Void
  47.     {
  48.         debug("Reset timeout to: " + _timeout);
  49.         mouseCountdownTime = _timeout;
  50.     }
  51.  
  52.     /*
  53.     * Stops the ticker and removes on mouse move event
  54.     */
  55.     public function remove():Void
  56.     {
  57.         clearInterval(tickerInterval);
  58.         delete _this.onMouseMove;
  59.         debug("Mouse move interval stopped and removed");
  60.     }
  61.  
  62.     /*------------------------------------------------------------------------------------------------------------------
  63.     * PRIVATE METHODS
  64.     */
  65.  
  66.     /*
  67.     * Set interval (to every second) to count mouse inactivity time
  68.     */
  69.     private function setMoveTimeout(mouseTimeout:Number):Void
  70.     {
  71.         debug("Start mouse move interval count down every: " + mouseTimeout + "[s]");
  72.        
  73.         reset();
  74.         tickerInterval = setInterval(Delegate.create(this, decreaseTimeout), mouseTimeout * 1000);
  75.     }
  76.  
  77.     /*
  78.     * Decrease the time and call state changing method when counter has expired
  79.     */
  80.     private function decreaseTimeout():Void
  81.     {
  82.         mouseCountdownTime --;
  83.        
  84.         debug("Mouse timeout in: " + mouseCountdownTime);
  85.  
  86.         if (mouseCountdownTime == 0)
  87.         {
  88.             _callback.call(_this, this);
  89.             reset();
  90.         }
  91.     }
  92.    
  93.     /*
  94.     * Easy way to disable debugging
  95.     */
  96.     private function debug(msg:String):Void
  97.     {
  98.         trace("[MMT] " + msg);
  99.     }
  100. }

Og2t,
I just edited your comment to wrap it around AS tags but the vertical scroller got cut off so to see the rest you'll just have to highlight the code and scroll down. Sorry.

Hey thanks for the speeeeedy response... wow!
This is a great class. I actually found one too, but its not a class and a little more compact... 🙂

Cheers!

Actionscript:
  1. //-----------------------------------------
  2. //Check For Mouse Idle
  3. //-----------------------------------------
  4.  
  5. function idleS( ) {
  6.  
  7.   // See if there has been any mouse movement in the last two seconds
  8.  
  9.   if ((_root._xmouse + _root._ymouse) != mousePos) {
  10.  
  11.     // If there has, restart the check for the idle timer
  12.  
  13.     //trace("resetting");
  14.  
  15.     gotoAndStop("noAttract");
  16.  
  17.     clearInterval(idle);
  18.  
  19.     idle = setInterval(idleTime, 28000);
  20.  
  21.     //} else {
  22.  
  23.     //trace("no movement this period");
  24.  
  25.   }
  26.  
  27.   // Store an integer representing the mouse position
  28.  
  29.   mousePos = _root._xmouse + _root._ymouse;
  30.  
  31. }
  32.  
  33. function startIdle( ) {
  34.  
  35.   mousePos = -100000// Initialize it to a dummy value
  36.  
  37.   idleSample = setInterval(idleS, 2000);
  38.  
  39. }
  40.  
  41. startIdle( );
  42.  
  43. stop( );
  44.  
  45. //--------------------------------------

I will save yours for when I am using a class structure.
BTW, what name did you use to save the as file?
Thanks again,

Karlos
Design Drumm

Is this the path?

net.blog2t.util.MouseMoveTimeout

Sorry I am new to classes.
THX

DD

Yeah, you can leave it out (just use MouseMoveTimeout) and save the file into you FLA directory as MouseMoveTimeout.as

Then type in the first frame on the timeline:
var mouseMoveTimeout = new MouseMoveTimeout(this, 5, action);

function action() {
trace("hello");
}

That function will be invoked every 5 seconds providing you're not moving your mouse.

Sweet deal..
What is your name so I can put your credits in my file?
Is that ok to ask? Sorry, forum newbie.
THX

DD

If you want, email it to me.
I like to give people credit for their intellectuals.
🙂
Thanks,

Design Drumm

Correction to code I posted above:

Actionscript:
  1. //-----------------------------------------
  2. //Check For Mouse Idle
  3. //-----------------------------------------
  4.  
  5. function idleTime( ) {
  6.  
  7.   // Play the attract animation
  8.  
  9.   //trace("playing the animation")
  10.  
  11.   gotoAndStop("attract");
  12.  
  13. }
  14.  
  15. function idleS( ) {
  16.  
  17.   // See if there has been any mouse movement in the last two seconds
  18.  
  19.   if ((_root._xmouse + _root._ymouse) != mousePos) {
  20.  
  21.     // If there has, restart the check for the idle timer
  22.  
  23.     //trace("resetting");
  24.  
  25.     gotoAndStop("noAttract");
  26.  
  27.     clearInterval(idle);
  28.  
  29.     idle = setInterval(idleTime, 28000);
  30.  
  31.     //} else {
  32.  
  33.     //trace("no movement this period");
  34.  
  35.   }
  36.  
  37.   // Store an integer representing the mouse position
  38.  
  39.   mousePos = _root._xmouse + _root._ymouse;
  40.  
  41. }
  42.  
  43. function startIdle( ) {
  44.  
  45.   mousePos = -100000// Initialize it to a dummy value
  46.  
  47.   idleSample = setInterval(idleS, 2000);
  48.  
  49. }
  50.  
  51. startIdle( );
  52.  
  53. stop( );
  54.  
  55. //--------------------------------------

Source: (did not show an authors name so here is the source)

http://etutorials.org/Macromedia/Flash+hacks.+100+industrial-strength+tips+tools/Chapter+10.+ActionScript/Hack+78+An+Idle+Timer+Timeout+Event/

This a great class and exactly what I was looking for. Thanks for sharing!

Genius,

Your a scholar and a gentleman! I'm going to tweak it into a screensaver for a flash program i'm doing!

Once again cheers!!

Great class, thanx you saved me a lot of time!

Thanks Matt Przybylski for this great class.
I have used it and had a necessary to make the apps active on mouse click also apart from just mouse move.

Hence I added this line in onTimer method:

this._stage.addEventListener( MouseEvent.MOUSE_DOWN, onMouseMove, false, 0, true );

and cleared it in onMouseMove method:
this._stage.removeEventListener( MouseEvent.MOUSE_DOWN, onMouseMove );

Just FYI that I edited it.

Best
DD

@Deepanjan: That is a good addition although it should not be added in onTimer because you just want it to be added once not added every time. I added it into the class but its part of the start method along with MOUSE_UP as well and then remove the listeners in the stop method. Thanks.

VERY NICE 🙂
Saved me a lot of time.
Thank You

Leave a comment

(required)

(required)