34

Mis disculpas si esto fue respondido en otra pregunta, no pude encontrar una respuesta específica para mi problema!jQuery arrastrar y soltar - verificar una caída fuera de un droppable

Estoy tratando de probar si un jQuery que se puede arrastrar se está dejando caer fuera de un droppable legal. Esto normalmente se resolvería el 90% del tiempo invirtiendo el arrastre, pero no quiero hacerlo. En cambio, quiero hacer una cosa si el arrastrable se deja caer en un droppable (¡funciona muy bien!), Y algo más si se descarta fuera de todos los posibles droppables (¡que en este momento estoy obteniendo lo mejor de mí!).

En pocas palabras:

jQuery('#droppable').droppable(
{ 
    accept: '#draggable', 
    drop: function(event, ui) 
    { 
     // awesome code that works and handles successful drops... 
    } 
}); 

jQuery('#draggable').draggable(
{ 
    revert: false, 
    stop: function() 
    { 
     // need some way to check to see if this draggable has been dropped 
     // successfully or not on an appropriate droppable... 
     // I wish I could comment out my headache here like this too... 
    } 
}); 

siento que me falta algo muy obvio ... gracias de antemano por cualquier ayuda!

Respuesta

52

Debido a que activa el evento de caída de la lanzables antes del evento de detención de la que pueden arrastrarse, creo que se puede establecer un indicador en el elemento de ser arrastrado en el caso de caída de este modo:

jQuery('#droppable').droppable(
{ 
    accept: '#draggable', 
    drop: function(event, ui) 
    { 
     ui.helper.data('dropped', true); 
     // awesome code that works and handles successful drops... 
    } 
}); 

jQuery('#draggable').draggable(
{ 
    revert: false, 
    start: function(event, ui) { 
     ui.helper.data('dropped', false); 
    }, 
    stop: function(event, ui) 
    { 
     alert('stop: dropped=' + ui.helper.data('dropped')); 
     // Check value of ui.helper.data('dropped') and handle accordingly... 
    } 
}); 
+3

Solución muy genial Lucas, gracias por esto ... ¡funcionó como un amuleto! –

+0

Increíble pero: ¿hay alguna documentación para .data? Para mí desciende un poco del cielo: 3 (léase: no se pudo encontrar más información) – yoshi

+0

http://api.jquery.com/jQuery.data/ –

4

Intente utilizar el evento "salir" de un elemento droppable.

Este es el documentation

"Este evento se activa cuando una arrastrable aceptado es arrastrado hacia fuera (dentro de la tolerancia de) este lanzables." Si estoy en lo cierto, esto es lo que necesitas.

Lo que también es posible es crear una superposición de elementos sobre toda la página. Si el elemento se cae allí, disparas tu evento. No es el mejor, pero creo que es la única forma de hacerlo. Porque necesita algún otro elemento "droppable" para disparar estos eventos.

+0

Hola ggzone, gracias por la respuesta rápida ... sería perfecto si el arrastrable que estaba arrastrando estuviera saliendo de un droppable válido. Si un objeto arrastrable fuera arrastrado desde su posición original y luego caído en algún lugar al azar lejos de un droppable legal, entonces este evento nunca se disparará, hasta donde yo sé. –

+0

he editado mi respuesta – ggzone

+0

Impresionante, gracias ggzone ... como dijiste, probablemente no sea la mejor, y si aún no has visto la respuesta proporcionada por Luke, creo que ofrece una solución mucho más elegante con la misma resultados! –

9

veo que usted ya tiene una respuesta ; de todos modos tenía este mismo problema hoy y he resuelto de esta manera:

var outside = 0; 

// this one control if the draggable is outside the droppable area 
$('#droppable').droppable({ 
    accept  : '.draggable', 
    out   : function(){ 
     outside = 1; 
    }, 
    over  : function(){ 
     outside = 0; 
    } 
}); 

// this one control if the draggable is dropped 
$('body').droppable({ 
    accept  : '.draggable', 
    drop  : function(event, ui){ 
     if(outside == 1){ 
      alert('Dropped outside!'); 
     }else{ 
      alert('Dropped inside!'); 
     } 
    } 
}); 

que necesitaba que debido a que no podía cambiar las opciones de mis draggables, así que tuve que trabajar sólo con droppables (lo necesitaba dentro de la impresionante FullCalendar plugin). Supongo que podría tener algunos problemas con la opción "codiciosa" de los elementos desplegables, pero debería funcionar en la mayoría de los casos.

PD: perdón por mi mal inglés.

EDITAR: Como sugerí, creé la versión usando jQuery.data; que se puede encontrar aquí: jsfiddle.net/Polmonite/WZma9/

De todos modos la documentación jQuery.data dicen:

Tenga en cuenta que este método actualmente no ofrece soporte multiplataforma para establecer datos de documentos XML, como Internet Explorer no permite que los datos para ser adjuntado a través de propiedades expando.

(lo que significa que no funciona en IE antes de 8)

EDIT 2: Como se ha señalado por @Darin Peterson, el código anterior no funciona con más de un área de colocación ; esto debería solucionar ese problema: http://jsfiddle.net/Polmonite/XJCmM/

EDIT 3: Ejemplo de EDIT 2 tiene un error. Si arrastro "Arrastrarme" en la parte inferior desplegable, luego suelte "Arrástreme también" hacia la parte superior desplegable y luego suelte "Arrástreme también" afuera, alerta "¡Caído adentro!" Entonces, no lo uses.

EDIT 4: Según lo observado por @Aleksey Gor, el ejemplo en Edit 2 era incorrecto; en realidad, fue más un ejemplo para explicar cómo recorrer todas las arrastrables/droppables, pero en realidad me olvidé de eliminar los mensajes de alerta, por lo que fue bastante confuso. Here el violín actualizado.

+0

¡Agradable y simple! Es una buena solución, especialmente cuando no tienes acceso a los juegos de arrastre. Me preguntaba, ahora pensando en posibles problemas de alcance, si pudiera usar los datos '$ (" # droppable "). (" Outside ", true);' to 'carry' el estado de la variable de forma más elegante? ¡Buena solución! ¡Gracias por su aporte! :) –

+1

Claro. Agregué la versión usando jQuery.data a la respuesta;) De todos modos, eso significa que no hay IE7 (en caso de que a alguien le importe). – Polmonite

+0

¡Brillante! ¡Gracias por la investigación y la respuesta expandida! +1 –

1

La ventaja del siguiente ejemplo, es que no es necesario cambiar o saber sobre el código lanzables:

La propiedad de reversión que pueden arrastrarse puede tener una función (valor) {}. Se pasa un valor como argumento, que indica si el ayudante se colocó en un elemento (el elemento desplegable), o 'falso' si no se dejó caer en un elemento (se descarta o no se acepta).

Nota: hay que devolver el valor bool correcta de ese revert-función, con el fin de decirle al ayudante para revertir o no (verdadero/falso). Verdadero significa sí, lleve al ayudante a su posición original , moviéndolo hacia atrás en cámara lenta (listo para usar). Falso significa que no, solo quita el asistente de forma abrupta. Al establecer la propiedad nuevamente a 'no válido', es un acceso directo de decir

  • 'sí, si se deja caer fuera, luego vuelve ayudante'
  • 'no, si se deja caer sobre un elemento lanzables y aceptado, entonces matar al ayudante de inmediato ".

Mi conjetura es que se puede añadir ayudante de la interfaz de usuario actual al contenedor se puede arrastrar con la propiedad de los datos durante el evento de inicio. A continuación, retírelo en la función de revertir desde la propiedad de datos. A continuación, agregue una propiedad al asistente, indicando si se cayó o no. Luego, en última instancia, en el evento de detención, verifique el valor de esta propiedad de datos y haga lo que desea.

Orden del evento/función exige que pueden arrastrarse: puesta en volver parar

Esto podría ser un ejemplo:

jQuery('#draggable').draggable(
{ 
    start: function(event, ui) { 
     $(this).data('uihelper', ui.helper); 
    }, 
    revert: function(value){ 
     var uiHelper = (this).data('uihelper'); 
     uiHelper.data('dropped', value !== false); 
     if(value === false){ 
      return true; 
     } 
     return false; 
    }, 
    stop: function(event, ui) 
    { 
     if(ui.helper.data('dropped') === true){ 
      // handle accordingly... 
     } 
    } 
}); 

Incluso puede devolver verdadero en la función de reversión, y acaba de quitar el ayudante durante el evento de detención en cambio, según el valor de los datos ('descartado') con ui.helper.remove(). O incluso podría explotarlo con CSS3 si todavía tiene un mal día;)

Cuestiones relacionadas