I am having a problem of calling the user defined JS function after I make the AJAX call. Basically, I created couple radio buttons on the main html page. When the user clicks on one of the radio button, it will trigger the AJAX call and return another html file in the “div” content that I set in the main html page. The other html file contains a user defined JS function (e.g. “updateContent()”) which use the onclick event handler to call the function. When I’m running the app, and click on the button. I had seen the firebug was complaining the “updateContent() is not defined” error. The function itself works fine and must be defined properly. Please help me about this! Thanks.
Here is the code in the main.html page:
<script type="text/javascript">
var asyncRequest;
function getTools(url){
try
{
asyncRequest = new XMLHttpRequest();
asyncRequest.onreadystatechange = stateChange;
asyncRequest.open('GET', url, true);
asyncRequest.send(null);
}
catch (exception){
alert('Your request is failed');
}
}
function stateChange(){
if (asyncRequest.readyState == 4 && asyncRequest.status == 200){
document.getElementById('toolArea').innerHTML = asyncRequest.responseText;
}
}
</script>..............
<body>
<input type="radio" name="weight" onclick="getTools('secondTool.html')" />
<input type="radio" name="weight" onclick="getTools('thirdTool.html')" />.......
<div class = "toolArea" id = "toolArea"> </div></body>
This other html file (e.g. secondTool.html) contains the user defined JS function:
stateChange() is within the scope of getTools() so that is not an issue (not a functional one at least). The issue is that your attempting to add a script dynamically using innerHTML, which won’t work. A script tag will need to be created as a node manually and injected into the DOM apart from innerHTML, which will not execute script tags. That is why updateContent() is undefined, because it isn’t seen. This were methods such as; JQuery.html() come handy, as it actually handles the dirty work of parsing script tags for you. Otherwise, you need to do it manually.
in this example, if you put requestHandler() outside of testAjax() then the alert() will not work and you will get a “scope” error (at least in my IE8 I do)
index.htm
<script type="text/javascript">
function startAJAX(){
var xmlHttp = null;
try {
// Firefox, Opera 8.0+, Safari Browsers
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
try {
// IE Browsers v6+
xmlHttp =new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
// IE Browsers v5+
xmlHttp =new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert("Your browser does not support AJAX!");
}
}
}
return xmlHttp;
}
//==========================================
function testAjax() {
var ajaxObj = startAJAX();
if(ajaxObj == null) return;
ajaxObj.onreadystatechange=requestHandler;
var url = "formProcessor.php";
ajaxObj.open("GET",url,true);
ajaxObj.send(null);
function requestHandler() {
if(ajaxObj.readyState==4 && (ajaxObj.status == 200 || ajaxObj.status == 304)) {
alert('response = '+ajaxObj.responseText);
}
}
}
</script>
<button onclick="testAjax();">test</button>
Yes, requestHandler() will not function as intended in that case because ajaxObj is declared within testAjax(). Therefore, requestHandler() will be called but ajaxObj will be undefined within the context of requestHandler(). Which is a significant difference to the original posters code because the asyncRequest is a global, accessible to all functions. Which is what I meant by it isn’t a functional issue, though we all know the story with globals. The real issue is that the poster is trying to execute dynamic JavaScript with innerHTML, which isn’t going to work. The dynamic JavaScript either needs to be evaled or added as a script node. This is where using event bubbling can come in handle to react to a click on the element added dynamically without using eval() or some other messy technique.
Even in published AJAX examples, it’s a common mistake to refer to the request object by name. It still works when the handler is nested but can cause problems.
Just use the this reference, which will reference the request object regardless of the location of the handling function:
function stateChange(){
if (this.readyState == 4 && this.status == 200){
document.getElementById('toolArea').innerHTML = this.responseText;
}
I think “mistake” is a bit harsh because technically it is not incorrect, but I can see your suggestion is a “better” or more “flexible” way of doing it.
but either way, my preference is to embed the request handler in the calling function, especially since it is unlikely to be used elsewhere, and thus keep everything together.
When the request object is global (which it doesn’t need to be), it could get re-assigned while a previous request is pending, causing the handler of the pending request to address the properties of the wrong object.
So far what I had tried to do is created a separated js file, and put it in each of the html file. After the AJAX call, and the custom function will be called by the event handler.
I would like to know how can I handle this using jQuery or other javascript libraries.