28

See the solution at the bottom of the question.

IE 8 (and lower) does not work good with unknown elements (ie. HTML5 elements), one cannot style them , or access most of their props. Their are numerous work arounds for this for example: http://remysharp.com/2009/01/07/html5-enabling-script/

The problem is that this works great for static HTML that was available on page load, but when one creates HTML5 elements afterward (for example AJAX call containing them, or simply creating with JS), it will mark these newly added elements them as HTMLUnknownElement as supposed to HTMLGenericElement (in IE debugger).

Does anybody know a work around for that, so that newly added elements will be recognized/enabled by IE 8?

Here is a test page:

<html><head><title>TIME TEST</title>
    <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
</head>

<body>
    <time>some time</time>
    <hr>
    <script type="text/javascript">
        $("time").text("WORKS GREAT");
        $("body").append("<time>NEW ELEMENT</time>"); //simulates AJAX callback insertion
        $("time").text("UPDATE");
    </script>
</body>
</html>

In IE you will see the: UPDATE , and NEW ELEMENT. In any other modern browser you will see UPDATE, and UPDATE

Gideon
  • 18,251
  • 5
  • 45
  • 64
  • Read my blog about how to use innerShiv and jQuery for ajaxing in HTML 5 content. http://tomcoote.co.uk/javascript/ajax-html5-in-ie/ –  Mar 05 '11 at 00:15

5 Answers5

25

for all html5 issues in IE7 i use html5shiv and to accommodate the html5 elements coming back in ajax calls i use innershiv.

these two small plugins worked for me like a charm so far.

-- Praveen Gunasekara

Scott Rippey
  • 15,614
  • 5
  • 70
  • 85
Praveen
  • 385
  • 3
  • 4
  • 2
    Just to add the reason for the HTML5 code to not work is because IE lacks of HTML5 support and recognize the HTML5 code as invalid(you will have the same if any of your tags are not closed). I had the same problem few months ago(http://ilian.i-n-i.org/internet-explorer-jquery-ajax-and-html5/) and it was really hard to find what exactly the problem was. – Ilian Iliev Jun 14 '11 at 06:49
  • Though it won't take anyone long to figure it out given the huge warning on the innershiv project page, the html5shiv project now incorporates the same polyfill for innerHTML modifications - so you no longer need innershiv. – Marcus Pope Sep 20 '12 at 23:34
  • rescued my day! For now you can just use the newest version of html5shiv, it does provide all the features u need (innershiv is obsolete). – Fabian S. Nov 28 '14 at 13:41
4

jQuery has some dark, magical ways of creating elements. Using document.createElement instead should make all the difference:

var time = document.createElement("time");
time.innerHTML = "WORKS GREAT";
document.appendChild(time);

I do not believe you can use the .append() syntax (like .innerHTML += "") with HTML5 and IE. The problem isn't IE's ability to use or display the HTML5 elements, it's its ability to parse them. Any time you programmatically instantiate an HTML5 element, you must do it with document.createElement.

mattbasta
  • 13,492
  • 9
  • 47
  • 68
  • I saw this works, but the page above was just an example, the real problem lays in the fact that these elements are loaded by ajax: $("#el").load("url"). So here your workaround doesn't apply. – Gideon Mar 02 '10 at 13:12
  • @Gidon: but again, you’re using jQuery to do your AJAX call there, right? jQuery seems to be the problem here, not AJAX. (Disclaimer: I may well be missing the point entirely.) – Paul D. Waite Mar 04 '10 at 20:52
  • @Gidon: Perhaps you can create the elements and just stick the values into them (as opposed to creating the elements by passing it in with jQuery). jQuery isn't IE-HTML5 safe, so you'll just have to load it in in that manner. Otherwise, just stick to XHTML. – mattbasta Mar 04 '10 at 20:57
  • This was indeed the only solution, yet since the ajax call return a whole set of html I had to parse it first, since document.createElement works only with one element at a time, and not a collection. I added my code in my answer. – Gideon Mar 07 '10 at 11:19
2

I too ran into trouble when fetching a bunch of HTML containing HTML5 elements from the server using AJAX. html5shiv wasn't able to save my day. My project template is based on the html5boilerplate and uses Modernizr to fix HTML5 tag behavior in IE < 9. After reading this thread I got a hunch and managed to get my code working.

The problematic code injecting the freshly squeezed HTML into the DOM was:

var wrapper = $('<div />')
    .addClass('wrapper')
    .html(data.html)
    .appendTo(wrapper);

Basically what happens here is:

  1. create a new element
  2. the innerHTML of the new element is updated
  3. the new element with its innerHTML is appended to an existing element in the DOM

Changing it to the following fixes my problem:

var wrapper = $('<div />')
    .addClass('wrapper')
    .appendTo(el);
wrapper.html(data.html);

What happens now is:

  1. create a new element
  2. the empty new element is appended to an existing element in the DOM
  3. the innerHTML of the newly appended element is updated

Now even IE7 has no choice but to display asynchronously loaded HTML5 elements like I want it to :)

Thanks Julio, will keep your plugin handy in case I need it in the future. But for now I am happy not to add the overhead of the extra DOM manipulations.

Maybe this workaround works for some other people too.

jiggybit
  • 21
  • 2
2

note that innershiv functionality is built into jquery as of 1.7 http://blog.jquery.com/2011/11/03/jquery-1-7-released/

schellmax
  • 5,678
  • 4
  • 37
  • 48
  • not sure what for you're adding the solution to the question itself. that's what the 'answers' part is for IMHO. you can mark the answer that fits best for you as 'accepted', then vote up alternatives and additions. – schellmax Nov 18 '11 at 11:11
  • I understand your point, but the person who gave the solution, pointed out to both plugins (html5shiv, and innershiv). You're just adding to the solution, saying that innershiv is part of jQuery now. People who are not using jQuery, still will be using innershiv. Since this answer is evolving all the time, I thought it would be wise to explain the solution also in the answer (happens a lot here in SO) – Gideon Nov 18 '11 at 12:43
  • hm, maybe i shouldn't have posted this as an answer but as a comment on the accepted answer. work in progress ;) – schellmax Nov 18 '11 at 21:08
0

Just leaving this to contribute to the discussion.

The script provided that @Gidon seems not working in IE8 (tested on two different machines). I had to remake the jQuery plugin in another way, see below:

/**
 * Enable HTML5 Elements on the fly. IE needs to create html5 elements every time.
 * @author Gidon
 * @author Julio Vedovatto <juliovedovatto@gmail.com>
 * @see http://stackoverflow.com/questions/2363040/how-to-enable-html5-elements-in-ie-that-were-inserted-by-ajax-call
 */
(function ($) {
    jQuery.fn.html5Enabler = function () {
        var element = this;

        if (!$.browser.msie)
            return element;

            $.each(
                ['abbr','article','aside','audio','canvas','details','figcaption','figure','footer','header','hgroup','mark','menu','meter','nav','output','progress','section','summary','time','video'],
                function() {
                    if ($(element).find(this).size() > 0) {
                        $(element).find(this).each(function(k,child){
                            var el = $(document.createElement(child.tagName));

                            for (var i = 0; i < child.attributes.length; i++)
                                el.attr(child.attributes[i].nodeName, child.attributes[i].nodeValue);

                            el.html(child.innerHTML);

                            $(child).replaceWith(el);
                        });
                    }
                }
            );
    };
})(jQuery);
Julio Vedovatto
  • 178
  • 1
  • 5
  • 13