jQuery可拖动+可放置:如何将已放置元素捆绑到已放置的元素上

31
我把屏幕分成了两个
。在左边的
中,我有几个50x50像素的
,在右边的
中,我有一个由80x80的
  • 组成的空格子。左边的
    是可拖动的,一旦放在
  • 上,它们应该捕捉到
  • 的中心。

    听起来很简单,对吧?但我不知道该怎么做。我尝试通过操纵放置的

    的top和left CSS属性来匹配它们放置到的
  • 的属性,但是left和top属性是相对于左侧的
    的。

    我最好如何将放置的元素捕捉到其放置的元素的中心?这一定很简单,对吧?

    编辑:我正在使用jQuery UI 1.7.2和jQuery 1.3.2。

    编辑2: 对于其他人也遇到这个问题的人,这就是我解决的方法:

    我在droppable插件的drop回调中使用Keith的解决方案,即删除拖动的元素并将其放置在被放置的元素内部:

    function gallerySnap(droppedOn, droppedElement)
    {
        $(droppedOn).html('<div class="drop_styles">'+$(droppedElement).html()+'</div>' );
        $(droppedElement).remove();
    }
    

    我不希望被删除的元素再次可拖动,但如果您需要,只需再次将可拖动绑定到该元素即可。

    对于我来说,这种方法还解决了当我将删除的元素定位时(这将相对于左侧的 DIV),并在第二个 DIV 中滚动时遇到的问题。(元素将保持在页面上固定,现在它们随着滚动而滚动)。

    我尝试调整了捕捉选项,以使拖动过程中看起来更好,因此感谢 karim79 的建议。

    我可能不会以此赢得任何令人惊叹的代码奖励,所以如果您发现有改进的空间,请分享!

  • 7个回答

    75

    我发现Keith的方法对我有用。因为他的回答没有包含示例实现,所以我将发布我的实现:

    $('.dropTarget').droppable({
        drop: function(ev, ui) {
            var dropped = ui.draggable;
            var droppedOn = $(this);
            $(dropped).detach().css({top: 0,left: 0}).appendTo(droppedOn);
        }
    });
    
    或者,略微更简洁地说:
    $('.dropTarget').droppable({
        drop: function(ev, ui) {
            $(ui.draggable).detach().css({top: 0,left: 0}).appendTo(this);
        }
    });
    

    1
    我认为这应该是 draggabledroppable 的默认行为。 - zepp133

    16

    我曾遇到类似的问题 - 我通过手动将被拖动元素从其旧父元素中移除并添加到放置的元素上来解决它。


    谢谢,我正在考虑这个解决方案。karim79的自动对齐解决方案并没有完全解决我的问题,所以我会尝试这个。 - 10goto10

    11

    谢谢您的帖子 - 它让我走上了正确的方向。 我发现设置可拖动对象的位置属性要比搞乱HTML代码更加清晰。这将使位置设置为droppable对象的左上角,但您也可以进行修改以使其居中。

    drop: function(event, ui) {
       $(ui.draggable).css('top', $(this).position().top);
       $(ui.draggable).css('left', $(this).position().left);
    }
    

    1
    +1 是因为接受的答案在很多情况下会破坏功能和布局,特别是如果 revert 在可放置区域之外使用。虽然这是正确的方法,但如果可放置元素不是可拖动元素的兄弟元素,则 position() 无法完成任务。在具有庞大 DOM 的复杂网站上,定位将是错误的。 - ProblemsOfSumit

    3
    我发现当您拖动时,jQuery UI会添加一个内联元素来告诉您放置的位置。以下是我用于将其捕捉到位的代码示例。
    $('.droppable').droppable({ drop: function(ev, ui) { 
        //Get Details of dragged and dropped
        var draggedclass = ui.draggable.attr('class'),
            droppedclass = 'class' + $(this).attr('name').toLowerCase();
    
        //update the classes so that it looks od.       
        ui.draggable.removeClass(draggedclass).addClass(droppedclass);  
        ui.draggable.removeAttr('style');
    });
    

    3
    $("form li").draggable({snap:'.ui-droppable', snapMode:'inner', revert:true});
    $('.drop').droppable({drop:function(ev, ui)
                               {$(ui.draggable).appendTo($(this))
                                               .css({position:'static', left:'0px', top:'0px'})
                                               .draggable('option', 'disabled', false)
                                               .css({position:'relative'});
                               }
                         }
                        );
    

    0
    如果左侧的
    实际上在右侧的
  • 中(您可以通过Firebug确认),并且如果所有的
  • 都在
      中(应该是这样),请尝试以下一种或两种方法:
      ul#right_div {
        text-align: center;
      }
      
      ul#right_div li {
        text-align: center;
      }
      

  • 我使用了FireBug进行检查,但是被删除的DIV仍然是左侧DIV的一部分,它们在HTML或DOM树中似乎没有移动? - 10goto10
    嗯,我相当确定Firebug是基于JavaScript事件更新的,但你可能需要确认一下。我知道Web Dev工具栏也有“查看生成的源代码”选项。你是在使用JQuery UI来完成这个任务吗?还是其他什么东西? - Anthony

    0

    基于Barry的代码,如果我们想要添加一个带有“x”按钮的选项,使元素可以从新父级中分离并重新附加到初始位置,该怎么办?

    我想到了类似这样的方法,但似乎不起作用... 创建一种保存初始状态的变量。

    var flag;
    $('.draggable-div').draggable({
        revert: 'invalid',
        stop: function(){
            $(this).draggable('option','revert','invalid');
            $(this).find('.undo').show();
        flag=$(this).parent();
        }
    });
    
    
    $('.draggable-div').find('.undo').click(function(i, e) {
        var $div = $(this).parent();
    $($div).detach().appendTo(flag);
     }
    

    有些东西肯定是出了问题,但我不知道你是否能理解这个概念... 只需要能够将你所丢弃的任何东西恢复到它们最初的状态。


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