1

Findings and Supporting Information

Thanks to user4749485 for pointing out a link I missed in the comments below. As pointed out by the person who made it, it seems this is caused by MS converting the HTMLElement to a normal Object before passing it to a function from another window as demonstrated here. I took the original a little bit farther and tested it on an iframe as well and added tests for same origin.


Modified the code from this answer to take a document context. It further confirms the suspicion that IE converts any Nodes from external windows to a plain Object before passing them to a function. I have updated this Plunkr with the new test byCustomImportNode.

Added another test byCustomImportNode2 which puts the custom import node function on the target document. It does make a clone of the elements, but the events are not kept. Appears I'm just going to have to make a special case.


Another example using angular that almost works. Opens the window, copies the content, and fails on the $compile. I assume it's because its trying to use import or adopt node for the ngInlcude.


Question

I'm trying to move elements from the current window to a new window that the page opens. The methods below work in all browsers except IE and Edge. Edge throws a No such interface supported error and IE throws a generic error. This post states that the problem is that it's trying to add multiple elements from a document fragment. However, in my test code below, I'm only adding one element and it's still failing. What's interesting is that it also fails on the importNode and adoptNode calls. Are there any workarounds that keep the attached data and listeners?

<!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>

EDIT

I have tried the items listed in this post. They do not solve the issue.

  • The page is being served from a server.
  • I have replaced the about:blank with both a blank string and a URL to a visually blank HTML page on the same sever. Neither solved the issue.
  • IE was always in standards mode. adoptNode and importNode were never undefined. They threw "No such interface supported" errors.

EDIT 2
Plunker test with the above edits. NOTE: The Plunker gives me a different error in IE 11 than the code running on my server. The Plunker throws a method not supported error.
Edge still throws the No such interface supported error

Community
  • 1
  • 1
Knyri
  • 2,968
  • 1
  • 17
  • 24
  • [importNode](https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode) is supported since IE 9. (Main difference to adoptNode is that is clones the original node, so if you want to have it removed from the original document, you have to explicitly do so afterwards.) – CBroe Aug 02 '16 at 17:02
  • Right. However, IE and Edge throw an error on `importNode` and `adoptNode`. The error is `No such interface supported` – Knyri Aug 02 '16 at 17:10
  • 1
    It's likely "about:blank" that's causing your problem, since it's not in the same domain as your current document. Try specifying the url to a blank HTML file on your server. – Heretic Monkey Aug 02 '16 at 17:14
  • 1
    Possible duplicate of [Why does the following throw an "Object doesn't support property or method 'importNode'" in IE11?](http://stackoverflow.com/questions/28704520/why-does-the-following-throw-an-object-doesnt-support-property-or-method-impo) – Heretic Monkey Aug 02 '16 at 17:14
  • @MikeMcCaughan Did not work. I still get `No such interface supported` errors in IE and Edge. The `about:blank` is now a blank page on the server. Both pages have a valid HTML5 doctype and IE is in standards mode for both pages. – Knyri Aug 02 '16 at 18:42
  • Might be worth trying to create something on jsFiddle, using their [echo functionality](http://doc.jsfiddle.net/use/echo.html), or plunkr or whatever. Unfortunately Stack Overflow's Stack Snippets does not offer the functionality to load documents. – Heretic Monkey Aug 02 '16 at 18:57
  • Question updated with a Plunkr. – Knyri Aug 02 '16 at 19:38
  • 1
    [in this demo](https://googledrive.com/host/0B8BLd2qPPV7Xd1dfV0JtbXpMbDA/adoptNode-test.html) the source of the problem seems to be that ms-browsers conceal the HTMLImageElement tag from the popup, instead just giving [object Object]. So importNode/adoptNode reject the "object" as not being an HTML element node. or maybe this is just a related symptom. – user4749485 Aug 03 '16 at 07:05
  • you can also click the image a few times to test nested divs. same thing happens. – user4749485 Aug 03 '16 at 07:13

1 Answers1

0

The solution isn't pretty. You need to compile it, get the HTML content, remove all occurrences of ngInclude, wrap it in a DIV, append the HTML string to the new window, and compile it again.

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('<div>'+$element.html().replace(/ng-include="[^"]+"/g,'')+'</div>');
    windowScope.$destroy();
    windowScope= $scope.$new();
    $compile(body)(windowScope);
}, 1000);
Knyri
  • 2,968
  • 1
  • 17
  • 24