jQuery detect mousedown inside an element and then mouseup outside the element
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 outside the canvas. Something like this:
$("#element").mousedown(function(){
$(document).mouseup(function(){
//do something
});
});
But this doesn't work of course. A plain $(document).mouseup doesn't work either, because I have many other UI elements and it saves the state each time you click on a UI element.
Any i开发者_运维技巧deas?
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.
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');
}
})
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 :(');
}
});
});
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.
}
});
精彩评论