8

Here is the jQuery code that I have written to drag multiple items at a time. It is draggable now but not droppable.

here is the code

    $(document).on('click', function (e) {
        var target = e.target;
        if (!$(target).hasClass('a')) $('.selected').removeClass('selected');
    });
    $(document).delegate('.a', 'dblclick', function (e) {
        $(this).addClass('selected');
    });

    $(document).delegate('.selected', 'mousedown', function (e) {
        var div = $('<div></div>');
        $('.selected').each(function () {
            div.append($(this).clone());
        });
        div.prop('id', 'currentDrag');
        $('#currentDrag').css({
            left: e.pageX + "px",
            top: e.pageY + "px"
        });
        $('body').append(div);
    });

    $(document).on('mouseup', function (e) {
        var tgt = e.target;
        var mPos = {
            x: e.pageX,
            y: e.pageY
        };
        $('.drop').each(function () {
            var pos = $(this).offset(),
                twt = $(this).width(),
                tht = $(this).height();
        });
        if((mPos.x > pos.left) && (mPos.x < (pos.left + twt)) && (mPos.y > targPos.top) && (mPos.y < (pos.top + tht))) {
            $(this).append($('#currentDrag').html());
        }
        $('.drop .selected').removeClass('selected');
        $('#currentDrag').remove();
    });
    $('.drop').on('mouseup', function (e) {
        $(tgt).append($('#currentDrag').html());
        $('.drop .selected').removeClass('selected');
        $('#currentDrag').remove();
    });

    $(document).on('mousemove', function (e) {
        $('#currentDrag').css({
            left: e.pageX + "px",
            top: e.pageY + "px"
        });
    });

What is the pronblem with my code and how can I achieve this. here is the fiddle http://jsfiddle.net/mDewr/27/

Exception
  • 8,111
  • 22
  • 85
  • 136
  • 2
    Ohh man we need fiddle and HTML too.. – Dipesh Parmar Sep 14 '13 at 06:24
  • 4
    Possible `$('#totalParent')`, total instead of totla? – maximkou Sep 14 '13 at 06:28
  • 2
    Why are you avoiding the jQuery UI drag and drop extension? – Itay Sep 14 '13 at 06:45
  • @Itay With jQuery UI I cannot drag more than one item at a time and implementing my own helps me too – Exception Sep 14 '13 at 06:51
  • You are describing an other problem in the title than you describe in the text. – Sumurai8 Sep 14 '13 at 07:33
  • javascript errors : pos is not defined. tgt is not defined. – Milche Patern Sep 23 '13 at 17:37
  • @Exception, could you point out what you don't like about my [answer](http://stackoverflow.com/a/18965160/1366033). I haven't been able to get the code from any other user to work on any browser I've tested. I really think it's the way you ought to go on this issue. – KyleMit Sep 24 '13 at 15:48
  • @KyleMit I am absolutely happy with the answer you have given. I am glad for effort made. The only reason that made me to accept that answer is that is exactly matching my criteria. For example I am asking which sandals are better to walk under sun, he said some brand name but you said why you want to go on foot, take a car. I cannot buy the car, I cannot afford it. Thats the only reason. Hope you understand. – Exception Sep 24 '13 at 16:26
  • I suppose I get it. To me, the expense of buying a car is hand writing pre-existing functionality yourself. Part of the responsibility of answerers on SO is to point out when things could be done simpler / easier. Part of the responsibility of the asker, is to challenge their preconceived notions about how things *ought* to be done. That said, I'd value working solutions over cleverness any day, but I can't get anyone else's solution to work. Hopefully you're having better luck. – KyleMit Sep 24 '13 at 16:38

3 Answers3

2

I would really recommend trying to find a way to make the jQuery UI draggable and droppable libraries work for you. Then the question becomes, similar to this one: How do I drag multiple elements with JavaScript or jQuery?.

Here's how we can apply one of the answers from that question to your problem. I'm using the jQuery UI multiple draggable plugin, the entire script of which can be found here: jquery.ui.multidraggable-1.8.8.js.

First let's simplify your HTML. By putting our draggable and dropable divs inside of elements, we don't have to apply redundant stylings to each one. Instead we can use the containing element to style

HTML

<div id="parent">
    <div id="dragTargets">
        <div>123</div>
        <div>456</div>
        <div>789</div>
    </div>
    <div id='dropTargets'>
        <div></div>
        <div></div>
    </div>
</div>

Using the plugin we can call multidraggable on each of the drag divs. And droppable anywhere they can be dropped

JavaScript

$("#dragTargets div").multidraggable();
$("#dropTargets div").droppable();

Customize

We can control the appearance with styling. As an example, we'll make anything that can receive drops yellow, anything you're about to drop as red, and anything that has received an element green.

Here's some styling as an example in CSS

.ui-state-highlight { background: green; }
.ui-state-active { background: yellow; }
.ui-state-hover { background: red; }

And we'll control when these classes are applied with JavaScript:

$("#dropTargets div").droppable({
    activeClass: "ui-state-active",
    hoverClass: "ui-state-hover",
    drop: function () {
        $(this).addClass("ui-state-highlight")
    }
});

Multi-Draggable

You should style the elements that are currently selected. The script will apply the class ui-multidraggable to all the currently selected elements. The following CSS will make it apparent to the user that their choice is selected.

.ui-multidraggable {
    background: tan;
}

Check out this demo. Just hold down ctrl to select more than one of the divs and then drag all of them at once.

jsFiddle

Community
  • 1
  • 1
KyleMit
  • 30,350
  • 66
  • 462
  • 664
1

There were several errors, which I'll not list now, but you can compare the old version with the new one.

    $(document).on('dblclick', '.a', function (e) {
      $(this).toggleClass('selected');
    });

    $(document).on('mousedown', '.selected', function (e) {
      var div = $('<div id="currentDrag"></div>');
      $('.selected').each(function () {
          div.append($(this).clone(true));
      });
      var p = $('body').offset();
      var l = e.pageX - p.left;
      var t = e.pageY - p.top;
      console.log(l, ', ', t);
      $('body').append(div);
      $('#currentDrag').css({
          left: l,
          top: t
      });

    });

    $(document).on('mouseup', '.selected', function (e) {
      $('.d').each(function(index, item){
          var $i = $(item);
          if (e.pageX >= $i.offset().left &&
              e.pageX <= $i.offset().left + $i.width() &&
              e.pageY >= $i.offset().top &&
              e.pageY <= $i.offset().top + $i.height()) {       
              console.log('Dropped');
              var $cl = $('#currentDrag').find('>*').clone(true);
              $i.append($cl);
          }
      });
      $('.selected').removeClass('selected');          
      $('#currentDrag').remove();
    });

    $(document).on('mousemove', function (e) {    
      var p = $('body').offset();
      $('#currentDrag').css({
          left: e.pageX - p.left,
          top: e.pageY - p.top
      });          
    });

http://jsfiddle.net/mDewr/43/

Everything should work perfectly in this version (this is an update). PS: I've changed to 1.7+ jQuery, but you can easily change it back to <1.7. Also you don't need custom attributes, use css classes instead.

Balint Bako
  • 2,500
  • 1
  • 14
  • 13
1

There are few errors in you code. You can check errors on browser console.
To check elements over droppable area, you should check the drop area in the each loop, rather than after each loop. When moving mouse, you should better turn off selection to avoid selected text flashing

$(document).on('click', '.a', function (e) {
   $(this).removeClass('selected');
});
$(document).on('dblclick', '.a', function (e) {
    $(this).toggleClass('selected');
});
$(document).on('mousedown', '.selected', function (e) {
    var dragMode = true;
    var div = $('<div></div>');
    $('.selected').each(function () {
        div.append($(this).clone());
    });
    div.prop('id', 'currentDrag');
    $('#currentDrag').css({
        left: e.pageX + "px",
        top: e.pageY + "px"
    });
    $('body').append(div);
    //disable selection on dropping start
    disableSelection();
    $(document).on('mousemove.drop', function(e){
       onDragging(e, dragMode);
    });
    $(document).on('mouseup.drop', function(e){
       onDragEnd(e, dragMode);
    });
});
function onDragEnd(e, dragMode){
    if(!dragMode)
       return;
    var tgt = e.target;
    var mPos = {
        x: e.pageX,
        y: e.pageY
    };
    $('.drop').each(function () {
        var pos = $(this).position(),
            twt = $(this).width(),
            tht = $(this).height();
         if((mPos.x > pos.left) && 
            (mPos.x < (pos.left + twt)) && 
            (mPos.y > pos.top) && 
            (mPos.y < (pos.top + tht))) {
            $(this).append($('#currentDrag').html());
        }
    });

    $('.drop .selected').removeClass('selected');
    $('#currentDrag').remove();
    $('.onDrop').removeClass('onDrop');
    //remove listener on docuemnt when drop end
    $(document).off('mousemove.drop');
    $(document).off('mouseup.drop');
    //enable selection
    enableSelection();
}    
function onDragging(e, dragMode){
    if(!dragMode)
       return;
    var p = $('body').offset();
    var mPos = {
        x: e.pageX,
        y: e.pageY
    }; 
    $('#currentDrag').css({
        left: mPos.x,
        top: mPos.y
    });
     $('.drop').each(function () {
        var pos = $(this).position(),
            twt = $(this).width(),
            tht = $(this).height();
         $(this).toggleClass("onDrop",
              (mPos.x > pos.left) 
                 && (mPos.x < (pos.left + twt)) 
                 && (mPos.y > pos.top) 
                 && (mPos.y < (pos.top + tht)) 
        );  
    });
}
function disableSelection(){
    $(document).on("selectstart", function(){   return false; });
    //firefox
    $("body").css("-moz-user-select", "none");
}  
function enableSelection(){
    $(document).off("selectstart");
    //firefox
    $("body").css("-moz-user-select", "");
}  

I updated your code: http://jsfiddle.net/mDewr/46/, may can help you.

iamght
  • 122
  • 1
  • 10
  • Items are struck when I start dragging the elements. Could you please tell me how to fix it. I have tried the same before and was unable to fix. – Exception Sep 24 '13 at 12:50
  • It works smoothly in [link]http://jsfiddle.net/mDewr/46/, is there any HTML or fiddle we can see? I have met performance problem once, you can refer to [link]http://www.iamght.com/wordpress/2013/07/jquery-ui-draggable-low-performance/ – iamght Sep 25 '13 at 00:48