4

I'll preface this by saying that I already solved this issue by fundamentally changing my approach. But in the process of solving it, I put together a test case that fascinates and vexes me.

I have a string returned from an AJAX call. The string contains HTML, most of which is useless. I want one element from the string (and all its children) inserted into the DOM. A simulation of this is:

<!DOCTYPE html>
<html>
<head>
    <title>wtf?</title>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script>
        $(document).ready(function() {
            var markup = '<div class="junk"><div class="good"><time datetime="2013-03-29">March 29, 2013</time></div></div>',
                output = $(markup).find('.good').clone().wrap('<div />').parent().html();

            $('body').append(output);
        });
    </script>
</head>

<body></body>
</html>

I have a hosted copy of this file up here: http://alala.smitelli.com/temp/wtf_ie.html (won't be up forever).

What this should do is extract the .good div and the child <time> element, then insert them into the body. I do .wrap().parent() to extract the element I selected in addition to its children (see this question). The .clone() and .html() are contrivances that demonstrate the problem.

To the user, it should show today's date. And it works in Chrome, Firefox, IE9, etc.:

March 29, 2013

But in IE7 and 8, the displayed text is:

<:time datetime="2013-03-29">March 29, 2013

The opening < is shown, and a colon has somehow been inserted. The closing </time> tag looks unaffected, and is not shown escaped.

What's going on here? Is this some sort of bug, or an expected behavior? Where is the colon coming from?

EDIT: As far as suggestions to add document.createElement('time') or html5shiv, neither of those seemed to change the behavior.

Community
  • 1
  • 1
smitelli
  • 6,835
  • 3
  • 31
  • 53
  • 2
    That is an HTML5 feature. I believe you'll need to use the html5shiv library to allow older browsers to support it – Ian Mar 29 '13 at 18:13
  • 1
    I'm surprised to find that adding `document.createElement('time')` doesn't fix it, at least not on IE7: http://jsbin.com/ifoxed/1 I was all ready to post that as an answer, but... – T.J. Crowder Mar 29 '13 at 18:16
  • It appears to work in IE9's IE7/8 mode, but i don't have a true version to test it with. – Kevin B Mar 29 '13 at 18:22
  • @KevinB: I do. It doesn't. :-( – T.J. Crowder Mar 29 '13 at 18:22
  • @KevinB Yeah, document.createElement('time') did not help. I will amend the question to say I tried it. – smitelli Mar 29 '13 at 18:27

1 Answers1

2

Very much to my surprise, I find that if I remove jQuery from the equation in terms of actually parsing the markup, the problem goes away (on both IE7 and IE8), even without createElement('time') or a shim/shiv:

<!DOCTYPE html>
<html>
<head>
    <title>wtf?</title>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script>
        $(document).ready(function() {
          var div, markup, output;

          markup = '<div class="junk"><div class="good"><time datetime="2013-03-29">March 29, 2013</time></div></div>';

          div = document.createElement('div');
          div.innerHTML = markup;

          output = $(div).find('.good').clone().wrap('<div />').parent().html();

          $('body').append(output);
        });
    </script>
</head>

<body></body>
</html>

Live Copy | Source

The change there is that I just use the browser's own handling of innerHTML and a disconnected div to parse markup, rather than letting jQuery do it for me.

So I'd have to say this may be a problem with jQuery's handling of HTML fragments on older browsers without support for HTML5 elements. But that would be a significant claim, and significant claims require significant evidence...

But if I change these lines:

div = document.createElement('div');
div.innerHTML = markup;

output = $(div).find('.good').clone().wrap('<div />').parent().html();

to:

div = $(markup);
output = div.find('.good').clone().wrap('<div />').parent().html();

I get the problem (on both IE7 and IE8): Live Copy | Source

So it does start seeming like a jQuery issue...

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Good work :) I had a feeling that once you confirmed the html5shiv library didn't work, it had to do with jQuery's methods in some way (for whatever reason). I wish I could've tested more with native browsers – Ian Mar 29 '13 at 18:41
  • @Ian: Thanks. Yeah, it's *really* handy. Means I have a lot of VMs lying around, but sometimes, it's useful. :-) – T.J. Crowder Mar 29 '13 at 18:42
  • Yeah, I'd use more VMs too, I just don't have enough memory on my computer (and too lazy to change numbers) to add specific ones for IE :( So in your latest edits, does it fix it if you add the `document.createElement("time")` before that code (just a feeble attempt)? If not, I smell a jQuery bug to report... – Ian Mar 29 '13 at 18:46
  • @Ian: No, it doesn't matter whether you do that nor not. Probably what jQuery's doing represents a trade-off -- lots of *other* things work that might not otherwise (table fragments, or the default value in a `select` [I recall that was a Safari thing], etc., etc.), but this doesn't. If that's the case, seems a reasonable trade-off. :-) – T.J. Crowder Mar 29 '13 at 19:13