web-dev-qa-db-fra.com

jQuery glissable et largable entre deux conteneurs et triable

Im essayant de développer une petite page qui a les fonctionnalités suivantes:

  1. La page aura deux divisions: l'une étant #Origin, contenant beaucoup d'images miniatures, et la seconde sera #drop, où les images peuvent être déposées (jusqu'à 3 seulement).
  2. il doit être possible de glisser-déposer les images de #drop vers Origin.
  3. #drop doit être triable, car l'ordre des 3 images sélectionnées est important.
  4. Lorsqu'elles sont déposées sur #drop, les images doivent s'aligner, comme si elles avaient été affichées comme telles depuis le début.

Je n'avais jamais utilisé jQuery auparavant, et j'avais même un prototype de page de travail auparavant, où j'avais déjà le glisser-déposer entre deux conteneurs via des événements natifs de glisser-déposer HTML5, mais quand j'ai ajouté la fonctionnalité jquery sortable () à #drop, les images ne pouvaient plus être glissées vers #Origin, ce qui casse ma fonctionnalité.

J'ai donc recommencé et je voulais implémenter à la fois la fonctionnalité glisser-déposer ainsi que le triable avec jQuery. J'ai lu à peu près l'intégralité de l'API pour toutes les fonctionnalités déplaçables, supprimables et triables, mais j'ai du mal à faire fonctionner cela. Je ne sais pas si ce sont les paramètres que j'utilise pour chaque fonctionnalité.

Sur le violon, vous pouvez voir que les images deviennent déplaçables et je peux voir les paramètres que je spécifie en effet (opacité, curseur), mais les images ne peuvent pas être déposées sur #drop.

D'après ce que je comprends, la combinaison de la possibilité de faire glisser des images, des images ayant une classe "déplaçable" et de la suppression de #drop avec une acceptation de ".draggable", cela devrait permettre les fonctionnalités les plus élémentaires, mais même cela ne semble pas prendre. J'ai également lu que si les deux draggable et droppable ont le même paramètre "portée", cela devrait également fonctionner, mais ce n'est pas le cas.

Voici une version simple du code de la page, plus un jsFiddle: http://jsfiddle.net/39khs/

Code:

css:

#Origin {
  background-color: green;
}
#drop {
  background-color: red;
  min-height: 120px;
}

js:

$("img").draggable({ helper: "clone", opacity: 0.5, cursor: "crosshair", scope: "drop" });
$("#drop").droppable({ accept: ".draggable", scope: "drop"});
$("#drop").sortable();

html:

<div id="wrapper">
    <div id="Origin" class="fbox">
        <img src="http://placehold.it/140x100" id="one" title="one" class="draggable" />
        <img src="http://placehold.it/140x100" id="two" title="two" class="draggable" />
        <img src="http://placehold.it/140x100" id="three" title="three" class="draggable" />
    </div>
  <p>test</p>
    <div id="drop" class="fbox">

    </div>
</div>

Toute aide est grandement appréciée.

27
GR7

Voici le violon avec le résultat final:

http://jsfiddle.net/39khs/82/

La clé était de gérer l'événement "drop" et de supprimer manuellement l'image supprimée de #Origin et de l'ajouter à #drop. C'est en fait ce que je faisais sur la première implémentation, mais je ne savais pas comment le faire exactement avec jQuery:

 $(dropped).detach().css({top: 0,left: 0}).appendTo(droppedOn);

Je ne sais pas pourquoi jQuery ne supprime pas vraiment l'élément glissé de l'ancien conteneur et ne l'ajoute pas au nouveau, mais c'est ce qui devait être fait pour que l'élément nouvellement déposé s'affiche correctement et pas seulement exactement où il a été déposé, sans tenir compte du placement/du style CSS.

La ligne clé était de @Barry Pitman sur la question suivante SO:

jQuery draggable + droppable: comment aligner un élément déposé sur un élément déposé

MISE À JOUR: J'ai eu un peu de temps libre aujourd'hui et je voulais vérifier si c'était possible avec juste triable, et voilà, ça l'était.

http://jsfiddle.net/wj4ak/5/

seulement deux lignes de code permettent de glisser-déposer d'un conteneur à un autre et de trier les éléments. Ils n'ont pas du tout besoin d'être dans des listes ul/ol. La seule chose ennuyeuse est que je n'avais pas l'intention de rendre les éléments de la div Orig triables, mais c'est quelque chose avec lequel je peux vivre pour l'instant.

64
GR7

Si vous souhaitez utiliser .droppable(), .draggable(), & .sortable(), il vous suffit d'utiliser .sortable().

À l'aide de votre jsfiddle, j'ai apporté les modifications suivantes:

HTML:

<div id="wrapper">
    <div id="Origin" class="fbox">
    <ul id="sort1" class="list">
      <li><img src="http://placehold.it/140x100" id="one" title="one" class="draggable" /></li>
      <li><img src="http://placehold.it/140x100" id="two" title="two" class="draggable" /></li>
      <li><img src="http://placehold.it/140x100" id="three" title="three" class="draggable" /></li>
    </ul>
    </div>
  <p>test</p>
    <div id="drop" class="fbox">
      <ul id="sort2" class="list"></ul>
    </div>
</div>

JAVASCRIPT:

$( "#sort1, #sort2" ).sortable({
      helper:"clone", 
      opacity:0.5,
      cursor:"crosshair",
      connectWith: ".list",
      receive: function( event, ui ){ //this will prevent move than 3 items in droppable list
         if($(ui.sender).attr('id')==='sort1' && $('#sort2').children('li').length>3){
           $(ui.sender).sortable('cancel');
         }
      }
});

$( "#sort1,#sort2" ).disableSelection();

CSS:

#Origin
{
  background-color: green;
}
#drop
{
  background-color: red;
  min-height: 120px;
}
.list
{ 
  min-height: 120px;
} 
.list li
{
 display: inline-block;
 list-style-type: none;
 padding-right: 20px;
}

DÉMO: http://jsfiddle.net/39khs/80/

J'espère que cela vous aide et faites-moi savoir si vous avez des questions!


21
Dom