使用jQuery将列表项移动到无序列表的顶部

29
假设我有以下无序列表。
<ul>
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>

我的需求是,当我点击Tom时,它会移动(带有动画且无需拖动)到列表的顶部(索引为0)。

我考虑过使用jQuery sortable,但我找不到一种以编程方式激活移动部分的方法。

5个回答

65

发现这个更简洁:

$('li').on('click', function() {
    $(this).parent().prepend(this);
});​

实时例子


7
移动到底部:$(this).parent().append(this); 的意思是将当前元素移动到其父元素的最后一个位置。 - Aaron Hoffman
如果你还没有猜到的话 - 移动到顶部:$(this).parent().prepend(this); - Joseph Woodward
我知道这是一个旧的回复,但我正在尝试使用这个解决方案。唯一的区别是,我想要一个单独的链接列表,人们可以点击以重新排序li。有人能给我一些建议,告诉我我需要改变什么才能让它工作吗?这是我目前拥有的: https://jsfiddle.net/ztny31py/ - Artsen
虚惊一场,我最终解决了我的问题,如果有人对我找到的解决方案感兴趣,可以在这里查看。https://jsfiddle.net/akcme1nh/ - Artsen

19

我想出了一个解决方案,它似乎运作得非常好。这只是一个概念验证,所以你可能需要稍微修改一下才能更好地适用于你的特定情况。此外,我只在Firefox中进行了测试,但我不认为这在所有浏览器中都无法工作。无论如何,这里是代码:

<script type="text/javascript">
  $(document).ready(function() {
    $('li').click(function() {
      // the clicked LI
      var clicked = $(this);

      // all the LIs above the clicked one
      var previousAll = clicked.prevAll();

      // only proceed if it's not already on top (no previous siblings)
      if(previousAll.length > 0) {
        // top LI
        var top = $(previousAll[previousAll.length - 1]);

        // immediately previous LI
        var previous = $(previousAll[0]);

        // how far up do we need to move the clicked LI?
        var moveUp = clicked.attr('offsetTop') - top.attr('offsetTop');

        // how far down do we need to move the previous siblings?
        var moveDown = (clicked.offset().top + clicked.outerHeight()) - (previous.offset().top + previous.outerHeight());

        // let's move stuff
        clicked.css('position', 'relative');
        previousAll.css('position', 'relative');
        clicked.animate({'top': -moveUp});
        previousAll.animate({'top': moveDown}, {complete: function() {
          // rearrange the DOM and restore positioning when we're done moving
          clicked.parent().prepend(clicked);
          clicked.css({'position': 'static', 'top': 0});
          previousAll.css({'position': 'static', 'top': 0}); 
        }});
      }
    });
  });
</script>

<ul>
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>
它计算了点击的 LI 与第一个 LI 之间的偏移量差,并通过将其 position 设置为 relative 并动画化 top 属性,将点击的元素移到顶部。同样地,它还计算了被点击的 LI 后面留下的空间大小,并相应地将所有前面的元素向下移动。完成动画后,它重新排列 DOM,以匹配新的顺序,并恢复定位样式。

希望这可以帮助你!


哇,那看起来非常有趣,我一定要试一试。点赞! - Fabian
有没有一种版本可以将li项目向下移动一个位置? - crosenblum

10

假设:

<ul id="list">
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>

那么:

$("#list a").click(function() {
  $(this).parent().before("#list a:first");
  return false;
});

如果您想要进行动画效果,那就有一点难度。一个选择是:

$("#list a").click(function() {
  $(this).parent().slideUp(500).before("#list a:first").slideDown(500);
  return false;
});

另一个选项:

$("#list a").click(function() {
  var item = $(this).parent();
  var prev = item.prev();
  while (prev.length > 0) {
    item.before(prev);
    prev = item.prev();
  }
  return false;
});

但我怀疑你不会以那种方式获得流畅的动画效果。


不完全是我想要的,但我猜那是下一个最好的选择。点赞。 - Fabian

2

我玩了一下“无惊喜”(No Surprises)的Demo代码,并扩展了它,使其可以交换任意两组元素(唯一的限制是它们必须直接跟在彼此后面)。

请参见这里:http://jsfiddle.net/ZXYZ3/139/


1

我想出了这个解决方案:http://jsfiddle.net/FabienDemangeat/TBYWw/

这个想法是选择要移动的Li元素的索引和它的目标位置。 如果目标值小于要移动的li元素的索引,则效果将被反转。

有些部分不完美,但可以作为起点。我从"No Surprises"提供的片段中获得了灵感。

主要函数swapLiElements交换两个li元素,并且回调函数作为参数允许轻松进行多次交换(请参见fiddle)。

function swapLiElements($northLi, $southLi, isPushingDown, duration, easing, callbackFunction) {

    var movement = $northLi.outerHeight();

    // Set position of the li elements to relative
    $northLi.css('position', 'relative');
    $southLi.css('position', 'relative');

    // Set the z-index of the moved item to 999 to it appears on top of the other elements
    if(isPushingDown)
        $northLi.css('z-index', '999');
    else        
        $southLi.css('z-index', '999');

    // Move down the first li
    $northLi.animate({'top': movement}, {
        duration: duration,
        queue: false,
        easing: easing,
        complete: function() {
            // Swap the li in the DOM
            if(isPushingDown)
                $northLi.insertAfter($southLi);
            else
                $southLi.insertBefore($northLi);

            resetLiCssPosition($northLi);
            resetLiCssPosition($southLi);

            callbackFunction();
        }
    });

    $southLi.animate({'top': -movement}, {
        duration: duration,
        queue: false,
        easing: easing,
    });

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接