function ajaxSend(url, callback){
// we use a javascript feature here called "inner functions"
// using these means the local variables retain their values after the outer function
// has returned. this is useful for thread safety, so
// reassigning the onreadystatechange function doesn't stomp over earlier requests.

   function ajaxBindCallback(){
      if (ajaxRequest.readyState == 4) {
         if (ajaxRequest.status == 200) {
            if (ajaxCallback){
               ajaxCallback(ajaxRequest.responseXML);
            } else {
               alert('no callback defined');
            }
         } else {
            alert("There was a problem retrieving the xml data:\n" + ajaxRequest.status + ":\t" + ajaxRequest.statusText + "\n" + ajaxRequest.responseText);
         }
      }
   }

   // use a local variable to hold our request and callback until the inner function is called...
   var ajaxRequest = null;
   var ajaxCallback = callback;

   // bind our callback then hit the server...
   if (window.XMLHttpRequest) {
      // moz et al
      ajaxRequest = new XMLHttpRequest();
      ajaxRequest.onreadystatechange = ajaxBindCallback;
      ajaxRequest.open("GET", url, true);
      ajaxRequest.send(null);
   } else if (window.ActiveXObject) {
      // ie
      ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
      if (ajaxRequest) {
         ajaxRequest.onreadystatechange = ajaxBindCallback;
         ajaxRequest.open("GET", url, true);
         ajaxRequest.send();
      }
   }
}