web-dev-qa-db-fra.com

regroupement d'objets déplaçables avec jquery-ui draggable

Je veux utiliser jquery draggable/droppable pour permettre à l'utilisateur de sélectionner un groupe d'objets (chacun a une case à cocher dans le coin), puis faites glisser tous les objets sélectionnés en tant que groupe ...

Je ne peux pas comprendre pour la vie de moi comment le faire haha.

Voici ce que je pense qui mènera à une solution utilisable, sur chaque objet déplaçable, utilisez l'événement start () et saisissez en quelque sorte tous les autres objets sélectionnés et ajoutez-les à la sélection

J'envisageais également de faire ressembler l'objet glissé à un groupe d'objets (ce sont des images, donc une pile de photos peut-être) pour des raisons de performances. Je pense que l'utilisation de la fonctionnalité de déplacement peut tomber si vous faites glisser plusieurs dizaines d'objets à la fois, cela semble-t-il une meilleure idée?

48
Jiaaro

Vous pouvez utiliser l'option helper du draggable pour faire glisser des groupes d'éléments.

Par exemple, si vos objets déplaçables ont des cases à cocher, vous pouvez renvoyer les éléments sélectionnés de la fonction d'assistance comme suit:

$('#dragSource li').draggable({
  helper: function(){
    var selected = $('#dragSource input:checked').parents('li');
    if (selected.length === 0) {
      selected = $(this);
    }
    var container = $('<div/>').attr('id', 'draggingContainer');
    container.append(selected.clone());
    return container; 
  }
}); 

Démo

J'ai installé une démo avec des images déplaçables avec des cases à cocher et une mise en page quelque peu fluide. Cliquez sur "Exécuter l'extrait de code" en bas pour voir le résultat:

$(function() {

  $('#dragSource li').draggable({
    helper: function() {
      var selected = $('#dragSource input:checked').parents('li');
      if (selected.length === 0) {
        selected = $(this);
      }
      var container = $('<div/>').attr('id', 'draggingContainer');
      container.append(selected.clone());
      return container;
    }
  });

  $('#dropTarget').droppable({
    tolerance: 'pointer',
    drop: function(event, ui) {
      $(this).append(ui.helper.children());
    }
  });

  $('#selectAll').click(function() {
    $('#dragSource input').prop('checked', true);
    return false;
  });

  $('#selectNone').click(function() {
    $('#dragSource input').prop('checked', false);
    return false;
  });

  $('#selectInvert').click(function() {
    $('#dragSource input').each(function() {
      var $this = $(this);
      if ($this.prop('checked')) {
        $this.prop('checked', false);
      } else {
        $this.prop('checked', true);
      }
    });
    return false;
  });
});
body {
  font-family: sans-serif;
  overflow-x: hidden;
}
div {
  margin: 5px;
  padding: 0;
}
ul {
  margin: 0;
  padding: 0;
}
li {
  list-style: none;
  padding: 0;
  margin: 0;
  float: left;
  white-space: nowrap;
}
#selectActions span,
#selectActions li {
  float: left;
  padding: 5px;
}
.droppableContainer {
  width: 48%;
  float: left;
  min-height: 200px
}
.droppableContainer li {
  height: 90px;
  width: 110px;
  margin: 2px;
  background-color: white;
  padding-bottom: 4px;
}
.droppableContainer img {
  width: 90px;
  max-height: 90px;
  max-width: 90px;
  width: 90px;
  vertical-align: middle;
}
.droppableContainer input {
  height: 90px;
  vertical-align: middle;
}
#draggingContainer {
  width: 48%;
}
#draggingContainer input {
  visibility: hidden;
}
#dropTarget {
  border: 3px dashed grey;
}
#dropTarget input {
  visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

<div id="selectActions">
  <span>Select:</span>
  <ul>
    <li><a id="selectAll" href="#">all</a>
    </li>
    <li><a id="selectNone" href="#">none</a>
    </li>
    <li><a id="selectInvert" href="#">invert</a>
    </li>
  </ul>
</div>
<div style="clear:left;">
  <div id="dragSource" class="droppableContainer">
    <ul>
      <li>
        <img src="http://imgs.xkcd.com/comics/drapes.png" /><input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/misusing_slang.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/donner.jpg" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/a_new_captcha_approach.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/bug.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/open_source.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/tag_combination.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/a_simple_plan.jpg" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/it_might_be_cool.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/hedgeclipper.jpg" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/pep_talk.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/regular_expressions.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/pwned.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/post_office_showdown.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/im_an_idiot.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/pointers.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/chess_photo.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/50_ways.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/e_to_the_pi_times_i.png" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/self-reference.jpg" />
        <input type="checkbox" />
      </li>
      <li>
        <img src="http://imgs.xkcd.com/comics/starwatching.png" />
        <input type="checkbox" />
      </li>
    </ul>
  </div>

  <div id="dropTarget" class="droppableContainer">
  </div>
</div>
78
brianpeiris

C'est exactement ce que j'essaie de faire. Jusqu'à présent, je n'ai pas réussi, mais j'ai trouvé ce gars l'a fait d'une manière très compliquée. vous pouvez le vérifier, vous pourriez peut-être faire quelque chose avec ça.

Cela devrait être une fonctionnalité de glisser-déplacer. J'espère qu'ils l'appliqueront plus tôt que tard

1
Allen Bargi

Ce que j'ai fait pour cela est créé une fonction à laquelle vous donnez les éléments esclave/maître, ce qui crée une fonction bind () pour le maître (je n'autorise un glissement du maître dans ce cas, vous pouvez contourner Je suis sûr que cela), ce qui oblige l'esclave à le suivre en utilisant le CSS jQuery standard.

    function overlap(slave,master) {
        $('a#groupTheseBlocks').click(function(){
            master.bind('drag', groupBlocks);
            slave.draggable('disable');

            // remember where the slave is in relation to the master
            sLeftRef = (slave.offset().left - master.offset().left);
            sTopRef = (slave.offset().top - master.offset().top);
        });


        function groupBlocks() {
            var left = master.offset().left;
            var top = master.offset().top;

            slave.draggable('disable');
            slave.css('left', (left + sLeftRef) + 'px');
            slave.css('top', (top + sTopRef) + 'px');

        } 
    }

Je suppose que je posterai plus à ce sujet une fois que j'aurai un exemple de travail. Dans l'état actuel des choses, cela fonctionne pour moi. Ce qui manque, c'est un moyen d'appeler le chevauchement (esclave, maître) avec les éléments que vous souhaitez regrouper. Je fais cela d'une manière vraiment spécifique. Vous pouvez trouver un moyen intelligent de le faire, j'en suis sûr.

1
kvnn

Idée de performance:

Créez un "objet de groupe" invisible. Lorsque les éléments sont vérifiés, faites-les enfants de l'objet groupe, lorsqu'ils ne sont pas sélectionnés, redéfinissez-les en tant qu'enfants du corps du document, ou parent statique ou autre. Vous devrez traduire la position des objets pour vous assurer qu'ils ne sautent pas, attacher/détacher également vos gestionnaires d'événements de souris aux enfants du groupe lorsque vous les ajoutez/supprimez.

Lorsque vous obtenez un événement souris haut/bas sur l'un des enfants, ce que vous déplacez est en fait cet objet de groupe.

Cela devrait le rendre globalement plus simple.

1
Paul