但是,只有在缓慢到正常拖动时才能可靠地工作。 在这些速度下,完全没有错误。 但是,如果用户相对较快地拖动元素(列表越大,它就越容易发生,因为鼠标有更多空间可以加速),则“change”事件会丢失一些步骤,从而丢失一些有用信息,而不会在控制台中抛出任何错误。 展示问题:
https://jsfiddle.net/yhp3m6L8/2/
在这个jsFiddle中,你可以拖动一个元素并查看其索引更改作为一个示例。在列表下方,在拖动时,您将有一个控制台仿真来跟踪黑色的索引。如果拖动得足够快,您会看到其中一些索引变成红色。这就是问题所在。这意味着在排序脚本的更改事件期间它们的先前位置被忽略了,原因我不明白。连续性被打破,而这种连续性对我的需求至关重要。 速度是唯一打破连续性的因素。但是,一个无法跟上相当快的鼠标拖动的“change”事件似乎相当奇怪。
脚本:
其中一半是为了跟踪索引,因为Sortable有一种奇特的引用索引的方式,这取决于方向(向上/向下),但也取决于元素相对于其初始位置(之前/之后)的当前位置。因此,需要最少量的代码来直观地理解这些索引。使用该脚本,元素会获得一个直观的视觉索引,按顺序排列。
然而,这个脚本可能只是问题的展示(请参见下面的附注)。
脚本的另一半只是为了模拟一种调试目的的控制台。
我的猜测:
我可能错了,但最终我认为这是“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”事件中的所有代码都是为了让您看到问题,而不是问题本身。我让您自己判断,但公平地提醒一下。
我的实际脚本在“change”部分是不同的。它会触发一些表格列的重新排序,这就是我发现问题的方式,因为在高速情况下表格重新排序会出现故障。因此,这里的虚拟脚本只是我将其缩小到最小限度,同时以视觉方式向您展示问题。
重点是评估这是否是可以解决的性能问题,我应该添加一个Sortable选项,可以修复拖动/光标延迟,还是有什么诀窍可以绕过这个跟踪问题。
我认为这是一个公平的警告,以防止您费力调试一个仅仅是展示用的虚拟脚本。但考虑到我只是一个新手,可能是错误的,请按照您的意愿进行操作。
在所有情况下,非常感谢您的帮助或意见。
编辑:这是我真正的(缩小范围后的)脚本,它会触发“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);
}
});