4

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.

15
  • Rather than the brute-force approach of setting the entire HTML section, just change small pieces as needed (such as setting the HTML and style of the div only). Commented Nov 2, 2015 at 1:45
  • right now I'm looking for an answer to the specific case I described above. Otherwise I change partsi normally. Commented Nov 2, 2015 at 1:45
  • @JaromandaX did you check the codepen link? Commented Nov 2, 2015 at 1:45
  • 1
    Post a complete code example in your question please. If codepen is ever inaccessible then your question loses all value without a complete example. That said, what do you expect href='style.css' to do in your example? How is codepen going to load that stylesheet? Commented Nov 2, 2015 at 1:47
  • complete code is posted. refresh and check please. Commented Nov 2, 2015 at 1:47

2 Answers 2

3

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!

Sign up to request clarification or add additional context in comments.

4 Comments

does this do the same? (innerHtml)
Why and who is downvoting this? Is there any problem with this?
@Mia Yes, jQuery's html should behave as a getter or setter of innerHTML. I guess I'm being downvoted by jQuery fans which don't like vanilla-js.
lol, okay, thanks. You got my vote up. However I want to understand what the problem is in my question.
0

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);

10 Comments

Ok fair enough. I tried it and that didn't work! Must have had a typo.
No worries, just don't be too quick to downvote next time. :)
@GuybrushThreepwood thanks for providing an answer --- I need the html tags in my current case. I'm loading full pages via ajax in the production version, this is just an oversimplified example.
also if you remove the link element it starts working. The main purpose of the question for me is to understand the reason of this behavior as well as finding the best answer
@GuybrushThreepwood almost exactly my case. I just want to replace my whole html document without changing the url.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.