2005-07-20 10:07:47 +02:00
< ? 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 ()
{
2005-07-27 12:04:52 +02:00
$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\ " ?> ";
2005-07-20 10:07:47 +02:00
$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 );
}
2005-07-27 12:04:52 +02:00
header ( " Content-type: text/xml; charset= $this->charset " );
2005-07-20 10:07:47 +02:00
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
?>