jQuery UI Sortable with multiple elements throws "TypeError: Cannot read property 'insertBefore' of null"
jQuery UI Sortable with multiple elements throws "TypeError: Cannot read property 'insertBefore' of null"
我正在尝试按照 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 中找不到任何关于可能破坏该脚本的更改的提示。
很遗憾,我无法更改我正在处理的项目中的版本。有没有可能让它与提到的版本一起工作?
那么问题的根源就在这里:
_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 Property
Return Value: A Node object, representing the parent node of a node, or null if the node has no parent
好的,所以我们确定 i.item[0].parentNode
正在重新调整 null
值并导致问题。
我怀疑问题的症结在于 helper
没有包装器,因此 stop
中的每个项目都没有 parent
;因此,没有 parentNode
。我认为解决方法是删除 1 个项目,然后在其后追加其他元素,或者在另一个回调事件中追加元素。
一旦我有更多信息,我会更新这个。
同样,这并不总是一个问题,到目前为止,这只是基于 Chrome 的浏览器中的一个问题。
更新 1
看起来将此从 stop
切换到 update
回调有所帮助。两者细微差别:
stop( event, ui )
This event is triggered when sorting has stopped.
VS
update( event, ui )
This event is triggered when the user stopped sorting and the DOM position has changed.
我曾希望这就是诀窍。更新后我最初没有得到它,然后我确实得到了它。将不得不继续工作。
更新 2
这个 fiddle 在 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
});
}
我找不到这两个库的区别。我也无法找出为什么一个操作没有错误而另一个没有。他们应该是一样的。
在我的测试中,我已经能够运行代码没有错误。希望对您有所帮助,您会将其标记为答案。
开发人员工具正在缓存控制台结果,但我没有看到错误出现。我返回到您的原始代码,应用了更改,但得到了同样的错误。
据我所知,问题是调用 parentNode.insertBefore
的元素是被拖动的元素之一(已从原始 table 中删除),因此确实不再有 parent。
真正让我明白的是,我认为问题不直接出在 helper
或 stop
函数中,而是介于两者之间,因为错误在 sort
之后立即被触发-事件。
我不知道这个问题是从哪里产生的,因为它在旧版本上运行,但通过反复试验,我可能找到了解决您问题的方法。
您可以隐藏它们并在将删除的元素插入列表后删除隐藏的元素,而不是删除您的助手中的元素。
参见 twistys fiddle I just updated。
这可能会解决您的问题,尽管这并不能解决(甚至找不到)导致此问题的原因。
我正在尝试按照 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 中找不到任何关于可能破坏该脚本的更改的提示。
很遗憾,我无法更改我正在处理的项目中的版本。有没有可能让它与提到的版本一起工作?
那么问题的根源就在这里:
_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 Property
Return Value: A Node object, representing the parent node of a node, or null if the node has no parent
好的,所以我们确定 i.item[0].parentNode
正在重新调整 null
值并导致问题。
我怀疑问题的症结在于 helper
没有包装器,因此 stop
中的每个项目都没有 parent
;因此,没有 parentNode
。我认为解决方法是删除 1 个项目,然后在其后追加其他元素,或者在另一个回调事件中追加元素。
一旦我有更多信息,我会更新这个。
同样,这并不总是一个问题,到目前为止,这只是基于 Chrome 的浏览器中的一个问题。
更新 1
看起来将此从 stop
切换到 update
回调有所帮助。两者细微差别:
stop( event, ui )
This event is triggered when sorting has stopped.
VS
update( event, ui )
This event is triggered when the user stopped sorting and the DOM position has changed.
我曾希望这就是诀窍。更新后我最初没有得到它,然后我确实得到了它。将不得不继续工作。
更新 2
这个 fiddle 在 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
});
}
我找不到这两个库的区别。我也无法找出为什么一个操作没有错误而另一个没有。他们应该是一样的。
在我的测试中,我已经能够运行代码没有错误。希望对您有所帮助,您会将其标记为答案。
开发人员工具正在缓存控制台结果,但我没有看到错误出现。我返回到您的原始代码,应用了更改,但得到了同样的错误。
据我所知,问题是调用 parentNode.insertBefore
的元素是被拖动的元素之一(已从原始 table 中删除),因此确实不再有 parent。
真正让我明白的是,我认为问题不直接出在 helper
或 stop
函数中,而是介于两者之间,因为错误在 sort
之后立即被触发-事件。
我不知道这个问题是从哪里产生的,因为它在旧版本上运行,但通过反复试验,我可能找到了解决您问题的方法。
您可以隐藏它们并在将删除的元素插入列表后删除隐藏的元素,而不是删除您的助手中的元素。
参见 twistys fiddle I just updated。
这可能会解决您的问题,尽管这并不能解决(甚至找不到)导致此问题的原因。