2010-11-30 12 views
16

Tengo algo similar a un lienzo de dibujo, y capturar su estado en el mouse para fines de deshacer. El lienzo no es de pantalla completa, por lo que puede dibujar con un pincel y soltarlo fuera del lienzo. Algo como esto:jQuery detectar mousedown dentro de un elemento y luego mouseup fuera del elemento

$("#element").mousedown(function(){ 
    $(document).mouseup(function(){ 
    //do something 
    }); 
}); 

Pero esto no funciona, por supuesto. Tampoco funciona un $ (documento) .mouseup simple, porque tengo muchos otros elementos de UI y guarda el estado cada vez que hace clic en un elemento de UI.

¿Alguna idea?

Respuesta

30
var isDown = false; 

$("#element").mousedown(function(){ 
    isDown = true; 
}); 

$(document).mouseup(function(){ 
    if(isDown){ 
     //do something 
     isDown = false; 
    } 
}); 

Por simplicidad puse isDown en el espacio de nombres global. En producción, probablemente desee aislar el alcance de esa variable.

+0

¡Funciona como un amuleto, gracias! Luché con esto por horas. – Duopixel

+1

* Importante * Esto no funcionará cuando se seleccione texto (al menos en Chrome, ya que se tratará como un evento de arrastre). Ver mi respuesta a continuación para la solución – bcoughlan

2

Esperamos que esta pequeña solución sea útil. Se puede ver en acción aquí: 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 :('); 
     } 
    }); 
}); 
6

Las respuestas anteriores no funcionarán cuando se selecciona texto.

La solución es dejar de texto de ser seleccionado cuando el ratón está abajo, y volver a habilitarlo cuando hace una copia de seguridad:

en tu CSS:

.noselect { 
    /* Prevent text selection */ 
    -webkit-user-select: none; 
    -khtml-user-select: none; 
    -moz-user-select: none; 
    -o-user-select: none; 
    user-select: none; 
} 

A continuación, sus 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'); 
    } 
}) 
+0

Ah gracias. No necesité selección de texto de todos modos, así que lo desactivé. Ver http://memela.com. Pero esta es una buena respuesta en caso de que alguien lo necesite. – Duopixel

+0

Sí, pero si el usuario se mueve fuera del elemento, puede terminar seleccionando texto, de modo que la próxima vez que el mouseUp no funcione – bcoughlan

+0

¡Excelente trabajo en ese sitio por cierto! – bcoughlan

0

Una posible implementación de las respuestas de mike y waitingforatrain en GWT. En la cabeza html gestionar los eventos del ratón hacia arriba (código JavaScript):

var mouseUpHook = false; 
    $(document).mouseup(function() { 
     if (mouseUpHook) { 
      mouseUpHook(null); 
      mouseUpHook = false; 
     } 
    }); 

Deje que su clase Widget personalizadas implementan mouseDownHandler y MouseUpHandler, y añadir esas líneas en su constructor para recibir eventos de ratón (código Java):

addDomHandler(this, MouseDownEvent.getType()); 
    addDomHandler(this, MouseUpEvent.getType()); 

por último, añadir esos métodos en su clase Widget personalizado (código java y JavaScript):

@Override 
public void onMouseUp (MouseUpEvent event) { 
    removeMouseUpHook(); 

    // ... do something else 
} 

private native void hookMouseUp() /*-{ 
    $wnd.$('body').addClass('noselect'); 
    var myThis = this; 
    $wnd.mouseUpHook = function() { 
     [email protected]::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(); 
} 

última línea es útil para evitar el arrastre de la imagen. De hecho, seleccionar por el usuario: ninguno no es suficiente.

0

Si tiene muchos elementos clicables como los que tengo, querrá crear un receptor de mouse global y establecer el código de mouse dentro de los mousedowns del elemento cliqueado. Aquí está el código que utilicé.

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. 
     } 
    }); 
Cuestiones relacionadas