Reputation: 6406
Please see this jsfiddle:
This is supposed to allow someone to put articles in stock or in a shelf. If you move twice the same pair of articles, you'll see that the target position is twice what it should be.
I feel I'm not doing things right. There must be a clean way to do this. Any ideas welcome :-)
Upvotes: 0
Views: 171
Reputation: 36015
From looking at your code you need to find a different approach. You are relying on relative positioning of your elements (rather than absolute) which means that your delta calculations are going to get very strange results. I'd implement a different approach anyway because even though what you've created might do what you want visually... you have no good way to detect which article is in which region - because you are only changing the coordinates of the articles... not the container they end up in. This will cause you problems if you need to do anything with the articles after the user has finished their arrangement work.
I'd implement a drag and drop interface that actually allows the items to be physically moved (i.e. in the DOM) from one UL list to another. When dragging and dropping you should just switch the items immediately, If you wanted to you could calculate a nice animation between the two, but the animation should really be secondary. When calculating your animation you should make sure you are reading absolute coordinates rather than relative ones... this means using $().offset()
not $().position()
I would use a DOM structure like this:
<ul class="shelf">
<li class="article">Article I</li>
<li class="article">Article II</li>
<li class="article">Article III</li>
</ul>
<ul class="stock">
<li class="article">Article IV</li>
<li class="article">Article V</li>
<li class="article">Article VI</li>
</ul>
Then when a drop event occurs on any article you just need to:
/// create a temporary element to hold our reciprocal position
var placeholder = $('<li class="placeholder"></li>');
/// insert the placeholder before the item we dragged
ui.draggable.before(placeholder);
/// now move off our dragged item and place it just before our drop item
ui.draggable.insertBefore(this);
/// now place our drop item in the DOM after our placeholder
placeholder.after(this);
/// get rid of the placeholder
placeholder.remove();
Obviously this means the switch over is instant... but using this as your base model you should be able to work out an animation - using .offset() to calculate the abs position of both drop and drag items - and you could either animate a fake switchover (just for the visual benefit)... or you could delay the instant switchover, animate the items moving and then finalise with the items exhanging places in the dom.
event.srcElement
Should be:
event.target
srcElement is Internet Explorer only, and as you are using jQuery, jQuery will automatically handle creating the .target attribute for Interner Explorer - so it is better to use the attribute that is more supported. Better still you shouldn't need to access the event
object to get ahold of your drop target as this should be accessible via $(this)
Upvotes: 2