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

时间:2009-10-26 17:01:08

标签: jquery

假设我有以下无序列表

<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可以排序,但我找不到以编程方式激活移动部件的方法。

5 个答案:

答案 0 :(得分:52)

发现这个更整洁:

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

Live example

答案 1 :(得分: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以匹配新订单并恢复定位样式。

希望有所帮助!

答案 2 :(得分: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;
});

但我怀疑你会以这种方式获得流畅的动画。

答案 3 :(得分:2)

我玩弄了没有惊喜的小提琴,并扩展了交换两组任意元素的代码(唯一的限制是它们必须直接相互跟随)。

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

答案 4 :(得分:1)

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

想法是选择将移动的Li元素的索引及其目的地。 如果目标值低于要移动的li元素的索引,则效果将反转。

有些部分并不完美,但它可以作为一个起点。我从“No Surprises”提供的片段中激发了自己的灵感。

主函数swapLiElements交换两个li元素,并且回调函数作为参数允许轻松地进行多个交换(see 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,
    });

}