我正在尝试实施拖放功能请按照this answer:http://jsfiddle.net/hQnWG/614/
中的示例删除多个元素该示例适用于jQuery 1.9.1和jQuery UI 1.9.2(最高1.10.1),但只要我使用较新版本,如jQuery 1.11.3和jQuery UI 1.10.2或更新版本我得到以下问题。
当选择多个元素并开始将最底部选定的元素缓慢拖动到顶部时,在它将捕捉到下一个位置之前,将引发以下JS错误:
Uncaught TypeError: Cannot read property 'insertBefore' of null
at t.(/hQnWG/614/anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:7:15171)
at t.(/hQnWG/614/anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:5028)
at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:7:6)
at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:5028)
at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:12328)
at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:5028)
at HTMLDocument.o._mouseCapture._mouseDistanceMet._mouseDelayMet._mouseMoveDelegate (VM687 jquery-ui.min.js:5)
at HTMLDocument.dispatch (VM251 jquery-1.11.3.min.js:4)
at HTMLDocument.r.handle (VM251 jquery-1.11.3.min.js:4)
以下是带有升级的jQuery版本的示例jsfiddle的分支: http://jsfiddle.net/v3p6wsk2/6/
我尝试调试它,但无法找到任何解释拖动项的parentNode如何为null。
我甚至无法在jQuery UI 1.10.2. change log中找到有关可能会破坏该脚本的更改的任何提示。
不幸的是,我无法更改我正在处理的项目中的版本。是否有可能使用上述版本?
答案 0 :(得分:4)
据我所知,问题是调用parentNode.insertBefore
的元素是被拖动的元素之一(从原始表中删除)因此实际上没有父元素了。
我真正得到的是,我认为问题并非直接位于helper
或stop
函数中,而是介于两者之间,因为错误会在sort
- 事件之后立即触发
我不知道这个问题出在哪里,因为它在旧版本中运行,但通过试用和错误我可能找到了解决问题的方法。
在将删除的元素插入列表后,您可以隐藏它们并删除隐藏的元素,而不是删除帮助程序中的元素。
请参阅twistys fiddle I just updated。
这可能会解决您的问题,但这并不能解决(甚至找不到)此问题的原因。
答案 1 :(得分:1)
问题的根源在于:
_rearrange: function(event, i, a, hardRefresh) {
a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
//Various things done here to improve the performance:
// 1. we create a setTimeout, that calls refreshPositions
// 2. on the instance, we have a counter variable, that get's higher after every append
// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
// 4. this lets only the last addition to the timeout stack through
this.counter = this.counter ? ++this.counter : 1;
var counter = this.counter;
this._delay(function() {
if(counter === this.counter) {
this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
}
});
}
当我使用未压缩版本生成错误时,我看到:
Uncaught TypeError: Cannot read property 'insertBefore' of null
at $.(anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.3/jquery-ui.js:4628:68)
at $.(anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.3/jquery-ui.js:401:25)
at $.(anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.3/jquery-ui.js:3879:11)
at $.(anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.3/jquery-ui.js:401:25)
at $.(anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.3/jquery-ui.js:933:9)
at $.(anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.3/jquery-ui.js:401:25)
at HTMLDocument._mouseMoveDelegate (https://code.jquery.com/ui/1.10.3/jquery-ui.js:911:16)
at HTMLDocument.dispatch (https://code.jquery.com/jquery-1.11.3.min.js:4:8549)
at HTMLDocument.r.handle (https://code.jquery.com/jquery-1.11.3.min.js:4:5252)
Location: jquery-ui.js:4628
_rearrange
函数以条件操作开头。如果存在a
,则append
占位符Else insertBefore()
数组内特定元素的parentNode
。
所以,我猜,.insertBefore()
是DOM方法,而不是jQuery方法。根据结构,parentNode
返回null
元素。
HTML DOM parentNode属性
返回值:Node对象,表示节点的父节点,如果节点没有父节点,则 null
好的,我们确定i.item[0].parentNode
正在重新调整null
值并导致问题。
我怀疑这是因为helper
没有包装,因此stop
的每个项目都没有parent
;因此,没有parentNode
。我认为修复将删除1个项目,然后在其后追加其他元素或将元素追加到另一个回调事件中。
我会在获得更多信息后更新此信息。
同样,这并不总是一个显示阻止,到目前为止,只是Chrome浏览器中的一个问题。
更新1
看起来将此问题从stop
切换到update
回调有所帮助。两者的细微差别:
停止(事件,用户界面)
排序停止时会触发此事件。
VS
更新(event,ui)
当用户停止排序并且DOM位置发生变化时,会触发此事件。
我曾希望这会成为伎俩。我在更新后最初没有得到它,然后我确实得到了它。必须继续工作。
更新2
这个小提琴在FF和Chromium中没有错误地运行:https://jsfiddle.net/Twisty/wzuak8as/99/
我能够在创建helper
时隔离错误。我认为这个问题涉及的是这行代码:
return helper.append(elements);
所以这段代码表明我们正在返回一个jQuery对象helper
,这是一个<li>
元素作为匿名函数的结果。与此同时,我们尝试将其他jQuery对象elements
附加到<li>
元素中。
当我将代码调整为:
helper.append(elements);
return helper;
错误不再出现。
我回去看了jQuery UI 1.9.2中的相同功能:
_rearrange: function(event, i, a, hardRefresh) {
a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
//Various things done here to improve the performance:
// 1. we create a setTimeout, that calls refreshPositions
// 2. on the instance, we have a counter variable, that get's higher after every append
// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
// 4. this lets only the last addition to the timeout stack through
this.counter = this.counter ? ++this.counter : 1;
var counter = this.counter;
this._delay(function() {
if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
});
}
我无法在两个库中找到差异。我也无法找出为什么一个人没有错误而且一个人没有错误。它们应该是一样的。
在我的测试中,我能够无误地运行代码。我希望这会有所帮助,你会将其标记为答案。
开发人员工具缓存了控制台结果,我没有看到错误出现。我回到原始代码,应用了更改,并得到了同样的错误。