2009-04-01 14 views
27

Estoy buscando implementar una interfaz web con un número de elementos que se pueden seleccionar y arrastrar para colocarlos, en grupos o por separado. Más bien como el escritorio de Windows, realmente.¿Existe un complemento JQuery que combine Arrastrable y seleccionable

Ya estamos usando JQuery, por lo que las adiciones a eso serían la primera opción. JQuery UI Draggables y Selectables individualmente hacen mucho de lo que queremos, pero realmente no funcionan juntos para dar el tipo de efecto que estamos buscando.

Estoy completamente abrumado por el sitio de plugin de JQ (su algoritmo 'popular' no parece muy útil) y agradecería la orientación sobre la mejor manera de evitar una gran reinvención de la rueda aquí, como yo diría que esta metáfora ya se ha hecho.

+0

Código en http://stackoverflow.com/questions/34698117/elements-became-randomly-non-resizable-after-dragging queston también contiene una respuesta a esta pregunta Sin embargo, el código en las respuestas causa una pérdida aleatoria del tamaño en el arrastre – Andrus

Respuesta

19

También necesitaba hacer lo mismo, y no quería utilizar la extensión de interfaz de eyecon.ro. Después de algunas investigaciones, encontré Combining Selectables And Draggables Using jQuery UI. Está muy bien dicho, pero para hacer que los fragmentos de código se ejecuten hay que profundizar en ello. Pude hacer que funcione. Lo cambié ligeramente, esta es mi manera de hacerlo. Necesita modificaciones para usar en el nivel de producción, pero espero que ayude.

// 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}); 
     }); 
    } 
}); 

Estilos CSS para ser capaz de ver lo que está sucediendo:

#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; 
    } 

Formato HTML:

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

principal problema con este código, no le permite controlar el clic para agregar elementos adicionales. –

+2

Esto parece que solo le permite arrastrar varios elementos seleccionados, no puedo seleccionar ningún elemento seleccionable con un solo clic (y mucho menos clic en clic) – digout

+0

Este código causa la pérdida aleatoria del tamaño en el arrastre. Esto se publica en http://stackoverflow.com/questions/34698117/elements-became-randomly-non-resizable-after-dragging ¿Cómo solucionarlo? – Andrus

4

He hecho algunas modificaciones a la respuesta dada por Sinan Yasar. No es perfecto, pero ya se comporta mucho más como lo haría excepto.

Una adición principal es un oyente de clic que llama a la selección.

// 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); 
}); 

Se puede ver un ejemplo de trabajo completa aquí: http://jsfiddle.net/DXrNn/4/

También hay un plugin jquery-ui disponibles que hace precisamente eso: http://code.google.com/p/jqdragdropmultiselect/ El probleme es que no se ve mantenida.

editar: si define la opción "filtro" del arrastrable, deberá llamar a seleccionable.refresh() antes del seleccionable._mouseStop (nulo).

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

No importa cuánto intente con su solución en jsfiddle, no puedo obtener ningún elemento para arrastrar, solo seleccione. Chrome 19. – trusktr

+1

@trusktr Pruebe i con 'jQuery 1.8.3' y' jQueryUI 1.9.2' – mraaroncruz

+1

@trusktr debido a esto http://stackoverflow.com/questions/14366322/error-jquery-ui-draggable-cannot- read-property-msie parece que necesitaría jQueryUI 1.10 para usar jQuery EDGE – mraaroncruz

10

Esta pregunta es relevante, pero es antigua; también lo son las respuestas. Here's an updated version de jsFiddle @ de idFlood, que funciona 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"); 
     } 
    } 
}); 

que tenía un problema con la llamada _mouseStop() lanzando un error, por lo que se lo quité; esto significa que el estado ui-selecting ya no ocurre al hacer clic, pero todas las demás funciones permanecen intactas.

+0

Esta solución funciona muy bien pero tengo problemas para hacer que funcione con droppable. ¿Hay algo intrínseco a la solución que crees que entraría en conflicto con la posibilidad de publicación o debería seguir golpeando mi cabeza contra este código? –

+0

@ericsoco Este código causa la eliminación aleatoria del tamaño en el arrastre. Esto se publica en http://stackoverflow.com/questions/34698117/elements-became-randomly-non-resizable-after-dragging ¿Cómo solucionarlo? – Andrus

Cuestiones relacionadas