jQueryUI 可排序和拖动速度问题
jQueryUI sortable and drag speed issue
我有一个列表正在使用 jQueryUI sortable。
根据插件的 "change" 事件,我需要在拖动时跟踪元素的每一步。
但它只能从缓慢到正常的拖动可靠地工作。在这些速度下,没有任何错误。但是,如果用户拖动元素的速度相对较快(列表越大,这种情况发生的频率就越高,因为鼠标有更多的空间来加快速度),"change" 事件会丢失一些步骤,因此,一些有用的信息是一路迷路,控制台中没有抛出任何错误。
显示问题:
https://jsfiddle.net/yhp3m6L8/2/
在此 jsFiddle 中,您可以拖动一个元素并查看其索引变化,如 示例。在列表下方,拖动时,您将有一个控制台模拟跟踪 black.
中的索引
如果拖动得相当快,您会看到其中一些索引变成 红色。这就是问题。这意味着他们之前的位置在更改事件期间被 sortable 脚本忽略,原因我只是不明白。连续性被打破了,而这种连续性对我的需求来说是最基本的。
速度是唯一打破连续性的东西。但是一个 "change" 事件跟不上相当快的鼠标拖动速度似乎很奇怪。
脚本:
其中一半是关于跟踪索引,因为 Sortable 有一种引用索引的特殊方式,它取决于方向 (up/down),但也取决于元素的当前位置相对于其初始位置 (before/after) 。因此,只需要最少的代码就可以从视觉上理解这些索引。使用该脚本,该元素会获得一个视觉索引,该索引直观地是您希望以有序的方式看到的索引。
然而,这个脚本是问题的展示,可能不是问题所在(见下面的旁注)。
脚本的另一半只是为了调试而模拟一种控制台。
我的猜测:
我可能错了,但我最终认为这是 "change" 事件的跟踪问题,或者被拖动的元素跟不上鼠标光标(感觉它并不总是在光标以相对较高的速度移动)。
除非有一个我不知道的 Sortable 选项可以使用...
我认为这是其中一种情况,因为无论我尝试在 "change" 事件中使用什么代码,我总是会遇到这个间隙问题。
HTML:
<html>
<body>
<div class="panel">
<ul class="panel_list">
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
</ul>
</div>
<div class='console'></div>
</body>
</html>
CSS:
.console{
width:100%;
}
.panel ul{
list-style-type:none;
width:30%;
}
.panel li{
height:29px;
border-bottom:1px solid #454d5a;
text-align: left;
vertical-align: middle;
line-height:29px;
padding-left:8px;
background: #666;
}
.panel_highlight{
height:29px;
background:#1c2128 !important;
}
.unticked{
color:#7c7a7d;
background:#222 !important;
}
jQuery:
// jQuery: 3.3.1
// jQueryUI: 1.11.4 (downgraded from 1.12.1, because of documented
// performance issues but...with no effect)
var origValue;
var oldInfo;
var c=0;
var x=0;
// LIST RELATED
//Just to have a visual on the indexes in the list.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
items : '>li.ticked',
cancel : '>li.unticked',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED (initialise variables)
$('.console').html('');oldInfo='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
//detect the direction of the dragging
if(idx - $(this).data('idx')==1)
{//downward dragging
//if the element is below its initial position (or x=1)
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
//if the element is still above its initial position
else {ui.item.text(a);};
}
else
{//upward dragging
//if the element is still below its initial position
if(a<=origValue) {ui.item.text(b);x=1;}
//if the element is above its initial position
else {ui.item.text(a);};
};
$(this).data('idx', idx);
// Update the visual on the indexes in the list.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED (show indexes progression and gaps)
var info=$('.console').html();
if(oldInfo !=''){
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{info=info+' + <span style="color:red">'+ui.item.text()+'</span>';};
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
旁注:
"change" 事件中的所有代码都是为您量身定制的,以便您查看问题,可能不是问题本身。我让你来评判它,但提及这一点才公平。
更改部分中我的实际脚本不同。它触发了一些 table 列的重新排序,这就是我第一次检测到问题的方式,因为 table 重新排序在高速下出现故障。所以这里的虚拟脚本只是我将它缩小到最低限度,同时显示你以视觉方式解决问题。
重点是评估它是否是一个可以解决的性能问题,缺少我应该添加的 Sortable 选项,一个可以修复的 drag/cursor 延迟,或者是否有以某种方式解决此跟踪问题的任何技巧。
我认为这是一个公平的警告,可以防止您调试一个只是展示的虚拟脚本的麻烦。但考虑到我只是一个新手,我可能是错的,按照你认为合适的方式去做。
在任何情况下,我们都非常感谢您的帮助或意见。
提前谢谢你。
编辑:这是我的真实(缩小范围)脚本,提供 "dataTable.colReorder.move" 事件。它涉及更多,因为它需要知道着陆索引 (a/b),而且还需要知道拖动元素的当前索引 (a/b/c/d)。 sortable 有自己的索引方式。
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
lastValue='';
origValue=ui.item.index();
$(this).data('idx', ui.item.index());
},
change: function(event, ui){
var x;
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a= ui.placeholder.index();
var b=a+1;var c=a+2;var d=a-1;
if(idx - $(this).data('idx')==1)
{//downward
if((origValue>=a) || (x==1)){dataTable.colReorder.move(a,b);lastValue=b;x=0}
else {dataTable.colReorder.move(d,a);lastValue=a;}
}
else
{//upward
if(origValue>=a) {dataTable.colReorder.move(c,b);lastValue=b;x=1}
else {dataTable.colReorder.move(b,a);lastValue=a;}
}
$(this).data('idx', idx);
}
});
遗憾的是...没有解决方案可以解决该问题。
我首先尝试使用 sort event callback
...同样的 "skipping" 问题发生在非常快的拖动上。
我想知道为什么 几分钟...
然后我教了 .sortable()
可能依赖什么......我带来了唯一可能的 "browser" 事件:mousemove
.
虽然 mousemove
经常触发...很像 "machine gun"...它的触发速度不够快,无法达到您的预期。
为了验证这一点,我只是在未更改的 Fiddle:
末尾添加了这个 mousemove
处理程序
$( ".panel_list" ).on("mousemove",function(e){
console.log($(e.target).index());
});
它 记录的数字 与您 div.console
.
中的数字完全相同
所以问题肯定不是 .sortable()
造成的。
编辑
我上面说的仍然是正确的......但是既然你已经有了"skip detection",为什么不用它来填补空白呢?
您有 oldInfo
,这是这个新 change
之前的最后一个 .index()
。
你有新的 .index()
...
根据运动是向上还是向下,您需要一个或另一个 for
循环来填补编号中的空白。 这也是你的触发点 你必须用这些数字做什么...
;)
更改部分如下:
// CONSOLE RELATED
info=$('.console').html();
if(oldInfo !=''){
var valReal = parseInt(ui.item.text()) - parseInt(oldInfo);
var valOld = parseInt(oldInfo);
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{
// ADDING THE SKIPPED ONES!
// Upward (in blue)
if(valReal>0){
for(i=valOld+1;i<valOld+valReal;i++){
info=info+' + <span style="color:blue">'+( i )+'</span>';
}
// Downward (in green)
}else{
for(i=valOld-1;i>valOld+valReal;i--){
info=info+' + <span style="color:green">'+( i )+'</span>';
}
}
// The one caugth after a gap (in red)
info=info+' + <span style="color:red">'+ui.item.text()+'</span>';
};
}
它值得一个片段......为了后代。 (运行 全页模式。)
var origValue;
var oldInfo;
var info;
var c=0;
var x=0;
// LIST RELATED
//With or without this, the problem will occur.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED
$('.console').html(''); oldInfo=''; info='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
if(idx - $(this).data('idx')==1)
{//downward dragging
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
else {ui.item.text(a);};
}
else
{//upward dragging
if(a<=origValue) {ui.item.text(b);x=1;}
else {ui.item.text(a);};
};
$(this).data('idx', idx);
//With or without this, the problem will occur.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED
info=$('.console').html();
if(oldInfo !=''){
var valReal = parseInt(ui.item.text()) - parseInt(oldInfo);
var valOld = parseInt(oldInfo);
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{
// ADDING THE SKIPPED ONES!
if(valReal>0){
for(i=valOld+1;i<valOld+valReal;i++){
info=info+' + <span style="color:blue">'+( i )+'</span>';
}
}else{
for(i=valOld-1;i>valOld+valReal;i--){
info=info+' + <span style="color:green">'+( i )+'</span>';
}
}
// The one caugth after a gap
info=info+' + <span style="color:red">'+ui.item.text()+'</span>';
};
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
.console{
width:100%;
}
.panel ul{
list-style-type:none;
width:30%;
}
.panel li{
height:29px;
border-bottom:1px solid #454d5a;
text-align: left;
vertical-align: middle;
line-height:29px;
padding-left:8px;
background: #666;
}
.panel_highlight{
height:29px;
background:#1c2128 !important;
}
.unticked{
color:#7c7a7d;
background:#222 !important;
}
.ui-sortable-helper{
background-color:red !important;
}
<link href="https://www.lexgotham.com/test5/styles/reset.css" rel="stylesheet"/>
<link href="https://www.lexgotham.com/test5/scripts/jQuery/jquery-ui-1.12.1/jquery-ui.css" rel="stylesheet"/>
<script src="https://www.lexgotham.com/test5/scripts/jQuery/jquery.3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<html>
<body>
<div class="panel">
<ul class="panel_list">
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
</ul>
</div>
<div class='console'></div>
</body>
</html>
之前回答的一些观察结果是正确的,但这是我的保留意见。顺便说一句,我相信这是 "fixable"..
我认为有一个非常简单的解决方案。每次出现 "skip" 时,sortable 不会告诉你所有的中间步骤,所以..你为什么不构造它们?..
var origValue;
var oldInfo;
var info;
var c=0;
var x=0;
// LIST RELATED
//With or without this, the problem will occur.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED
$('.console').html(''); oldInfo=''; info='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
if(idx - $(this).data('idx')==1)
{//downward dragging
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
else {ui.item.text(a);};
}
else
{//upward dragging
if(a<=origValue) {ui.item.text(b);x=1;}
else {ui.item.text(a);};
};
$(this).data('idx', idx);
//With or without this, the problem will occur.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED
info=$('.console').html();
if(oldInfo !=''){
oIv = parseInt(oldInfo);
uiV = parseInt(ui.item.text());
stepIn = (uiV > oIv ? 1 : -1);
switch (stepIn) {
case 1:
for (i=oIv+1;i<uiV;i++) {info=info+' + <span style="color:green">'+i+'</span>';}
break;
case -1:
for (i=uiV+1;i<=oIv;i++) {info=info+' + <span style="color:red">'+i+'</span>';}
break;
}
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
正如您在此处看到的,如果发生跳过,我将向信息变量中添加更改事件遗漏的所有步骤……但是,遗憾的是,这仍然不起作用……原因很简单..更改事件的重入。
现在,我没有时间编写一个可行的解决方案,但这是我的想法。每次更改事件结束时,您都必须使用缺少的中间值重建列表。这样你就可以有一个连续的序列。因此,从您的原始代码中,只需向停止事件添加一个方法,该方法基于更改创建的序列填充中间值,瞧,您就有了序列。
让我知道这是否满足您的要求。
我有一个列表正在使用 jQueryUI sortable。 根据插件的 "change" 事件,我需要在拖动时跟踪元素的每一步。
但它只能从缓慢到正常的拖动可靠地工作。在这些速度下,没有任何错误。但是,如果用户拖动元素的速度相对较快(列表越大,这种情况发生的频率就越高,因为鼠标有更多的空间来加快速度),"change" 事件会丢失一些步骤,因此,一些有用的信息是一路迷路,控制台中没有抛出任何错误。
显示问题:
https://jsfiddle.net/yhp3m6L8/2/
在此 jsFiddle 中,您可以拖动一个元素并查看其索引变化,如 示例。在列表下方,拖动时,您将有一个控制台模拟跟踪 black.
中的索引如果拖动得相当快,您会看到其中一些索引变成 红色。这就是问题。这意味着他们之前的位置在更改事件期间被 sortable 脚本忽略,原因我只是不明白。连续性被打破了,而这种连续性对我的需求来说是最基本的。 速度是唯一打破连续性的东西。但是一个 "change" 事件跟不上相当快的鼠标拖动速度似乎很奇怪。
脚本:
其中一半是关于跟踪索引,因为 Sortable 有一种引用索引的特殊方式,它取决于方向 (up/down),但也取决于元素的当前位置相对于其初始位置 (before/after) 。因此,只需要最少的代码就可以从视觉上理解这些索引。使用该脚本,该元素会获得一个视觉索引,该索引直观地是您希望以有序的方式看到的索引。
然而,这个脚本是问题的展示,可能不是问题所在(见下面的旁注)。
脚本的另一半只是为了调试而模拟一种控制台。
我的猜测:
我可能错了,但我最终认为这是 "change" 事件的跟踪问题,或者被拖动的元素跟不上鼠标光标(感觉它并不总是在光标以相对较高的速度移动)。 除非有一个我不知道的 Sortable 选项可以使用...
我认为这是其中一种情况,因为无论我尝试在 "change" 事件中使用什么代码,我总是会遇到这个间隙问题。
HTML:
<html>
<body>
<div class="panel">
<ul class="panel_list">
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
</ul>
</div>
<div class='console'></div>
</body>
</html>
CSS:
.console{
width:100%;
}
.panel ul{
list-style-type:none;
width:30%;
}
.panel li{
height:29px;
border-bottom:1px solid #454d5a;
text-align: left;
vertical-align: middle;
line-height:29px;
padding-left:8px;
background: #666;
}
.panel_highlight{
height:29px;
background:#1c2128 !important;
}
.unticked{
color:#7c7a7d;
background:#222 !important;
}
jQuery:
// jQuery: 3.3.1
// jQueryUI: 1.11.4 (downgraded from 1.12.1, because of documented
// performance issues but...with no effect)
var origValue;
var oldInfo;
var c=0;
var x=0;
// LIST RELATED
//Just to have a visual on the indexes in the list.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
items : '>li.ticked',
cancel : '>li.unticked',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED (initialise variables)
$('.console').html('');oldInfo='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
//detect the direction of the dragging
if(idx - $(this).data('idx')==1)
{//downward dragging
//if the element is below its initial position (or x=1)
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
//if the element is still above its initial position
else {ui.item.text(a);};
}
else
{//upward dragging
//if the element is still below its initial position
if(a<=origValue) {ui.item.text(b);x=1;}
//if the element is above its initial position
else {ui.item.text(a);};
};
$(this).data('idx', idx);
// Update the visual on the indexes in the list.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED (show indexes progression and gaps)
var info=$('.console').html();
if(oldInfo !=''){
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{info=info+' + <span style="color:red">'+ui.item.text()+'</span>';};
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
旁注:
"change" 事件中的所有代码都是为您量身定制的,以便您查看问题,可能不是问题本身。我让你来评判它,但提及这一点才公平。
更改部分中我的实际脚本不同。它触发了一些 table 列的重新排序,这就是我第一次检测到问题的方式,因为 table 重新排序在高速下出现故障。所以这里的虚拟脚本只是我将它缩小到最低限度,同时显示你以视觉方式解决问题。
重点是评估它是否是一个可以解决的性能问题,缺少我应该添加的 Sortable 选项,一个可以修复的 drag/cursor 延迟,或者是否有以某种方式解决此跟踪问题的任何技巧。
我认为这是一个公平的警告,可以防止您调试一个只是展示的虚拟脚本的麻烦。但考虑到我只是一个新手,我可能是错的,按照你认为合适的方式去做。
在任何情况下,我们都非常感谢您的帮助或意见。 提前谢谢你。
编辑:这是我的真实(缩小范围)脚本,提供 "dataTable.colReorder.move" 事件。它涉及更多,因为它需要知道着陆索引 (a/b),而且还需要知道拖动元素的当前索引 (a/b/c/d)。 sortable 有自己的索引方式。
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
lastValue='';
origValue=ui.item.index();
$(this).data('idx', ui.item.index());
},
change: function(event, ui){
var x;
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a= ui.placeholder.index();
var b=a+1;var c=a+2;var d=a-1;
if(idx - $(this).data('idx')==1)
{//downward
if((origValue>=a) || (x==1)){dataTable.colReorder.move(a,b);lastValue=b;x=0}
else {dataTable.colReorder.move(d,a);lastValue=a;}
}
else
{//upward
if(origValue>=a) {dataTable.colReorder.move(c,b);lastValue=b;x=1}
else {dataTable.colReorder.move(b,a);lastValue=a;}
}
$(this).data('idx', idx);
}
});
遗憾的是...没有解决方案可以解决该问题。
我首先尝试使用 sort event callback
...同样的 "skipping" 问题发生在非常快的拖动上。
我想知道为什么 几分钟...
然后我教了 .sortable()
可能依赖什么......我带来了唯一可能的 "browser" 事件:mousemove
.
虽然 mousemove
经常触发...很像 "machine gun"...它的触发速度不够快,无法达到您的预期。
为了验证这一点,我只是在未更改的 Fiddle:
末尾添加了这个mousemove
处理程序
$( ".panel_list" ).on("mousemove",function(e){
console.log($(e.target).index());
});
它 记录的数字 与您 div.console
.
所以问题肯定不是 .sortable()
造成的。
编辑
我上面说的仍然是正确的......但是既然你已经有了"skip detection",为什么不用它来填补空白呢?
您有 oldInfo
,这是这个新 change
之前的最后一个 .index()
。
你有新的 .index()
...
根据运动是向上还是向下,您需要一个或另一个 for
循环来填补编号中的空白。 这也是你的触发点 你必须用这些数字做什么...
;)
更改部分如下:
// CONSOLE RELATED
info=$('.console').html();
if(oldInfo !=''){
var valReal = parseInt(ui.item.text()) - parseInt(oldInfo);
var valOld = parseInt(oldInfo);
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{
// ADDING THE SKIPPED ONES!
// Upward (in blue)
if(valReal>0){
for(i=valOld+1;i<valOld+valReal;i++){
info=info+' + <span style="color:blue">'+( i )+'</span>';
}
// Downward (in green)
}else{
for(i=valOld-1;i>valOld+valReal;i--){
info=info+' + <span style="color:green">'+( i )+'</span>';
}
}
// The one caugth after a gap (in red)
info=info+' + <span style="color:red">'+ui.item.text()+'</span>';
};
}
它值得一个片段......为了后代。 (运行 全页模式。)
var origValue;
var oldInfo;
var info;
var c=0;
var x=0;
// LIST RELATED
//With or without this, the problem will occur.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED
$('.console').html(''); oldInfo=''; info='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
if(idx - $(this).data('idx')==1)
{//downward dragging
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
else {ui.item.text(a);};
}
else
{//upward dragging
if(a<=origValue) {ui.item.text(b);x=1;}
else {ui.item.text(a);};
};
$(this).data('idx', idx);
//With or without this, the problem will occur.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED
info=$('.console').html();
if(oldInfo !=''){
var valReal = parseInt(ui.item.text()) - parseInt(oldInfo);
var valOld = parseInt(oldInfo);
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{
// ADDING THE SKIPPED ONES!
if(valReal>0){
for(i=valOld+1;i<valOld+valReal;i++){
info=info+' + <span style="color:blue">'+( i )+'</span>';
}
}else{
for(i=valOld-1;i>valOld+valReal;i--){
info=info+' + <span style="color:green">'+( i )+'</span>';
}
}
// The one caugth after a gap
info=info+' + <span style="color:red">'+ui.item.text()+'</span>';
};
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
.console{
width:100%;
}
.panel ul{
list-style-type:none;
width:30%;
}
.panel li{
height:29px;
border-bottom:1px solid #454d5a;
text-align: left;
vertical-align: middle;
line-height:29px;
padding-left:8px;
background: #666;
}
.panel_highlight{
height:29px;
background:#1c2128 !important;
}
.unticked{
color:#7c7a7d;
background:#222 !important;
}
.ui-sortable-helper{
background-color:red !important;
}
<link href="https://www.lexgotham.com/test5/styles/reset.css" rel="stylesheet"/>
<link href="https://www.lexgotham.com/test5/scripts/jQuery/jquery-ui-1.12.1/jquery-ui.css" rel="stylesheet"/>
<script src="https://www.lexgotham.com/test5/scripts/jQuery/jquery.3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<html>
<body>
<div class="panel">
<ul class="panel_list">
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
</ul>
</div>
<div class='console'></div>
</body>
</html>
之前回答的一些观察结果是正确的,但这是我的保留意见。顺便说一句,我相信这是 "fixable"..
我认为有一个非常简单的解决方案。每次出现 "skip" 时,sortable 不会告诉你所有的中间步骤,所以..你为什么不构造它们?..
var origValue;
var oldInfo;
var info;
var c=0;
var x=0;
// LIST RELATED
//With or without this, the problem will occur.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED
$('.console').html(''); oldInfo=''; info='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
if(idx - $(this).data('idx')==1)
{//downward dragging
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
else {ui.item.text(a);};
}
else
{//upward dragging
if(a<=origValue) {ui.item.text(b);x=1;}
else {ui.item.text(a);};
};
$(this).data('idx', idx);
//With or without this, the problem will occur.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED
info=$('.console').html();
if(oldInfo !=''){
oIv = parseInt(oldInfo);
uiV = parseInt(ui.item.text());
stepIn = (uiV > oIv ? 1 : -1);
switch (stepIn) {
case 1:
for (i=oIv+1;i<uiV;i++) {info=info+' + <span style="color:green">'+i+'</span>';}
break;
case -1:
for (i=uiV+1;i<=oIv;i++) {info=info+' + <span style="color:red">'+i+'</span>';}
break;
}
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
正如您在此处看到的,如果发生跳过,我将向信息变量中添加更改事件遗漏的所有步骤……但是,遗憾的是,这仍然不起作用……原因很简单..更改事件的重入。
现在,我没有时间编写一个可行的解决方案,但这是我的想法。每次更改事件结束时,您都必须使用缺少的中间值重建列表。这样你就可以有一个连续的序列。因此,从您的原始代码中,只需向停止事件添加一个方法,该方法基于更改创建的序列填充中间值,瞧,您就有了序列。
让我知道这是否满足您的要求。