views:

1396

answers:

3

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?

A: 

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!

Keith Bentrup
Raybiez
+1  A: 

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

Raybiez
+1  A: 

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)

nivcaner