Javascript JQuery可排序列表,其中某些元素按顺序冻结?

Javascript JQuery可排序列表,其中某些元素按顺序冻结?,javascript,jquery,jquery-ui,Javascript,Jquery,Jquery Ui,我正在寻找一种方法,该方法具有类似于sortable list()的JQuery,但其中一些元素处于固定的不可拆分位置 使某些元素不可拖动很简单,但它们的位置不会保持不变,因为它们上面和下面的可拖动元素的数量可以更改 更具体地说: 我有一张10个项目的排名表。我希望用户能够通过拖动(一个可排序列表)来更改某些项目的排名,但不能更改其他冻结元素的排名。标准JQuery sortable undraggable特性允许通过更改冻结项上方或下方的元素数量来更改冻结项的排名 我尝试过在拖动时通过“交换”

我正在寻找一种方法,该方法具有类似于sortable list()的JQuery,但其中一些元素处于固定的不可拆分位置

使某些元素不可拖动很简单,但它们的位置不会保持不变,因为它们上面和下面的可拖动元素的数量可以更改

更具体地说: 我有一张10个项目的排名表。我希望用户能够通过拖动(一个可排序列表)来更改某些项目的排名,但不能更改其他冻结元素的排名。标准JQuery sortable undraggable特性允许通过更改冻结项上方或下方的元素数量来更改冻结项的排名

我尝试过在拖动时通过“交换”列表元素手动执行此操作。也就是说,当一个列表元素被拖动到一个非冻结的元素上时,两个元素的位置被交换。这提供了我想要的语义,但是被拖动的项在其新位置和当前“拖动”位置之间明显地“跳跃”。(我希望它保持在当前的拖动位置;只有它在DOM中的位置应该更改。但是当DOM位置更改时,必须重新计算拖动偏移坐标。我不知道如何原子地同时更改DOM位置和拖动偏移坐标,以防止两者之间的重绘。目前,有时是重绘发生在两者之间,元素明显地(尽管很短)跳跃。)

编辑 下面是一个JSFIDLE,显示了我的手动方法: . 玩一会儿,你会注意到我提到的闪烁/跳跃。

1)如果你不想更改的项目都在列表的顶部和/或底部,你可以在列表之外创建这些项目,从而只允许对其他项目进行排序,并保留不可变项目的排名


2) 您能否使用“停止”事件检查您想要的排名是否已保留?也就是说,检查排名第四的项目上面是否只有3个项目,如果没有,将新的“第四”移动到排名第四的项目下面?基本上,在项目被拖到非法位置后强制重新移动项目?

我看了你的小提琴,有了另一个想法,这里有一种方法可以使用
sortable
:在
开始
将固定索引位置存储在每个固定项目的
数据
对象中,然后在任何
更改
,将固定项目移回原位

$(function() {   
    $('#rankings').sortable({
        axis: 'y',
        items: '.sortable',
        start: function () {
            $(this).find("li:not(.sortable)").each(function () {
                $(this).data("fixedIndex", $(this).index());
            });
        },        
        change: function () {
            $(this).find("li:not(.sortable)").each(function () {
                $(this).detach().insertAfter($("#rankings li:eq(" + ($(this).data("fixedIndex")-1) + ")"));
            });
        }
    });
});
使用以下列表:

<ol id="rankings">
    <li class="sortable">Dog</li>
    <li class="">Cat</li>
    <li class="sortable">Parrot</li>
    <li class="sortable">Gerbil</li>
    <li class="sortable">Snake</li>
    <li class="">Goldfish</li>
</ol>

狗
猫
鹦鹉
沙鼠
蛇
  • 金鱼

  • 我想我可能已经破解了-。不过,这是一个相当大的挑战。在这一过程中,有几件事起了作用

    • 使用更结构化的标记
    • 使用droppable的over事件交换列表项,而不是drop事件(改为使用dragstop)
    • 在内部项目上设置一些位置,以便在更改其父元素后将其保持在正确的位置

    尽管阅读@GraphicsDivine上面的答案,看起来您一直真正需要的是jquery ui sortable

    您是否尝试过将您的行为绑定到
    beforeStop
    事件?这听起来很有趣,我想您已经有了一些几乎可以工作的代码了?请考虑用你所拥有的来创建一个JSoFdle!LinusGThiel,我添加了一个指向JSFIDLE的链接,显示了我的手动尝试。@GraphicsDive,你能扩展一下吗?在Forestop
    之前我应该添加什么行为?(1)不是选项;冷冻物品可以出现在中间。(2) 是一种选择,尽管我担心重新调整将导致的闪烁量。即使是简单的交换方法也是显而易见的。我肯定听说。。。您对更平稳的过渡感觉如何,在这种过渡中,物品会慢慢进入新的位置?我意识到这并不理想。。。我会继续考虑的。。。这是一个有趣的问题!如果您没有进行硬交换(如JSFIDLE示例中所示),而是进行了平滑的转换,那又如何呢?慢慢地将被替换的物品滑入新位置,并使用放置处理程序将新物品放置到该位置?我认为,如果冻结物品最终都会被放置,那么选项1是最好的解决方案。因为放置占位符不会对用户撒谎,并且会减少检查次数。但当然,只有在冻结的项目必须在最后的情况下。我想为了提高效率,您可能还需要在分离和移动它们之前检查不可排序的项目是否不合适;这是迄今为止最干净的解决方案。所有的重新排列都会导致偶尔的结巴,但对于小列表来说,这并不太明显。如果列表中的第一项不可排序,这将失败,因为您将尝试在索引-1之后插入。添加虚拟元素。更简单的解决方案:只需检查fixedIndex 0并跳过它。Sortable一开始不会移动该元素。检查fixedIndex==$(this).index()执行相同的操作。+1。杰出的解决了我的问题。实际上,我只是在寻找
    项:'.sortable'
    部分,但整个解决方案非常有趣。这个解决方案仍然有些缺陷,因为无法轻松地将项目拖回其初始位置。将项目“A”拖到项目“B”上时,“B”将移到“A”旧位置。但是,将“A”移回“B”上方并不会将“B”返回到其原始位置。这可能是可以修复的,但我还没有看过代码。