使用jquery-ui draggable对可拖动对象进行分组

时间:2021-06-11 20:34:47

I want to use jquery draggable/droppable to let the user select a group of objects (each one has a checkbox in the corner) and then drag all the selected objects as a group...

我想使用jquery draggable / droppable让用户选择一组对象(每个对象在角落都有一个复选框),然后将所有选定的对象作为一个组拖动...

I can't figure out for the life of me how to do it haha.

我无法弄清楚我的生活怎么做哈哈。

Here is what I'm thinking will lead to a usable solution, on each draggable object, use the start() event and somehow grab all the other selected objects and add them to the selection

以下是我想要在每个可拖动对象上实现可用解决方案的内容,使用start()事件并以某种方式获取所有其他选定对象并将其添加到选择中

I was also considering just making the dragged object look like a group of objects (they're images, so a pile of photos maybe) for performance reasons. I think using the draggable functionality might fall over if you drag several dozen objects at once, does that sound like a better idea?

出于性能原因,我还在考虑让拖动的物体看起来像一组物体(它们是图像,所以可能是一堆照片)。我认为如果你一次拖动几十个对象,使用可拖动功能可能会失败,这听起来更好吗?

4 个解决方案

#1


74  

You could use the draggable's helper option to drag groups of items.

您可以使用draggable的帮助程序选项来拖动项目组。

For example, if your draggables have checkboxes, you can return the selected items from the helper function like so:

例如,如果您的draggables有复选框,您可以从辅助函数返回所选项,如下所示:

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

Demo

I've setup a demo with draggable images with checkboxes and somewhat fluid layout. Click "Run Code Snippet" at the bottom to see the result:

我已经设置了一个带有可拖动图像的演示,带有复选框和一些流畅的布局。点击底部的“运行代码段”查看结果:

$(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>

#2


1  

Performance Idea:

绩效理念:

Make an invisible 'group object'. When the items are checked, make them children of the group object, when unselected, set them back as children of the document body, or static parent or whatever. You'll have to translate the objects' position to make sure they don't jump around, also attach/detach your mouse event handlers to the children of the group as you add/remove them.

制作一个看不见的“群组对象”。检查项目时,将它们设为组对象的子项,取消选中时,将它们设置为文档正文的子项,或静态父项或其他项。您必须转换对象的位置以确保它们不会跳转,还可以在添加/删除它们时将鼠标事件处理程序附加/分离给组的子项。

When you get a mouse down/up event on any of the children, what you'll move is actually that group object.

当您在任何一个孩子上获得鼠标按下/向上事件时,您将移动的实际上是该组对象。

This should make it simpler overall.

这应该使整体更简单。

#3


1  

This the exact thing I'm trying to do. So far I've not been successful, but I've found this guy done it in a very complicated way. you could check it out maybe you could do somthing with that.

这正是我想要做的事情。到目前为止我还没有成功,但我发现这个人以一种非常复杂的方式完成了它。你可以检查一下,也许你可以用那个做点什么。

This should be a feature in draggable. I hope they implement it sooner than later

这应该是可拖动的功能。我希望他们能早日实施

#4


1  

What I've done for this is created a function that you give the slave / master elements to, which creates a bind() function for the master (I'm only allowing a drag from the master in this case, you can work around this I'm sure), which makes the slave follow it around using standard jQuery css.

我为此做了什么创建了一个函数,你给slave / master元素,它为master创建一个bind()函数(在这种情况下我只允许从master中拖动,你可以解决这我确定),这使得奴隶使用标准的jQuery css来跟随它。

    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');

        } 
    }

I guess I'll post more to this once I have a working example. As it stands this is working for me. What is missing is a way to call overlap(slave, master) with the elements you want to group together. I'm doing this in a really specific way. You can clever a way to do it, I'm sure.

一旦我有一个有效的例子,我想我会发布更多内容。目前看来这对我有用。缺少的是一种将重叠(slave,master)与要组合在一起的元素调用的方法。我是以一种非常具体的方式做到这一点的。我敢肯定,你可以巧妙地做到这一点。

#1


74  

You could use the draggable's helper option to drag groups of items.

您可以使用draggable的帮助程序选项来拖动项目组。

For example, if your draggables have checkboxes, you can return the selected items from the helper function like so:

例如,如果您的draggables有复选框,您可以从辅助函数返回所选项,如下所示:

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

Demo

I've setup a demo with draggable images with checkboxes and somewhat fluid layout. Click "Run Code Snippet" at the bottom to see the result:

我已经设置了一个带有可拖动图像的演示,带有复选框和一些流畅的布局。点击底部的“运行代码段”查看结果:

$(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>

#2


1  

Performance Idea:

绩效理念:

Make an invisible 'group object'. When the items are checked, make them children of the group object, when unselected, set them back as children of the document body, or static parent or whatever. You'll have to translate the objects' position to make sure they don't jump around, also attach/detach your mouse event handlers to the children of the group as you add/remove them.

制作一个看不见的“群组对象”。检查项目时,将它们设为组对象的子项,取消选中时,将它们设置为文档正文的子项,或静态父项或其他项。您必须转换对象的位置以确保它们不会跳转,还可以在添加/删除它们时将鼠标事件处理程序附加/分离给组的子项。

When you get a mouse down/up event on any of the children, what you'll move is actually that group object.

当您在任何一个孩子上获得鼠标按下/向上事件时,您将移动的实际上是该组对象。

This should make it simpler overall.

这应该使整体更简单。

#3


1  

This the exact thing I'm trying to do. So far I've not been successful, but I've found this guy done it in a very complicated way. you could check it out maybe you could do somthing with that.

这正是我想要做的事情。到目前为止我还没有成功,但我发现这个人以一种非常复杂的方式完成了它。你可以检查一下,也许你可以用那个做点什么。

This should be a feature in draggable. I hope they implement it sooner than later

这应该是可拖动的功能。我希望他们能早日实施

#4


1  

What I've done for this is created a function that you give the slave / master elements to, which creates a bind() function for the master (I'm only allowing a drag from the master in this case, you can work around this I'm sure), which makes the slave follow it around using standard jQuery css.

我为此做了什么创建了一个函数,你给slave / master元素,它为master创建一个bind()函数(在这种情况下我只允许从master中拖动,你可以解决这我确定),这使得奴隶使用标准的jQuery css来跟随它。

    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');

        } 
    }

I guess I'll post more to this once I have a working example. As it stands this is working for me. What is missing is a way to call overlap(slave, master) with the elements you want to group together. I'm doing this in a really specific way. You can clever a way to do it, I'm sure.

一旦我有一个有效的例子,我想我会发布更多内容。目前看来这对我有用。缺少的是一种将重叠(slave,master)与要组合在一起的元素调用的方法。我是以一种非常具体的方式做到这一点的。我敢肯定,你可以巧妙地做到这一点。