Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

detecting the current state of a mouse in javascript or jquery i.e wheather its down or up

I am building a web application that involves alot of dragging and dropping of text from within the web page and from other applications eg word and pdf documents. I need to get the current state of the mouse if its down(clicked) or up(release). Currently I am able to get the current state of the mouse if I am dragging text within the web page but am not able to get the mouse state if the mouse is coming from another application say word and its dragging some text. Any pointers to get the down or up state of the mouse are really appreciated.

like image 580
Shadrack B. Orina Avatar asked Apr 11 '12 09:04

Shadrack B. Orina


2 Answers

The issue as I understand it is that you need to determine whether the left mouse button is pressed if it was pressed outside of the window (for a dragging operation).

There are a number of issues:

  • there are no mousemove events fired during a dragging operation
  • data of current button states differs between browsers

I have come up with this solution:

/**
 * keeps track of the current active mouse button.
 * @param notifier {Function} called when the active button is updated.
 * @param oneCallPerStateChange {Boolean} (defaults to false) if true the notifier will be called only when the active button changes.
 */
function initActiveButtonWatcher(notifier, oneCallPerStateChange) {

    // create variable to store button states.
    var _activeButton = -1, activeButton = 0

    // function to set the current active button.
    function updateMouseState(e) {

        // update active button.
        activeButton = typeof e.buttons === "number" ? e.buttons : e.which

        // notify if the active button is different.
        if ( oneCallPerStateChange? (_activeButton !== activeButton && typeof notifier === "function") : (typeof notifier === "function")) {
            notifier(activeButton)
        }

        // store the last state in order to be able to tell if the state has changed.
        _activeButton = activeButton
    }

    // function to get the current active button.
    function getButtonState() { return activeButton }

    // update the button state when the mouse is moved
    // or an item is dragged into the window.
    window.addEventListener("mousemove", updateMouseState, false)
    window.addEventListener("dragover", function() { updateMouseState({which: 1}) }, false)
    window.addEventListener("dragleave", function() { updateMouseState({which: 0}) }, false)

    // expose the getter on the global object.
    window.getButtonState = getButtonState
}

The above solution binds to the mousemove event, and the dragover event. Chrome gets a valid event object with the correct button values in the dragover event, however I found that FireFox did not. I figure the state of the left mouse button is pretty obvious during a drag operation, it's going to be pressed, right? You can't drag without clicking and moving. So I just set state to 1 (left down) on dragover. Likewise, on dragleave, the value is set to zero.

You'd do all of the normal dragover, dragstart, end, drop, etc handling to prevent the default browser actions and the value returned by window.getButtonState() should always be the value of the currently active mouse button.

Here's some example usage that sets the value of the first h1 tag in the page to the currently pressed button:

;(function() {

    var active = document.getElementsByTagName("h1")[0]

    function translate(n) {
        switch (n) {

            case 0:
                return "none"
                break;
            case 1:
                return "left"
                break;
            case 2: case 4: // Firefox calls it 4, the values differ between browsers I find.
                return "middle"
                break;
            case 3:
                return "right"
        }
    }

    initActiveButtonWatcher(
        function(currentActive) {
            active.innerHTML = "Active button: " + translate(currentActive)
        }
    )

})()

You'll have to do some tweaking cross browsers for handling the different values (FF reported 4 for the middle button, etc.) but you should be able to get the current button reasonably well with this method.

Try it out: http://jsfiddle.net/6BUA4/

like image 69
Luke Channings Avatar answered Oct 31 '22 23:10

Luke Channings


When you select text in an external program(such as Word) and drag it onto a web page, elements on the page will generate dragenter Mouse events. I tested this in Chrome and it worked for me. For instance, I can bind a dragenter listener to document.body and receive the events even though no normal mouse events are fired:

function logEvent(e) {
    console.log(e);
}

document.body.addEventListener('dragenter', logEvent);

// MouseEvent {dataTransfer: Clipboard, toElement: body, ..., button: 0, ...}

Perhaps you can use this to your advantage, since the dragenter event means that the mouse is dragging and that the button must be pressed. In addition, you can get the text being dragged by getting the data from the event:

e.dataTransfer.getData('text/plain');

You need to use the correct data type in the getData call. I typed some text into Word and was able to get that dragged text with text/plain.

like image 29
Zenwolf Avatar answered Oct 31 '22 23:10

Zenwolf