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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1625960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 11:52:35  来源:igfitidea点击:

Move list item to top of unordered list using jQuery

jquery

提问by Fabian

Lets say i have the following unordered list

假设我有以下无序列表

<ul>
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>

What im looking for is when i click on Tom, that it moves (animated and without dragging) to the top of the list (index 0).

我要寻找的是当我单击 Tom 时,它会移动(动画且不拖动)到列表的顶部(索引 0)。

Ive considered jquery sortable, but i cant find a way to activate the moving part programmatically.

我认为 jquery 是可排序的,但我找不到以编程方式激活移动部分的方法。

采纳答案by No Surprises

I came up with a solution that seems to work pretty well. It's a proof of concept, so you'll probably have to modify it a bit to work better for your specific case. Also, I only tested it in Firefox, but I don't see any reason why this wouldn't work in all the browsers. Anyway, here it is:

我想出了一个似乎工作得很好的解决方案。这是一个概念证明,因此您可能需要对其进行一些修改才能更好地适应您的特定情况。此外,我只在 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>

It calculates the difference in offsets between the clicked LIand first LIand moves the clicked one up to the top by setting its positionto relativeand animating the topproperty. Similarly, it calculates how much space was left behind by the clicked LIand moves all the previous ones down accordingly. When it's done with the animations, it rearranges the DOM to match the new order and restores the positioning styles.

它计算单击LI和第一个之间的偏移量差异,并LI通过将其设置positionrelative和动画top属性将单击的一个向上移动到顶部。类似地,它会计算点击后留下的空间,LI并相应地向下移动所有先前的空间。完成动画后,它会重新排列 DOM 以匹配新顺序并恢复定位样式。

Hope that helps!

希望有帮助!

回答by Hymantheripper

Found this even neater:

发现这个更整洁:

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

Live example

活生生的例子

回答by cletus

Assuming:

假设:

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

then:

然后:

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

If you want to animate then it's a little harder. One option:

如果你想制作动画,那就有点难了。一种选择:

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

Another option:

另外一个选项:

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

but I doubt you'll get smooth animation that way.

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

回答by stephan hattinger

i played around with the fiddle No Surprises has made, and extended the code for swapping two arbitrary sets of elements (the only restriction being they must directly follow each other).

我玩弄了 No Surprises 制作的小提琴,并扩展了交换两个任意元素集的代码(唯一的限制是它们必须直接相互跟随)。

see here: http://jsfiddle.net/ZXYZ3/139/

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

回答by Fabien Demangeat

I came up with this solution: http://jsfiddle.net/FabienDemangeat/TBYWw/

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

The idea is to choose the index of the Li element which will move and its destination. If the destination value is inferior to the index of the li element to move, the effect will be reversed.

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

Some parts are not perfect but it can be a start point. I inspired myself from the snippet provided by "No Surprises"

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

The main function swapLiElementsswaps two li elements and the callback function as parameters allows to do more than one swap easily (see fiddle).

main 函数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,
    });

}