在IE和Edge中,在子窗口上调用adoptNode和importNode失败
调查结果和支持信息
感谢user4749485指出我在以下评论中遗漏的链接 。 正如制作它的人所指出的那样,这似乎是由于MS将HTMLElement转换为普通对象,然后将其传递给另一个窗口的函数,如此处所示。 我把原件放得更远,并在iframe上进行了测试,并添加了相同原点的测试。
修改了此答案中的代码以获取文档上下文。 它进一步证实了IE将任何节点从外部窗口转换为普通对象,然后将它们传递给函数的怀疑。 我用新的测试byCustomImportNode更新了这个 Plunkr。
添加了另一个测试byCustomImportNode2,它将自定义导入节点function放在目标文档上。 它确实克隆了元素,但事件没有保留。 出现我只是要做一个特例。
使用角度的另一个例子几乎可行。 打开窗口,复制内容,并在$ compile上失败。 我认为这是因为它试图使用导入或采用节点用于ngInlcude。
题
我正在尝试将元素从当前窗口移动到页面打开的新窗口。 以下方法适用于除IE和Edge之外的所有浏览器。 Edge抛出一个No such interface supported
错误,IE抛出一般错误。 这篇文章指出问题是它试图从文档片段添加多个元素。 但是,在我下面的测试代码中,我只添加一个元素,但它仍然失败。 有趣的是它在importNode
和adoptNode
调用上也失败了。 是否有任何变通方法可以保留附加的数据和监听器?
test function byHtml(){ var nwin= window.open('about:blank','',''); // Works but loses any bound listeners $(nwin.document.body).append($('#test').html()); } function byClone(){ var nwin= window.open('about:blank','',''); // Fails in Edge and IE $(nwin.document.body).append($('#test').clone()); } function byDirect(){ var nwin= window.open('about:blank','',''); var node= document.getElementById('test'); // Fails in Edge and IE nwin.document.body.appendChild(node); } function byAdoptNode(){ var nwin= window.open('about:blank','',''); // IE and Edge fail on the adoptNode var node= nwin.document.adoptNode(document.getElementById('test')); nwin.document.body.appendChild(node); } function byImportNode(){ var nwin= window.open('about:blank','',''); // IE and Edge fail on the importNode var node= nwin.document.importNode(document.getElementById('test'), true); nwin.document.body.appendChild(node); }
编辑
我试过这篇文章中列出的项目。 他们没有解决问题。
- 该页面是从服务器提供的。
- 我已经将空白字符串和URL替换为
about:blank
,并将其替换为同一服务器上的视觉空白HTML页面。 都没有解决这个问题。 - IE始终处于标准模式。 adoptNode和importNode从未定义过。 他们抛出“没有这样的界面支持”的错误。
编辑2
使用上述编辑进行Plunker测试 。 注意:在IE 11中,Plunker给出的错误与我服务器上运行的代码不同。 Plunker抛出一个不支持的方法错误。
Edge仍然会抛出No such interface supported error
解决方案并不漂亮。 您需要编译它,获取HTML内容,删除所有出现的ngInclude,将其包装在DIV中,将HTML字符串附加到新窗口,然后再次编译。
Plnkr: http ://plnkr.co/edit/aGpN3LHllU2ReHp1zG26?p = preview
$scope.window= window.open('', '', ''); var windowScope= $scope.$new(); var body= angular.element($scope.window.document.body); var contents= $compile($element.contents())(windowScope); setTimeout(function(){ // The div is needed // http://stackoverflow.com/a/38599093/631295 body.append(''+$element.html().replace(/ng-include="[^"]+"/g,'')+''); windowScope.$destroy(); windowScope= $scope.$new(); $compile(body)(windowScope); }, 1000);