简体   繁体   中英

jQuery .html() not setting content correctly?

Here is the example I prepared to tell about the problem easier.

http://codepen.io/anon/pen/EVpYXm

As you can see the initial <html> is set to display a text:

"This is the old html!"

It sets the whole content to the data in the variable myHtml . however here is what I notice:

the style is not carried from the <body> element. Moreover, the <body> element is somehow not created at all!

Here is the sring myHtml , tidied up to display as an html:

<html>
<head>
<title>Title Here</title>
<link href='style.css' rel='stylesheet' type='text/css'/>
</head>
<body style='background-color: red'>
<div>Div!</div>
</body>
</html>

I've realized that when link element is removed, everything works fine. Try it, see it yourself.

Stuck with this issue for the last few hours. Looking for a result.

Here is the full code:

page html:

<html>
  This is the old html!
</html>

javascript:

$(function(){
  var myHtml = "<html><head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body></html>"
  $("html").html(myHtml);
})

The main purpose of this question is to understand the reason of this behavior as well as finding the best solution.

The issue is that, when you use jQuery's html(val) , it does something like this:

html: function(value) {
  /* ... */
  // See if we can take a shortcut and just use innerHTML
  if ( typeof value === "string" && !rnoInnerhtml.test( value ) && /* ... */) {
    /* ... */ elem.innerHTML = value; /* ... */
  }
  /* ... */
}

That is, it checks the string with the regex rnoInnerhtml , which is

rnoInnerhtml = /<(?:script|style|link)/i

Therefore, presumably to avoid inserting stylesheets, jQuery avoids innerHTML and does complicated things with domManip .

I recommend using native innerHTML :

$("html").prop('innerHTML', myHtml);

 var myHtml = "<head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body>" $("html").prop('innerHTML', myHtml);
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> This is the old html!

Or with vanilla-js:

document.documentElement.innerHTML = myHtml;

 var myHtml = "<head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body>" document.documentElement.innerHTML = myHtml;
 This is the old html!

The problem is that you're appending an html element inside the root html element, which is undefined behavior and cannot be rendered reliably by the browser. Strip the opening and closing <html> and </html> tags from your myHtml string and it works!

Working demo

$(function() {
  var myHtml = "<head><title>Title Here</title></head><body style='background-color: red; '><div>Div!</div></body>"
  $('html').html(myHtml);
})

Alternatively, you could keep the tags and write directly to the document object instead, which opens a new stream and overwrites the previous document.

// ...
document.write(myHtml);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM