如何根据条件恢复jQuery UI可拖动元素的位置

32

我有一个可拖拽的元素和一个可放置的元素。当拖拽的项被放置在放置区域上时,我尝试执行以下jQuery伪代码:

if(draggedelement == value){

$(draggedelement).hide();

}
else{

$(draggedelement).revert();

}

通过使用revert()函数,可以将拖动的项目移回到其原始位置。

如何实现这一点?

P.S. 我知道可拖动的“还原”选项,但仅在拖动的项目未到达放置区域时才会激活。

5个回答

78

有一些内置选项可以做到这一点,在您的.draggable()中,将revert选项设置为'invalid',如果未成功拖放到可放置区域,它就会返回到原位置,代码如下:

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

然后在您的.droppable()中,使用accept选项设置投放有效内容,例如:

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

当你松开鼠标时,与该选择器不匹配的任何内容都会被重置,您可以在此处查看完整演示。如果您需要进行筛选,但选择器无法提供,则 accept 选项还可以接受函数,例如:

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

@Nick Craver,能否请您在这里查看一个与jQuery可拖放相关的问题:https://dev59.com/MbHma4cB1Zd3GeqPNpII? - Istiaque Ahmed

11

我有一个使用情况,在可投放元素的drop方法中运行一些逻辑来确定可拖动元素是否应该还原。我使用以下代码实现:

$('.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');
    }
  }
});

我的使用情况是一个表格,每个单元格都是一个可拖放的对象,表示5分钟的时间段。我的可拖拽对象是预订,它们从一个单元格开始,但在一行中运行多个单元格来表示预订时间。

我不希望任何可拖动的对象重叠,因为这将表示双重预订。因此,在拖放后,我查找行中除了刚刚移动的对象之外的所有可拖动对象,并检查是否有重叠。如果有重叠,我的条件逻辑返回真,并还原可拖动对象。

下一阶段是触发一个ajax调用以更新数据库,如果服务器端逻辑认为移动无效,我希望返回一个错误状态并还原可拖动对象。

附言:这是我的第一个答案,如果有做错什么,请见谅。欢迎提供如何提供好答案的提示。

编辑:在尝试我的AJAX调用后,我意识到在可拖放的对象还原函数运行之前,droppable.drop函数有机会执行它的操作。当我的AJAX调用返回false时,窗口已经过去,类被添加太晚,使得可拖动对象无法反应。

因此,我不再依赖于可拖动对象还原函数,而是仅根据AJAX响应行动,如果返回false,则使用animate()将可拖动对象返回到其原始位置,代码如下:

$( '.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 );
      }
    }
  }
});

你可能需要在可拖动对象的draggable.start/drag事件中添加原始left和top值作为数据属性,但对我而言以上代码已经可以正常工作。


在我看来,最优雅的解决方案。使用 droppable 的 accept 过于复杂,因为它将在每次拖动时进行评估。相反,只有在拖动对象实际被放置时,才会对 draggable 的 revert 进行评估。 - Ayan Sengupta
很棒的答案。运行良好。 - Roubi

4
尝试将该代码添加到“drop”事件中。这里有一个演示链接
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>

脚本

$(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);
   }
  }
 });

});

正如脚本中所示,您可以查找.correct类或其内部的文本(已注释的行)


1
$("#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;
    }
}
});​

这个功能用于从一组可拖动的元素中仅接受一个元素,放置到一组正确的目标元素中。
注:如果语言不易理解,请见谅 =)

0
我发现如果我仅设置top:0和left:0,该项就无法拖动。为了“强制”执行还原,我必须这样做:
$draggedObj.css({ top: 0, left: 0 })
$draggedObj.draggable( "destroy" )
$draggedObj.draggable({...whatever my draggable options are...});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接