Mouse providers an interface that represents the mouse itself as an object with state. window.Mouse
points to the constructor. Only one instance of Mouse
should exist per window
. window.mouse
points to a context's single mouse instance.
The follow is an example of a right mouse button drag+drop that works for everything on the page. This shows the power of binding events to the mouse itself, allowing one set of handlers to work with everything.
(function moveAnything(){
var style, x, y;
// window.mouse is automatically initialized for you
mouse.on('down', 'right', function(e){
// prevent default text selection
e.preventDefault();
});
mouse.on('grab', 'right', function(e){
// `e.target` is the element the mouse is acting on
var computed = getComputedStyle(e.target);
style = e.target.style;
// `this` refers to the mouse itself
x = (parseFloat(computed.left) || 0) - this.x;
y = (parseFloat(computed.top) || 0) - this.y;
if (computed.position === 'static')
style.position = 'relative';
});
mouse.on('drag', 'right', function(e){
// update position
style.left = (this.x + x) + 'px';
style.top = (this.y + y) + 'px';
});
mouse.on('drop', 'right', function(e){
// free reference and prevent context menu
style = null;
e.preventDefault();
});
})();
window.mouse
(just mouse
from now on) provides existing mouse methods as well as normalizes some and adds new ones.
- down: mousedown
- up: mouseup
- move: mousemove
- click: click and contextmenu
- dblclick: dbleclick
- leave: Uses mouseout but only fires when the mouse leaves the window entirely
- enter: Uses mouseover but only fires when the mouse enters the window from outside
- wheel: mousewheel and wheel events
- grab: first move after a button is press and held
- drag: while any button is held and dragged, each move event becomes both a move and a drag event
- drop: first button release after grab + drag
The following functions are provided to allow management of listeners. types
is a string of type names separated by spaces for multiple events. buttons
is an optional parameter that will pre-filter what events you're notified of. Buttons can be one of:
- string like "left" or "left+right"
- a bitmask where
left === 1
,middle === 2
, andright === 4
(so left | right is 5) - an object like
{ left: true, right: true }
.
If button filter is omitted then the callback becomes the second param.
- mouse.on(types, [buttons], callback): add callback as listener for each type in types
- mouse.off(types, [buttons], callback): remove callback from listeners for each type in types
- mouse.once(types, [buttons], callback): add callback as listener for the first time each type in types fires, then removes it
- mouse.emit(evt): takes MouseEvent object and runs the event through the callbacks the same as when a native event is received. Type is determined from the event object
- new Mouse(view): initializes mouse instance for given view. This is done automatically for main window, but this could be run on, for example, an iframe's window to provide a mouse object scope to the iframe.
Mouse button state is tracked and MouseEvent.prototype
is augmented in two ways:
- buttons: a getter that returns the buttons as per the W3C spec (only first 3 buttons currently). That is logical combination of the button states. left is 1, middle is 2, right is 4. All through would be 7, etc.
- buttonStates: is a frozen object that maps the bitmask out to an object, like
{ left: true/false, middle: true/false, right: true/false }
. Performance is maintained because there's only 8 variations so the same frozen objects are simply reused