Javascript 在IE和Edge中,在子窗口上调用adoptNode和importNode失败

Javascript 在IE和Edge中,在子窗口上调用adoptNode和importNode失败,javascript,jquery,internet-explorer,microsoft-edge,Javascript,Jquery,Internet Explorer,Microsoft Edge,调查结果和支持信息 感谢用户4749485在下面的评论中指出了一个错误。正如制作它的人所指出的,这似乎是由MS在将HtmleElement从另一个窗口传递到函数之前将其转换为普通对象引起的,如图所示。我把原始版本放远了一点,并在iframe上对其进行了测试,并添加了相同来源的测试 修改源代码以获取文档上下文。它进一步证实了IE将任何节点从外部窗口转换为普通对象,然后再将其传递给函数的怀疑。我已经更新了CustomImportNode的新测试 添加了CustomImportNode2的另一个测试

调查结果和支持信息

感谢用户4749485在下面的评论中指出了一个错误。正如制作它的人所指出的,这似乎是由MS在将HtmleElement从另一个窗口传递到函数之前将其转换为普通对象引起的,如图所示。我把原始版本放远了一点,并在iframe上对其进行了测试,并添加了相同来源的测试


修改源代码以获取文档上下文。它进一步证实了IE将任何节点从外部窗口转换为普通对象,然后再将其传递给函数的怀疑。我已经更新了CustomImportNode的新测试

添加了CustomImportNode2的另一个测试,它将自定义导入节点函数放在目标文档上。它确实克隆了元素,但没有保留事件。看来我要做个特殊的案子了


另一个几乎有效。打开窗口,复制内容,并在$compile上失败。我认为这是因为它试图为ngInlcude使用import或adopt节点


问题

我正在尝试将元素从当前窗口移动到页面打开的新窗口。以下方法适用于除IE和Edge之外的所有浏览器。Edge抛出一个
不支持的此类接口
错误,IE抛出一个通用错误。 声明问题在于它试图从一个文档片段添加多个元素。然而,在下面的测试代码中,我只添加了一个元素,但仍然失败。有趣的是,它在调用
importNode
adoptNode
时也会失败。是否存在保留附加数据和侦听器的解决方法

<!doctype html>
<html>
    <head>
        <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
    <head>
    <body>
    <div id="test">test</div>
    <button onclick="byHtml()">by html()</button>
    <button onclick="byClone()">by clone()</button>
    <button onclick="byDirect()">direct append</button>
    <button onclick="byAdoptNode()">adoptNode()</button>
    <button onclick="byImportNode()">importNode()</button>
    <script>
        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);
        }
    </script>
    </body>
</html>

测试
按html()编写
按克隆()
直接附加
adoptNode()
importNode()
函数byHtml(){
var nwin=window.open('about:blank','','');
//可以工作,但会丢失所有绑定的侦听器
$(nwin.document.body).append($('#test').html());
}
函数byClone(){
var nwin=window.open('about:blank','','');
//在Edge和IE中失败
$(nwin.document.body).append($('#test').clone());
}
函数byDirect(){
var nwin=window.open('about:blank','','');
var节点=document.getElementById('test');
//在Edge和IE中失败
nwin.document.body.appendChild(节点);
}
函数byAdoptNode(){
var nwin=window.open('about:blank','','');
//应用节点上的IE和边缘故障
var node=nwin.document.adoptNode(document.getElementById('test');
nwin.document.body.appendChild(节点);
}
函数byImportNode(){
var nwin=window.open('about:blank','','');
//IE和Edge在导入节点上失败
var node=nwin.document.importNode(document.getElementById('test'),true);
nwin.document.body.appendChild(节点);
}
编辑

我试过表中列出的项目。他们不能解决问题

  • 正在从服务器提供该页面
  • 我已经用一个空白字符串和一个指向同一服务器上一个可视空白HTML页面的URL替换了
    about:blank
    。两人都没有解决问题
  • IE总是处于标准模式。adoptNode和importNode从未定义过。他们抛出了“不支持这样的接口”错误
编辑2
通过以上编辑注意:Plunker在IE 11中给我的错误与在我的服务器上运行的代码不同。Plunker抛出一个不支持的方法错误。

Edge仍然抛出
无此接口支持的错误

解决方案不太好。您需要编译它,获取HTML内容,删除所有出现的ngInclude,将其包装在一个DIV中,将HTML字符串附加到新窗口中,然后再次编译它

Plnkr:

$scope.window=window.open(“”,“”);
var windowScope=$scope.$new();
var body=angular.element($scope.window.document.body);
var contents=$compile($element.contents())(WindowsScope);
setTimeout(函数(){
//这个部门是需要的
// http://stackoverflow.com/a/38599093/631295
body.append(“”+$element.html().replace(/ng include=“[^”]+”/g,”)+“”);
windowScope.$destroy();
WindowsScope=$scope.$new();
$compile(body)(windowScope);
}, 1000);

解决方案不太好。您需要编译它,获取HTML内容,删除所有出现的ngInclude,将其包装在一个DIV中,将HTML字符串附加到新窗口中,然后再次编译

Plnkr:

$scope.window=window.open(“”,“”);
var windowScope=$scope.$new();
var body=angular.element($scope.window.document.body);
var contents=$compile($element.contents())(WindowsScope);
setTimeout(函数(){
//这个部门是需要的
// http://stackoverflow.com/a/38599093/631295
body.append(“”+$element.html().replace(/ng include=“[^”]+”/g,”)+“”);
windowScope.$destroy();
WindowsScope=$scope.$new();
$compile(body)(windowScope);
}, 1000);

自IE 9以来一直受支持。(与adoptNode的主要区别是克隆原始节点,因此如果要将其从原始文档中删除,则必须在以后明确地执行此操作。)对。但是,IE和Edge在
importNode
adoptNode
上抛出错误。错误是
不支持此类接口
可能是“about:blank”导致了您的问题,因为它与当前文档不在同一域中。请尝试指定服务器上空白HTML文件的url。问题的根源可能是ms浏览器在弹出窗口中隐藏了HTMLImageElement标记,而只是给出了[object]。因此importNode/adoptNode拒绝“
$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('<div>'+$element.html().replace(/ng-include="[^"]+"/g,'')+'</div>');
    windowScope.$destroy();
    windowScope= $scope.$new();
    $compile(body)(windowScope);
}, 1000);