I want to create a totally encapsulated sub-document in JavaScript, with its own <head>
, <body>
, styles, html, and js. Basically a shadow dom, or an iframe, but without an src attribute.
Though I love the idea of shadow dom, its support is very low, and thus is not ready for prime time.
So I have been working on creating an iframe, but have been hitting various road-blocks along the way. Here is a jsFiddle demonstrating my various attempts.
The iframe cannot exist in the dom. This part is critical. To clarify, it is okay if it momentarily exists in the dom, but it must be able to be extracted and exist only in JS.
$('body').append('<iframe id="iframeGenerator" />');
var iframe3 = $('#iframeGenerator');
var iframe3Contents = iframe3.contents();
$('#iframeGenerator').remove();
var head = iframe3.contents().find('head');
sweet, we have the head
console.log(head.length);
but what do the contents look like?
console.log(iframe3Contents.get(0));
It is a document, but not inside of an element so lets try to put it in the dom or inside of another element? both of the following attempts don't work because the selector has no context or something ...
$('body').append(iframe3Contents);
var generatedIframe = $('<iframe />').append(iframe3Contents);
I would love to be able to create the iframe / subdocuemnt without appending anything to the dom... but if I must, I would still like to be able to subsequently remove it from the dom and manage it further in js.
I have this little function, which doesn't work, but illustrates the kind of iframe or subdocument generator I would like to create
var iframeHtml;
giveMeIframe = function() {
var iframeContents;
if (iframeHtml) {
return iframeHtml;
} else {
$('body').append('<iframe id="iframeGenerator" style="display: none" />');
iframeContents = $('#iframeGenerator').contents();
iframeHtml = $('<iframe />');
iframeHtml.append(iframeContents);
$('#iframeGenerator').remove();
return iframeHtml;
}
}
I played around with your fiddle and was able to get it working. I'm using seamless (only Chrome) to make it behave more in line with what you're looking for and I have a CSS fallback for other browsers.
As a note, the iframe needs to be added to the DOM before you start editing it's contents(adding styles and body). You can remove afterwards
document.body.removeChild(iframe);
.There is still a lot you can do to make it behave very similarly to a shadow DOM element, this presentation will help you out Seamless iframes: The future, today!
JS
CSS
To access info from the frame (or write to the frame), it must be in the DOM. It can be hidden, but it still must live in the frames object. JQuery is accessing the iFrame through the frames object and when removed from the dom, it's removed from the frames object
For future reference to anyone stumbling across this question, you can get the encapsulation like so:
Here's an example: http://jsfiddle.net/yP34y/4/
In the jsfiddle example, notice everything only works after it's been added to the DOM.