2009-10-26 133 views
24

无序列表的顶部可以说我有以下无序列表移动列表项目使用jQuery

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

什么即时寻找的是当我点击汤姆,其移动(动画和无拖)到列表顶部(索引0)。

我认为jquery可排序,但我无法找到一种方法来以编程方式激活运动部件。

回答

17

我想出了一个似乎工作得很好的解决方案。这是一个概念证明,所以你可能需要修改它以适合你的特定情况。另外,我只在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之间偏移的差异,通过设置它的positionrelative并动态top财产移动点击一个到顶部。同样,它会计算点击的LI剩下多少空间,并相应地减少之前的所有空间。完成动画后,它会重新排列DOM以匹配新订单并恢复定位样式。

希望有帮助!

+0

哇,这看起来非常intresting,我肯定会给这个去。投了! – Fabian 2009-10-27 13:44:55

+0

有没有一个版本可以让李项目向下移动? – crosenblum 2010-04-16 18:57:46

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; 
}); 

,但我怀疑你会得到平滑的动画的方式。

+0

不完全是我在找什么,但我想这是下一个最好的事情。投了票。 – Fabian 2009-10-27 08:34:50

2

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

在这里看到:http://jsfiddle.net/ZXYZ3/139/

45

发现这甚至更加整洁:

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

Live example

+4

并移动到底部:'$(this).parent()。append(this);' – 2013-04-10 21:46:32

+0

如果您还没有猜到它 - 移到顶端:'$(this).parent()。 (this);' – 2015-07-24 16:13:01

+0

~~ LOVELOVELOVE ~~ – flunder 2015-12-08 16:21:33

1

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

的想法是选择的索引李元素将移动和目的地。 如果目标值低于要移动的li元素的索引,则效果将被颠倒。

有些零件并不完美,但它可以作为一个起点。我从“没有惊喜”提供的片段中启发我自己

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

}