Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

grouping draggable objects with jquery-ui draggable

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...

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

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?

like image 301
Jiaaro Avatar asked Apr 27 '09 13:04

Jiaaro


People also ask

How does jQuery ui draggable work?

jQueryUI provides draggable() method to make any DOM element draggable. Once the element is draggable, you can move that element by clicking on it with the mouse and dragging it anywhere within the viewport.

Why is draggable not working?

You have one of these problems: Your jQuery or jQuery UI Javascript path files are wrong. Your jQuery UI does not include draggable. Your jQuery or jQuery UI Javascript files are corrupted.

How do you get the position of the draggable element?

The . position() method allows us to retrieve the current position of an element relative to the offset parent. Contrast this with . offset() , which retrieves the current position relative to the document.


3 Answers

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

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

$('#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>
like image 71
brianpeiris Avatar answered Oct 09 '22 03:10

brianpeiris


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.

like image 39
Paul Avatar answered Oct 09 '22 04:10

Paul


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

like image 21
Allen Bargi Avatar answered Oct 09 '22 02:10

Allen Bargi