setCapture. It's proprietary, and it's native to only the IE browser (as far as I know).
What's .setCapture() good for?
.setCapture() redirects all mouse events to a specified DOM element until a call to
.releaseCapture() is made. Why would you want this? I can think of a couple scenarios.
- Drag n' Drop: you wire up mousedown to some element to start the drag operation, but wiring up mousemove and mouseup on that same element could be problematic -- the user may mouse too fast and your code might not be able to "keep up." Using
.setCapture()on said element however, will redirect all mouse events to the appropriate element so that the mousemove and mouseup handlers are guaranteed to execute.
- Dropdown Menus: you want the next mousedown to dismiss a dropdown menu. A first crack at this might be to wire up mousedown to the
<body>element, but if some other element on the page is listening for mousedown and is stopping event propagation, the mousedown may never make it to the
.setCapture()will solve this problem.
These aren't the only applications of
.setCapture() of course, but they're two of the most common and they're a good illustration of how
.setCapture() can be useful.
Gimme's version of .setCapture(..)
Even though Mozilla/Firefox and other W3C browsers don't natively support
.setCapture(), Gimme solves this problem by simulating the capability for browsers that don't natively support it. Using Gimme's version is a snap.
var dragElem = Gimme.id('dragElem');
// #dragElem will capture all mouse events until
// a call to Gimme.Events.releaseMouse() is made
A simple call to
Gimme.Events.captureMouse(myElem) will do the trick (where
myElem is the DOM element that should capture all mouse events).
This example, of course, doesn't accomplish anything very useful, but here's an example that's a bit more practical.
This snippet gives drag/drop capabilities to all elements marked with the class "draggable" (it looks long but that's just comments and a big font).
// variables to keep track of the drag element's start position
// and the initial mousedown position
var elemStartPos, mouseStartPos;
// wire up mousedown to start the drag operation
// and stop click events from propagating (just in case)
// instruct all mouse events to be redirected to the current dragElem
// prevent the mousedown event from propagating
// create a gimme object from the element being moused down on
var gObj = g(this);
// keep a ref to the dragElem's start position
// and to the initial mousedown position
elemStartPos = gObj.getPagePosition();
mouseStartPos = Gimme.Screen.getMousePosition(e);
// now, hook the mousemove and mouseup events
// prevent the mousemove event from propagating
// get the current mouse position
var mousePos = Gimme.Screen.getMousePosition(e);
// position the dragElem (element's start position + mouse delta)
.setStyle('top', elemStartPos.y + (mousePos.y - mouseStartPos.y) + 'px')
.setStyle('left', elemStartPos.x + (mousePos.x - mouseStartPos.x) + 'px');
// instruct Gimme to stop capturing mouse events
// prevent the mouseup event from propagating
// remove the mousemove and mouseup handlers
Before I get into an explanation of the code, the following note is significant:
Gimme.Events.captureMouse(..). This capability is new to Gimme (Caspian) which is currently in a pre-release state. You can access Caspian now by visiting the Source Code Section on the Gimme Codeplex site, or you can wait for the official release of Caspian, which should be sometime in late January.
If you understand Gimme, the code here is really pretty straight-forward.
A mousedown event starts the drag operation by recording the mouse down position and the element's start position. Then, the
mouseMove handler ensures that the element moves along with the mouse delta (delta from the mouse start position). Finally, the
mouseUp handler ends the drag operation by removing event handlers that are no longer needed and releasing capture.
We prevent events from propagating (bubbling) in all cases, so that we don't get other elements interfering during a drag operation. And we use Gimme's
Gimme.Events.captureMouse(..) capabilities to ensure the the mousemove and mouseup events are directed to the appropriate element. Otherwise we risk some other element "stealing" the mousemove or mouseup away from the intended element.
this refer to exactly?
Good question; it's the one thing in the Gimme drag/drop code that I can see tripping people up. The
this keyword is somewhat polymorphic in Gimme, so what does it refer to exactly?
The answer is that is depends on context. Most of the time in Gimme, you'll be using
this inside of an event handler function. In that case,
this refers to the DOM element to which the event was wired up. For example:
// alerts "myElem"
// since 'this' refers to #myElem in the current context
In some cases though, you may want to use the Gimme .iterate(..) function. In that case,
this refers to the current Gimme Object being iterated over, not a DOM element, but it's possible to combine both concepts. For instance:
// here, 'this' refers to the current Gimme Object,
// which is why .addEvent(..) is okay here
// here, 'this' refers to the DOM element receiving the click event,
// so we can access native properties, like .parentNode
In case you hadn't figured it out, the above snippet makes it so that all elements with the class "funny" that are direct children of
#container will be removed from the DOM when clicked -- pretty trivial with Gimme.
But this is all secondary to the discussion at hand: capturing mouse events, which, thanks to Gimme, is also pretty trivial!
You can also download a debug version of Caspian here if you just want to monkey around with it.
Note once again, that an official (and compressed) version of Caspian will be available sometime in late January.