2010-10-16 30 views
8

Estoy haciendo una aplicación, que está usando un droppable div y unos pocos div s arrastrables. ¿Cómo puedo hacer que el droppable no acepte más de un div arrastrable? Busqué en Google, pero no encontré ninguna solución.jQuery UI - Droppable solo acepta un arrastrable


Me surgió una solución alternativa. ¿Cómo puedo verificar si hay un elemento descartado en este div desprendible? Si está ocupado entonces revertir esta arrastrable, que está tratando de que se retiren

Respuesta

5

Puede destruir el widget .droppable() después de la primera drop, así:

$(".droppable").droppable({ 
    drop: function(event, ui) { 
     $(this).droppable("destroy"); 
    } 
}); 

You can try out a demo here.

+0

bien, pero cuando me libero este campo lanzables, cómo hazlo de nuevo desplegable –

+2

@Emil - Puedes usar '" deshabilitar "' luego '" habilitar "' más tarde en lugar de '" destruir "' si necesitas volver a habilitarlo :) –

+1

lo hice, pero no sé cómo para habilitarlo. Intenté con: enable_Droppable, pero no funcionó. ¿Qué debo usar en lugar de 'salir' –

0

que le permita, utilice la opción: $(".selector").droppable({ disabled: **false** });

25

OK encontró una buena solución para esto, esencialmente en 'caída' fijo el lanzables para aceptar sólo el ítem que ha sido arrastrado a ella.

Cuando 'deshabilita', el evento de 'salida' que necesita reiniciar ya no está disponible, así que en su lugar acabo de cambiar los artículos elegibles.

Entonces es posible que yo utilizo el evento OUT volver a aceptar todos los artículos que se pueden arrastrar y porque nada más se acepta la OUT no se activará por otros draggables:

$(".drop-zone").droppable({ 
    drop: function(event, ui) { 
     $(this).droppable('option', 'accept', ui.draggable); 
    }, 
    out: function(event, ui){ 
     $(this).droppable('option', 'accept', '.drag-item'); 
     } 
    }); 
}); 
+0

? He tenido el mismo problema. Muy buena solución, gracias. – flash

+0

Nota rápida: esto solo funciona desde jQuery 1.6 – Narretz

+0

Tuve el mismo problema también. ¡Solución inteligente! ¡Gran trabajo! –

1

¿Qué tal esto:

$(".drop-zone").droppable({ 
    accept: function(draggable) { 
     return $(this).find("*").length == 0; 
    }); 
}); 

De esta forma, la función de aceptación devuelve verdadera solo cuando no se han eliminado elementos.

0

También podría hacerlo al revés, invirtiendo el elemento arrastrable cuando el elemento desplegable tiene cierta clase o atributo (basándose en este ejemplo: https://stackoverflow.com/a/3418306/1005334).

Así, por ejemplo, mediante el atributo rel (usted podría también utilizar class o algo más), para la lanzables:

$('.drop-zone').droppable({ 
    drop: function() { 
     drop.attr('rel', 'filled'); 
    } 
}); 

Y el arrastrable:

$('.draggable').draggable({ 
    revert: function (droppable) { 

     if (droppable.attr('rel') == 'filled') { 
      return true; 
     } 
    } 
}); 
3

Fácil Peasey. Solamente es necesario activar toda la de cuando se cernía sobre ellos y, a continuación, comprobar si el momento se cernía .drop-zona contiene un elemento arrastrable

$('.drop-zone').droppable({ 
    over: function(event, ui) { 

    // Enable all the .droppable elements 
    $('.droppable').droppable('enable'); 

    // If the droppable element we're hovered over already contains a .draggable element, 
    // don't allow another one to be dropped on it 
    if($(this).has('.draggable').length) { 
     $(this).droppable('disable'); 
    } 
    } 
}); 
+1

sólo quiero señalar que esta es una de las pocas respuestas en aquí que realmente funcionan. – maxheld

+0

$ (this) .has ('. Draggable'). Length devuelve siempre 0 para mí. ¿Hay tal vez una nueva sintaxis? – Metaphysiker

2

Esta solución resuelve un error importante en la respuesta de Likwid_T .drop zona.

$('.draggable').draggable({ 
    start: function(ev, ui) { 
    $('.ui-droppable').each(function(i, el) { 
     if (!$(el).find('.ui-draggable').length) $(el).droppable('enable'); 
    }); 
    } 
}); 

$('.droppable').droppable({ 
    drop: function(ev, ui) { 
    $(ev['target']).droppable('disable'); 
    } 
}); 
0

Mi solución es similar a la de Likwid_T, excepto que utiliza el evento drop lanzables, así como el mantenimiento de los vínculos entre draggables y droppables en lugar de lanzables del evento out. Creo que el problema con el uso de out es que se dispara incluso cuando se arrastra un elemento arrastrable sobre un elemento desplegable ya "completo" y luego "sale" de él.

droppable({ 
    drop: function(event, ui) { 
    var $droppable = $(this); 
    var $draggable = ui.draggable; 

    // If the draggable is moved from another droppable, unlink it from the old droppable 
    var oldDropped = $draggable.data('dropped'); 
    if(oldDropped) { 
     $draggable.data('dropped', null); 
     oldDropped.data('dragged', null); 
    } 

    // Link the draggable and droppable 
    $draggable.data('dropped', $droppable); 
    $droppable.data('dragged', $draggable); 
    }, 
    accept: function() { 
    // Only accept if there is no draggable already associated 
    return !$(this).data('dragged'); 
    } 
}); 

Una característica relacionada es que uno arrastra un elemento más de un lanzables que ya tiene una arrastrable, el viejo conseguiría sustituir y volver a su posición inicial. Así es como lo hago:

droppable({ 
    drop: function(event, ui) { 
    var $droppable = $(this); 
    var $draggable = ui.draggable; 

    // Reset position of any old draggable here 
    var oldDragged = $droppable.data('dragged'); 
    if(oldDragged) { 
     // In the CSS I have transitions on top and left for .ui-draggable, so that it moves smoothly 
     oldDragged.css({top: 0, left: 0}); 
     oldDragged.data('dropped', null); 
    } 

    // If the draggable is moved from another droppable, unlink it from the old droppable 
    var oldDropped = $draggable.data('dropped'); 
    if(oldDropped) { 
     $draggable.data('dropped', null); 
     oldDropped.data('dragged', null); 
    } 

    // Link the draggable and droppable 
    $draggable.data('dropped', $droppable); 
    $droppable.data('dragged', $draggable); 
    }, 
}); 
1

que pasan muchas horas para averiguarlo y, finalmente, a mí me funciona de esta manera:

$(".drop-zone").droppable({ 
    classes: { 
     "ui-droppable-active": "ui-state-active", 
     "ui-droppable-hover": "ui-state-hover" 
    }, 
    accept: function(draggable){ 
     if (!$(this).hasClass('dropped') || draggable.hasClass('dropped')){ 
      return true; 
     } 
     return false; 
    }, 
    drop: function(event, ui) { 
     $(this).addClass('dropped'); 
     ui.draggable.addClass('dropped'); 
    }, 
    out: function(event, ui){ 
     $(this).removeClass('dropped'); 
     ui.draggable.removeClass('dropped'); 
    } 
}); 
Cuestiones relacionadas