While converting a script to not require jQuery, I've discovered that if I load my content (a partial html page with html and javascript) via XMLHttpRequest, the javascript in the partial page does not work. But if I load the partial using jQuery.load, it does work.
I've tried digging through jQuery's load function to see if it's doing anything special and nothing jumped out at me. I've been banging my head against the wall and searching for an answer for a couple of days now to no avail.
What am I doing wrong/how can I make it work like it does when loaded with jQuery.load?
EDIT
I got the XMLHttpRequest method to work by splitting out out my javascript from the html in the fragment and loading the javascript using the suggested technique here: . However, that still does not provide an explanation of why jQuery.load works. Is jQuery umtimately parsing the HTML and doing the same thing for any scripts it finds within the content it loads?
I've set up a plunker () with the following code that demonstrates the issue. Note: once you load the fragment with jQuery, it will continue to work and you'll have to restart the plunk for the XMLHttpRequest method to fail again.
index.html:
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery@*" data-semver="3.0.0" src=".0.0/jquery.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h3>Buttons</h3>
<div>
<input type="button" value="Load with XMLHttpRequest" onclick="loadXMLDoc('ajaxContentDiv', 'fragmentToLoad.html');"> (Links do not work if loaded this way... Script from fragmentToLoad.html not loaded in DOM?) <br/><br/>
<input type="button" value="Load with JQuery" onclick="jQuery('#ajaxContentDiv').load('fragmentToLoad.html');"> (Links will work if loaded this way)
</div>
<br/>
<br/>
<br/>
<div id="ajaxContentDiv">Content will load here...</div>
</body>
</html>
script.js:
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
document.getElementById(targetDivName).innerHTML = xmlhttp.responseText;
}
}
};
xmlhttp.send();
}
fragmentToLoad.html:
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div>
<a href="#" onclick="updateDiv('Hello World 1');">Link 1</a><br>
<a href="#" onclick="updateDiv('Hello World 2');">Link 2</a><br>
<a href="#" onclick="updateDiv('Hello World 3');">Link 3</a><br>
</div>
<script>
function updateDiv(string){
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
</script>
While converting a script to not require jQuery, I've discovered that if I load my content (a partial html page with html and javascript) via XMLHttpRequest, the javascript in the partial page does not work. But if I load the partial using jQuery.load, it does work.
I've tried digging through jQuery's load function to see if it's doing anything special and nothing jumped out at me. I've been banging my head against the wall and searching for an answer for a couple of days now to no avail.
What am I doing wrong/how can I make it work like it does when loaded with jQuery.load?
EDIT
I got the XMLHttpRequest method to work by splitting out out my javascript from the html in the fragment and loading the javascript using the suggested technique here: https://stackoverflow./a/11695198/362958. However, that still does not provide an explanation of why jQuery.load works. Is jQuery umtimately parsing the HTML and doing the same thing for any scripts it finds within the content it loads?
I've set up a plunker (https://plnkr.co/edit/wE9RuULx251C5ARnUbCh) with the following code that demonstrates the issue. Note: once you load the fragment with jQuery, it will continue to work and you'll have to restart the plunk for the XMLHttpRequest method to fail again.
index.html:
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery@*" data-semver="3.0.0" src="https://cdnjs.cloudflare./ajax/libs/jquery/3.0.0/jquery.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h3>Buttons</h3>
<div>
<input type="button" value="Load with XMLHttpRequest" onclick="loadXMLDoc('ajaxContentDiv', 'fragmentToLoad.html');"> (Links do not work if loaded this way... Script from fragmentToLoad.html not loaded in DOM?) <br/><br/>
<input type="button" value="Load with JQuery" onclick="jQuery('#ajaxContentDiv').load('fragmentToLoad.html');"> (Links will work if loaded this way)
</div>
<br/>
<br/>
<br/>
<div id="ajaxContentDiv">Content will load here...</div>
</body>
</html>
script.js:
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
document.getElementById(targetDivName).innerHTML = xmlhttp.responseText;
}
}
};
xmlhttp.send();
}
fragmentToLoad.html:
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div>
<a href="#" onclick="updateDiv('Hello World 1');">Link 1</a><br>
<a href="#" onclick="updateDiv('Hello World 2');">Link 2</a><br>
<a href="#" onclick="updateDiv('Hello World 3');">Link 3</a><br>
</div>
<script>
function updateDiv(string){
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
</script>
Share
Improve this question
edited May 23, 2017 at 12:08
CommunityBot
11 silver badge
asked Dec 12, 2016 at 22:00
JohnJohn
2454 silver badges10 bronze badges
10
-
updateDiv
function is not defined athtml
at global attribute event whendocument
is loaded. – guest271314 Commented Dec 12, 2016 at 22:08 -
1
@Barmar OP's Question is slightly more plicated than linked Question and Answers. That is, separating
html
elements withinfragmentToLoad.html
that are not<script>
from<script>
element withinfragmentToLoad.html
; also, OP needs to attachclick
event listener to eacha
element, which linked Question does not address. From perspective here, the linked Question is not an "exact duplicate". – guest271314 Commented Dec 12, 2016 at 22:45 -
1
jQuery parses the HTML and searches for
<script>
tags, and emulates them itself because assigning to.innerHTML
doesn't execute scripts. – Barmar Commented Dec 12, 2016 at 22:50 -
OP is attempting to not use jQuery. How does linked Question address attaching
click
event to dynamic<a>
elements appended todocument
? – guest271314 Commented Dec 12, 2016 at 22:50 -
3
The reason nothing in the
.load()
function jumped out at you is that it's done in the.html()
function..load()
is simply a shortcut that performs an AJAX call and then uses.html()
on the result. Finding the actual code that performs the<script>
emulation can be difficult, because it's buried way down. – Barmar Commented Dec 12, 2016 at 23:00
1 Answer
Reset to default 3You can use single .html
file, and you are on the correct track by splitting the html
content - though you can also split the html
content of a single file, rather than requesting two files. @Barmar explains the functionality of jQuery's .load()
method at this ment.
script.js
function loadXMLDoc(targetDivName, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
// create a `div` elemenent, append response to `div` element
// get specific elements by `id`, append `script` element to `document.body`
var content = document.createElement("div");
content.innerHTML = xmlhttp.responseText
var div = content.querySelector("#htmlContent");
var contentScript = content.querySelector("#contentScript");
var script = document.createElement("script");
script.textContent = contentScript.textContent;
document.getElementById(targetDivName).innerHTML = div.innerHTML;
document.body.appendChild(script);
}
}
};
xmlhttp.send();
}
fragmentToLoad.html
<div id="htmlContent">
<div id="divToBeUpdated">
<span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div class="links">
<a href="#">Link 1</a>
<br>
<a href="#">Link 2</a>
<br>
<a href="#">Link 3</a>
<br>
</div>
</div>
<script type="text/javascript" id="contentScript">
function updateDiv(string) {
var stringBox = document.getElementById('stringBox');
stringBox.innerHTML = string;
}
// attach `click` event to `.link a` elements here
var links = document.querySelectorAll(".links a");
for (var i = 0; i < links.length; i++) {
(function(link, i) {
console.log(i)
link.addEventListener("click", function(e) {
e.preventDefault();
updateDiv("Hello World " + i)
})
})(links[i], i)
}
</script>
plnkr https://plnkr.co/edit/7fLtGRSV7WlH2enLbwSW?p=preview