2011-12-23 23 views
21

Cuando arrastro un elemento sobre otro div en el que tengo un evento mouseover, el evento no se desencadena. Sin embargo, funciona si me desplazo sobre él sin arrastrarlo.Cómo iniciar el evento mouseover mientras arrastra

¿Hay alguna forma de detectar eventos de desplazamiento sobre un elemento si arrastro otro sobre él?

+0

¿Está utilizando jQuery UI? – Purag

+0

No, estoy usando dragg creado personalizado – user969724

+0

Ayudaría a ver ese código. O póngalo en la pregunta o péguelo en un [jsfiddle] (http://jsfiddle.net). – Purag

Respuesta

13

Aquí hay un ejemplo con la solución de coordenadas XY.

Working example on jsfiddle

El ejemplo se puede mejorar, pero es un buen punto de partida.

Simplemente realiza un seguimiento de la ubicación del mouse y comprueba si parece estar dentro de los cuadros delimitadores de los objetos que se pueden colocar. Por lo tanto, si el evento mouseup se activa en cualquiera de ellos, se descarta el objeto arrastrado.

También puede usar las coordenadas del objeto que está arrastrando para detectar si está en un cuadro desplegable, pero requiere un poco más de código para encontrar las coordenadas del cuadro delimitador y usar el mouse es suficiente para mí.

El código usa jQuery pero no jQueryUI. He probado en Chrome, Firefox y Opera, pero no en IE :)

También estoy agregando el código aquí si jsfiddle no está accesible.

HTML

<p>Drag orange boxes to grey ones</p> 
<div class="droppable"></div> 
<div class="droppable"></div> 
<div class="droppable"></div> 
<div class="droppable"></div> 

<div class="draggable"></div> 
<div class="draggable"></div> 
<div class="draggable"></div> 

CSS

.droppable { 
    width:50px; 
    height:50px; 
    float: left; 
    background-color: #DDD; 
    margin: 5px; 
} 

.draggable { 
    width:40px; 
    height:40px; 
    float: right; 
    background-color: #FC0; 
    margin: 5px; 
    cursor: pointer; 
} 

.dropped { 
    background-color: #FC0; 
} 

.somethingover { 
    background-color: #FCD; 
} 

JS

var dragged, mousex, mousey, coordinates = []; 

var continueDragging = function(e) { 
    // Change the location of the draggable object 
    dragged.css({ 
     "left": e.pageX - (dragged.width()/2), 
     "top": e.pageY - (dragged.height()/2) 
    }); 

    // Check if we hit any boxes 
    for (var i in coordinates) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       // Lets change the background color 
       coordinates[i].dom.addClass("somethingover"); 
      } 
     } else { 
      // Nope, we did not hit any objects yet 
      coordinates[i].dom.removeClass("somethingover"); 
     } 
    } 

    // Keep the last positions of the mouse coord.s 
    mousex = e.pageX; 
    mousey = e.pageY; 
} 

var endDragging = function(e) { 
    // Remove document event listeners 
    $(document).unbind("mousemove", continueDragging); 
    $(document).unbind("mouseup", endDragging); 

    // Check if we hit any boxes 
    for (var i in coordinates) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       droptarget = coordinates[i].dom; 
       droptarget.removeClass("somethingover").addClass("dropped"); 
       dragged.hide("fast", function() { 
        $(this).remove(); 
       }); 
      } 
     } 
    } 

    // Reset variables 
    mousex = 0; 
    mousey = 0; 
    dragged = null; 
    coordinates = []; 
} 

var startDragging = function(e) { 
    // Find coordinates of the droppable bounding boxes 
    $(".droppable").each(function() { 
     var lefttop = $(this).offset(); 
     // and save them in a container for later access 
     coordinates.push({ 
      dom: $(this), 
      left: lefttop.left, 
      top: lefttop.top, 
      right: lefttop.left + $(this).width(), 
      bottom: lefttop.top + $(this).height() 
     }); 
    }); 

    // When the mouse down event is received 
    if (e.type == "mousedown") { 
     dragged = $(this); 
     // Change the position of the draggable 
     dragged.css({ 
      "left": e.pageX - (dragged.width()/2), 
      "top": e.pageY - (dragged.height()/2), 
      "position": "absolute" 
     }); 
     // Bind the events for dragging and stopping 
     $(document).bind("mousemove", continueDragging); 
     $(document).bind("mouseup", endDragging); 
    } 
} 

// Start the dragging 
$(".draggable").bind("mousedown", startDragging); 
+0

Al principio era un poco escéptico, pero esta técnica me ha funcionado muy bien, ¡muchas gracias! – OrganicPanda

+0

¡gran solución! Gracias !! – Denis

3

Hay dos maneras básicas que puede hacer esto:

  1. pista mousemove y reaccionar a coordenadas x/y
  2. tienen un blanco transparente que tiene un mayor z-index que el contenedor de arrastre

La primera opción realmente no usa el evento mouseover, pero le dará el mismo resultado neto.

Tenga en cuenta que algunos navegadores (es decir) no activarán mouseover en elementos transparentes, por lo que debe falsificarlo configurando una imagen de fondo que sea transparente o estableciendo una imagen aleatoria como fondo y colocándola fuera del elemento como este :

element { 
background: url(/path/to/img) no-repeat -10000px 0; 
} 
+0

Eso * podría * interferir con el elemento que se está arrastrando, dependiendo de cómo lo haya configurado. – Purag

0

Modifing un poco el código Publicado por emrahgunduz, específicamente el bucle, también puede gestionar área lanzables anidada.

var dragged, mousex, mousey, coordinates = []; 

var continueDragging = function(e) { 
    // Change the location of the draggable object 
    dragged.css({ 
     "left": e.pageX - (dragged.width()/2), 
     "top": e.pageY - (dragged.height()/2) 
    }); 

    // Check if we hit any boxes 
    for (var i = coordinates.length - 1; i >= 0; i--) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       // Lets change the background color 
       $('.droppable').removeClass("somethingover"); 
       coordinates[i].dom.addClass("somethingover"); 
       break; 
      } 
     } else { 
      // Nope, we did not hit any objects yet 
      coordinates[i].dom.removeClass("somethingover"); 
     } 
    } 

    // Keep the last positions of the mouse coord.s 
    mousex = e.pageX; 
    mousey = e.pageY; 
}; 

var endDragging = function(e) { 
    // Remove document event listeners 
    $(document).unbind("mousemove", continueDragging); 
    $(document).unbind("mouseup", endDragging); 

    // Check if we hit any boxes 
    for (var i = coordinates.length - 1; i >= 0; i--) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       droptarget = coordinates[i].dom; 
       droptarget.removeClass("somethingover").addClass("dropped"); 
       dragged.hide("fast", function() { 
        $(this).remove(); 
       }); 
      } 
     } 
    } 

    // Reset variables 
    mousex = 0; 
    mousey = 0; 
    dragged = null; 
    coordinates = []; 
}; 

var startDragging = function(e) { 
    // Find coordinates of the droppable bounding boxes 
    $(".droppable").each(function() { 
     var lefttop = $(this).offset(); 
     // and save them in a container for later access 
     coordinates.push({ 
     dom: $(this), 
     left: lefttop.left, 
     top: lefttop.top, 
     right: lefttop.left + $(this).width(), 
     bottom: lefttop.top + $(this).height() 
    }); 
}; 

// When the mouse down event is received 
if (e.type == "mousedown") { 
    dragged = $(this); 
    // Change the position of the draggable 
    dragged.css({ 
     "left": e.pageX - (dragged.width()/2), 
     "top": e.pageY - (dragged.height()/2), 
     "position": "absolute" 
    }); 
    // Bind the events for dragging and stopping 
    $(document).bind("mousemove", continueDragging); 
    $(document).bind("mouseup", endDragging); 
} 

// Start the dragging 
$(".draggable").bind("mousedown", startDragging); 
6

En todas las respuestas que se presentan, no veo la más simple y obvia (tal vez me falta algo en cuestión OP). Pero, si alguien se tropiezan con esto más adelante, y necesita una solución rápida y sencilla en JS puros ..

Lo hace mediante el cambio de elemento className ondragover, y cambiando de nuevo a clase original OnDragLeave

my_element.ondragover = function(ev) { 
ev.preventDefault(); 
this.className = 'myElem_dragover'; 
} 
my_element.ondragleave = function(ev) { 
ev.preventDefault(); 
this.className = 'myElem_orig'; 
} 

CSS

.myElem_orig {  //this is your initial class for element 
    top: 30px; 
    left: 20px; 
    ..... 
    background-color: blue; 
} 

.myElem_orig:hover { //this is hover state, just changing bg color 
    background-color: red; 
} 

.myElem_dragover { //new class, needs all attributes from original class 
    top: 30px; 
    left: 20px; 
    ........ 
    background-color: red; //behaves the same like hover does 
} 

edición:
se olvidó de ment ion, debe traer de vuelta la clase original ondrop también, de lo contrario, div permanecerá en la clase de dragover

+1

Creo que esta pregunta es anterior al uso generalizado del atributo incorporado arrastrable en HTML, que definitivamente es la forma más fácil de hacerlo, a menos que esté haciendo comportamientos personalizados. –

+0

Eso es lo que estaba buscando, no un comportamiento personalizado. Gracias. – Wellyngton

+0

Estoy de acuerdo con Greg. Esta respuesta es excelente ahora y se hará popular muy pronto. –

0

Encontró un pequeño error en el ejemplo de jsfiddle. Cuando abandona el área de caída verticalmente, el área de caída todavía tiene la clase 'somethinghover'.

http://jsfiddle.net/MAazv

Reemplazar esta

if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
 
    if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
 
    // Yes, the mouse is on a droppable area 
 
    // Lets change the background color 
 
    coordinates[i].dom.addClass("somethingover"); 
 
    } 
 
} else { 
 
    // Nope, we did not hit any objects yet 
 
    coordinates[i].dom.removeClass("somethingover"); 
 
}

http://jsfiddle.net/MAazv/122

con esto:

if (mousex >= coordinates[i].left && mousex <= coordinates[i].right && mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
 
    // Yes, the mouse is on a droppable area 
 
    // Lets change the background color 
 
    coordinates[i].dom.addClass("somethingover"); 
 
} else { 
 
    // Nope, we did not hit any objects yet 
 
    coordinates[i].dom.removeClass("somethingover"); 
 
}

Cuestiones relacionadas