user2246120
user2246120

Reputation: 1505

How do I animate moving a list item to the top?

I have a list and would like to move the item to the top when it's clicked on. Simultaneously, all other items should move down to make space.

That's what I have so far:

<ul id="list">
  <li id="one">item-1</li>
  <li id="two">item-2</li>
  <li id="three">item-3</li>
  <li id="four">item-4</li>
</ul>

//

  $('li').on('click', function () {
    $(this).css({ position : 'absolute', top : $(this).position().top });
    var height = $(this).parent().children().first().height();
    var list = $(this).parent();
    $(this).animate({top: '0px'}, { duration: 500, queue: false });

    list.children().each(function( index, element) {
    var $liElement = $(element);
    if($liElement != $(this))
    {
        $liElement.animate({top: height + 'px'}, { duration: 500, queue: false });     
    }
  });
});

Here is the link: http://jsfiddle.net/5qgnjvdp/

I see the item moving on top but all others don't move at all. What is wrong here? Should I use prepend() to insert the list item on top when the animation is finished?

Upvotes: 0

Views: 2074

Answers (2)

Scott
Scott

Reputation: 21882

While not really an "animation", I was working on something some time ago along similar lines. What I ended up using was a slideUp, then a slideDown to give a sense of animation without actual animation connected to the move.

$('li').click(function() {
        $(this).slideToggle(500, function() {
        $(this).prependTo('#list').slideToggle(500); });
    });
li { list-style: none; background: #ddd;padding: 5px 10px; border: 1px solid #aaa; margin: 10px; text-transform: uppercase; font-weight: bold;color:#fff; }
#list { margin:20px; padding:0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<ul id="list" data-role="listview">
    <li id="one">item-1</li>
    <li id="two">item-2</li>
    <li id="three">item-3</li>
    <li id="four">item-4</li>
</ul>

$('li').click(function() {
        $(this).slideToggle(500, function() {
        $(this).prependTo('#list').slideToggle(500); });
    });

fiddle update

Again, I realize this isn't really an animation beyond the slide toggles, but it conveys a sense of interactivity similar to an animation.

Upvotes: 4

hsan
hsan

Reputation: 1559

There are a couple of problems with your script.

  • When comparing $liElement != $(this) you are in the scope of the each function where this refers to the current list child, which is the same as element. Store the clicked li in a variable outside of the looping function and compare with that. Also no need to compare the $(...) objects. element != clickedLi would suffice.
  • When you animate the other li elements they don't have position: absolute (or relative) so you won't see their movement.
  • If you assign the other li elements an absolute position you move all of them to the same position, the second row in the list. You could use position relative to move them down. You should just make sure to exclude the elements that come after the original position of the clicked li.

After the animation is complete you should insert the list item as the first child of the list and then remove the absolute/relative positioning, including the top style to make sure it works a second time (and to ensure that the visible representation is in line with the elements' structure.

Upvotes: 0

Related Questions