Hari Hari - 2 months ago 28
Javascript Question

Javascript - Track mouse position

I am hoping to track the position of the mouse cursor, periodically every t mseconds. So essentially, when a page loads - this tracker should start and for (say) every 100 ms, I should get the new value of posX and posY and print it out in the form.

I tried the following code - but the values do not get refreshed - only the initial values of posX and posY show up in the form boxes. Any ideas on how I can get this up and running ?

<html>
<head>
<title> Track Mouse </title>
<script type="text/javascript">
function mouse_position()
{
var e = window.event;

var posX = e.clientX;
var posY = e.clientY;

document.Form1.posx.value = posX;
document.Form1.posy.value = posY;

var t = setTimeout(mouse_position,100);

}
</script>

</head>

<body onload="mouse_position()">
<form name="Form1">
POSX: <input type="text" name="posx"><br>
POSY: <input type="text" name="posy"><br>
</form>
</body>
</html>

Answer

The mouse's position is reported on the event object received by a handler for the mousemove event, which you can attach to the window (the event bubbles):

(function() {
    document.onmousemove = handleMouseMove;
    function handleMouseMove(event) {
        var dot, eventDoc, doc, body, pageX, pageY;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        // Use event.pageX / event.pageY here
    }
})();

(Note that the body of that if will only run on old IE.)

Example of the above in action - it draws dots as you drag your mouse over the page. (Tested on IE8, IE11, Firefox 30, Chrome 38.)

If you really need a timer-based solution, you combine this with some state variables:

(function() {
    var mousePos;

    document.onmousemove = handleMouseMove;
    setInterval(getMousePosition, 100); // setInterval repeats every X ms

    function handleMouseMove(event) {
        var dot, eventDoc, doc, body, pageX, pageY;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        mousePos = {
            x: event.pageX,
            y: event.pageY
        };
    }
    function getMousePosition() {
        var pos = mousePos;
        if (!pos) {
            // We haven't seen any movement yet
        }
        else {
            // Use pos.x and pos.y
        }
    }
})();

As far as I'm aware, you can't get the mouse position without having seen an event, something which this answer to another Stack Overflow question seems to confirm.

Side note: If you're going to do something every 100ms (10 times/second), try to keep the actual processing you do in that function very, very limited. That's a lot of work for the browser, particularly older Microsoft ones. Yes, on modern computers it doesn't seem like much, but there is a lot going on in browsers... So for example, you might keep track of the last position you processed and bail from the handler immediately if the position hasn't changed.