假设我有以下无序列表
<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可以排序,但我找不到以编程方式激活移动部件的方法。
答案 0 :(得分:52)
答案 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)
我玩弄了没有惊喜的小提琴,并扩展了交换两组任意元素的代码(唯一的限制是它们必须直接相互跟随)。
答案 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,
});
}