JQuery html() vs. innerHTML
Asked Answered
I

8

87

Can I completely rely upon jQuery's html() method behaving identical to innerHTML? Is there any difference between innerHTML and jQuery's html() method? If these methods both do the same, can I use jQuery's html() method in place of innerHTML?

My problem is: I am working on already designed pages, the pages contains tables and in JavaScript the innerHTML property is being used to populate them dynamically.

The application is working fine on Firefox but Internet Explorer fires an error: unknown runtime exception. I used jQuery's html() method and IE's error has disappeared. But I'm not sure it will work for all browsers and I'm not sure whether to replace all innerHTML properties with jQuery's html() method.

Thanks a lot.

Iguanodon answered 25/8, 2010 at 5:36 Comment(1)
use jQuery html(). I had problems with innerHTML on many occasions. And html() will works on all browsers.Americana
A
125

To answer your question:

.html() will just call .innerHTML after doing some checks for nodeTypes and stuff. It also uses a try/catch block where it tries to use innerHTML first and if that fails, it'll fallback gracefully to jQuery's .empty() + append()

Agnosticism answered 25/8, 2010 at 5:43 Comment(2)
Note that with Internet Explorer 8 (and most probably earlier) the additional checks can add a significant performance hit for large inserts, so if performance on IE is important you may want to consider using innerHTML directly.Feuilleton
A concise performance comparison: jsperf.com/innerhtml-vs-html-vs-empty-appendDominicadominical
D
17

Specifically regarding "Can I rely completely upon jquery html() method that it'll perform like innerHTML" my answer is NO!

Run this in internet explorer 7 or 8 and you'll see.

jQuery produces bad HTML when setting HTML containing a <FORM> tag nested within a <P> tag where the beginning of the string is a newline!

There are several test cases here and the comments when run should be self explanatory enough. This is quite obscure, but not understanding what's going on is a little disconcerting. I'm going to file a bug report.

<html>

    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>   

        <script>
            $(function() {

                // the following two blocks of HTML are identical except the P tag is outside the form in the first case
                var html1 = "<p><form id='form1'><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></form></p>";
                var html2 = "<form id='form1'><p><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></p></form>";

                // <FORM> tag nested within <P>
                RunTest("<FORM> tag nested within <P> tag", html1);                 // succeeds in Internet Explorer    
                RunTest("<FORM> tag nested within <P> tag with leading newline", "\n" + html1);     // fails with added new line in Internet Explorer


                // <P> tag nested within <HTML>
                RunTest("<P> tag nested within <FORM> tag", html2);                 // succeeds in Internet Explorer
                RunTest("<P> tag nested within <FORM> tag with leading newline", "\n" + html2);     // succeeds in Internet Explorer even with \n

            });

            function RunTest(testName, html) {

                // run with jQuery
                $("#placeholder").html(html);
                var jqueryDOM = $('#placeholder').html();
                var jqueryFormSerialize = $("#placeholder form").serialize();

                // run with innerHTML
                $("#placeholder")[0].innerHTML = html;

                var innerHTMLDOM = $('#placeholder').html();
                var innerHTMLFormSerialize = $("#placeholder form").serialize();

                var expectedSerializedValue = "field1=111&field2=222";

                alert(  'TEST NAME: ' + testName + '\n\n' +
                    'The HTML :\n"' + html + '"\n\n' +
                    'looks like this in the DOM when assigned with jQuery.html() :\n"' + jqueryDOM + '"\n\n' +
                    'and looks like this in the DOM when assigned with innerHTML :\n"' + innerHTMLDOM + '"\n\n' +

                    'We expect the form to serialize with jQuery.serialize() to be "' + expectedSerializedValue + '"\n\n' +

                    'When using jQuery to initially set the DOM the serialized value is :\n"' + jqueryFormSerialize + '\n' +
                    'When using innerHTML to initially set the DOM the serialized value is :\n"' + innerHTMLFormSerialize + '\n\n' +

                    'jQuery test : ' + (jqueryFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED") + '\n' +
                    'InnerHTML test : ' + (innerHTMLFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED") 

                    );
            }

        </script>
    </head>

    <div id="placeholder">
        This is #placeholder text will 
    </div>

</html>
Dollfuss answered 22/11, 2010 at 22:42 Comment(2)
I think this bug report came back as telling me I had invalid HTML with respect to what was allowed in a <P> tag - or something like that. this was quite a while ago so I'm not sure if anything changed, but this is still getting upvotes 3 years later so if anyone has anything to add please add a commentDollfuss
This is still here in IE9, just try with that: $("body").html("<p><form><div>See what I did there ?</div></form></p>");Radiotelegraph
M
8

If you're wondering about functionality, then jQuery's .html() performs the same intended functionality as .innerHTML, but it also performs checks for cross-browser compatibility.

For this reason, you can always use jQuery's .html() instead of .innerHTML where possible.

Melodramatize answered 25/8, 2010 at 6:5 Comment(1)
innerHTML is a property on document/element property and not a method.Thermit
C
6

innerHTML is not standard and may not work in some browsers. I have used html() in all browsers with no problem.

Coriecorilla answered 25/8, 2010 at 6:9 Comment(1)
it is standard now (don't know about the time the question was asked): domparsing.spec.whatwg.org/#innerhtmlTicknor
H
5

Given the general support of .innerHTML these days, the only effective difference now is that .html() will execute code in any <script> tags if there are any in the html you give it. .innerHTML, under HTML5, will not.

From the jQuery docs:

By design, any jQuery constructor or method that accepts an HTML string — jQuery(), .append(), .after(), etc. — can potentially execute code. This can occur by injection of script tags or use of HTML attributes that execute code (for example, <img onload="">). Do not use these methods to insert strings obtained from untrusted sources such as URL query parameters, cookies, or form inputs. Doing so can introduce cross-site-scripting (XSS) vulnerabilities. Remove or escape any user input before adding content to the document.

Note: both .innerHTML and .html() can execute js other ways (e.g the onerror attribute).

Hotspur answered 11/5, 2018 at 21:46 Comment(4)
Very interesting. So how can we force HTML5 to execute <script> tags when inserted?Jassy
It's a bit old but I still think another answer's solution would work well today. You could of course just use .html() if you're using jQuery.Hotspur
Now that I look at it again, that answer does miss the step of parsing script tags out of a larger html fragment. Maybe a new question/answer is in order?Hotspur
Handling of script elements: In earlier versions of jQuery, the html() method executed any <script> elements found in the HTML being set via the method. In jQuery 3.0, this behavior was changed such that any scripts present in the HTML are not executed by default, unless the third argument of the html() method is explicitly set to true.Halfblood
E
3

"This method uses the browser's innerHTML property." - jQuery API

http://api.jquery.com/html/

Ema answered 25/8, 2010 at 5:39 Comment(0)
D
0

Here is some code to get you started. You can modify the behavior of .innerHTML -- you could even create your own complete .innerHTML shim. (P.S.: redefining .innerHTML will also work in Firefox, but not Chrome -- they're working on it.)

if (/(msie|trident)/i.test(navigator.userAgent)) {
 var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
 var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
 Object.defineProperty(HTMLElement.prototype, "innerHTML", {
  get: function () {return innerhtml_get.call (this)},
  set: function(new_html) {
   var childNodes = this.childNodes
   for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
    this.removeChild (childNodes[0])
   }
   innerhtml_set.call (this, new_html)
  }
 })
}

var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)

document.body.innerHTML = ""
console.log (mydiv.innerHTML)

http://jsfiddle.net/DLLbc/9/

Derick answered 21/1, 2014 at 7:30 Comment(0)
E
0

A key difference is that jQuery's .html() method executes any inline <script> tags inside the HTML.

This was key for me as I was using a fetch request to get a response that had HTML that had <script> tags inside as part of making a modal work in WordPress. It wasn't working and I narrowed it down to .html() vs .innerHTML which I thought were identical. After console logging the response and copying it to a file and searching for <script> I found the code that was being run with .html() and not with .innerHTML.

There is also type checking as mentioned by jAndy.

For executing the scripts, check this question linked in the above comments by RedRiderX: how to run javascript in html loaded via ajax


jQuery .html() documentation, which isn't super helpful for this niche question: https://api.jquery.com/html/

Electrostatics answered 1/3, 2023 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.