Opened 4 years ago

Closed 3 years ago

Last modified 3 years ago

#9446 closed bug (fixed)

Draggable: helper function cannot emulate default behavior

Reported by: Bob Stein, VisiBone Owned by: Bob Stein, VisiBone
Priority: minor Milestone: 1.11.2
Component: ui.draggable Version: 1.10.3
Keywords: Cc:
Blocked by: Blocking:


In the .draggable() widget, the "helper" object is what visually moves around the screen while dragging. The default behavior has the draggable element itself serve as the helper object.

When specifying a helper function, I sometimes want to mimic this default condition, where the helper is the draggable. But returning the draggable element (as a jQuery object) doesn't do this, that just makes the helper invisible.

In this jsfiddle demo, the first img drags, but the second doesn't seem to budge. The dragging is going on however, a stop function would get called.

Using jQuery 1.10.2, UI 1.10.3 in my application and seeing this. The jsfiddle demo uses 1.9.1/1.9.2

Change History (12)

comment:1 Changed 4 years ago by tj.vantoll

  • Status changed from new to open
  • Summary changed from .draggable() helper function, cannot emulate default behavior to Draggable: helper function cannot emulate default behavior

This happens because of this check in _createHelper:

if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
	helper.css("position", "absolute");

Because the helper is the element, it is never set to position: absolute so dragging it does not work. This seems like a valid use case.

comment:2 Changed 4 years ago by scottgonzalez

  • Owner set to Bob Stein, VisiBone
  • Status changed from open to pending

This seems like an edge case. Can you explain why you'd be using a function to return the original element?

comment:3 Changed 4 years ago by Bob Stein, VisiBone

  • Status changed from pending to new

Sure! Maybe it only seems like a pointlessly simple edge case because I was trying to make a very simple example to demonstrate the bug.

I'm trying to visually simulate a "stack" of identical objects. Think of a pad of post-it notes. When the "stack" contains 2 or more, I want to clone the image as I drag the "top" object off of the "stack". When the "stack" only has 1 left, I want to drag the object itself, leaving nothing behind. Akin to moving the last post-it note in a pad. So within the helper-function, I want to do some logic, and then decide whether to return $(this) or $(this).clone(). The latter works. The former doesn't. So I just wanted to demonstrate that.

Seem less edgy now? ;-)

comment:4 Changed 4 years ago by scottgonzalez

  • Status changed from new to open

Still seems like an edge case to me. You could just set the helper option appropriately ahead of time (you know when the stack gets to one). I'll leave this open, but it's unlikely to be fixed prior to the interaction rewrite unless someone send a pull request with tests.

comment:5 Changed 4 years ago by Bob Stein, VisiBone

Thanks for the workaround Scott, already doing something like that. But the function remains broken. Doesn't it strike you as a let-down when the function-flavor of a parameter does less than the string-flavor?

I'm wondering how you understand the term "edge case". I thought it meant an extreme, like a gigabyte image, or dragging at relativistic speeds. We're talking about the default behavior of a draggable's helper, and the function can't even do that. It's like a Swiss Army knife that has every tool but a knife. Or a calculator that can add any number but zero. "Why would anyone have a legitimate need to add zero to a number? You already have your answer right there!"

comment:6 Changed 4 years ago by scottgonzalez

Please, no analogies. They're almost always fatally flawed. Like having a swiss army knife and being bummed about the fact that it doesn't have a blade while you're holding a perfectly sharp knife in your other hand.

The helper option exists to generate a helper. So, yes, returning the original element and claiming that it's the helper, when in fact you do not want a helper at all, is an edge case. I would venture a guess that this behavior has existed for several years; if this is just now being reported then it's a good assumption that this is almost never attempted, which also indicates that this is an edge case.

comment:7 Changed 4 years ago by Bob Stein, VisiBone

That's okay, the calculator analogy was better. The default condition isn't that there is no helper, it's that the helper is the original object. This form is in the documentation:

        helper: "original"

(Just verified that it works.) A helper function should be capable of degrading gracefully and making the default condition happen.

comment:8 Changed 4 years ago by scottgonzalez

No, the default condition is that there is no helper. The fact that it uses a string "original" is just another example of the terrible API that draggable has. The upcoming API does not accept string values.

comment:9 Changed 4 years ago by Bob Stein, VisiBone

No strings? You're saying helper: "clone" is going away? That means my workaround is going to break. Will the following continue to work?

        helper: function(){
            return $(this).clone();

comment:10 Changed 4 years ago by scottgonzalez

helper: true will replace helper: "clone" (The user should only indicate that they want a helper, not that there is a specific implementation of cloning that they care about). The clone function will also continue to work.

comment:11 Changed 3 years ago by Mike Sherov

  • Resolution set to fixed
  • Status changed from open to closed

Draggable: Ensure helper is positioned even if its the element itself

Fixes #9446

Changeset: 451dded230c3832a1baacc89333727b25c44cfc7

comment:12 Changed 3 years ago by mikesherov

  • Milestone changed from none to 1.11.2
Note: See TracTickets for help on using tickets.