Reputation: 404
This is a very common question in here related to AJAX, but I can't seem to find one for my case, because most of them used jQuery, and other reasons. Probably mine isn't efficient/recommended, but either way, here we go.
I have a button [let's say we have a reference to it for the sake of it called btn
].
It listens for a clicking event. When the user clicks the button, it makes an AJAX request to a .txt file present in the same directory the main HTML/CSS/JS file is. Let's call it test.txt
.
Now, it changes the <html>
's innerHTML(not the head/body, the html), and the innerHTML is the response from the AJAX request.
test.txt
holds HTML code. And within that HTML code there's <script src="another-js-file.js">
.
This doesn't get executed, this is the problem.
Before you scream at me INNERHTML DOESN'T EXECUTE ANY SCRIPTS I know that. I've seen other answers saying to create a <script>
tag within a div that's within yet another div, but it doesn't seem to work with external js files, and the solutions indeed used innerHTML.
Okay, here's a sketch:
btn.onclick = function(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState = XMLHttpRequest.DONE){
document.documentElement.innerHTML = this.responseText;
}
}
xhr.open("GET", "./test.txt");
xhr.send();
}
Where test.txt
holds:
<head>
<title>Document</title>
<link rel="stylesheet" href="test.css">
<script src="another-js-file.js"></script>
</head>
<body>
<h1>Hello World!</h1>
</body>
No jQuery.
Upvotes: 0
Views: 845
Reputation: 338
I noticed in your initial XHR request you wrote:
if(xhr.readyState = XMLHttpRequest.DONE)
This should actually be triple === not the single one.
Add this function to your initial JS file where you make the XHR request,
function setInnerHtml(el, html) {
el.innerHTML = html;
// Get all the scripts from the new HTML
const scripts = el.querySelectorAll('script');
// Loop through all the scripts
for (let i = 0; i < scripts.length; i++)
{
// Create a new script
const s = document.createElement('script');
// Go through all the attributes on the script
for (let j = 0; j < scripts[i].attributes.length; j++) {
const a = scripts[i].attributes[j];
// Add each attribute to the new script
s.setAttribute(a.name, a.value);
}
// Incase there is code inside the script tag
// Example: <script>alert</script>
s.innerHTML = scripts[i].innerHTML;
// Append the new script to the head (you could change this to the end of the body as well)
document.head.appendChild(s);
}
}
Then when you go to set the innerHTML of the root document object, use the above function instead.
if(xhr.readyState === XMLHttpRequest.DONE){
setInnerHtml(document.documentElement, this.responseText);
}
Upvotes: 1
Reputation: 404
I found that by creating a script element and setting its source to "another-file.js" like this worked:
var script = document.createElement("script");
script.src = "test.js";
document.body.appendChild(script);
THIS GOES AFTER document.documentElement.innerHTML = this.responseText;
Upvotes: 1