jQuery: drag and drop e posizionamento

jQuery: drag and drop e posizionamento

Ho appena pubblicato un test che dimostra quanto sia difficile gestire il drag and drop con jQuery se non si conoscono i dettagli del posizionamento degli elementi. In breve, jQuery UI usa il posizionamento relativo sugli elementi, ma le coordinate dell'elemento oggetto dell'azione vengono calcolate e quindi aggiunte come stili CSS inline in modo cumulativo, ossia come il risultato di tutto lo spostamento dell'elemento da una parte all'altra dello schermo.

Se si vuole spostare un elemento dal suo genitore ad un elemento esterno si deve:

  • impostare lo z-index dell'elemento di destinazione su un valore negativo (-1) per impedire che l'elemento trascinato scompaia dietro l'elemento di destinazione durante il trascinamento
  • impostare i valori delle proprietà top e left dell'elemento trascinato su 0 tramite l'ausilio della direttiva !important per azzerare le coordinate impostate da jQuery UI e quindi impedire che l'elemento finisca fuori dall'elemento di destinazione.

Con questa struttura:


<div id="grid">

	<div class="row">
		<div class="box">1</div>
		<div class="box">2</div>
		<div class="box">3</div>
	</div>
	
	<div class="row">
		<div class="box">4</div>
		<div class="box">5</div>
		<div class="box">6</div>
		
		
	</div>
	
</div>

<div id="grid2"></div>

dovremo fare attenzione a questi stili CSS:


#grid2 {
	width: 615px;
	margin: 1em auto;
	padding: 0;
	height: 370px;
	background: silver;
	position: relative;
	z-index: -1;
}

#grid2 div.box {
	top: 0 !important;
	left: 0 !important;
}

Per lo spostamento da un elemento all'altro la procedura è semplice: si clona l'elemento, si aggiunge la copia all'elemento di destinazione e quindi si rimuove l'elemento originale. Quindi avremo:


var context = $('#grid');
var boxes = $('div.box', context);
var target = $('#grid2');


var runMovements = function() {
  
  
    boxes.each(function() {
    
      var box = $(this);
      
      box.draggable({
        
        start: function() {
        
          target.animate({
            opacity: 0.7
          }, 'slow');       
        
        },
        
        stop: function() {
          
         var copy = box.clone();
         copy.appendTo(target);
         box.remove();
         
         target.animate({
         
           opacity: 1
         
         }, 'slow');
        
         
        
        }
        
      });
    
    
    });
    
  
  
};

La copia e la cancellazione dell'elemento avvengono quando il trascinamento è concluso.

Torna su