NeilC
NeilC

Reputation: 1390

Trigger Mouse Dragging in jQuery UI

Using jQuery 1.2.x and jQuery UI 1.5.x, one was able to trigger dragging manually like so:

jQuery("#myDiv").mousedown(function(ev) {
target = jQuery(ev.target);
if (target.hasClass("drag-me")) {
    target.draggable({
        helper: "clone",
        start: function()
        {
            console.log("drag start");
        },
        stop: function()
        {
            jQuery(this).draggable("destroy");
        }
    }).trigger("mousedown.draggable", [ev]);
} });

It is applied to the following HTML:

<div id="myDiv">
<div class="drag-me"></div>
<div class="drag-me"></div>
<div class="drag-me"></div>
<div class="drag-me"></div>
<div class="drag-me"></div>
<div class="drag-me"></div>
<div class="drag-me"></div>
</div>

It was a handy way to apply dragging to elements inside a container that has its children changed dynamically. I like to call it "drag delegation".

However with the release of jQuery 1.3.x & jQuery 1.6+, the script above stopped working. Using jQuery 1.3.2 & jQuery UI 1.7.1 returns an error "too much recursion".

How can I trigger dragging manually? Any suggestions?

Upvotes: 3

Views: 16119

Answers (5)

dav
dav

Reputation: 9267

the other answers did not work for me, I did using jquery ui simulate plugin

https://github.com/jquery/jquery-ui/blob/9e8e339648901899827a58e5bf919f7dda03b88e/tests/jquery.simulate.js

$("#myElement").simulate('drag');

Upvotes: 0

John Milmine
John Milmine

Reputation: 266

Answers above seem overcomplicated.

$('.nonDraggableObjectWhichTriggersDrag').mousedown(function(e) {
   $('.draggableObject').trigger(e);
});

Upvotes: 12

NeilC
NeilC

Reputation: 1390

It turns out to be much simpler than you'd expect. Looking at the .trigger() method's documentation, no mention is made to the fact that one can also supply the original event as an argument and not just a string representation of the event type.

Thus one can achieve delegated dragging more efficiently like so:

$("ul#dynamiclist").delegate("li", "mousedown", function(event) {
    $(this).draggable({
            helper: "clone",
            cursorAt: { left: 5, top: -5 },
            cursor: "move",
            stop: function() {
                    $(this).draggable("destroy");
            }
    }); });

The ideal solution would have been for the UI library to have some method to perform this type of delegation natively for dynamic elements....

Note that this is applicable to jQuery 1.4.2 & jQuery UI 1.7.2

Upvotes: 3

nivcaner
nivcaner

Reputation: 1194

I case you're not using jQuery 1.4 (and thus don't have the delegate() method), there is another solution.

what you have to do to stop the recurssion from occuring is call stopPropagate() on the mousedown events for all elements:

$('drag-me').mousedown(function(ev){
  ev.stopPropagation();
});

Also change your code like this (notice the stopPropagation() call at the bottom):

jQuery("#myDiv").mousedown(function(ev) {
target = jQuery(ev.target);
if (target.hasClass("drag-me")) {
        target.draggable({
                helper: "clone",
                start: function()
                {
                        console.log("drag start");
                },
                stop: function()
                {
                        jQuery(this).draggable("destroy");
                }
        }).trigger("mousedown.draggable", [ev]);
        ev.stopPropagation()
    }
});

This should fix up your unending recurssion. (at least it did for me in a similar situation)

Upvotes: 3

Keith Bentrup
Keith Bentrup

Reputation: 11975

If you could post an entire code sample (with html & relevant script tags with nonworking versions), I could help probably point out what's wrong and/or verify the problem ....

However, I'm not sure that you want to pass an array of 1 object [ev] as the second parameter to your trigger call.

The documentation says "Finally, you can pass a literal object with data. It will be copied to a real jQuery.Event object. Note that you must specify a type attribute in this case."

Can you verify that it (should be|worked before) as you've written and/or possibly paste some more code or URL to the relevant page? I'd be happy to take another look at it.

Hope that helps. :)

Edit: Taking another look at it. It's doing exactly what you ask it to. On the mousedown event, you do some things, and then end by triggering another mousedown event which will do some things and then cause another mouse down event and so on ... and so ...

You've created an infinite loop.

Why not just make the relevant divs all draggable when the page loads rather than when they are first clicked? Wouldn't that avoid this problem?

Also have a look at this post, and I'd be very interested to see some code that used to work. As written, I'm not sure that I understand the sequence of how the code would emulate a complete "drag" event - composed of mousedown, mousemove, and mouse up events. Let me know. Thanks!

Upvotes: 1

Related Questions