JavaScript: how to load dynamic contents (HTML String, JSON) to iframe

The story

Although people are suggesting the replacement of <iframe> by <div> due to the poor usability of <iframe>,  there are still some cases that <iframe> is the only way to go.

Consider such case : you want to show a preview screen before the user hit “submit” button on a page with form (the data input page). When the preview button is hit, an ajax request is sent to the server asking a validation of the user input. Then the server either generates the preview page HTML code (if the input is valid) or error message (if the input is not valid), in JSON format. The client receives the JSON response. If the JSON is an error message, then the client alerts user the error, otherwise, presents the preview screen (the HTML codes in JSON).

All of these seem very straight forward, until the time that you are presenting the preview page HTML codes. As the preview page HTML is a full set of HTML code, including the <html>, <head> and <body>tags, and more importantly it includes a new set of CSS styles and JavaScript codes. If you present these codes inside a <div> tag, the new CSS styles and JavaScript codes will definitely interferer the CSS styles and JavaScript codes of the data input page, making the both preview screen and the data input page extremely awful.

In such case, the proper way is to present the preview screen as an independent section from the data input page. This is where <iframe> should be used instead of <div>. Everything in <iframe> is independent from its parent document, so the <iframe> can have its own <doctype>, <html>,<head>, <body>, and CSS styles and JavaScript.

The problem

However, according to the specification of <iframe>, the content of <iframe> is specified by the “src” attribute which accepts values in URL format, like “http://www.something.com/”. It cannot load dynamic HTML codes. Moreover, as <iframe> is treated like an independent section from the current page, JavaScript frameworks such as jQuery has limited ability to modify its contents: you can only select and modify the contents inside the <body> of the <iframe> contents, you can do nothing outside the <body>, not to mention the jQuery ready() function doesn’t even work properly for <iframe>.

The solution

However, after some studies on the relationship between <iframe> and its associated document contents and combined the discussion on the web, we successfully inject HTML codes into an <iframe>. Here is how we do that:

<html>
    <head>
    </head>
<body>
    <h1>Test iframe</h1>
    <iframe id="test_iframe" src="about:blank" width=400 height=400></iframe>

	<button onClick="javascript:injectHTML();">Inject HTML</button>
</body>

<script language="javascript">
function injectHTML(){

	//step 1: get the DOM object of the iframe.
	var iframe = document.getElementById('test_iframe');

	var html_string = '<html><head></head><body><p>iframe content injection</p></body></html>';

	/* if jQuery is available, you may use the get(0) function to obtain the DOM object like this:
	var iframe = $('iframe#target_iframe_id').get(0);
	*/

	//step 2: obtain the document associated with the iframe tag
	//most of the browser supports .document. Some supports (such as the NetScape series) .contentDocumet, while some (e.g. IE5/6) supports .contentWindow.document
	//we try to read whatever that exists.
	var iframedoc = iframe.document;
		if (iframe.contentDocument)
			iframedoc = iframe.contentDocument;
		else if (iframe.contentWindow)
			iframedoc = iframe.contentWindow.document;

	 if (iframedoc){
		 // Put the content in the iframe
		 iframedoc.open();
		 iframedoc.writeln(html_string);
		 iframedoc.close();
	 } else {
		//just in case of browsers that don't support the above 3 properties.
		//fortunately we don't come across such case so far.
		alert('Cannot inject dynamic contents into iframe.');
	 }

}

</script>
</html>

We have tested this code with Firefox 3.5 / 4 / 5, IE 6,7,8,9 and Chrome and fortunately all of them supports the dynamic HTML loading with this method.

12 Replies to “JavaScript: how to load dynamic contents (HTML String, JSON) to iframe”

  1. This is not working in IE 8 for me. Instead it injects to the iframe, the HTML shows outside of the iframe. the iframe is loaded with no content.. 🙁
    Do you have any idea about why it happens. I’m using IE8 64bit version

    1. I have updated the example with complete HTML and JS codes. It works in IE7/8/9 (I use the developer’s toolbar shipped with IE9 to simulate IE7 & IE8)

      Pls let me know if this new example works in your browser.

        1. You may copy the above code to a new HTML file and open it in IE. In my computer, the above codes wok in IE9, and inIE7 & 8 simulated by developer’s toolbar.

  2. Thanks, been looking for something like this. Tested working on FF9 and Chrome 16. If anyone is implementing this in their code, remember to set the iframe src to “about:blank”, or else Chrome will inject the HTML as raw text instead of actual HTML.

  3. Hi,
    Thanks, It is working. But I had problem loading a html having images as the files are pointing to different path.

    1. Would you mind posting your code here? One thing you may need to pay extra attention is that you may want to use absolute path in the img tag’s “src” attribute.

  4. What is the ‘writeIn’ (line 35) function that you use to add the string to the iframe, is this native javascript or jquery or something home-made, as I get the following error when I try this –

    -TypeError: iframedoc.writeIn is not a function

    here is my code:


    $.ajax({
    url: "hotKeyProcess.php",
    data: { 'hotKeyId' : hotKeyId },
    success: function(data){

    if ( data.error == 'false') {

    iframe = $('#view_hotkey').get(0);

    iframedoc = iframe.document;
    if (iframe.contentDocument){
    iframedoc = iframe.contentDocument;
    }
    else if (iframe.contentWindow) {
    iframedoc = iframe.contentWindow.document;
    };

    if(iframedoc){
    iframedoc.open();
    iframedoc.writeIn(data.message);
    iframedoc.close();
    };
    $('#view_dialog').dialog('open');
    }else if ( data.error == 'true' ) {
    $.msg(data.message,{live:3000,fadeTime:2000});
    }
    }
    });

    Thanks in advance for any help you can offer.

    1. Yes, writeln() is a native function call for HTML DOM document object. You may refer to this
      http://www.w3schools.com/jsref/met_doc_writeln.asp

      and this:

      http://www.htmlgoodies.com/beyond/javascript/javascript-dynamic-document-creation.html

      I would suggest you checking the object “iframe” in your code to make sure the code iframe=$(‘#view_hotkey’).get(0); does give you a DOM object (not null, false, error object or anything other than DOM object.)

      As in this line: iframedoc = iframe.document; is only valid when iframe is a DOM object.

      In my code, I use:
      var iframe = document.getElementById(‘test_iframe’);

      to make sure the iframe is a DOM object.

      Hope it helps.

    2. The function is called writeln, not writeIn. You have an ‘I’, where it should be a lowercase ‘L’. It’s writeln as in ‘write line to the iframe’, not writeIn as in ‘write in the iframe’.

Leave a Reply

Your email address will not be published. Required fields are marked *