zaterdag 25 september 2010

AJAX Script with simultaneously sessions and execution of Javascript in loaded page

While working on a project I needed an AJAX script which works with simultaneously AJAX sessions and execution of Javascript in the loaded page. For the simultaneously AJAX sessions I found an existing script on the net which I used.

Because the page that is loaded by AJAX contains some Javascript I build a "Javascript executer" in the AJAX script, based on the information on this page. The Javascript executer in this script searches the AJAX result for "script-tags" and evaluates the content of those tags.

/*
Source #1: http://javascripthowtos.blogspot.com/2009/02/ajax-requests-class.html
Source #2: http://www.salix.gr/load_js_with_ajax

Javascript AJAX
- Works with unlimited AJAX sessions simultaneously.
- Supports Javascript in AJAX loaded page.

*/
//The parameters passed to the function are as fallows:
//url - the url of the script that we wanna request. You can use either full or relative to your server urls.
//elmnts - this is either the id of the element that will contain the response from our request, or can also be a whole array (REMOVED) of elements
//REMOVED: loadingMsg - if this parameter is set, after the request has been send, the content of the changed element(s) will be set to whatever this variable is set, i.e. "Loading! Please wait...".
//addorreplace - if parameter is set to "a" or "add" the responseText will be added to the target element. Else the responseText will replace the current value of the target element (Default = R)
function ajaxObj(url, elmnt, addorreplace)
{
 this.obj = new Object();
 
 this.url = url;
 
 this.loadInto = elmnt;
 
 if ( addorreplace == 'a' || addorreplace == 'add' )
 {
  this.addorreplace = 'a';
 }
 else
 {
  this.addorreplace = 'r';
 }
 
 //This prototype is used to create our request, send it and handle it
 this.init();
}

//Now, the prototype that creates the XMLHttpRequest that will be used for our script. 
//This function tries if different objects are available, untill it finds one that works, cause all the major browsers use different techniques to send the request
ajaxObj.prototype.create = function()
{
 try
 {
  xmlHttp = new XMLHttpRequest();
 }
 catch(e)
 {
  try
  {
   xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
  }
  catch(e)
  {
   try
   {
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
   }
   catch(e)
   {
    return false;
   }
  }
 }
 
 this.obj = xmlHttp;
}

//Now that we have the request object, we need to make sure it will be handled properly before sending it: 
ajaxObj.prototype.handle = function()
{
 var o = this.obj;
 var into = this.loadInto;
 var addorreplace = this.addorreplace;
 
 o.onreadystatechange = function() //Set an event handler that is triggered everytime the readystate of the object has changed
 {
  if(o.readyState == 4) //If the readyState is 4, the request has been completed - we can proceed with using the response
  {
   if(typeof(into) != 'object') //if we want to change just one element - set it's innerHTML equal to the response 
   {
    if ( addorreplace == 'a')
    {
     var div = document.createElement('div');
     div.innerHTML = o.responseText;
     document.getElementById(into).appendChild(div); 
    }
    else
    {
     document.getElementById(into).innerHTML = o.responseText;
    }    

    
    // Retrieve script tags and evaluate
    // Create element on the fly and insert ajax response in innerHTML so we can use getElementsByTagName on the response
    var noElement = document.createElement('div');
    noElement.innerHTML = o.responseText;
    
    var aScript = noElement.getElementsByTagName('script');
    for(x = 0; x < aScript.length; x++)
    {  
     eval(aScript[x].innerHTML);  
    } 
   }
  }
 }
}

//The important thing about the above prototype is that if we want to change more than one element, we need to put delimeters in the response. The delimeter I've chosen is "@@", as this symbols are very rarely used in the content of a web page. We have a request, we can handle it properly, the only thing left is to send it: 
//This prototype simply sends the request to the desired url
ajaxObj.prototype.send = function()
{
 this.obj.open('GET', this.url, true);
 this.obj.send(null);
}

//There's just one more prototype that's left, the one that initializes the object: 
//This prototype calls all the other ones in the proper order. It's not really necessary, cause we can just call 
//this prototypes from within the object constructor, but I use it, cause I'm planning to extend this object in the future. 
ajaxObj.prototype.init = function()
{
 this.obj = null;
 
 this.create();
 
 this.handle();
 
 this.send();
}

//To create a new request you just need to create a new ajaxObj object. Here is an example: 
//new ajaxObj('myscript.php', 'myTestElement', 'a');