3

I'm working on a project where a user has to drag and drop the correct items onto a technical drawing. For example, a motherboard: the user will get a picture of a CPU or DDR memory, and he will have to drag that CPU onto the socket and the memory into the corresponding slot.

It's working great and it get's loaded into our website inside an iFrame. Since this website is responsive, the drag & drop app need to resize too. We resized the iFrame by scaling the body element inside using CSS3 transforms.

This too works, but the issue which then pops up is that all our drop zones are off. Now, one has to drop the CPU next to the socket to get it to react.

Here a simple example of what I mean: http://jsfiddle.net/78EYh/

Simply drag the blue square onto the red rectangle, and you'll see the red rectangle registering it's on top of it when you're not. Remove the div that scales, and all is normal. Only problem is I can't get around scaling the iframe, so I need a fix.

Has anyone encountered this issue before? Anyway to fix it?

HTML:

<div id="scale">
  <span id="drop-1" class="drop"></span>

  <span id="drag-1" class="drag"></span>
</div>

jQuery:

$("#drop-1").droppable({
  over: function() {
    $(this).css({'opacity' : '.4'});
  },
  out: function() {
    $(this).css({'opacity' : '1'});
  }
});

$("#drag-1").draggable();
William Turrell
  • 3,227
  • 7
  • 39
  • 57
deadconversations
  • 1,927
  • 2
  • 13
  • 14
  • It's a [known issue](http://bugs.jqueryui.com/ticket/6844) - [jQueryUI Draggable](http://jqueryui.com/draggable/) doesn't take account of CSS transforms when calculating the zones. They don't intend to fix it. – William Turrell Jul 19 '13 at 10:55
  • possible duplicate of [jQuery - draggable div with zoom](http://stackoverflow.com/questions/8605439/jquery-draggable-div-with-zoom) – Mosh Feu Mar 12 '14 at 12:39

1 Answers1

0

how about writing your own drag n drop implementation. I tried it with your example and got it work with following implementation:

    $.fn.scaleDroppable = function(params, scaleFactor){
            var offset = $(this).offset();
            var bottom = offset.top + $(this).height() * scaleFactor;
            var right = offset.left + $(this).width() * scaleFactor;
            var element = this;
            $(document).mousemove(function(e){
                if(typeof($(document).data("dragObject")) != "undefined"){
                    if( e.pageX <= right && e.pageX >= offset.left &&  e.pageY <= bottom && e.pageY >= offset.top ){
                        //movein
                        if(typeof(params.over)=="function"){                        
                            params.over.call(element);
                            if( typeof($(document).data("dragObject").data("inElements")) == "undefined")
                                $(document).data("dragObject").data("inElements", []);
                                $(document).data("dragObject").data("inElements").push(element);
                        }
                    }else{
                        //moveout
                        var objectIndex = ($(document).data("dragObject").data("inElements") || []).indexOf(element);
                        if(typeof(params.out)=="function" && objectIndex > -1){
                            params.out.call(element);
                            $(document).data("dragObject").data("inElements").splice(objectIndex, 1);
                        }
                    }
                }
            });
        };

        $.fn.scaleDraggable = function(scaleFactor){
            $(this).mousedown(function(){
                $(document).data("dragObject", $(this));
                var moveObject = function(event){
                    $(document).data("dragObject").offset({top: event.pageY - ($(document).data("dragObject").height() * scaleFactor / 2), left: event.pageX -($(document).data("dragObject").innerWidth()  * scaleFactor / 2)});
                };
                $(document).mousemove(moveObject);
                $(document).one('mouseup', function(){
                    $(document).removeData("dragObject");
                    $(document).unbind("mousemove", moveObject);
                });
            });
        };


    $(document).ready(function(){

        $("#drop-1").scaleDroppable(
                {
                    over: function() {
                        $(this).css({'opacity' : '.4'});
                    },
                    out: function() {
                        $(this).css({'opacity' : '1'});
                    }
                },0.5   
        );

        $("#drag-1").scaleDraggable(0.5);

    });

You can check it at http://jsfiddle.net/VNwb8/
This of course takes the scaleFactor as parameter. If you want to retrieve the scaleFactor automatically you could write a implementation for getting it automatically. Some ideas for this you could get from Get the scale value of an element?

Community
  • 1
  • 1
L. Monty
  • 872
  • 9
  • 17
  • I know I'm a little late with a year later answer. But i hope this to be helpful for somebody – L. Monty Mar 30 '14 at 00:03
  • here how can i use the `drop: function` in droppable – Ashok Shah Mar 07 '17 at 10:49
  • I dont know if I get u right. But if u want execute a callback on drop u can simply add an callback-parameter to scaleDraggable-function and execute it at the end in $(document).one('mouseup', function(){...}. – L. Monty Apr 02 '17 at 13:09