In the interest of learning how to do this more efficiently, i'm curious to any thoughts of how to improve this or if i'm walking down the wrong road all together.
So far I have written, http://jsfiddle.net/mstefanko/LEjf8/9/
This handles basically what I want it to on a small scale.
There are some bugs and I don't feel confident at all that this is as good as it could be written, might be an idiot for not trying to latch onto jquery ui sortable. But with needing to do this without a simple list of items, and with wanting to expand this to include multiple drag and drop, I wanted to at least walk through what I needed to do to make this happen even if it was just to learn how sorting functions like these work.
The problem child,
This is all in a function called on the over event of the droppable()
I have an array of empty spots
var emptyHolders = [];
$('.pipeline-holder').each(function(){
if($(this).hasClass('holder-empty')){
var eid = $(this).attr('id');
emptyHolders.push(eid.substring(14));
}
});
cid is the droppable element that you're over top of, so I find the next open slot using
for (var i = 0; i < emptyHolders.length; i++) {
var currentEmpty = emptyHolders[i];
if (currentEmpty > cid) {
nextEmpty = currentEmpty;
i = emptyHolders.length;
} else {
prevEmpty = parseInt(currentEmpty);
}
}
If there is a an empty slot further down the list, I use a for loop to loop through moving the items around the DOM to make the space needed to drop the element.
if (nextEmpty != null) {
var moveMe = nextEmpty -1;
for (var i = moveMe; i >= cid; i--) {
var nextcount = i + 1;
var me = $('#pipeline-rank-' + i);
var next = $('#pipeline-rank-' + i).parents('.pipeline-rank-row').next().find('.pipeline-holder');
var pid = $('#pipeline-rank-' + i).find('.content-wrapper').attr('id');
next.append($('#pipeline-rank-' + i).find('.content-wrapper'));
next.removeClass('holder-empty');
next.siblings('.remember-my-position-hover').html(pid);
}
$('#pipeline-rank-' + cid).addClass('holder-empty');
}
If there is not one further down the list, I do the same thing in reverse to check if there is a spot above the droppable to push items up into.
Any thoughts are extremely appreciated!
For something like this it is probably worth manipulating DOM elements directly and keeping references to them in an array rather than using jQuery selectors. You started to do this with emptyHolders
but I would do it for all the containers (droppable elements).
I'd keep two lists/arrays: one with the state before the drag and one to display. Whenever the drag goes over a new container I would first reset the state to the pre-drag state and then recompute the changed state from there and then show the new changed state. (To avoid flicker, I would not actually show the pre-drag state, just reset my internal list to it.) That way you avoid disturbing the list with the new addition as much as possible.
To make space for the new element, I suggest the following:
That is, assuming I understand your needs correctly. The more common case is to not allow empty spaces anywhere. All insertions add to the end of the list or the head of the list or go between two list members with no spaces added. If you drop something on the list it immediately floats up until it runs into another item or is the first item on the list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With