7

I have a situation where inside a div there are draggable items. However, when the parent div is scaled using -webkit-transform, the draggable obviously stops working properly.

I've reproduced the scenario here.

As you can see, the draggable item moves relative to the document, even though the parent is in an entirely different scale.

I have the scale (1.5 in the example) as a variable in JS, so I can use that, but where? I'd need to divide the dragging distance by the scale, right? Where could I do this?

Edit: I've tried setting a function to drag-event, but haven't been able to figure out how to actually alter the dragging distance.

Edit2: I digged the jQuery UI source, and it seems that there's no way to do this from the event drag:

if(this._trigger('drag', event, ui) === false) {
    this._mouseUp({});
    return false;
}

As you can see, the return value of the callback-function isn't stored in any way. The position of the element is changed after the callback has fired, so changing the CSS inside the callback doesn't work.

You can see the relevant code here by using in-browser search with this string:

_mouseDrag: function(event, noPropagation) {
Martti Laine
  • 12,655
  • 22
  • 68
  • 102
  • Aren't you missing 'containment' in the options of your example? Like this: $('.draggable').draggable({ containment: "parent" });​ Only then I can reproduce your issue. – hyankov Dec 14 '12 at 16:11
  • Are you sure you're not seeing the issue without that? The issue is that the dragged element moves in a different scale, thus faster or slower than cursor. – Martti Laine Dec 14 '12 at 16:16

3 Answers3

25

Due to my small amount of experience with JavaScript I didn't realise that the callback could in fact modify the position, even though it doesn't return anything. This is because in JS apparently parameters are by default passed by reference.

Here's a working code:

// Couldn't figure out a way to use the coordinates
// that jQuery also stores, so let's record our own.
var click = {
    x: 0,
    y: 0
};

$('.draggable').draggable({

    start: function(event) {
        click.x = event.clientX;
        click.y = event.clientY;
    },

    drag: function(event, ui) {

        // This is the parameter for scale()
        var zoom = 1.5;

        var original = ui.originalPosition;

        // jQuery will simply use the same object we alter here
        ui.position = {
            left: (event.clientX - click.x + original.left) / zoom,
            top:  (event.clientY - click.y + original.top ) / zoom
        };

    }

});
Martti Laine
  • 12,655
  • 22
  • 68
  • 102
  • All complex types (arrays, objects) are passed by reference in javascript. This has nothing to do with parameters :) – AgnosticMantis Jul 14 '13 at 02:15
  • 1
    Though this solves the purpose bug containment "parent" for the draggable doesn't work after applying this code. Do you know how to overcome that? – Prateek Jain Jan 09 '15 at 09:18
  • @PrateekJain - I adapted Martti's answer to account for the containment (see http://stackoverflow.com/a/40196570/1009922). – ConnorsFan Oct 23 '16 at 03:56
  • @Martti Laine - I'd recommend storing the zoom (aka. scale) in the start callback. I use this method with the resizeable widget, albeit with ui.size and ui.originalSize. – Borgboy Feb 15 '21 at 13:48
0

I know my answer is so late, this issue is posted 8 years ago but I did face it just yesterday, and I couldn't find any solution online.

Here's my solution on GitHub

var element_inside_the_scaled_container = $('#element');

$(element_inside_the_scaled_container).draggable({

    drag: function (event, ui) {

        var constants = normalize_ui_position('#elem_container', UI);

        console.log(constants); // They could be useful!

    }

});

The function I've called is available on my github

-1

I think you need the Transformable (http://plugins.jquery.com/project/transformable) jQuery plugin, in order to 'normalize' the WebKit scaling. Then dragging will work as in Firefox.

Here is the plugin - http://flin.org/js/jquery.transformable.js. I think it should resolve your problem. Here is my version of your code: http://jsfiddle.net/vMaXm/4/

$("#parent").setTransform("scalex", 1.5);
//$("#parent").setTransform("scaley", 1.5);
$('.draggable').draggable({ containment: "parent" });

However, at this moment, if I uncomment the middle line I get the same problem you report.

hyankov
  • 4,049
  • 1
  • 29
  • 46
  • Unfortunately I can't see the desired effect. Seems like `setTransform` simply resizes the parent back to normal size, though being in a different position. – Martti Laine Dec 14 '12 at 16:44