문제

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;
  }
}
도움이 되었습니까?

해결책

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:

$('#iframeGenerator2').contents().find('html').html(frame2HTML);

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.

다른 팁

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

var styles = '<style> .pink { color: pink; width: 100px; height: 100px; } body{background-color:#eee;}</style>';

var html = '<div class="pink">PINK!</div>';

// create iframe
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);

//add head and body
iframe.contentDocument.open();
iframe.contentDocument.write(styles);
iframe.contentDocument.write(html);
iframe.contentDocument.close();
iframe.setAttribute('seamless', 'seamless');

//check everything
console.log(iframe);
var head = $(iframe).contents().find('head')[0];
console.log(head);
var body = $(iframe).contents().find('body')[0];
console.log(body);

//remove from DOM
//document.body.removeChild(iframe);

CSS

iframe[seamless]{
    background-color: transparent;
    border: 0px none transparent;
    padding: 0px;
    overflow: hidden;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top