eventos - object mouse event javascript
Respondiendo al evento onmousemove fuera de la ventana del navegador en IE (2)
En Internet Explorer 7 el cuerpo onmousemove o document.onmousemove los eventos solo parecen dispararse mientras el mouse está dentro de la ventana del navegador, no cuando está afuera. Sin embargo, en Firefox, el evento onmousemove se llama correctamente cuando me muevo fuera de la ventana del navegador.
¿Cómo puedo configurar un evento para que se llame fuera de la ventana del navegador en IE?
Google Maps hace esto en IE. Si mantiene presionado el botón del mouse y mueve el mouse fuera de la ventana del navegador, puede ver que el mapa aún se mueve.
Puede ver el código aquí, ya que parece funcionar en IE8 y FF3.5. Si puedes entender su código genial. http://www.walterzorn.de/en/dragdrop/dragdrop_e.htm
(Nota: esta respuesta se refiere exclusivamente a la implementación de arrastre "estándar" de mousedown -> mousemove -> mouseup
. No es aplicable a la especificación de arrastre HTML5 ).
Permitir que se arrastre fuera de la ventana del navegador es un viejo problema que los diferentes navegadores han resuelto de dos maneras.
Con la excepción de IE, cuando un usuario inicia una operación de arrastre a través de mousedown
navegadores han hecho algo ordenado (y todo esto solo por observación): una especie de statemachine se activa para manejar el caso especial de movimientos del mouse fuera de la ventana:
- El usuario desencadena el evento
mousedown
dentro deldocument
- El usuario desencadena el evento
mousemove
. El evento se dispara incluso cuando se desencadena desde el exterior deldocument
(es decir, la ventana) - El usuario activa el evento
mouseup
(dentro o fuera deldocument
).mousemove
eventosmousemove
desencadenados desde fuera del documento ya no disparan
IE y versiones anteriores de Firefox [tan tarde como 2.0.20] no muestran este comportamiento. Arrastrar fuera de la ventana simplemente no funciona 1 .
El problema para IE y FF2 en realidad reside en si un elemento es "seleccionable" o no (Vea here y here ). Si una implementación de arrastre no hace nada (lo que permite la selección con el mouse), dicha implementación no tiene que tener en cuenta los movimientos fuera de la ventana; el navegador continuará y mousemove
correctamente y el usuario podrá arrastrar libremente fuera de la ventana. Bonito.
Sin embargo, al dejar que el navegador decida qué hacer en mousemove se obtiene este efecto cuando el navegador piensa que el usuario está tratando de "seleccionar" algo (por ejemplo, el elemento), en lugar de moverlo, y procede a buscar frenéticamente el elemento o texto en el mismo cuando el mouse se cruza dentro o fuera del elemento durante el arrastre.
La mayoría de las implementaciones de arrastre que he visto hacen un pequeño truco para hacer que el elemento sea arrastrado "no seleccionable", tomando así el control total del mousemove
para simular el arrastre:
elementToDrag.unselectable = "on";
elementToDrag.onselectstart = function(){return false};
elementToDrag.style.userSelect = "none"; // w3c standard
elementToDrag.style.MozUserSelect = "none"; // Firefox
Esto funciona bien, pero se rompe arrastrando fuera de la ventana . 2
De todos modos , para responder a su pregunta, para obtener IE (todas las versiones) para permitir el arrastre fuera de la ventana, use setCapture
(y de forma inversa releaseCapture
cuando releaseCapture
el mouse).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Simple drag demo</title>
<style>
#dragme {
position:absolute;
cursor:move;
background:#eee;
border:1px solid #333;
padding:10px;
}
</style>
<script>
function makeDraggable(element) {
/* Simple drag implementation */
element.onmousedown = function(event) {
document.onmousemove = function(event) {
event = event || window.event;
element.style.left = event.clientX + ''px'';
element.style.top = event.clientY + ''px'';
};
document.onmouseup = function() {
document.onmousemove = null;
if(element.releaseCapture) { element.releaseCapture(); }
};
if(element.setCapture) { element.setCapture(); }
};
/* These 3 lines are helpful for the browser to not accidentally
* think the user is trying to "text select" the draggable object
* when drag initiation happens on text nodes.
* Unfortunately they also break draggability outside the window.
*/
element.unselectable = "on";
element.onselectstart = function(){return false};
element.style.userSelect = element.style.MozUserSelect = "none";
}
</script>
</head>
<body onload="makeDraggable(document.getElementById(''dragme''))">
<div id="dragme">Drag me (outside window)</div>
</body>
</html>
Esto es exactamente lo que hace Google Maps (como descubrí desde ingeniería inversa google maps en 2004 cuando se lanzó por primera vez).
1 Creo que en realidad solo se rompe cuando se inicia una operación de arrastre (es decir, mousedown
) en un nodo de texto. Los nodos de elemento / contenedor no muestran el mismo comportamiento y se pueden arrastrar dentro o fuera del documento, siempre que el usuario esté mousado en una parte "vacía" del elemento
2 Nuevamente, para iniciaciones de arrastre en textnodes.