grouping draggable objects with jquery-ui draggable

前端 未结 4 649
青春惊慌失措
青春惊慌失措 2020-11-28 20:20

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.

相关标签:
4条回答
  • 2020-11-28 21:05

    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>

    0 讨论(0)
  • 2020-11-28 21:05

    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.

        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.

    0 讨论(0)
  • 2020-11-28 21:06

    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.

    0 讨论(0)
  • 2020-11-28 21:14

    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

    0 讨论(0)
提交回复
热议问题