gethyn1 gethyn1 - 4 months ago 12
Javascript Question

Reordering elements both visually and in the DOM

I am creating a filtering function that will animate the reordering of a set of elements (projects in this case) as well as update their position within the DOM. Please see comments in js for the basic idea.

The function works the first time a category filter is clicked. Repeat use of the category filters breaks the function however.

The issue seems to be the elements using their original onload position for the animation rather than their updated current position.

I have tried various things to fix but nothing seems to work so any help is greatly appreciated.

I have tried to simplify my code as much as possible:



$('#filterNav').find('a').click(function() {
var navItem = $(this);
slideSwap(navItem);
return false;
});


function slideSwap(navItem) {

var projContainer = $('#projectContainer');
var projects = projContainer.find('li');
var category = navItem.data('sort');

// 1. Record each project's current positioning
projects.each(function() {

$(this).attr('data-latpos', $(this).position().left)
.attr('data-vertpos', $(this).position().top);

});

// 2. Reorder the project list based on selected category
projects.each(function() {

if ($(this).data('cat').indexOf(category) != -1) {
$(this).prependTo(projContainer);
}
});

// 3. Record new project positions
projects.each(function() {

$(this).attr('data-newlatpos', $(this).position().left)
.attr('data-newvertpos', $(this).position().top);

});

// 4. Reset to original position with absolute positioning
projects.each(function() {

$(this).css({
position: 'absolute',
left: $(this).data('latpos'),
top: $(this).data('vertpos')
});

});

// 5. Animate from original position to new position
projects.each(function() {

var project = $(this);

$(this).animate({
left: $(this).data('newlatpos'),
top: $(this).data('newvertpos')
}, 1000, function() {
$(this).css('position', 'static');
});

});

}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="filterNav">
<li><a href="#" data-sort="cat-1">Cat 1</a>
</li>
<li><a href="#" data-sort="cat-2">Cat 2</a>
</li>
<li><a href="#" data-sort="cat-3">Cat 3</a>
</li>
</ul>

<ul id="projectContainer">
<li data-cat="cat-1">Cat 1</li>
<li data-cat="cat-3">Cat 3</li>
...
<li data-cat="cat-2">Cat 2</li>
</ul>




Answer

Answering my own question.. the issue was I didn't fully understand how data attributes affect their elements.

The data attributes need to be removed at the end of step 5 via removeData(). Now the animation seems to work correctly:

    // 5. Animate from original position to new position
    projects.each(function() {

        var project = $(this);

        $(this).animate({
            left: $(this).data('newlatpos'),
            top: $(this).data('newvertpos')
        }, 1000, function() {
            $(this).css('position', 'static');

            // Remove data attributes
            $(this).removeData('latpos').removeData('vertpos').removeData('newlatpos').removeData('newvertpos');
        });

    });
Comments