Friday, June 8, 2012

How to "enable' HTML5 elements in IE that were inserted by AJAX call?


See the solution at the bottom of the question.



IE 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?



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


Source: Tips4all

6 comments:

  1. 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

    ReplyDelete
  2. 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.

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

    ReplyDelete
  4. 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/

    ReplyDelete
  5. 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:


    create a new element
    the innerHTML of the new element is updated
    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:


    create a new element
    the empty new element is appended to an existing element in the DOM
    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.

    ReplyDelete
  6. 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);

    ReplyDelete