/**
*>*************************************************************************<
* Copyright (C) 2006  Ed Cradock
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
* Name : Simplejax Access Library
* Author : Ed Cradock <ed.spam.me+simplejax@gmail.com
* Modified : 10 October 2006
* Version : v1.3
* 
* Method : __construct
*
* @param string uri - URI associated to page for data retrieval
* @param object callback - Callback function for successful data retrieval
* @param +object errorHandler - Callback function for error handler
*
* @return void
*
* Description:
* Simplejax library for clean page requests. Supports both POST and GET.
*>**************************************************************************<
*/
function simplejax(uri, callback, errorHandler)
{
   /* Default error handler, can be overloaded */
   if(typeof(errorHandler) == 'function')
   this.error = errorHandler;
   else simplejax.prototype.error = function(context){alert(context);}
   
   this.uri = uri;                  // Uri to retrieve
   this.methodType = 'GET';         // Method type
   this.postArgs = false;           // Post arguments
   this.returnXML = false;          // Return XML flag
   this.json = false;
   
   this.callback = callback;        // Callback function
   this.cbArgs = new Array();        // Callback arguments
   this.errorHandler = this.error;  // Error handler callback
   
   this.source = false;             // Internal buffer for source
   this.http = false;               // HTTP request object
}

/**
*>***************************************************************<
* Method : construct
* Access : PRIVATE
*
* @param void
*
* @return object ^ bool
*
* Description:
* Object creation method, privately accessed, handles both ActiveX
* and Netscape's proprietary object
*>***************************************************************<
*/
simplejax.prototype.construct = function()
{
   var reqObj = false;
   try{reqObj = new ActiveXObject("Microsoft.XMLHTTP");}
   catch(e){reqObj = new XMLHttpRequest()}

   if(reqObj)
   {
      reqObj.open(this.methodType, this.uri, true);

      if(this.methodType == 'POST')
      {
         reqObj.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
         var post = true;
      }
     
      reqObj.send((post == true && this.postArgs != false) ? this.postArgs : null);

      post = false; this.postArgs = false; this.methodType = 'GET';

      return reqObj;
   }
   else
      this.errorHandler.call(this, 'Failure to create HTTP Request Object, please use a supported browser.');
}

/**
*>***************************************************************<
* Method : set
* Access : PUBLIC 
*
* @param enum option - set option
* @param mixed value - Value for option
* @param +string argument - POST argument string
*
* @return void
*
* Description:
* Set options, values are saved in reserved buffer variables and
* are accessed when invoke method is invoked.
* 
* Extra:
* Available options:
* string URL - Assign a new url
* object CALLBACK - Assign a new callback function
* mixed ARGUMENT - Provide the value to an argument in the callback
* enum(GET,POST) METHOD - second parameter is the post arguments
* bool XML - Return content type as XML
* bool JSON - Parse as JSON and return object
*>***************************************************************<
*/
simplejax.prototype.set = function(option, value, argument)
{
   option = option.toLowerCase(); 
   switch(option)
   {
      case 'url':
      this.uri = value;
      break;

      case 'callback':
      this.callback = value;
      break;

      case 'argument':
      this.cbArgs.push(value);
      break;

      case 'method':
      value = value.toUpperCase();
      this.methodType = (value != 'POST') ? 'GET' : value;
      this.postArgs = argument;
      break;

      case 'form':
      var element = document.getElementById(value);
      var exists = eval(element);
      if(!exists)
      {
         this.errorHandler.call(this, 'Form ' + value + ' does not exist!');
         break;
      }

      var argumentsA = new Array();
      for(var i = 0; i <= element.elements.length-1; i++)
      {
         if(element.elements[i].name == '') continue;
         argumentsA.push(element.elements[i].name + '=' + escape(element.elements[i].value));
      }

      this.methodType = element.method.toUpperCase();
      this.postArgs = argumentsA.join('&');
      break;

      case 'xml':
      this.returnXML = (value != true) ? false : value;
      break;

      case 'json':
      this.json = (value != true) ? false : value;
      break;

      default:
      this.errorHandler.call(this, 'Invalid option ' + option);
   }
}

/**
*>***************************************************************<
* Method : invoke
* Access : PUBLIC 
*
* @param +mixed options - arguments to provide to callback
*
* @return void ^bool
*
* Description:
* Invoke object creation and establish callback.
*>***************************************************************<
*/
simplejax.prototype.invoke = function()
{
   // Build optional argument values
   for(var i = 0; i <= arguments.length-1; i++)
      this.cbArgs.push(arguments[i]);

   simplejax.http = simplejax.construct();

   if(typeof(simplejax.http) != undefined)
      simplejax.http.onreadystatechange = simplejax.getsource;
   else
      return false;
}

/**
*>****************************************************************<
* Method : getsource
* Access : PRIVATE 
*
* @param void 
*
* @return void
*
* Description:
* Retrieves source of URI and stores in associated reserved buffer
* variable and invokes callback function.
*>****************************************************************<
*/
simplejax.prototype.getsource = function()
{
   if(simplejax.http.readyState == 4)
   {
      if(simplejax.http.status == 200)
      {
         if(simplejax.returnXML === true)
            simplejax.source = simplejax.http.responseXML;
         else if(simplejax.json == true)
            simplejax.source = eval(simplejax.http.responseText);
         else
            simplejax.source = simplejax.http.responseText;
   
         simplejax.http = false;

         if(simplejax.cbArgs.length > 0)
         {
            simplejax.cbArgs.unshift(simplejax.source);
            simplejax.callback.apply(this, simplejax.cbArgs);
         }else
            simplejax.callback.call(this, simplejax.source);
      }
      else
         simplejax.error.call(this, 'Status returned : ' + simplejax.http.status);

      simplejax.cbArgs = new Array();
   }
}
