I have something similar to a drawing canvas, and I capture it\'s state on mouseup for undo purposes. The canvas isn\'t full screen, so you can draw with a brush and release
var isDown = false;
$("#element").mousedown(function(){
isDown = true;
});
$(document).mouseup(function(){
if(isDown){
//do something
isDown = false;
}
});
For the sake of simplicity I put isDown
in the global namespace. In production you would probably want to isolate the scope of that variable.
A possible implementation of mike's and waitingforatrain's answers in GWT. In the html head manage mouse up events (javascript code):
var mouseUpHook = false;
$(document).mouseup(function() {
if (mouseUpHook) {
mouseUpHook(null);
mouseUpHook = false;
}
});
Let your custom Widget class implement MouseDownHandler and MouseUpHandler, and add those lines in your constructor to receive mouse events (java code):
addDomHandler(this, MouseDownEvent.getType());
addDomHandler(this, MouseUpEvent.getType());
Finally, add those methods in your custom Widget class (java and javascript code):
@Override
public void onMouseUp (MouseUpEvent event) {
removeMouseUpHook();
// ... do something else
}
private native void hookMouseUp () /*-{
$wnd.$('body').addClass('noselect');
var myThis = this;
$wnd.mouseUpHook = function () {
myThis.@your.custom.widget.class.full.qualified.Name::onMouseUp(Lcom/google/gwt/event/dom/client/MouseUpEvent;)(null);
};
}-*/;
private native void removeMouseUpHook () /*-{
$wnd.$('body').removeClass('noselect');
}-*/;
@Override
public void onMouseDown (MouseDownEvent event) {
hookMouseUp();
// ... do something else
event.preventDefault();
}
Last line is usefull to prevent image dragging. Infact, user-select: none is not sufficent.
If you've got a lot of clickable elements like I have, you're gonna want to create a global mouse catcher and set your mouseup code within the mousedowns of clicked element. Here's the code I used.
var MouseCatcher=function()
{
this.init=function()
{
var mc = this;
$(document).bind({
mouseup:function(e)
{
mc.mouseup();
}
});
}
this.mouseup=function()
{
return false;
}
}
var mouseCatcher = new MouseCatcher();
mouseCatcher.init();
$('#clickableElement').bind({
mousedown: function(e)
{
console.log('mousedown on element');
mouseCatcher.mouseup=function()
{
console.log('mouseup called from MouseCatcher');
this.mouseup = function(){return false;}
}
},
mouseup:function(e)
{
//mouseup within element, no use here.
}
});
Hopefully you find this little solution to be helpful. You can see it in action here: http://jsfiddle.net/neopreneur/PR2yE/
$(document).ready(function(){
var startMouseDownElement = null;
$('#element').mousedown(function(){
// do whatever
//...
// set mousedown start element
startMouseDownElement = $(this);
});
// handle bad mouseup
// $('#container, #container *').mouseup would be more efficient in a busy DOM
$('body *').mouseup(function(event){
event.stopPropagation(); // stop bubbling
if($(this).attr('id') != $(startMouseDownElement).attr('id')){
//oops, bad mouseup
alert('bad mouseup :(');
}
});
});
The above answers will not work when text is selected.
The fix is to stop text from being selected when the mouse is down, and re-enable it when it's back up:
in your CSS:
.noselect {
/* Prevent text selection */
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
Then your JS:
var myButtonDown=false;
$('.ff', ffrw).mousedown(function() {
myButtonDown=true;
$('body').addClass('noselect');
//Your code here
});
$(document).mouseup(function() {
if (myButtonDown) {
myButtonDown = false;
$('body').removeClass('noselect');
}
})