¿Hay un plugin jQuery que combina Arrastrable y Seleccionable


Estoy buscando implementar una interfaz web con una serie de elementos que se pueden seleccionar y arrastrar para colocarlos, ya sea en grupos o individualmente. Más bien como el escritorio de Windows, en realidad.

Ya estamos usando jQuery, por lo que las adiciones a eso serían la primera opción. jQuery UI Draggables y Seleccionables 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 JQ sitio plugin (es algoritmo 'popular' no parece muy útil), y agradecería orientación en cuanto a la mejor manera de evitar una gran cantidad de rueda de reinvención aquí, ya que supongo que esta metáfora ya se ha hecho.

Author: Will Dean, 2009-04-01

3 answers

También necesitaba hacer lo mismo, y no quería usar la extensión de la interfaz desde eyecon.ro. Después de algunas investigaciones, encontré Combinando Selectables Y Draggables Usando jQuery UI. Está muy bien dicho, pero para hacer que los fragmentos de código se ejecuten tienes que profundizar en él. Pude hacer que funcionara. Lo cambié un poco, esta es mi manera de hacerlo. Necesita modificaciones para su uso a 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 poder ver lo que hay 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;
    }

Marcado HTML:

<div id="selectable">
    <div>item 1</div>
    <div>item 2</div>
    <div>item 3</div>
    <div>item 4</div>
</div>
 20
Author: Sinan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-08 22:53:39

Esta pregunta es relevante, pero es antigua; también lo son las respuestas. Aquí está una versión actualizada 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");
        }
    }
});

Tuve un problema con la llamada _mouseStop() lanzando un error, así que lo eliminé; esto significa que el estado ui-selecting ya no sucede al hacer clic, pero todas las demás funcionalidades permanecen intactas.

 10
Author: ericsoco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-20 03:14:54

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

Una adición principal es un oyente de clics que llama a select.

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

Puedes ver un ejemplo completo aquí: http://jsfiddle.net/DXrNn/4 /

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

Editar: si define la opción "filtro" del arrastrable, tendrá que llamar seleccionable.refresh() antes del seleccionable._mouseStop (nulo).

$( "#selectable > div" ).click( function(e){
  ...
  var selectable = $("#container").data("selectable");
  selectable.refresh();
  selectable._mouseStop(null);
  ...
 4
Author: idFlood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-27 13:32:40