web-dev-qa-db-fra.com

comment rétablir la position d'une interface utilisateur jquery déplaçable en fonction d'une condition

J'ai un élément déplaçable et un élément largable. Une fois l’élément déposé déposé dans la zone de dépôt, j’essaie d’exécuter le code psuedo jquery suivant:

if(draggedelement == value){

$(draggedelement).hide();

}
else{

$(draggedelement).revert();

}

où la fonction revert() ramène l'élément déplacé à sa position d'origine. 

Comment peut-on accomplir cela?

P.S. Je suis conscient de l'option 'Réversible' déplaçable, mais elle ne s'active que si l'élément déplacé ne parvient pas à la zone de dépôt.

29
Ash

Il y a quelques options intégrées pour cela, sur votre .draggable() , définissez l'option revert sur 'invalid', et elle reviendra si elle n'a pas été déposée avec succès sur une table, comme ceci:

$("#draggable").draggable({ revert: 'invalid' });

Puis, dans votre .droppable() , définissez ce qui est valable pour un dépôt à l’aide de l’option accept , par exemple:

$("#droppable").droppable({ accept: '#draggable' });​

Tout ce qui ne correspond pas à ce sélecteur est réinitialisé lorsque vous le lâchez, vous pouvez voir une démonstration complète ici . L'option accept a également une fonction si vous avez besoin d'un filtre qu'un sélecteur ne peut pas fournir, comme ceci:

$("#droppable").droppable({ 
  accept: function(dropElem) {
    //dropElem was the dropped element, return true or false to accept/refuse it
  }
});​
74
Nick Craver

J'ai eu un cas d'utilisation où je devais exécuter une logique dans la méthode de dépôt de la droppable pour déterminer si le draggable devait revenir. J'ai utilisé ce qui suit pour y parvenir:

$('.draggable-elements').draggable({
  revert: function() {
    if ($(this).hasClass('drag-revert')) {
      $(this).removeClass('drag-revert');
      return true;
    }
  }
});

$('.droppable-elements').droppable({
  drop: function(event, ui) {
    if ( % conditional logic check here % ) {
      return $(ui.draggable).addClass('drag-revert');
    }
  }
});

Mon cas d'utilisation est un tableau où chaque cellule est une liste déroulante représentant une période de 5 minutes. Mes objets mobiles sont des réservations qui commencent dans une seule cellule, mais sont exécutées sur plusieurs cellules d'affilée pour représenter l'heure de la réservation. 

Je ne voulais pas que les objets glissables se chevauchent, cela représenterait une double réservation. Ainsi, après le largage, je trouve tous les objets glissables de la ligne, à l’exclusion de celui que je viens de déplacer, et vérifie tout chevauchement. S'il y a un chevauchement, ma logique conditionnelle retourne true et je retourne le glissable.

L'étape suivante consiste à déclencher un appel ajax pour mettre à jour la base de données. Si la logique côté serveur indique que le déplacement est invalide, j'espère retourner un statut d'erreur et rétablir le contenu déplaçable.

P.S. C’est ma première réponse, désolé si j’ai fait quelque chose de mal. Conseils sur la façon de fournir de bonnes réponses acceptées avec plaisir.

Edit: Après avoir essayé mon appel AJAX, je me suis rendu compte que la fonction droppable.drop offrait une fenêtre d'opportunité avant que la fonction draggable.revert ne soit exécutée. Au moment où mon appel AJAX a renvoyé la valeur false, la fenêtre était terminée et la classe était ajoutée trop tard pour que draggable.revert puisse réagir.

En tant que tel, je ne compte plus sur la fonction draggable.revert, mais plutôt sur la réponse AJAX. Si la valeur est false, utilisez animate () pour ramener l'élément déplaçable à sa position d'origine, comme suit:

$( '.draggable-elements' ).draggable();

$( '.droppable-elements' ).droppable({
  drop: function( event, ui ) {
    var postData = {
      id: 1,
      ...
    };
    $.post( '/ajax/url', postData, function( response ) {
      var response = $.parseJSON( response );
      if ( response.status != 1 ) {
        return ui.draggable.animate( {left: 0, top: 0}, 500 );
      }
    }
  }
});

Il peut être nécessaire que draggable.start/drag ajoute les valeurs d'origine gauche et supérieure du draggable en tant qu'attributs de données, mais pour moi, le processus ci-dessus a bien fonctionné.

7
PaulPrecept

Essayez d'ajouter ce code dans l'événement "drop". Voici un demo .

HTML

<div class="draggable ui-widget-content correct"><p>1</p></div>
<div class="draggable ui-widget-content"><p>2</p></div>
<div class="draggable ui-widget-content"><p>3</p></div>
<div class="draggable ui-widget-content"><p>4</p></div>
<br style="clear: both">
<div id="droppable" class="ui-widget-header">
  <p>Drop me here</p>
</div>

Scénario

$(function() {

 $(".draggable").draggable({ revert: true });

 $("#droppable").droppable({
  activeClass: 'ui-state-hover',
  hoverClass: 'ui-state-active',
  // uncomment the line below to only accept the .correct class..
  // Note: the "drop" function will not be called if not ".correct"
  //  accept : '.correct',
  drop: function(event, ui) {
   // alternative method:
   // if (ui.draggable.find('p').text() == "1") {
   if (ui.draggable.is('.correct')) {
    $(this).addClass('ui-state-highlight').find('p').html('You got it!');
    // cloning and appending prevents the revert animation from still occurring
    ui.draggable.clone(true).css('position', 'inherit').appendTo($(this));
    ui.draggable.remove();
   } else {
    $('#droppable > p').html('Not that one!')
    setTimeout(function(){ $('#droppable > p').html('Drop here'); }, 1000);
   }
  }
 });

});

Comme vous pouvez le constater dans le script, vous pouvez rechercher la classe .correct ou le texte contenu à l'intérieur (ligne mise en commentaire).

4
Mottie
$("#droppable").droppable({ 
    accept: function(dropElem) {
        //dropElem was the dropped element, return true or false to accept/refuse it
        if($(this).data('stoneclass') == dropElem.attr("id")){
            return true;
    }
}
});​

Cela a été utilisé pour n'accepter qu'un seul objet glissable, parmi un groupe d'objets glissables; à une bonne goutte, dans un groupe de bave.

P.S désolé pour la langue si ce n'est pas compréhensible =)

1
Roshan Poudyal

J'ai constaté que si je définissais simplement top: 0 et left: 0, l'élément ne pouvait plus être déplacé. Pour "forcer" un retour, je devais faire ceci:

$draggedObj.css({ top: 0, left: 0 })
$draggedObj.draggable( "destroy" )
$draggedObj.draggable({...whatever my draggable options are...});
0