views:

138

answers:

2

I have a script that loads info from external XML file and inserts it into the HTML page on click. Here's the code of this script:

  var xmlhttp;
function loadXMLDoc(url,target) {
xmlhttp = null;
if (window.XMLHttpRequest) { // code for all new browsers
    xmlhttp = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // code for IE5 and IE6
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
if (xmlhttp != null) {
    xmlhttp.onreadystatechange = state_Change;
    xmlhttp.open("GET", url, true);
    xmlhttp.send(null);
}
else {
    alert("Your browser does not support XMLHTTP.");
}
}
function state_Change() {
if (xmlhttp.readyState == 4) { // 4 = "loaded"
    if (xmlhttp.status == 200) { // 200 = OK    
        var markers = xmlhttp.responseXML.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
            var name = markers[i].getElementsByTagName("name")[0].firstChild.nodeValue;
            //etc...
document.getElementById(target).innerHTML += '<li>' + name + '</li>\n';
        }
    }
    else {
        alert("Problem retrieving XML data");
    }
}
}

Here's the HTML:

  <ul id="list_puncts">
<li><a href="javascript:;" onclick="loadXMLDoc('./content/geo_points/slovenia.xml','list_sl')">Republika Slovenija (RS)</a>
 <ul id="list_sl">
   <!--here should be some info from XML file-->
     </ul></li>
     <li><a href="javascript:;" onclick="loadXMLDoc('./content/geo_points/horvatia.xml','list_hr')">Republika Hrvatska (RH)</a>
    <ul id="list_hr">
    <!--here should be some info from XML file-->
    </ul></li>
   </ul>

However, it does not work - after the link is clicked, XML gets loaded (it can be seen in Firebug), but the second variable - target - cannot make its way into the state_Change function, so no real action is done. If target in document.getElementById(target).innerHTML is replaced by some static id (like list_sl), it is working, but I have many of these links in the HTML, not only Slovenia and Horvatia, so the variable is strongly needed.

Thanks for any help.

+1  A: 

Put the state_Change logic in an anonymous function within loadXMLDoc.

function loadXMLDoc(url,target) {
    // ... code to instantiate XMLHttprequest goes here ...

    if (xmlhttp != null) {
        xmlhttp.onreadystatechange = function() {
            // Your state_Change() logic goes here.
            // This has access to the variable "target" because
            // it's within the same enclosing function's scope.
        };
        xmlhttp.open("GET", url, true);
        xmlhttp.send(null);
    }
}

The drawback to this is that a new instance of the function is instantiated each time loadXMLDoc is called.

Nate
I deleted, and then undeleted this because I made a mistake in the first version. Sorry, I'm still kind of new on Stack Overflow.
Nate
This is kind of very simple solution, also worked for me, thanks Nate
certainlyakey
And it works in IE/Opera which I had problems with...
certainlyakey
+1  A: 

If you use global variables (both for XMLHttpRequests and your targets), you can't support parallel requests (i.e. a user clicks on another link before one XMLHttpRequest returns). One way to implement it is to keep the xmlhttp variable in your loadXMLDoc function's scope and add your target as a property to the XMLHttpRequest object:

function loadXMLDoc(url, target) {
    var xmlhttp;
    // create XMLHttpRequest instance
    if(xmlhttp != null) {
     xmlhttp.onreadystatechange = state_Change;
     xmlhttp.targetListId = target;
     xmlhttp.open(); // etc.
    }
};

In your state_Change function you can access the XMLHttpRequest instance using the event's target property:

function state_Change(e) {
    var xmlhttp = e.target;
    // check readystate & status

    var targetList = document.getElementById(xmlhttp.targetListId);
    targetList.innerHTML = ''; // fill with data, etc.
};
Josef
Thank you, i was already desperate to use setTimeout to make the second function wait for the first. This works flawlessly.
certainlyakey
Well, it seems it doesn't work in IE (6-7-8, all of them). Gives 'Message: 'target' is null or not an object' error.
certainlyakey
Sorry, didn't test IE and don't have one on my system. IE has many proprietary features/bugs which is why I strongly encourage you to use a Javascript library to abstract away browser differences.
Josef
Well, I use JQuery most of the time, but in this project don't want to overload the size of the resources.
certainlyakey