egroupware_official/phpgwapi/inc/xajax.inc.php
2005-07-27 10:04:52 +00:00

1091 lines
33 KiB
PHP

<?php
///////////////////////////////////////////////////////////////////////////////
// xajax version 0.1 beta4
// copyright (c) 2005 by J. Max Wilson
// http://xajax.sourceforge.net
//
//
// xajax is an open source PHP class library for easily creating powerful
// PHP-driven, web-based AJAX Applications. Using xajax, you can asynchronously
// call PHP functions and update the content of your your webpage without
// reloading the page.
//
// xajax is released under the terms of the LGPL license
// http://www.gnu.org/copyleft/lesser.html#SEC3
//
// 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 St, Fifth Floor, Boston, MA 02110-1301 USA
///////////////////////////////////////////////////////////////////////////////
// The xajaxResponse class is used to created responses to be sent back to your
// webpage. A response contains one or more command messages for updating your page.
// Currently xajax supports five kinds of command messages:
// * Assign - sets the specified attribute of an element in your page
// * Append - appends data to the end of the specified attribute of an element in your page
// * Prepend - prepends data to teh beginning of the specified attribute of an element in your page
// * Replace - searches for and replaces data in the specified attribute of an element in your page
// * Script - runs JavaScript
// * Alert - shows an alert box with the suplied message text
// elements are identified by their HTML id
class xajaxResponse
{
var $xml;
// Constructor
function xajaxResponse()
{
$this->charset = is_object($GLOBALS['egw']->translation) ? $GLOBALS['egw']->translation->charset() : 'UTF-8';
//error_log("xajaxResponse: charset=$this->charset");
$this->xml = "<?xml version=\"1.0\" encoding=\"$this->charset\"?>";
$this->xml .= "<xajax>";
}
// addAssign() adds an assign command message to your xml response
// $sTarget is a string containing the id of an HTML element
// $sAttribute is the part of the element you wish to modify ("innerHTML", "value", etc.)
// $sData is the data you want to set the attribute to
// usage: $objResponse->addAssign("contentDiv","innerHTML","Some Text");
function addAssign($sTarget,$sAttribute,$sData)
{
$this->xml .= "<update action=\"assign\">";
$this->xml .= "<target attribute=\"$sAttribute\">$sTarget</target>";
$this->xml .= "<data><![CDATA[$sData]]></data>";
$this->xml .= "</update>";
}
// addAppend() adds an append command message to your xml response
// $sTarget is a string containing the id of an HTML element
// $sAttribute is the part of the element you wish to modify ("innerHTML", "value", etc.)
// $sData is the data you want to append to the end of the attribute
// usage: $objResponse->addAppend("contentDiv","innerHTML","Some Text");
function addAppend($sTarget,$sAttribute,$sData)
{
$this->xml .= "<update action=\"append\">";
$this->xml .= "<target attribute=\"$sAttribute\">$sTarget</target>";
$this->xml .= "<data><![CDATA[$sData]]></data>";
$this->xml .= "</update>";
}
// addPrepend() adds an prepend command message to your xml response
// $sTarget is a string containing the id of an HTML element
// $sAttribute is the part of the element you wish to modify ("innerHTML", "value", etc.)
// $sData is the data you want to prepend to the beginning of the attribute
// usage: $objResponse->addPrepend("contentDiv","innerHTML","Some Text");
function addPrepend($sTarget,$sAttribute,$sData)
{
$this->xml .= "<update action=\"prepend\">";
$this->xml .= "<target attribute=\"$sAttribute\">$sTarget</target>";
$this->xml .= "<data><![CDATA[$sData]]></data>";
$this->xml .= "</update>";
}
// addReplace() adds an replace command message to your xml response
// $sTarget is a string containing the id of an HTML element
// $sAttribute is the part of the element you wish to modify ("innerHTML", "value", etc.)
// $sSearch is a string to search for
// $sData is a string to replace the search string when found in the attribute
// usage: $objResponse->addReplace("contentDiv","innerHTML","text","<b>text</b>");
function addReplace($sTarget,$sAttribute,$sSearch,$sData)
{
$this->xml .= "<update action=\"replace\">";
$this->xml .= "<target attribute=\"$sAttribute\">$sTarget</target>";
$this->xml .= "<search><![CDATA[$sSearch]]></search>";
$this->xml .= "<data><![CDATA[$sData]]></data>";
$this->xml .= "</update>";
}
// addClear() adds an clear command message to your xml response
// $sTarget is a string containing the id of an HTML element
// $sAttribute is the part of the element you wish to clear ("innerHTML", "value", etc.)
// usage: $objResponse->addClear("contentDiv","innerHTML");
function addClear($sTarget,$sAttribute)
{
$this->xml .= "<update action=\"clear\">";
$this->xml .= "<target attribute=\"$sAttribute\">$sTarget</target>";
$this->xml .= "</update>";
}
// addAlert() adds an alert command message to your xml response
// $sMsg is a text to be displayed in the alert box
// usage: $objResponse->addAlert("This is some text");
function addAlert($sMsg)
{
$this->xml .= "<alert><![CDATA[$sMsg]]></alert>";
}
// addScript() adds a jscript command message to your xml response
// $sJS is a string containing javascript code to be executed
// usage: $objResponse->addAlert("var x = prompt('get some text');");
function addScript($sJS)
{
$this->xml .= "<jscript><![CDATA[$sJS]]></jscript>";
}
// addRemove() adds a Remove Element command message to your xml response
// $sTarget is a string containing the id of an HTML element to be removed
// from your page
// usage: $objResponse->addRemove("Div2");
function addRemove($sTarget)
{
$this->xml .= "<update action=\"remove\">";
$this->xml .= "<target>$sTarget</target>";
$this->xml .= "</update>";
}
function addCreate($sParent, $sTag, $sId, $sType="")
{
$this->xml .= "<update action=\"create\">";
$this->xml .= "<target attribute=\"$sTag\">$sParent</target>";
$this->xml .= "<data><![CDATA[$sId]]></data>";
if ($sType != "")
$this->xml .= "<type><![CDATA[$sType]]></type>";
$this->xml .= "</update>";
}
// getXML() returns the xml to be returned from your function to the xajax
// processor on your page
// usage: $objResponse->getXML();
function getXML()
{
if (strstr($this->xml,"</xajax>") == false)
$this->xml .= "</xajax>";
return $this->xml;
}
}// end class xajaxResponse
// Communication Method Defines
if (!defined ('GET'))
{
define ('GET', 0);
}
if (!defined ('POST'))
{
define ('POST', 1);
}
// the xajax class generates the xajax javascript for your page including the
// javascript wrappers for the PHP functions that you want to call from your page.
// It also handles processing and executing the command messages in the xml responses
// sent back to your page from your PHP functions.
class xajax
{
var $aFunctions; // Array of PHP functions that will be callable through javascript wrappers
var $aFunctionRequestTypes; // Array of RequestTypes to be used with each function (key=function name)
var $sRequestURI; // The URI for making requests to the xajax object
var $bDebug; // Show debug messages true/false
var $sWrapperPrefix; // The prefix to prepend to the javascript wraper function name
var $bStatusMessages; // Show debug messages true/false
var $aObjArray; // Array for parsing complex objects
var $iPos; // Position in $aObjArray
// Contructor
// $sRequestURI - defaults to the current page
// $bDebug Mode - defaults to false
// $sWrapperPrefix - defaults to "xajax_";
// usage: $xajax = new xajax();
function xajax($sRequestURI="",$sWrapperPrefix="xajax_",$bDebug=false)
{
$this->aFunctions = array();
$this->sRequestURI = $sRequestURI;
if ($this->sRequestURI == "")
$this->sRequestURI = $this->detectURI();
$this->sWrapperPrefix = $sWrapperPrefix;
$this->bDebug = $bDebug;
}
// detectURL() returns the current URL based upon the SERVER vars
// used internally
function detectURI()
{
$aUri = array();
if (!empty($_SERVER['REQUEST_URI']))
{
$aUri = parse_url($_SERVER['REQUEST_URI']);
}
if (empty($aUri['scheme']))
{
if (!empty($_SERVER['HTTP_SCHEME']))
{
$aUri['scheme'] = $_SERVER['HTTP_SCHEME'];
}
else
{
$aUri['scheme'] = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http';
}
if (!empty($_SERVER['HTTP_HOST']))
{
if (strpos($_SERVER['HTTP_HOST'], ':') > 0)
{
list($aUri['host'], $aUri['port']) = explode(':', $_SERVER['HTTP_HOST']);
}
else
{
$aUri['host'] = $_SERVER['HTTP_HOST'];
}
}
else if (!empty($_SERVER['SERVER_NAME']))
{
$aUri['host'] = $_SERVER['SERVER_NAME'];
}
else
{
print "xajax Error: xajax failed to automatically identify your Request URI.";
print "Please set the Request URI explicitly when you instantiate the xajax object.";
exit();
}
if (empty($aUri['port']) && !empty($_SERVER['SERVER_PORT']))
{
$aUri['port'] = $_SERVER['SERVER_PORT'];
}
if (empty($aUri['path']))
{
if (!empty($_SERVER['PATH_INFO']))
{
$path = parse_url($_SERVER['PATH_INFO']);
}
else
{
$path = parse_url($_SERVER['PHP_SELF']);
}
$aUri['path'] = $path['path'];
unset($path);
}
}
$sUri = $aUri['scheme'] . '://';
if (!empty($aUri['user']))
{
$sUri .= $aUri['user'];
if (!empty($aUri['pass']))
{
$sUri .= ':' . $aUri['pass'];
}
$sUri .= '@';
}
$sUri .= $aUri['host'];
if (!empty($aUri['port']) && (($aUri['scheme'] == 'http' && $aUri['port'] != 80) || ($aUri['scheme'] == 'https' && $aUri['port'] != 443)))
{
$sUri .= ':'.$aUri['port'];
}
// And finally path, without script name
$sUri .= substr($aUri['path'], 0, strrpos($aUri['path'], '/') + 1);
unset($aUri);
return $sUri.basename($_SERVER['SCRIPT_NAME']);
}
// setRequestURI() sets the URI to which requests will be made
// usage: $xajax->setRequestURI("http://xajax.sourceforge.net");
function setRequestURI($sRequestURI)
{
$this->sRequestURI = $sRequestURI;
}
// debugOn() enables debug messages for xajax
// usage: $xajax->debugOn();
function debugOn()
{
$this->bDebug = true;
}
// debugOff() disables debug messages for xajax
// usage: $xajax->debugOff();
function debugOff()
{
$this->bDebug = false;
}
// statusMessagesOn() enables messages in the statusbar for xajax
// usage: $xajax->statusMessagesOn();
function statusMessagesOn()
{
$this->bStatusMessages = true;
}
// statusMessagesOff() disables messages in the statusbar for xajax
// usage: $xajax->statusMessagesOff();
function statusMessagesOff()
{
$this->bStatusMessages = false;
}
// setWrapperPrefix() sets the prefix that will be appended to the javascript
// wraper functions.
function setWrapperPrefix($sPrefix)
{
$this->sWrapperPrefix = $sPrefix;
}
//Dpericated. Use registerFunction();
function addFunction($sFunction,$sRequestType=POST)
{
trigger_error("xajax: the <b>addFunction()</b> method has been renamed <b>registerFunction()</b>. <br />Please use ->registerFunction('$sFunction'".($sRequestType==GET?",GET":"")."); instead.",E_USER_WARNING);
$this->registerFunction($sFunction,$sRequestType);
}
// registerFunction() registers a PHP function to be callable through xajax
// $sFunction is a string containing the function name
// $sRequestType is the RequestType (GET/POST) that should be used
// for this function. Defaults to POST.
// usage: $xajax->registerFunction("myfunction",POST);
function registerFunction($sFunction,$sRequestType=POST)
{
$this->aFunctions[] = $sFunction;
$this->aFunctionRequestTypes[$sFunction] = $sRequestType;
}
// generates the javascript wrapper for the specified PHP function
// used internally
function wrap($sFunction,$sRequestType=POST)
{
$js = "function ".$this->sWrapperPrefix."$sFunction(){xajax.call(\"$sFunction\", arguments, ".$sRequestType.");}\n";
return $js;
}
// processRequests() is the main communications engine of xajax
// The engine handles all incoming xajax requests, calls the apporiate PHP functions
// and passes the xml responses back to the javascript response handler
// if your RequestURI is the same as your web page then this function should
// be called before any headers or html has been sent.
// usage: $xajax->processRequests()
function processRequests()
{
if (!empty($_GET['xajaxjs']))
{
header("Content-type: text/javascript");
print $this->generateJavascript();
exit();
return;
}
$requestMode = -1;
$sFunctionName = "";
$aArgs = array();
$sResponse = "";
if (!empty($_GET["xajax"]))
$requestMode = GET;
if (!empty($_POST["xajax"]))
$requestMode = POST;
if ($requestMode == -1)
return;
if ($requestMode == POST)
{
$sFunctionName = $_POST["xajax"];
if (!empty($_POST["xajaxargs"]))
$aArgs = $_POST["xajaxargs"];
}
else
{
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
header("Content-type: text/xml");
$sFunctionName = $_GET["xajax"];
if (!empty($_GET["xajaxargs"]))
$aArgs = $_GET["xajaxargs"];
}
if (!in_array($sFunctionName, $this->aFunctions))
{
$objResponse = new xajaxResponse();
$objResponse->addAlert("Unknown Function $sFunctionName.");
$sResponse = $objResponse->getXML();
}
else if ($this->aFunctionRequestTypes[$sFunctionName] != $requestMode)
{
$objResponse = new xajaxResponse();
$objResponse->addAlert("Incorrect Request Type.");
$sResponse = $objResponse->getXML();
}
else
{
for ($i = 0; $i < sizeof($aArgs); $i++)
{
if (stristr($aArgs[$i],"<xjxobj>") != false)
{
$aArgs[$i] = $this->xmlToArray("xjxobj",$aArgs[$i]);
}
else if (stristr($aArgs[$i],"<xjxquery>") != false)
{
$aArgs[$i] = $this->xmlToArray("xjxquery",$aArgs[$i]);
}
}
$sResponse = call_user_func_array($sFunctionName, $aArgs);
}
header("Content-type: text/xml; charset=$this->charset");
print $sResponse;
exit();
}
// xmlToArray() takes a string containing xajax xjxobj xml or xjxquery xml
// and builds an array representation of it to pass as an argument to
// the php function being called. Returns an array.
// used internally
function xmlToArray($rootTag, $sXml)
{
$aArray = array();
$sXml = str_replace("<$rootTag>","<$rootTag>|~|",$sXml);
$sXml = str_replace("</$rootTag>","</$rootTag>|~|",$sXml);
$sXml = str_replace("<e>","<e>|~|",$sXml);
$sXml = str_replace("</e>","</e>|~|",$sXml);
$sXml = str_replace("<k>","<k>|~|",$sXml);
$sXml = str_replace("</k>","|~|</k>|~|",$sXml);
$sXml = str_replace("<v>","<v>|~|",$sXml);
$sXml = str_replace("</v>","|~|</v>|~|",$sXml);
$sXml = str_replace("<q>","<q>|~|",$sXml);
$sXml = str_replace("</q>","|~|</q>|~|",$sXml);
$this->aObjArray = explode("|~|",$sXml);
$this->iPos = 0;
$aArray = $this->parseObjXml($rootTag);
return $aArray;
}
// parseObjXml() is a recursive function that generates an array from the
// contents of $this->aObjArray. Returns an array.
// used internally
function parseObjXml($rootTag)
{
$aArray = array();
if ($rootTag == "xjxobj")
{
while(!stristr($this->aObjArray[$this->iPos],"</xjxobj>"))
{
$this->iPos++;
if(stristr($this->aObjArray[$this->iPos],"<e>"))
{
$key = "";
$value = null;
$this->iPos++;
while(!stristr($this->aObjArray[$this->iPos],"</e>"))
{
if(stristr($this->aObjArray[$this->iPos],"<k>"))
{
$this->iPos++;
while(!stristr($this->aObjArray[$this->iPos],"</k>"))
{
$key .= $this->aObjArray[$this->iPos];
$this->iPos++;
}
}
if(stristr($this->aObjArray[$this->iPos],"<v>"))
{
$this->iPos++;
while(!stristr($this->aObjArray[$this->iPos],"</v>"))
{
if(stristr($this->aObjArray[$this->iPos],"<xjxobj>"))
{
$value = $this->parseObjXml("xjxobj");
$this->iPos++;
}
else
{
$value .= $this->aObjArray[$this->iPos];
}
$this->iPos++;
}
}
$this->iPos++;
}
$aArray[$key]=$value;
}
}
}
if ($rootTag == "xjxquery")
{
$sQuery = "";
$this->iPos++;
while(!stristr($this->aObjArray[$this->iPos],"</xjxquery>"))
{
if (stristr($this->aObjArray[$this->iPos],"<q>") || stristr($this->aObjArray[$this->iPos],"</q>"))
{
$this->iPos++;
continue;
}
$sQuery .= $this->aObjArray[$this->iPos];
$this->iPos++;
}
parse_str($sQuery, $aArray);
}
return $aArray;
}
// Depricated. Use printJavascript();
function javascript($sJsURI="")
{
trigger_error("xajax: the <b>javascript()</b> method has been renamed <b>printJavascript()</b>. <br />Please use ->printJavascript(".($sJsURI==""?"":"'$sJsURI'")."); instead.",E_USER_WARNING);
$this->printJavascript($sJsURI);
}
// printJavascript() prints the xajax javascript code into your page
// it should only be called between the <head> </head> tags
// usage:
// <head>
// ...
// <?php $xajax->printJavascript();
function printJavascript($sJsURI="")
{
print $this->getJavascript($sJsURI);
}
// getJavascript() returns the xajax javascript code that should be added to
// your page between the <head> </head> tags
// usage:
// <head>
// ...
// <?php $xajax->getJavascript();
function getJavascript($sJsURI="")
{
if ($sJsURI == "")
$sJsURI = $this->sRequestURI;
$separator=strpos($sJsURI,'?')==false?'?':'&';
$html = "<script type=\"text/javascript\">var xajaxRequestUri=\"".$this->sRequestURI."\";</script>\n";
$html .= "\t<script type=\"text/javascript\" src=\"".$sJsURI.$separator."xajaxjs=xajaxjs\"></script>\n";
return $html;
}
// compressJavascript() compresses the javascript code for more efficient delivery
// used internally
// $sJS is a string containing the javascript code to compress
function compressJavascript($sJS)
{
//remove windows cariage returns
$sJS = str_replace("\r","",$sJS);
//array to store replaced literal strings
$literal_strings = array();
//explode the string into lines
$lines = explode("\n",$sJS);
//loop through all the lines, building a new string at the same time as removing literal strings
$clean = "";
$inComment = false;
$literal = "";
$inQuote = false;
$escaped = false;
$quoteChar = "";
for($i=0;$i<count($lines);$i++)
{
$line = $lines[$i];
$inNormalComment = false;
//loop through line's characters and take out any literal strings, replace them with ___i___ where i is the index of this string
for($j=0;$j<strlen($line);$j++)
{
$c = substr($line,$j,1);
$d = substr($line,$j,2);
//look for start of quote
if(!$inQuote && !$inComment)
{
//is this character a quote or a comment
if(($c=="\"" || $c=="'") && !$inComment && !$inNormalComment)
{
$inQuote = true;
$inComment = false;
$escaped = false;
$quoteChar = $c;
$literal = $c;
}
else if($d=="/*" && !$inNormalComment)
{
$inQuote = false;
$inComment = true;
$escaped = false;
$quoteChar = $d;
$literal = $d;
$j++;
}
else if($d=="//") //ignore string markers that are found inside comments
{
$inNormalComment = true;
$clean .= $c;
}
else
{
$clean .= $c;
}
}
else //allready in a string so find end quote
{
if($c == $quoteChar && !$escaped && !$inComment)
{
$inQuote = false;
$literal .= $c;
//subsitute in a marker for the string
$clean .= "___" . count($literal_strings) . "___";
//push the string onto our array
array_push($literal_strings,$literal);
}
else if($inComment && $d=="*/")
{
$inComment = false;
$literal .= $d;
//subsitute in a marker for the string
$clean .= "___" . count($literal_strings) . "___";
//push the string onto our array
array_push($literal_strings,$literal);
$j++;
}
else if($c == "\\" && !$escaped)
$escaped = true;
else
$escaped = false;
$literal .= $c;
}
}
if($inComment) $literal .= "\n";
$clean .= "\n";
}
//explode the clean string into lines again
$lines = explode("\n",$clean);
//now process each line at a time
for($i=0;$i<count($lines);$i++)
{
$line = $lines[$i];
//remove comments
$line = preg_replace("/\/\/(.*)/","",$line);
//strip leading and trailing whitespace
$line = trim($line);
//remove all whitespace with a single space
$line = preg_replace("/\s+/"," ",$line);
//remove any whitespace that occurs after/before an operator
$line = preg_replace("/\s*([!\}\{;,&=\|\-\+\*\/\)\(:])\s*/","\\1",$line);
$lines[$i] = $line;
}
//implode the lines
$sJS = implode("\n",$lines);
//make sure there is a max of 1 \n after each line
$sJS = preg_replace("/[\n]+/","\n",$sJS);
//strip out line breaks that immediately follow a semi-colon
$sJS = preg_replace("/;\n/",";",$sJS);
//curly brackets aren't on their own
$sJS = preg_replace("/[\n]*\{[\n]*/","{",$sJS);
//finally loop through and replace all the literal strings:
for($i=0;$i<count($literal_strings);$i++)
$sJS = str_replace("___".$i."___",$literal_strings[$i],$sJS);
return $sJS;
}
// generateJavascript() generates all of the xajax javascript code including the javascript
// wrappers for the PHP functions specified by the registerFunction() method and the response
// xml parser
// used internally
function generateJavascript()
{
$js = "";
if ($this->bDebug){ $js .= "var xajaxDebug=".($this->bDebug?"true":"false").";\n"; }
ob_start();
?>
function Xajax()
{
<?php if ($this->bDebug){ ?>this.DebugMessage = function(text){if (xajaxDebug) alert("Xajax Debug:\n " + text)}<?php } ?>
this.workId = 'xajaxWork'+ new Date().getTime();
this.depth = 0;
//Get the XMLHttpRequest Object
this.getRequestObject = function()
{
<?php if ($this->bDebug){ ?>this.DebugMessage("Initializing Request Object..");<?php } ?>
var req;
try
{
req=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
req=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e2)
{
req=null;
}
}
if(!req && typeof XMLHttpRequest != "undefined")
req = new XMLHttpRequest();
<?php if ($this->bDebug){ ?>if (!req) this.DebugMessage("Request Object Instantiation failed.");<?php } ?>
return req;
}
// xajax.$() is shorthand for document.getElementById()
this.$ = function(sId)
{
return document.getElementById(sId);
}
// xajax.getFormValues() builds a query string XML message from the elements of a form object
this.getFormValues = function(frm)
{
var objForm;
if (typeof(frm) == "string")
objForm = this.$(frm);
else
objForm = frm;
var sXml = "<xjxquery><q>";
if (objForm && objForm.tagName == 'FORM')
{
var formElements = objForm.elements;
for( var i=0; i < formElements.length; i++)
{
if ((formElements[i].type == 'radio' || formElements[i].type == 'checkbox') && formElements[i].checked == false)
continue;
var name = formElements[i].name;
if (name)
{
if (sXml != '<xjxquery><q>')
sXml += '&';
sXml += name+"="+encodeURIComponent(formElements[i].value);
}
}
}
sXml +="</q></xjxquery>";
return sXml;
}
// Generates an XML message that xajax can understand from a javascript object
this.objectToXML = function(obj)
{
var sXml = "<xjxobj>";
for (i in obj)
{
try
{
if (i == 'constructor')
continue;
if (obj[i] && typeof(obj[i]) == 'function')
continue;
var key = i;
var value = obj[i];
if (value && typeof(value)=="object" &&
(value.constructor == Array
) && this.depth <= 50)
{
this.depth++;
value = this.objectToXML(value);
this.depth--;
}
sXml += "<e><k>"+key+"</k><v>"+value+"</v></e>";
}
catch(e)
{
<?php if ($this->bDebug){ ?>this.DebugMessage(e);<?php } ?>
}
}
sXml += "</xjxobj>";
return sXml;
}
// Sends a XMLHttpRequest to call the specified PHP function on the server
this.call = function(sFunction, aArgs, sRequestType)
{
var i,r,postData;
if (document.body)
document.body.style.cursor = 'wait';
<?php if ($this->bStatusMessages == true){?>window.status = 'Sending Request...';<?php } ?>
<?php if ($this->bDebug){ ?>this.DebugMessage("Starting xajax...");<?php } ?>
var xajaxRequestType = sRequestType;
var uri = xajaxRequestUri;
var value;
switch(xajaxRequestType)
{
case <?php print GET; ?>:{
var uriGet = uri.indexOf("?")==-1?"?xajax="+encodeURIComponent(sFunction):"&xajax="+encodeURIComponent(sFunction);
for (i = 0; i<aArgs.length; i++)
{
value = aArgs[i];
if (typeof(value)=="object")
value = this.objectToXML(value);
uriGet += "&xajaxargs[]="+encodeURIComponent(value);
}
uriGet += "&xajaxr=" + new Date().getTime();
uri += uriGet;
postData = null;
} break;
case <?php print POST; ?>:{
postData = "xajax="+encodeURIComponent(sFunction);
postData += "&xajaxr="+new Date().getTime();
for (i = 0; i <aArgs.length; i++)
{
value = aArgs[i];
if (typeof(value)=="object")
value = this.objectToXML(value);
postData = postData+"&xajaxargs[]="+encodeURIComponent(value);
}
} break;
default:
alert("Illegal request type: " + xajaxRequestType); return false; break;
}
r = this.getRequestObject();
r.open(xajaxRequestType==<?php print GET; ?>?"GET":"POST", uri, true);
if (xajaxRequestType == <?php print POST; ?>)
{
try
{
r.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
catch(e)
{
alert("Your browser does not appear to support asynchronous requests using POST.");
return false;
}
}
r.onreadystatechange = function()
{
if (r.readyState != 4)
return;
if (r.status==200)
{
<?php if ($this->bDebug){ ?>xajax.DebugMessage("Received:\n" + r.responseText);<?php } ?>
var data = r.responseXML;
if (data)
xajax.processResponse(data);
}
}
<?php if ($this->bDebug){ ?>this.DebugMessage("Calling "+sFunction +" uri="+uri+" (post:"+ postData +")");<?php } ?>
r.send(postData);
<?php if ($this->bStatusMessages == true){?>window.status = 'Waiting for data...';<?php } ?>
<?php if ($this->bDebug){ ?>this.DebugMessage(sFunction + " waiting..");<?php } ?>
delete r;
return true;
}
// Tests if the new Data is the same as the extant data
this.willChange = function(element, attribute, newData)
{
var oldData;
if (attribute == "innerHTML")
{
tmpXajax = this.$(this.workId);
if (tmpXajax == null)
{
tmpXajax = document.createElement("div");
tmpXajax.setAttribute('id',this.workId);
tmpXajax.style.display = "none";
tmpXajax.style.visibility = "hidden";
document.body.appendChild(tmpXajax);
}
tmpXajax.innerHTML = newData;
newData = tmpXajax.innerHTML;
}
eval("oldData=document.getElementById('"+element+"')."+attribute);
if (newData != oldData)
return true;
return false;
}
//Process XML xajaxResponses returned from the request
this.processResponse = function(xml)
{
<?php if ($this->bStatusMessages == true){?> window.status = 'Recieving data...'; <?php } ?>
var tmpXajax = null;
xml = xml.documentElement;
for (i=0; i<xml.childNodes.length; i++)
{
if (xml.childNodes[i].nodeName == "alert")
{
if (xml.childNodes[i].firstChild)
alert(xml.childNodes[i].firstChild.nodeValue);
}
if (xml.childNodes[i].nodeName == "jscript")
{
if (xml.childNodes[i].firstChild)
eval(xml.childNodes[i].firstChild.nodeValue);
}
if (xml.childNodes[i].nodeName == "update")
{
var action;
var element;
var attribute;
var search;
var data;
var type;
var objElement;
for (j=0; j<xml.childNodes[i].attributes.length; j++)
{
if (xml.childNodes[i].attributes[j].name == "action")
{
action = xml.childNodes[i].attributes[j].value;
}
}
var node = xml.childNodes[i];
for (j=0;j<node.childNodes.length;j++)
{
if (node.childNodes[j].nodeName == "target")
{
for (k=0; k<node.childNodes[j].attributes.length; k++)
{
if (node.childNodes[j].attributes[k].name == "attribute")
{
attribute = node.childNodes[j].attributes[k].value;
}
}
element = node.childNodes[j].firstChild.nodeValue;
}
if (node.childNodes[j].nodeName == "search")
{
if (node.childNodes[j].firstChild)
search = node.childNodes[j].firstChild.nodeValue;
else
search = "";
}
if (node.childNodes[j].nodeName == "data")
{
if (node.childNodes[j].firstChild)
data = node.childNodes[j].firstChild.nodeValue;
else
data = "";
}
if (node.childNodes[j].nodeName == "type")
{
if (node.childNodes[j].firstChild)
type = node.childNodes[j].firstChild.nodeValue;
else
type = "";
}
}
if (action=="assign")
{
if (this.willChange(element,attribute,data))
{
eval("document.getElementById('"+element+"')."+attribute+"=data;");
}
}
if (action=="append")
eval("document.getElementById('"+element+"')."+attribute+"+=data;");
if (action=="prepend")
eval("document.getElementById('"+element+"')."+attribute+"=data+document.getElementById('"+element+"')."+attribute);
if (action=="replace")
{
eval("var v=document.getElementById('"+element+"')."+attribute);
var v2 = v.indexOf(search)==-1?v:"";
while (v.indexOf(search) > -1)
{
x = v.indexOf(search)+search.length+1;
v2 += v.substr(0,x).replace(search,data);
v = v.substr(x,v.length-x);
}
if (this.willChange(element,attribute,v2))
eval('document.getElementById("'+element+'").'+attribute+'=v2;');
}
if (action=="clear")
eval("document.getElementById('"+element+"')."+attribute+"='';");
if (action=="remove")
{
objElement = this.$(element);
if (objElement.parentNode && objElement.parentNode.removeChild)
{
objElement.parentNode.removeChild(objElement);
}
}
if (action=="create")
{
var objParent = this.$(element);
objElement = document.createElement(attribute);
objElement.setAttribute('id',data);
if (type && type != '')
objElement.setAttribute('type',type);
objParent.appendChild(objElement);
if (objParent.tagName == "FORM")
{
}
}
}
}
document.body.style.cursor = 'default';
<?php if ($this->bStatusMessages == true){?> window.status = 'Done'; <?php } ?>
}
}
var xajax = new Xajax();
<?php
$js .= ob_get_contents()."\n";
ob_end_clean();
foreach($this->aFunctions as $sFunction)
$js .= $this->wrap($sFunction,$this->aFunctionRequestTypes[$sFunction]);
if ($this->bDebug == false)
$js = $this->compressJavascript($js);
print $js;
}
}// end class xajax
?>