Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#6807 closed bug (notabug)

Draggable DOM Helper Deleted - Causes JS Errors on Next Drag

Reported by: taitems Owned by:
Priority: minor Milestone: 1.9.0
Component: ui.draggable Version: 1.8.7
Keywords: Cc:
Blocked by: Blocking:

Description

I found this odd bug when experimenting with jQuery UI draggable and droppable.

JSFiddle is located here: http://jsfiddle.net/RBzUa/1/

Essentially, I read online how to specify an existing DOM element as a helper by using the function argument (and using a return). This can be done for many reasons: in my non-fiddle case we need to show an icon in the helper and the helper has been constructed elsewhere in plain html.

On line 437 of jquery.ui.draggable.js the object is removed once it has been used. The next time you try and drag this object (and its helper) it will throw an error because the object can no longer be found.

Firefox shows:

this.offsetParent[0] is undefined

While Chrome shows:

Cannot read property 'tagName' of undefined

For now I can get around this issue by doing an "if exists" check in the function - but recreating the DOM every time is a pain. The alternative to this is using a clone, but for more complex structures this may become troublesome. There are certain tricks to get around this bug, for sure, but I thought I should draw this to your attention as I couldn't find anything online.

Change History (6)

comment:1 Changed 9 years ago by Scott González

Resolution: invalid
Status: newclosed

The helper isn't meant to work that way. The helper is always removed after the drag and therefore you're not returning a valid helper on the second drag.

comment:2 Changed 9 years ago by taitems

Yep, that's my diagnosis - but should this be a feature request for the future? Allow a selector to be passed in the helper argument?

comment:3 Changed 9 years ago by Scott González

The jQuery UI team had an API design meeting a few months ago where we reviewed the API of all existing plugins. Here are the relevant notes about draggable's helper option:

keep helper (though try to find a better name), but change values
change "original" to false, meaning don't use a helper
change "clone" to true, meaning use a helper (that its cloning the original element is just an implementation detail, can be mentioned in the docs)
keep the function argument for customizing the helper

I don't think the use case for using existing DOM elements is that big. Cloning an existing element should work fine (and is easily implemented using a function). I'm not sure why you said "recreating the DOM every time is a pain." What is painful about it?

comment:4 Changed 9 years ago by taitems

My specific scenario involves showing whether a CMS component is being inserted or moved, the icon of the component and the name of the component. Considering it's also for an enterprise web app, my helper's rounded corners require extra HTML and CSS to work in older versions of IE. Below is a rough replication of the HTML, which is why I think it lends itself more to a clone() or tmpl() rather than a "from scratch" creation.

<div id="mouseFollow">
   <div>
      <span></span>
      <span><img /></span>
      <span></span>
   </div>
</div>

I'm glad you could share the team discussion notes with me as it gives me a clearer picture. Thanks for the help Scott :)

comment:5 Changed 9 years ago by Scott González

Sure, you could easily do:

$( elem ).draggable({
    helper: function() {
        return $( "#mouseFollow" ).clone().removeAttr( "id" );
    }
});

or use .tmpl() instead of .clone() as you've said.

You could probably even build an extension that accepts a selector, but my main concern would be people not realizing that internally the extension would do a clone on the element found by the selector and they might end up with duplicate ids.

comment:6 Changed 9 years ago by Scott González

Also, the notes from the design meeting are gradually being posted on the blog and forum for feedback. It'll still be a few weeks before we get to draggable.

Note: See TracTickets for help on using tickets.