2009-04-01 9 views
27

Sto cercando di implementare un'interfaccia web con un numero di elementi che possono essere selezionati e trascinati per posizionarli, in gruppi o singolarmente. Piuttosto come il desktop di Windows, davvero.C'è un plugin JQuery che combina Draggable e selezionabile

Stiamo già utilizzando JQuery, quindi le aggiunte a quella sarebbero la prima scelta. JQuery UI Draggables e Selectables eseguono individualmente molto di ciò che vogliamo, ma non lavorano davvero insieme per dare quel tipo di effetto che stiamo cercando.

Sono completamente sopraffatto dal sito del plug-in JQ (l'algoritmo "popolare" non sembra molto utile) e vorrei ricevere una guida sul modo migliore per evitare un sacco di reinvenzione della ruota qui, come direi che questa metafora è già stata fatta.

+0

Codice in http://stackoverflow.com/questions/34698117/elements-became-randomly-non-resizable-after-dragging queston contiene anche la risposta a questa domanda Tuttavia il codice nelle risposte causa la perdita casuale di ridimensionabile alla resistenza – Andrus

risposta

19

Avevo anche bisogno di fare la stessa cosa, e non volevo usare l'estensione dell'interfaccia da eyecon.ro. Dopo alcune ricerche, ho trovato Combining Selectables And Draggables Using jQuery UI. È ben detto, ma per far funzionare i frammenti di codice devi scavare in esso. Sono stato in grado di farlo funzionare. L'ho leggermente cambiato, questo è il mio modo di farlo. Ha bisogno di modifiche per l'utilizzo a livello di produzione, ma spero che aiuti.

// this creates the selected variable 
// we are going to store the selected objects in here 
var selected = $([]), offset = {top:0, left:0}; 

// initiate the selectable id to be recognized by UI 
$("#selectable").selectable({ 
    filter: 'div', 
}); 

// declare draggable UI and what we are going to be doing on start 
$("#selectable div").draggable({ 
    start: function(ev, ui) { 
     selected = $(".ui-selected").each(function() { 
      var el = $(this); 
      el.data("offset", el.offset()); 
     }); 

     if(!$(this).hasClass("ui-selected")) $(this).addClass("ui-selected"); 
     offset = $(this).offset(); 
    }, 
    drag: function(ev, ui) { 
     var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left; 

     // take all the elements that are selected expect $("this"), which is the element being dragged and loop through each. 
     selected.not(this).each(function() { 
      // create the variable for we don't need to keep calling $("this") 
      // el = current element we are on 
      // off = what position was this element at when it was selected, before drag 
      var el = $(this), off = el.data("offset"); 
      el.css({top: off.top + dt, left: off.left + dl}); 
     }); 
    } 
}); 

Stili CSS per essere in grado di vedere ciò che sta succedendo:

#selectable { width: 100%; height: 100%;} 
#selectable div { 
    background: #ffc; 
    line-height: 25px; 
    height: 25px; 
    width: 200px; 
    border: 1px solid #fcc; 
    } 
#selectable div.ui-selected { 
    background: #fcaf3e; 
    } 
#selectable div.ui-selecting { 
    background: #8ae234; 
    } 

Tag HTML:

<div id="selectable"> 
    <div>item 1</div> 
    <div>item 2</div> 
    <div>item 3</div> 
    <div>item 4</div> 
</div> 
+2

problema principale con questo codice che non ti lascia il controllo clicca per aggiungere altri elementi. –

+2

Questo sembra consentire solo di trascinare più elementi selezionati, non sono in grado di selezionare qualsiasi elemento selezionabile con un solo clic (men che meno ctrl clic) – digout

+0

Questo codice causa la perdita casuale di ridimensionabile durante il trascinamento. Questo è pubblicato in http://stackoverflow.com/questions/34698117/elements-became-randomly-non-resizable-after-dragging Come risolvere? – Andrus

4

Ho fatto qualche modifica alla risposta data da Sinan Yasar. Non è perfetto, ma si comporta già molto più come se non fosse.

Un'aggiunta principale è un listener di clic che chiama la selezione.

// manually trigger the "select" of clicked elements 
$("#selectable > div").click(function(e){ 
    if (e.metaKey == false) { 
     // if command key is pressed don't deselect existing elements 
     $("#selectable > div").removeClass("ui-selected"); 
     $(this).addClass("ui-selecting"); 
    } 
    else { 
     if ($(this).hasClass("ui-selected")) { 
      // remove selected class from element if already selected 
      $(this).removeClass("ui-selected"); 
     } 
     else { 
      // add selecting class if not 
      $(this).addClass("ui-selecting"); 
     } 
    } 

    $("#selectable").data("selectable")._mouseStop(null); 
}); 

Si può vedere un esempio funzionante completo qui: http://jsfiddle.net/DXrNn/4/

C'è anche un plugin jQuery-ui disponibile che fa proprio questo: http://code.google.com/p/jqdragdropmultiselect/ Il probleme è che non sembra mantenuta.

modifica: se si definisce l'opzione "filtro" del trascinabile, sarà necessario chiamare selectable.refresh() prima di selezionare._mouseStop (null).

$("#selectable > div").click(function(e){ 
    ... 
    var selectable = $("#container").data("selectable"); 
    selectable.refresh(); 
    selectable._mouseStop(null); 
    ... 
+2

Non importa quanto provi la tua soluzione in jsfiddle, non riesco a ottenere nessun elemento da trascinare, ma solo selezionare. Chrome 19. – trusktr

+1

@trusktr Prova con 'jQuery 1.8.3' e' jQueryUI 1.9.2' – mraaroncruz

+1

@trusktr a causa di questo http://stackoverflow.com/questions/14366322/error-jquery-ui-draggable-cannot- read-property-msie sembra che sia necessario jQueryUI 1.10 per usare jQuery EDGE – mraaroncruz

10

Questa domanda è pertinente, ma è vecchia; così come le risposte. Here's an updated version di @ di idFlood jsfiddle, che funziona con jQuery 1.9.1 + jQueryUI 1.10.3:

// store selected elements and the offset of the dragged element 
var selected = $([]), offset = {top:0, left:0}; 

$("#selectable > div").draggable({ 
    start: function (event, ui) { 
     var $this = $(this); 

     if ($this.hasClass("ui-selected")) { 
      // if this is selected, attach current offset 
      // of each selected element to that element 
      selected = $(".ui-selected").each(function() { 
       var el = $(this); 
       el.data("offset", el.offset()); 
      }); 
     } else { 
      // if this is not selected, clear current selection 
      selected = $([]); 
      $("#selectable > div").removeClass("ui-selected"); 
     } 
     offset = $this.offset(); 
    }, 

    drag: function (event, ui) { 
     // drag all selected elements simultaneously 
     var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left; 
     selected.not(this).each(function() { 
      var $this = $(this); 
      var elOffset = $this.data("offset"); 
      $this.css({top: elOffset.top + dt, left: elOffset.left + dl}); 
     }); 
    } 
}); 

// enable marquee selecting and deselect on outside click... 
$("#selectable").selectable(); 

// ...but manually implement selection to prevent interference from draggable() 
$("#selectable").on("click", "div", function (e) { 
    if (!e.metaKey && !e.shiftKey) { 
     // deselect other elements if meta/shift not held down 
     // $("#dc-modules .dc-module").removeClass("ui-selected"); 
     $("#selectable > div").removeClass("ui-selected"); 
     $(this).addClass("ui-selected"); 
    } else { 
     if ($(this).hasClass("ui-selected")) { 
      $(this).removeClass("ui-selected"); 
     } else { 
      $(this).addClass("ui-selected"); 
     } 
    } 
}); 

ho avuto un problema con il() chiamata _mouseStop gettando un errore, così ho rimosso; ciò significa che lo stato ui-selecting non si verifica più al clic, ma tutte le altre funzionalità rimangono intatte.

+0

Questa soluzione funziona molto bene ma ho problemi a farlo funzionare con droppable. C'è qualcosa di intrinseco alla soluzione che pensi possa entrare in conflitto con la droppable o dovrei continuare a sbattere contro questo codice? –

+0

@ericsoco Questo codice causa il loff casuale ridimensionabile durante il trascinamento. Questo è pubblicato in http://stackoverflow.com/questions/34698117/elements-became-randomly-non-resizable-after-dragging Come risolvere? – Andrus

Problemi correlati