Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery UI Sortable animations

I have a grid-like list, and have the sortable functionality working in it, like planned. I want to animate every item except the one being manipulated to smoothly slide in the list. I have an example set up here: http://jsfiddle.net/wpmte/.

<ul id="sort">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    <li>Item 7</li>
    <li>Item 8</li>
    <li>Item 9</li>
</ul>

The CSS:

ul {
    margin: 0;
    padding: 0;
}
li {
    display: inline-block;
    margin: 5px;
    padding: 5px;
    background: #0f0;
    width: 25%;
}
.ui-sortable-placeholder {
    height: 0 !important;
}

And finally, the JS:

$('#sort').sortable({ 

});

How can I animate the elements to fill in the space with transitions rather than just jumping?

like image 859
Chad Avatar asked Jul 31 '13 15:07

Chad


1 Answers

Here's how I did it:

// needed to allow for multiple placeholders as they animate
var placeholderNumber = 0;

$('#new-ct-banner-tree').sortable({
    // basic setup
    distance: 15,
    placeholder: 'tree-drop-placeholder',
    items: ".tree-item:not(.new-ct-tree-group-item, .group-add-button)",
    connectWith: ".connectedSortable",
    handle: ".top-drag-handle",
    helper: "clone",
    opacity: 0.75,
    revert: 300,
    scrollSpeed: 4,
    cursor: "move",

    start: function(event, ui) {
        // When starting the drag, add our replacement placeholder. We set the height of the default placeholder to 30px (see css below), so the replacement needs to be that same height and the original gets a negative margin of that height and our replacement consumes the original.
        $(ui.placeholder).before('<div class="temp-spacer-' + placeholderNumber +     '"></div>').css('margin-top', '-30px');
        $('.temp-spacer-' + placeholderNumber).css('height', '30px');
    },
    change: function(e, ui) {
        // When placeholder changes, animage away old one, and animate in new one, but only if a little delay has passed to avoid crazy jank town.
        if ($(ui.item).parent().hasClass('delayPlaceholderMovement') == false) {
            // If the parent doesn't have the 'delay' class, proceed to animating away the current placeholder.
            $('.temp-spacer-' + placeholderNumber).animate({
                height: "0px"
            }, 200, function() {
                $(this).remove();
            });
            // iterate the placeholder number to keep old and new ones separated.
            placeholderNumber = placeholderNumber + 1;

            // add and animate in the new location placeholder.
            $(ui.placeholder).before('<div style="height:0px;" class="temp-spacer-' + placeholderNumber + '"></div>');
            $('.temp-spacer-' + placeholderNumber).animate({
                height: "30px"
            }, 200);
        };
        // add the 'delay' class to the parent
        $(ui.item).parent().addClass('delayPlaceholderMovement');
        // and set a timeout to remove the parent after 40ms
        window.setTimeout(function() {
            $(ui.item).parent().removeClass('delayPlaceholderMovement');
        }, 40);
    },
    stop: function(event, ui) {
        // remove our fake placeholder and strip the regular placeholders negative margin.
        $('.temp-spacer-' + placeholderNumber).css('height', 0).remove();
        $(ui.placeholder).css('margin-top', '0px');
        // clear placeholder number so this doesn't go a bagillions after performing a few dragg events.
        placeholderNumber = 0;
    }
});


// CSS:
// Setting the height of the default placeholder. If you want to style the placeholder, you'd probably set an additional class on our replacement animated placeholder.
.tree-drop-placeholder {
    height: 30px;
    width: 100%;
}

So the default placeholder is removed and added very abruptly in jquery UI, it just takes it from one place, adds it to the new place with no way to add css animations or anything.

What we did here was replaced the default placeholder with our own that we can animate. We iterate a unique number for each replacement placeholder created so that we can have multiple existing at once and animate them in and out more gradually.

Hope this helps! Haven't tested it in many browsers and there's probably a better place than the global scope to put the 'placeholderNumber' variable.

like image 159
BrandonReid Avatar answered Nov 13 '22 04:11

BrandonReid