diff options
-rw-r--r-- | modules/xajax/README.txt | 106 | ||||
-rw-r--r-- | modules/xajax/xajax.inc.php | 1239 | ||||
-rw-r--r-- | modules/xajax/xajaxCompress.php | 182 | ||||
-rw-r--r-- | modules/xajax/xajaxResponse.inc.php | 580 | ||||
-rw-r--r-- | modules/xajax/xajax_js/xajax.js | 172 | ||||
-rw-r--r-- | modules/xajax/xajax_js/xajax_uncompressed.js | 795 |
6 files changed, 3074 insertions, 0 deletions
diff --git a/modules/xajax/README.txt b/modules/xajax/README.txt new file mode 100644 index 00000000..c14ad804 --- /dev/null +++ b/modules/xajax/README.txt @@ -0,0 +1,106 @@ +====================================================================
+ xajax PHP Class Library
+ The easiest way to develop asynchronous Ajax applications with PHP
+
+ Version 0.2.4 (stable release)
+ README Text File
+
+ ------------------------------------------------------
+ | Release Notes: |
+ | http://wiki.xajaxproject.org/0.2.4_Release_Notes |
+ | |
+ | Lead Developers: |
+ | Jared White (jared@intuitivefuture.com) |
+ | J. Max Wilson (jmaxwilson@users.sourceforge.net) |
+ | Eion Robb (eion@bigfoot.com) |
+ ------------------------------------------------------
+====================================================================
+
+ :: To find out what's changed since the 0.2.3 release of xajax, ::
+ :: view the Release Notes in the link above. ::
+
+1. Introduction
+
+xajax is a PHP library that you can include in your PHP scripts
+to provide an easy way for Web pages to call PHP functions or
+object methods using Ajax (Asynchronous Javascript And XML). Simply
+register one or more functions/methods with the xajax object that
+return a proper XML response using the supplied response class, add
+a statement in your HTML header to print the Javascript include,
+and run a request processor prior to outputting any HTML. Then add
+some simple Javascript function calls to your HTML, and xajax takes
+care of the rest!
+
+xajax includes a Javascript object to facilitate the communication
+between the browser and the server, and it can also be used as a
+Javascript library directly to simplify certain DOM and event
+manipulations. However, you can definitely choose to use a
+dedicated Javascript "engine" of your liking and integrate it with
+xajax's client/server communication features in a number of ways.
+More tightly-coupled integration will be forthcoming in a future
+version of xajax.
+
+2. For More Information
+
+The official xajax Web site is located at:
+http://www.xajaxproject.org
+
+Visit the xajax Forums at:
+http://community.xajaxproject.org
+to keep track of the latest news and participate in the community
+discussion.
+
+There is also a wiki with documentation, tips & tricks, and other
+information located at:
+http://wiki.xajaxproject.org
+
+3. Installation
+
+To run xajax, you need:
+* Apache Web Server or IIS for Windows XP/2003 Server
+ (other servers may or may not work and are not supported at this
+ time)
+* PHP 4.3.x or PHP 5.x
+* Minimum supported browsers: Internet Explorer 5.5, Firefox 1.0 (or
+ equivalent Gecko-based browser), Safari 1.3, Opera 8.5 (older
+ versions only work with GET requests)
+
+To install xajax:
+Unpack the contents of this archive and copy them to your main Web
+site folder. Or if you wish, you can put all of the files in a
+dedicated "xajax" folder on your Web server (make sure that you
+know what that URL is relative your site pages so you can provide
+xajax with the correct installed folder URL). Note that the
+ +"thewall" folder in the "examples" folder needs to be writable by +
+the Web server for that example to function.
+
+Within the main xajax folder there are two folders: "examples"
+and "tests". You should be able to view these PHP pages from your
+Web browser and see xajax working in action. If you can view the
+pages but the AJAX calls are not working, there may be something
+wrong with your server setup or perhaps your browser is not
+supported or configured correctly. If worst comes to worst, post
+a message in our forums and someone may be able to help you.
+
+4. Documentation
+
+Detailed documentation for the xajax PHP classes is available on
+our wiki (URL listed above in section 2), and more is on the way
+(particularly in regards to the Javascript component of xajax).
+Another good way of learning xajax is to look at the code for the
+examples and tests. If you need any help, pop in the forums and
+ask for assistance (and the more specific your questions are,
+the better the answers will be).
+
+5. Contributing to xajax
+
+xajax is released under the LGPL open source license. If you wish
+to contribute to the project or suggest new features, introduce
+yourself on the forums or you can e-mail the lead developers at
+the addresses listed at the top of this README.
+
+6. Good luck and enjoy!
+
+====================================================================
diff --git a/modules/xajax/xajax.inc.php b/modules/xajax/xajax.inc.php new file mode 100644 index 00000000..602a0493 --- /dev/null +++ b/modules/xajax/xajax.inc.php @@ -0,0 +1,1239 @@ +<?php +/** + * xajax.inc.php :: Main xajax class and setup file + * + * xajax version 0.2.4 + * copyright (c) 2005 by Jared White & J. Max Wilson + * http://www.xajaxproject.org + * + * 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 + * + * @package xajax + * @version $Id$ + * @copyright Copyright (c) 2005-2006 by Jared White & J. Max Wilson + * @license http://www.gnu.org/copyleft/lesser.html#SEC3 LGPL License + */ + +/* + ---------------------------------------------------------------------------- + | Online documentation for this class is available on the xajax wiki at: | + | http://wiki.xajaxproject.org/Documentation:xajax.inc.php | + ---------------------------------------------------------------------------- +*/ + +/** + * Define XAJAX_DEFAULT_CHAR_ENCODING that is used by both + * the xajax and xajaxResponse classes + */ +if (!defined ('XAJAX_DEFAULT_CHAR_ENCODING')) +{ + define ('XAJAX_DEFAULT_CHAR_ENCODING', 'utf-8' ); +} + +require_once(dirname(__FILE__)."/xajaxResponse.inc.php"); + +/** + * Communication Method Defines + */ +if (!defined ('XAJAX_GET')) +{ + define ('XAJAX_GET', 0); +} +if (!defined ('XAJAX_POST')) +{ + define ('XAJAX_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. + * + * @package xajax + */ +class xajax +{ + /**#@+ + * @access protected + */ + /** + * @var array Array of PHP functions that will be callable through javascript wrappers + */ + var $aFunctions; + /** + * @var array Array of object callbacks that will allow Javascript to call PHP methods (key=function name) + */ + var $aObjects; + /** + * @var array Array of RequestTypes to be used with each function (key=function name) + */ + var $aFunctionRequestTypes; + /** + * @var array Array of Include Files for any external functions (key=function name) + */ + var $aFunctionIncludeFiles; + /** + * @var string Name of the PHP function to call if no callable function was found + */ + var $sCatchAllFunction; + /** + * @var string Name of the PHP function to call before any other function + */ + var $sPreFunction; + /** + * @var string The URI for making requests to the xajax object + */ + var $sRequestURI; + /** + * @var string The prefix to prepend to the javascript wraper function name + */ + var $sWrapperPrefix; + /** + * @var boolean Show debug messages (default false) + */ + var $bDebug; + /** + * @var boolean Show messages in the client browser's status bar (default false) + */ + var $bStatusMessages; + /** + * @var boolean Allow xajax to exit after processing a request (default true) + */ + var $bExitAllowed; + /** + * @var boolean Use wait cursor in browser (default true) + */ + var $bWaitCursor; + /** + * @var boolean Use an special xajax error handler so the errors are sent to the browser properly (default false) + */ + var $bErrorHandler; + /** + * @var string Specify what, if any, file xajax should log errors to (and more information in a future release) + */ + var $sLogFile; + /** + * @var boolean Clean all output buffers before outputting response (default false) + */ + var $bCleanBuffer; + /** + * @var string String containing the character encoding used + */ + var $sEncoding; + /** + * @var boolean Decode input request args from UTF-8 (default false) + */ + var $bDecodeUTF8Input; + /** + * @var boolean Convert special characters to HTML entities (default false) + */ + var $bOutputEntities; + /** + * @var array Array for parsing complex objects + */ + var $aObjArray; + /** + * @var integer Position in $aObjArray + */ + var $iPos; + + /**#@-*/ + + /** + * Constructor. You can set some extra xajax options right away or use + * individual methods later to set options. + * + * @param string defaults to the current browser URI + * @param string defaults to "xajax_"; + * @param string defaults to XAJAX_DEFAULT_CHAR_ENCODING defined above + * @param boolean defaults to false + */ + function xajax($sRequestURI="",$sWrapperPrefix="xajax_",$sEncoding=XAJAX_DEFAULT_CHAR_ENCODING,$bDebug=false) + { + $this->aFunctions = array(); + $this->aObjects = array(); + $this->aFunctionIncludeFiles = array(); + $this->sRequestURI = $sRequestURI; + if ($this->sRequestURI == "") + $this->sRequestURI = $this->_detectURI(); + $this->sWrapperPrefix = $sWrapperPrefix; + $this->bDebug = $bDebug; + $this->bStatusMessages = false; + $this->bWaitCursor = true; + $this->bExitAllowed = true; + $this->bErrorHandler = false; + $this->sLogFile = ""; + $this->bCleanBuffer = false; + $this->setCharEncoding($sEncoding); + $this->bDecodeUTF8Input = false; + $this->bOutputEntities = false; + } + + /** + * Sets the URI to which requests will be made. + * <i>Usage:</i> <kbd>$xajax->setRequestURI("http://www.xajaxproject.org");</kbd> + * + * @param string the URI (can be absolute or relative) of the PHP script + * that will be accessed when an xajax request occurs + */ + function setRequestURI($sRequestURI) + { + $this->sRequestURI = $sRequestURI; + } + + /** + * Sets the prefix that will be appended to the Javascript wrapper + * functions (default is "xajax_"). + * + * @param string + */ + // + function setWrapperPrefix($sPrefix) + { + $this->sWrapperPrefix = $sPrefix; + } + + /** + * Enables debug messages for xajax. + * */ + function debugOn() + { + $this->bDebug = true; + } + + /** + * Disables debug messages for xajax (default behavior). + */ + function debugOff() + { + $this->bDebug = false; + } + + /** + * Enables messages in the browser's status bar for xajax. + */ + function statusMessagesOn() + { + $this->bStatusMessages = true; + } + + /** + * Disables messages in the browser's status bar for xajax (default behavior). + */ + function statusMessagesOff() + { + $this->bStatusMessages = false; + } + + /** + * Enables the wait cursor to be displayed in the browser (default behavior). + */ + function waitCursorOn() + { + $this->bWaitCursor = true; + } + + /** + * Disables the wait cursor to be displayed in the browser. + */ + function waitCursorOff() + { + $this->bWaitCursor = false; + } + + /** + * Enables xajax to exit immediately after processing a request and + * sending the response back to the browser (default behavior). + */ + function exitAllowedOn() + { + $this->bExitAllowed = true; + } + + /** + * Disables xajax's default behavior of exiting immediately after + * processing a request and sending the response back to the browser. + */ + function exitAllowedOff() + { + $this->bExitAllowed = false; + } + + /** + * Turns on xajax's error handling system so that PHP errors that occur + * during a request are trapped and pushed to the browser in the form of + * a Javascript alert. + */ + function errorHandlerOn() + { + $this->bErrorHandler = true; + } + + /** + * Turns off xajax's error handling system (default behavior). + */ + function errorHandlerOff() + { + $this->bErrorHandler = false; + } + + /** + * Specifies a log file that will be written to by xajax during a request + * (used only by the error handling system at present). If you don't invoke + * this method, or you pass in "", then no log file will be written to. + * <i>Usage:</i> <kbd>$xajax->setLogFile("/xajax_logs/errors.log");</kbd> + */ + function setLogFile($sFilename) + { + $this->sLogFile = $sFilename; + } + + /** + * Causes xajax to clean out all output buffers before outputting a + * response (default behavior). + */ + function cleanBufferOn() + { + $this->bCleanBuffer = true; + } + /** + * Turns off xajax's output buffer cleaning. + */ + function cleanBufferOff() + { + $this->bCleanBuffer = false; + } + + /** + * Sets the character encoding for the HTTP output based on + * <kbd>$sEncoding</kbd>, which is a string containing the character + * encoding to use. You don't need to use this method normally, since the + * character encoding for the response gets set automatically based on the + * <kbd>XAJAX_DEFAULT_CHAR_ENCODING</kbd> constant. + * <i>Usage:</i> <kbd>$xajax->setCharEncoding("utf-8");</kbd> + * + * @param string the encoding type to use (utf-8, iso-8859-1, etc.) + */ + function setCharEncoding($sEncoding) + { + $this->sEncoding = $sEncoding; + } + + /** + * Causes xajax to decode the input request args from UTF-8 to the current + * encoding if possible. Either the iconv or mb_string extension must be + * present for optimal functionality. + */ + function decodeUTF8InputOn() + { + $this->bDecodeUTF8Input = true; + } + + /** + * Turns off decoding the input request args from UTF-8 (default behavior). + */ + function decodeUTF8InputOff() + { + $this->bDecodeUTF8Input = false; + } + + /** + * Tells the response object to convert special characters to HTML entities + * automatically (only works if the mb_string extension is available). + */ + function outputEntitiesOn() + { + $this->bOutputEntities = true; + } + + /** + * Tells the response object to output special characters intact. (default + * behavior). + */ + function outputEntitiesOff() + { + $this->bOutputEntities = false; + } + + /** + * Registers a PHP function or method to be callable through xajax in your + * Javascript. If you want to register a function, pass in the name of that + * function. If you want to register a static class method, pass in an + * array like so: + * <kbd>array("myFunctionName", "myClass", "myMethod")</kbd> + * For an object instance method, use an object variable for the second + * array element (and in PHP 4 make sure you put an & before the variable + * to pass the object by reference). Note: the function name is what you + * call via Javascript, so it can be anything as long as it doesn't + * conflict with any other registered function name. + * + * <i>Usage:</i> <kbd>$xajax->registerFunction("myFunction");</kbd> + * or: <kbd>$xajax->registerFunction(array("myFunctionName", &$myObject, "myMethod"));</kbd> + * + * @param mixed contains the function name or an object callback array + * @param mixed request type (XAJAX_GET/XAJAX_POST) that should be used + * for this function. Defaults to XAJAX_POST. + */ + function registerFunction($mFunction,$sRequestType=XAJAX_POST) + { + if (is_array($mFunction)) { + $this->aFunctions[$mFunction[0]] = 1; + $this->aFunctionRequestTypes[$mFunction[0]] = $sRequestType; + $this->aObjects[$mFunction[0]] = array_slice($mFunction, 1); + } + else { + $this->aFunctions[$mFunction] = 1; + $this->aFunctionRequestTypes[$mFunction] = $sRequestType; + } + } + + /** + * Registers a PHP function to be callable through xajax which is located + * in some other file. If the function is requested the external file will + * be included to define the function before the function is called. + * + * <i>Usage:</i> <kbd>$xajax->registerExternalFunction("myFunction","myFunction.inc.php",XAJAX_POST);</kbd> + * + * @param string contains the function name or an object callback array + * ({@link xajax::registerFunction() see registerFunction} for + * more info on object callback arrays) + * @param string contains the path and filename of the include file + * @param mixed the RequestType (XAJAX_GET/XAJAX_POST) that should be used + * for this function. Defaults to XAJAX_POST. + */ + function registerExternalFunction($mFunction,$sIncludeFile,$sRequestType=XAJAX_POST) + { + $this->registerFunction($mFunction, $sRequestType); + + if (is_array($mFunction)) { + $this->aFunctionIncludeFiles[$mFunction[0]] = $sIncludeFile; + } + else { + $this->aFunctionIncludeFiles[$mFunction] = $sIncludeFile; + } + } + + /** + * Registers a PHP function to be called when xajax cannot find the + * function being called via Javascript. Because this is technically + * impossible when using "wrapped" functions, the catch-all feature is + * only useful when you're directly using the xajax.call() Javascript + * method. Use the catch-all feature when you want more dynamic ability to + * intercept unknown calls and handle them in a custom way. + * + * <i>Usage:</i> <kbd>$xajax->registerCatchAllFunction("myCatchAllFunction");</kbd> + * + * @param string contains the function name or an object callback array + * ({@link xajax::registerFunction() see registerFunction} for + * more info on object callback arrays) + */ + function registerCatchAllFunction($mFunction) + { + if (is_array($mFunction)) { + $this->sCatchAllFunction = $mFunction[0]; + $this->aObjects[$mFunction[0]] = array_slice($mFunction, 1); + } + else { + $this->sCatchAllFunction = $mFunction; + } + } + + /** + * Registers a PHP function to be called before xajax calls the requested + * function. xajax will automatically add the request function's response + * to the pre-function's response to create a single response. Another + * feature is the ability to return not just a response, but an array with + * the first element being false (a boolean) and the second being the + * response. In this case, the pre-function's response will be returned to + * the browser without xajax calling the requested function. + * + * <i>Usage:</i> <kbd>$xajax->registerPreFunction("myPreFunction");</kbd> + * + * @param string contains the function name or an object callback array + * ({@link xajax::registerFunction() see registerFunction} for + * more info on object callback arrays) + */ + function registerPreFunction($mFunction) + { + if (is_array($mFunction)) { + $this->sPreFunction = $mFunction[0]; + $this->aObjects[$mFunction[0]] = array_slice($mFunction, 1); + } + else { + $this->sPreFunction = $mFunction; + } + } + + /** + * Returns true if xajax can process the request, false if otherwise. + * You can use this to determine if xajax needs to process the request or + * not. + * + * @return boolean + */ + function canProcessRequests() + { + if ($this->getRequestMode() != -1) return true; + return false; + } + + /** + * Returns the current request mode (XAJAX_GET or XAJAX_POST), or -1 if + * there is none. + * + * @return mixed + */ + function getRequestMode() + { + if (!empty($_GET["xajax"])) + return XAJAX_GET; + + if (!empty($_POST["xajax"])) + return XAJAX_POST; + + return -1; + } + + /** + * This is the main communications engine of xajax. The engine handles all + * incoming xajax requests, calls the apporiate PHP functions (or + * class/object methods) 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. + */ + function processRequests() + { + + $requestMode = -1; + $sFunctionName = ""; + $bFoundFunction = true; + $bFunctionIsCatchAll = false; + $sFunctionNameForSpecial = ""; + $aArgs = array(); + $sPreResponse = ""; + $bEndRequest = false; + $sResponse = ""; + + $requestMode = $this->getRequestMode(); + if ($requestMode == -1) return; + + if ($requestMode == XAJAX_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"); + + $sFunctionName = $_GET["xajax"]; + + if (!empty($_GET["xajaxargs"])) + $aArgs = $_GET["xajaxargs"]; + } + + // Use xajax error handler if necessary + if ($this->bErrorHandler) { + $GLOBALS['xajaxErrorHandlerText'] = ""; + set_error_handler("xajaxErrorHandler"); + } + + if ($this->sPreFunction) { + if (!$this->_isFunctionCallable($this->sPreFunction)) { + $bFoundFunction = false; + $objResponse = new xajaxResponse(); + $objResponse->addAlert("Unknown Pre-Function ". $this->sPreFunction); + $sResponse = $objResponse->getXML(); + } + } + //include any external dependencies associated with this function name + if (array_key_exists($sFunctionName,$this->aFunctionIncludeFiles)) + { + ob_start(); + include_once($this->aFunctionIncludeFiles[$sFunctionName]); + ob_end_clean(); + } + + if ($bFoundFunction) { + $sFunctionNameForSpecial = $sFunctionName; + if (!array_key_exists($sFunctionName, $this->aFunctions)) + { + if ($this->sCatchAllFunction) { + $sFunctionName = $this->sCatchAllFunction; + $bFunctionIsCatchAll = true; + } + else { + $bFoundFunction = false; + $objResponse = new xajaxResponse(); + $objResponse->addAlert("Unknown Function $sFunctionName."); + $sResponse = $objResponse->getXML(); + } + } + else if ($this->aFunctionRequestTypes[$sFunctionName] != $requestMode) + { + $bFoundFunction = false; + $objResponse = new xajaxResponse(); + $objResponse->addAlert("Incorrect Request Type."); + $sResponse = $objResponse->getXML(); + } + } + + if ($bFoundFunction) + { + for ($i = 0; $i < sizeof($aArgs); $i++) + { + // If magic quotes is on, then we need to strip the slashes from the args + if (get_magic_quotes_gpc() == 1 && is_string($aArgs[$i])) { + + $aArgs[$i] = stripslashes($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]); + } + else if ($this->bDecodeUTF8Input) + { + $aArgs[$i] = $this->_decodeUTF8Data($aArgs[$i]); + } + } + + if ($this->sPreFunction) { + $mPreResponse = $this->_callFunction($this->sPreFunction, array($sFunctionNameForSpecial, $aArgs)); + if (is_array($mPreResponse) && $mPreResponse[0] === false) { + $bEndRequest = true; + $sPreResponse = $mPreResponse[1]; + } + else { + $sPreResponse = $mPreResponse; + } + if (is_a($sPreResponse, "xajaxResponse")) { + $sPreResponse = $sPreResponse->getXML(); + } + if ($bEndRequest) $sResponse = $sPreResponse; + } + + if (!$bEndRequest) { + if (!$this->_isFunctionCallable($sFunctionName)) { + $objResponse = new xajaxResponse(); + $objResponse->addAlert("The Registered Function $sFunctionName Could Not Be Found."); + $sResponse = $objResponse->getXML(); + } + else { + if ($bFunctionIsCatchAll) { + $aArgs = array($sFunctionNameForSpecial, $aArgs); + } + $sResponse = $this->_callFunction($sFunctionName, $aArgs); + } + if (is_a($sResponse, "xajaxResponse")) { + $sResponse = $sResponse->getXML(); + } + if (!is_string($sResponse) || strpos($sResponse, "<xjx>") === FALSE) { + $objResponse = new xajaxResponse(); + $objResponse->addAlert("No XML Response Was Returned By Function $sFunctionName."); + $sResponse = $objResponse->getXML(); + } + else if ($sPreResponse != "") { + $sNewResponse = new xajaxResponse($this->sEncoding, $this->bOutputEntities); + $sNewResponse->loadXML($sPreResponse); + $sNewResponse->loadXML($sResponse); + $sResponse = $sNewResponse->getXML(); + } + } + } + + $sContentHeader = "Content-type: text/xml;"; + if ($this->sEncoding && strlen(trim($this->sEncoding)) > 0) + $sContentHeader .= " charset=".$this->sEncoding; + header($sContentHeader); + if ($this->bErrorHandler && !empty( $GLOBALS['xajaxErrorHandlerText'] )) { + $sErrorResponse = new xajaxResponse(); + $sErrorResponse->addAlert("** PHP Error Messages: **" . $GLOBALS['xajaxErrorHandlerText']); + if ($this->sLogFile) { + $fH = @fopen($this->sLogFile, "a"); + if (!$fH) { + $sErrorResponse->addAlert("** Logging Error **\n\nxajax was unable to write to the error log file:\n" . $this->sLogFile); + } + else { + fwrite($fH, "** xajax Error Log - " . strftime("%b %e %Y %I:%M:%S %p") . " **" . $GLOBALS['xajaxErrorHandlerText'] . "\n\n\n"); + fclose($fH); + } + } + + $sErrorResponse->loadXML($sResponse); + $sResponse = $sErrorResponse->getXML(); + + } + if ($this->bCleanBuffer) while (@ob_end_clean()); + print $sResponse; + if ($this->bErrorHandler) restore_error_handler(); + + if ($this->bExitAllowed) + exit(); + } + + /** + * Prints the xajax Javascript header and wrapper code into your page by + * printing the output of the getJavascript() method. It should only be + * called between the <pre><head> </head></pre> tags in your HTML page. + * Remember, if you only want to obtain the result of this function, use + * {@link xajax::getJavascript()} instead. + * + * <i>Usage:</i> + * <code> + * <head> + * ... + * < ?php $xajax->printJavascript(); ? > + * </code> + * + * @param string the relative address of the folder where xajax has been + * installed. For instance, if your PHP file is + * "http://www.myserver.com/myfolder/mypage.php" + * and xajax was installed in + * "http://www.myserver.com/anotherfolder", then $sJsURI + * should be set to "../anotherfolder". Defaults to assuming + * xajax is in the same folder as your PHP file. + * @param string the relative folder/file pair of the xajax Javascript + * engine located within the xajax installation folder. + * Defaults to xajax_js/xajax.js. + */ + function printJavascript($sJsURI="", $sJsFile=NULL) + { + print $this->getJavascript($sJsURI, $sJsFile); + } + + /** + * Returns the xajax Javascript code that should be added to your HTML page + * between the <kbd><head> </head></kbd> tags. + * + * <i>Usage:</i> + * <code> + * < ?php $xajaxJSHead = $xajax->getJavascript(); ? > + * <head> + * ... + * < ?php echo $xajaxJSHead; ? > + * </code> + * + * @param string the relative address of the folder where xajax has been + * installed. For instance, if your PHP file is + * "http://www.myserver.com/myfolder/mypage.php" + * and xajax was installed in + * "http://www.myserver.com/anotherfolder", then $sJsURI + * should be set to "../anotherfolder". Defaults to assuming + * xajax is in the same folder as your PHP file. + * @param string the relative folder/file pair of the xajax Javascript + * engine located within the xajax installation folder. + * Defaults to xajax_js/xajax.js. + * @return string + */ + function getJavascript($sJsURI="", $sJsFile=NULL) + { + $html = $this->getJavascriptConfig(); + $html .= $this->getJavascriptInclude($sJsURI, $sJsFile); + + return $html; + } + + /** + * Returns a string containing inline Javascript that sets up the xajax + * runtime (typically called internally by xajax from get/printJavascript). + * + * @return string + */ + function getJavascriptConfig() + { + $html = "\t<script type=\"text/javascript\">\n"; + $html .= "var xajaxRequestUri=\"".$this->sRequestURI."\";\n"; + $html .= "var xajaxDebug=".($this->bDebug?"true":"false").";\n"; + $html .= "var xajaxStatusMessages=".($this->bStatusMessages?"true":"false").";\n"; + $html .= "var xajaxWaitCursor=".($this->bWaitCursor?"true":"false").";\n"; + $html .= "var xajaxDefinedGet=".XAJAX_GET.";\n"; + $html .= "var xajaxDefinedPost=".XAJAX_POST.";\n"; + $html .= "var xajaxLoaded=false;\n"; + + foreach($this->aFunctions as $sFunction => $bExists) { + $html .= $this->_wrap($sFunction,$this->aFunctionRequestTypes[$sFunction]); + } + + $html .= "\t</script>\n"; + return $html; + } + + /** + * Returns a string containing a Javascript include of the xajax.js file + * along with a check to see if the file loaded after six seconds + * (typically called internally by xajax from get/printJavascript). + * + * @param string the relative address of the folder where xajax has been + * installed. For instance, if your PHP file is + * "http://www.myserver.com/myfolder/mypage.php" + * and xajax was installed in + * "http://www.myserver.com/anotherfolder", then $sJsURI + * should be set to "../anotherfolder". Defaults to assuming + * xajax is in the same folder as your PHP file. + * @param string the relative folder/file pair of the xajax Javascript + * engine located within the xajax installation folder. + * Defaults to xajax_js/xajax.js. + * @return string + */ + function getJavascriptInclude($sJsURI="", $sJsFile=NULL) + { + if ($sJsFile == NULL) $sJsFile = "xajax_js/xajax.js"; + + if ($sJsURI != "" && substr($sJsURI, -1) != "/") $sJsURI .= "/"; + + $html = "\t<script type=\"text/javascript\" src=\"" . $sJsURI . $sJsFile . "\"></script>\n"; + $html .= "\t<script type=\"text/javascript\">\n"; + $html .= "window.setTimeout(function () { if (!xajaxLoaded) { alert('Error: the xajax Javascript file could not be included. Perhaps the URL is incorrect?\\nURL: {$sJsURI}{$sJsFile}'); } }, 6000);\n"; + $html .= "\t</script>\n"; + return $html; + } + + /** + * This method can be used to create a new xajax.js file out of the + * xajax_uncompressed.js file (which will only happen if xajax.js doesn't + * already exist on the filesystem). + * + * @param string an optional argument containing the full server file path + * of xajax.js. + */ + function autoCompressJavascript($sJsFullFilename=NULL) + { + $sJsFile = "xajax_js/xajax.js"; + + if ($sJsFullFilename) { + $realJsFile = $sJsFullFilename; + } + else { + $realPath = realpath(dirname(__FILE__)); + $realJsFile = $realPath . "/". $sJsFile; + } + + // Create a compressed file if necessary + if (!file_exists($realJsFile)) { + $srcFile = str_replace(".js", "_uncompressed.js", $realJsFile); + if (!file_exists($srcFile)) { + trigger_error("The xajax uncompressed Javascript file could not be found in the <b>" . dirname($realJsFile) . "</b> folder. Error ", E_USER_ERROR); + } + require(dirname(__FILE__)."/xajaxCompress.php"); + $javaScript = implode('', file($srcFile)); + $compressedScript = xajaxCompressJavascript($javaScript); + $fH = @fopen($realJsFile, "w"); + if (!$fH) { + trigger_error("The xajax compressed javascript file could not be written in the <b>" . dirname($realJsFile) . "</b> folder. Error ", E_USER_ERROR); + } + else { + fwrite($fH, $compressedScript); + fclose($fH); + } + } + } + + /** + * Returns the current URL based upon the SERVER vars. + * + * @access private + * @return string + */ + function _detectURI() { + $aURL = array(); + + // Try to get the request URL + if (!empty($_SERVER['REQUEST_URI'])) { + $aURL = parse_url($_SERVER['REQUEST_URI']); + } + + // Fill in the empty values + if (empty($aURL['scheme'])) { + if (!empty($_SERVER['HTTP_SCHEME'])) { + $aURL['scheme'] = $_SERVER['HTTP_SCHEME']; + } else { + $aURL['scheme'] = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http'; + } + } + + if (empty($aURL['host'])) { + if (!empty($_SERVER['HTTP_HOST'])) { + if (strpos($_SERVER['HTTP_HOST'], ':') > 0) { + list($aURL['host'], $aURL['port']) = explode(':', $_SERVER['HTTP_HOST']); + } else { + $aURL['host'] = $_SERVER['HTTP_HOST']; + } + } else if (!empty($_SERVER['SERVER_NAME'])) { + $aURL['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($aURL['port']) && !empty($_SERVER['SERVER_PORT'])) { + $aURL['port'] = $_SERVER['SERVER_PORT']; + } + + if (empty($aURL['path'])) { + if (!empty($_SERVER['PATH_INFO'])) { + $sPath = parse_url($_SERVER['PATH_INFO']); + } else { + $sPath = parse_url($_SERVER['PHP_SELF']); + } + $aURL['path'] = $sPath['path']; + unset($sPath); + } + + if (!empty($aURL['query'])) { + $aURL['query'] = '?'.$aURL['query']; + } + + // Build the URL: Start with scheme, user and pass + $sURL = $aURL['scheme'].'://'; + if (!empty($aURL['user'])) { + $sURL.= $aURL['user']; + if (!empty($aURL['pass'])) { + $sURL.= ':'.$aURL['pass']; + } + $sURL.= '@'; + } + + // Add the host + $sURL.= $aURL['host']; + + // Add the port if needed + if (!empty($aURL['port']) && (($aURL['scheme'] == 'http' && $aURL['port'] != 80) || ($aURL['scheme'] == 'https' && $aURL['port'] != 443))) { + $sURL.= ':'.$aURL['port']; + } + + // Add the path and the query string + $sURL.= $aURL['path'].@$aURL['query']; + + // Clean up + unset($aURL); + return $sURL; + } + + /** + * Returns true if the function name is associated with an object callback, + * false if not. + * + * @param string the name of the function + * @access private + * @return boolean + */ + function _isObjectCallback($sFunction) + { + if (array_key_exists($sFunction, $this->aObjects)) return true; + return false; + } + + /** + * Returns true if the function or object callback can be called, false if + * not. + * + * @param string the name of the function + * @access private + * @return boolean + */ + function _isFunctionCallable($sFunction) + { + if ($this->_isObjectCallback($sFunction)) { + if (is_object($this->aObjects[$sFunction][0])) { + return method_exists($this->aObjects[$sFunction][0], $this->aObjects[$sFunction][1]); + } + else { + return is_callable($this->aObjects[$sFunction]); + } + } + else { + return function_exists($sFunction); + } + } + + /** + * Calls the function, class method, or object method with the supplied + * arguments. + * + * @param string the name of the function + * @param array arguments to pass to the function + * @access private + * @return mixed the output of the called function or method + */ + function _callFunction($sFunction, $aArgs) + { + if ($this->_isObjectCallback($sFunction)) { + $mReturn = call_user_func_array($this->aObjects[$sFunction], $aArgs); + } + else { + $mReturn = call_user_func_array($sFunction, $aArgs); + } + return $mReturn; + } + + /** + * Generates the Javascript wrapper for the specified PHP function. + * + * @param string the name of the function + * @param mixed the request type + * @access private + * @return string + */ + function _wrap($sFunction,$sRequestType=XAJAX_POST) + { + $js = "function ".$this->sWrapperPrefix."$sFunction(){return xajax.call(\"$sFunction\", arguments, ".$sRequestType.");}\n"; + return $js; + } + + /** + * 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. + * + * @param string the root tag of the XML + * @param string XML to convert + * @access private + * @return array + */ + 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; + } + + /** + * A recursive function that generates an array from the contents of + * $this->aObjArray. + * + * @param string the root tag of the XML + * @access private + * @return array + */ + 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]; + if ($this->bDecodeUTF8Input) + { + $value = $this->_decodeUTF8Data($value); + } + } + $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); + if ($this->bDecodeUTF8Input) + { + foreach($aArray as $key => $value) + { + $aArray[$key] = $this->_decodeUTF8Data($value); + } + } + // If magic quotes is on, then we need to strip the slashes from the + // array values because of the parse_str pass which adds slashes + if (get_magic_quotes_gpc() == 1) { + $newArray = array(); + foreach ($aArray as $sKey => $sValue) { + if (is_string($sValue)) + $newArray[$sKey] = stripslashes($sValue); + else + $newArray[$sKey] = $sValue; + } + $aArray = $newArray; + } + } + + return $aArray; + } + + /** + * Decodes string data from UTF-8 to the current xajax encoding. + * + * @param string data to convert + * @access private + * @return string converted data + */ + function _decodeUTF8Data($sData) + { + $sValue = $sData; + if ($this->bDecodeUTF8Input) + { + $sFuncToUse = NULL; + + if (function_exists('iconv')) + { + $sFuncToUse = "iconv"; + } + else if (function_exists('mb_convert_encoding')) + { + $sFuncToUse = "mb_convert_encoding"; + } + else if ($this->sEncoding == "ISO-8859-1") + { + $sFuncToUse = "utf8_decode"; + } + else + { + trigger_error("The incoming xajax data could not be converted from UTF-8", E_USER_NOTICE); + } + + if ($sFuncToUse) + { + if (is_string($sValue)) + { + if ($sFuncToUse == "iconv") + { + $sValue = iconv("UTF-8", $this->sEncoding.'//TRANSLIT', $sValue); + } + else if ($sFuncToUse == "mb_convert_encoding") + { + $sValue = mb_convert_encoding($sValue, $this->sEncoding, "UTF-8"); + } + else + { + $sValue = utf8_decode($sValue); + } + } + } + } + return $sValue; + } + +}// end class xajax + +/** + * This function is registered with PHP's set_error_handler() function if + * the xajax error handling system is turned on. + */ +function xajaxErrorHandler($errno, $errstr, $errfile, $errline) +{ + $errorReporting = error_reporting(); + if (($errno & $errorReporting) == 0) return; + + if ($errno == E_NOTICE) { + $errTypeStr = "NOTICE"; + } + else if ($errno == E_WARNING) { + $errTypeStr = "WARNING"; + } + else if ($errno == E_USER_NOTICE) { + $errTypeStr = "USER NOTICE"; + } + else if ($errno == E_USER_WARNING) { + $errTypeStr = "USER WARNING"; + } + else if ($errno == E_USER_ERROR) { + $errTypeStr = "USER FATAL ERROR"; + } + else if ($errno == E_STRICT) { + return; + } + else { + $errTypeStr = "UNKNOWN: $errno"; + } + $GLOBALS['xajaxErrorHandlerText'] .= "\n----\n[$errTypeStr] $errstr\nerror in line $errline of file $errfile"; +} + +?>
\ No newline at end of file diff --git a/modules/xajax/xajaxCompress.php b/modules/xajax/xajaxCompress.php new file mode 100644 index 00000000..327a92df --- /dev/null +++ b/modules/xajax/xajaxCompress.php @@ -0,0 +1,182 @@ +<?php +/** + * xajaxCompress.php :: function to compress Javascript + * + * xajax version 0.2.4 + * copyright (c) 2005 by Jared White & J. Max Wilson + * http://www.xajaxproject.org + * + * 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 + * + * @package xajax + * @version $Id$ + * @copyright Copyright (c) 2005-2006 by Jared White & J. Max Wilson + * @license http://www.gnu.org/copyleft/lesser.html#SEC3 LGPL License + */ + +/** + * Compresses the Javascript code for more efficient delivery. + * (used internally) + * + * @param string contains the Javascript code to compress + */ +function xajaxCompressJavascript($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; +} +?>
\ No newline at end of file diff --git a/modules/xajax/xajaxResponse.inc.php b/modules/xajax/xajaxResponse.inc.php new file mode 100644 index 00000000..1c0aeb60 --- /dev/null +++ b/modules/xajax/xajaxResponse.inc.php @@ -0,0 +1,580 @@ +<?php +/** + * xajaxResponse.inc.php :: xajax XML response class + * + * xajax version 0.2.4 + * copyright (c) 2005 by Jared White & J. Max Wilson + * http://www.xajaxproject.org + * + * 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 + * + * @package xajax + * @version $Id$ + * @copyright Copyright (c) 2005-2006 by Jared White & J. Max Wilson + * @license http://www.gnu.org/copyleft/lesser.html#SEC3 LGPL License + */ + +/* + ---------------------------------------------------------------------------- + | Online documentation for this class is available on the xajax wiki at: | + | http://wiki.xajaxproject.org/Documentation:xajaxResponse.inc.php | + ---------------------------------------------------------------------------- +*/ + +/** + * The xajaxResponse class is used to create responses to be sent back to your + * Web page. A response contains one or more command messages for updating + * your page. + * Currently xajax supports 21 kinds of command messages, including some common + * ones such as: + * <ul> + * <li>Assign - sets the specified attribute of an element in your page</li> + * <li>Append - appends data to the end of the specified attribute of an + * element in your page</li> + * <li>Prepend - prepends data to the beginning of the specified attribute of + * an element in your page</li> + * <li>Replace - searches for and replaces data in the specified attribute of + * an element in your page</li> + * <li>Script - runs the supplied JavaScript code</li> + * <li>Alert - shows an alert box with the supplied message text</li> + * </ul> + * + * <i>Note:</i> elements are identified by their HTML id, so if you don't see + * your browser HTML display changing from the request, make sure you're using + * the right id names in your response. + * + * @package xajax + */ +class xajaxResponse +{ + /**#@+ + * @access protected + */ + /** + * @var string internal XML storage + */ + var $xml; + /** + * @var string the encoding type to use + */ + var $sEncoding; + /** + * @var boolean if special characters in the XML should be converted to + * entities + */ + var $bOutputEntities; + + /**#@-*/ + + /** + * The constructor's main job is to set the character encoding for the + * response. + * + * <i>Note:</i> to change the character encoding for all of the + * responses, set the XAJAX_DEFAULT_ENCODING constant before you + * instantiate xajax. + * + * @param string contains the character encoding string to use + * @param boolean lets you set if you want special characters in the output + * converted to HTML entities + * + */ + function xajaxResponse($sEncoding=XAJAX_DEFAULT_CHAR_ENCODING, $bOutputEntities=false) + { + $this->setCharEncoding($sEncoding); + $this->bOutputEntities = $bOutputEntities; + } + + /** + * Sets the character encoding for the response based on $sEncoding, which + * is a string containing the character encoding to use. You don't need to + * use this method normally, since the character encoding for the response + * gets set automatically based on the XAJAX_DEFAULT_CHAR_ENCODING + * constant. + * + * @param string + */ + function setCharEncoding($sEncoding) + { + $this->sEncoding = $sEncoding; + } + + /** + * Tells the response object to convert special characters to HTML entities + * automatically (only works if the mb_string extension is available). + */ + function outputEntitiesOn() + { + $this->bOutputEntities = true; + } + + /** + * Tells the response object to output special characters intact. (default + * behavior) + */ + function outputEntitiesOff() + { + $this->bOutputEntities = false; + } + + /** + * Adds a confirm commands command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addConfirmCommands(1, "Do you want to preview the new data?");</kbd> + * + * @param integer the number of commands to skip if the user presses + * Cancel in the browsers's confirm dialog + * @param string the message to show in the browser's confirm dialog + */ + function addConfirmCommands($iCmdNumber, $sMessage) + { + $this->xml .= $this->_cmdXML(array("n"=>"cc","t"=>$iCmdNumber),$sMessage); + } + + /** + * Adds an assign command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addAssign("contentDiv", "innerHTML", "Some Text");</kbd> + * + * @param string contains the id of an HTML element + * @param string the part of the element you wish to modify ("innerHTML", + * "value", etc.) + * @param string the data you want to set the attribute to + */ + function addAssign($sTarget,$sAttribute,$sData) + { + $this->xml .= $this->_cmdXML(array("n"=>"as","t"=>$sTarget,"p"=>$sAttribute),$sData); + } + + /** + * Adds an append command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addAppend("contentDiv", "innerHTML", "Some New Text");</kbd> + * + * @param string contains the id of an HTML element + * @param string the part of the element you wish to modify ("innerHTML", + * "value", etc.) + * @param string the data you want to append to the end of the attribute + */ + function addAppend($sTarget,$sAttribute,$sData) + { + $this->xml .= $this->_cmdXML(array("n"=>"ap","t"=>$sTarget,"p"=>$sAttribute),$sData); + } + + /** + * Adds an prepend command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addPrepend("contentDiv", "innerHTML", "Some Starting Text");</kbd> + * + * @param string contains the id of an HTML element + * @param string the part of the element you wish to modify ("innerHTML", + * "value", etc.) + * @param string the data you want to prepend to the beginning of the + * attribute + */ + function addPrepend($sTarget,$sAttribute,$sData) + { + $this->xml .= $this->_cmdXML(array("n"=>"pp","t"=>$sTarget,"p"=>$sAttribute),$sData); + } + + /** + * Adds a replace command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addReplace("contentDiv", "innerHTML", "text", "<b>text</b>");</kbd> + * + * @param string contains the id of an HTML element + * @param string the part of the element you wish to modify ("innerHTML", + * "value", etc.) + * @param string the string to search for + * @param string the string to replace the search string when found in the + * attribute + */ + function addReplace($sTarget,$sAttribute,$sSearch,$sData) + { + $sDta = "<s><![CDATA[$sSearch]]></s><r><![CDATA[$sData]]></r>"; + $this->xml .= $this->_cmdXML(array("n"=>"rp","t"=>$sTarget,"p"=>$sAttribute),$sDta); + } + + /** + * Adds a clear command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addClear("contentDiv", "innerHTML");</kbd> + * + * @param string contains the id of an HTML element + * @param string the part of the element you wish to clear ("innerHTML", + * "value", etc.) + */ + function addClear($sTarget,$sAttribute) + { + $this->addAssign($sTarget,$sAttribute,''); + } + + /** + * Adds an alert command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addAlert("This is important information");</kbd> + * + * @param string the text to be displayed in the Javascript alert box + */ + function addAlert($sMsg) + { + $this->xml .= $this->_cmdXML(array("n"=>"al"),$sMsg); + } + + /** + * Uses the addScript() method to add a Javascript redirect to another URL. + * + * <i>Usage:</i> <kbd>$objResponse->addRedirect("http://www.xajaxproject.org");</kbd> + * + * @param string the URL to redirect the client browser to + */ + function addRedirect($sURL) + { + //we need to parse the query part so that the values are rawurlencode()'ed + //can't just use parse_url() cos we could be dealing with a relative URL which + // parse_url() can't deal with. + $queryStart = strpos($sURL, '?', strrpos($sURL, '/')); + if ($queryStart !== FALSE) + { + $queryStart++; + $queryEnd = strpos($sURL, '#', $queryStart); + if ($queryEnd === FALSE) + $queryEnd = strlen($sURL); + $queryPart = substr($sURL, $queryStart, $queryEnd-$queryStart); + parse_str($queryPart, $queryParts); + $newQueryPart = ""; + foreach($queryParts as $key => $value) + { + $newQueryPart .= rawurlencode($key).'='.rawurlencode($value).ini_get('arg_separator.output'); + } + $sURL = str_replace($queryPart, $newQueryPart, $sURL); + } + $this->addScript('window.location = "'.$sURL.'";'); + } + + /** + * Adds a Javascript command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addScript("var x = prompt('get some text');");</kbd> + * + * @param string contains Javascript code to be executed + */ + function addScript($sJS) + { + $this->xml .= $this->_cmdXML(array("n"=>"js"),$sJS); + } + + /** + * Adds a Javascript function call command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addScriptCall("myJSFunction", "arg 1", "arg 2", 12345);</kbd> + * + * @param string $sFunc the name of a Javascript function + * @param mixed $args,... optional arguments to pass to the Javascript function + */ + function addScriptCall() { + $arguments = func_get_args(); + $sFunc = array_shift($arguments); + $sData = $this->_buildObjXml($arguments); + $this->xml .= $this->_cmdXML(array("n"=>"jc","t"=>$sFunc),$sData); + } + + /** + * Adds a remove element command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addRemove("Div2");</kbd> + * + * @param string contains the id of an HTML element to be removed + */ + function addRemove($sTarget) + { + $this->xml .= $this->_cmdXML(array("n"=>"rm","t"=>$sTarget),''); + } + + /** + * Adds a create element command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addCreate("parentDiv", "h3", "myid");</kbd> + * + * @param string contains the id of an HTML element to to which the new + * element will be appended. + * @param string the tag to be added + * @param string the id to be assigned to the new element + * @param string deprecated, use the addCreateInput() method instead + */ + function addCreate($sParent, $sTag, $sId, $sType="") + { + if ($sType) + { + trigger_error("The \$sType parameter of addCreate has been deprecated. Use the addCreateInput() method instead.", E_USER_WARNING); + return; + } + $this->xml .= $this->_cmdXML(array("n"=>"ce","t"=>$sParent,"p"=>$sId),$sTag); + } + + /** + * Adds a insert element command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addInsert("childDiv", "h3", "myid");</kbd> + * + * @param string contains the id of the child before which the new element + * will be inserted + * @param string the tag to be added + * @param string the id to be assigned to the new element + */ + function addInsert($sBefore, $sTag, $sId) + { + $this->xml .= $this->_cmdXML(array("n"=>"ie","t"=>$sBefore,"p"=>$sId),$sTag); + } + + /** + * Adds a insert element command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addInsertAfter("childDiv", "h3", "myid");</kbd> + * + * @param string contains the id of the child after which the new element + * will be inserted + * @param string the tag to be added + * @param string the id to be assigned to the new element + */ + function addInsertAfter($sAfter, $sTag, $sId) + { + $this->xml .= $this->_cmdXML(array("n"=>"ia","t"=>$sAfter,"p"=>$sId),$sTag); + } + + /** + * Adds a create input command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addCreateInput("form1", "text", "username", "input1");</kbd> + * + * @param string contains the id of an HTML element to which the new input + * will be appended + * @param string the type of input to be created (text, radio, checkbox, + * etc.) + * @param string the name to be assigned to the new input and the variable + * name when it is submitted + * @param string the id to be assigned to the new input + */ + function addCreateInput($sParent, $sType, $sName, $sId) + { + $this->xml .= $this->_cmdXML(array("n"=>"ci","t"=>$sParent,"p"=>$sId,"c"=>$sType),$sName); + } + + /** + * Adds an insert input command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addInsertInput("input5", "text", "username", "input1");</kbd> + * + * @param string contains the id of the child before which the new element + * will be inserted + * @param string the type of input to be created (text, radio, checkbox, + * etc.) + * @param string the name to be assigned to the new input and the variable + * name when it is submitted + * @param string the id to be assigned to the new input + */ + function addInsertInput($sBefore, $sType, $sName, $sId) + { + $this->xml .= $this->_cmdXML(array("n"=>"ii","t"=>$sBefore,"p"=>$sId,"c"=>$sType),$sName); + } + + /** + * Adds an insert input command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addInsertInputAfter("input7", "text", "email", "input2");</kbd> + * + * @param string contains the id of the child after which the new element + * will be inserted + * @param string the type of input to be created (text, radio, checkbox, + * etc.) + * @param string the name to be assigned to the new input and the variable + * name when it is submitted + * @param string the id to be assigned to the new input + */ + function addInsertInputAfter($sAfter, $sType, $sName, $sId) + { + $this->xml .= $this->_cmdXML(array("n"=>"iia","t"=>$sAfter,"p"=>$sId,"c"=>$sType),$sName); + } + + /** + * Adds an event command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addEvent("contentDiv", "onclick", "alert(\'Hello World\');");</kbd> + * + * @param string contains the id of an HTML element + * @param string the event you wish to set ("onclick", "onmouseover", etc.) + * @param string the Javascript string you want the event to invoke + */ + function addEvent($sTarget,$sEvent,$sScript) + { + $this->xml .= $this->_cmdXML(array("n"=>"ev","t"=>$sTarget,"p"=>$sEvent),$sScript); + } + + /** + * Adds a handler command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addHandler("contentDiv", "onclick", "content_click");</kbd> + * + * @param string contains the id of an HTML element + * @param string the event you wish to set ("onclick", "onmouseover", etc.) + * @param string the name of a Javascript function that will handle the + * event. Multiple handlers can be added for the same event + */ + function addHandler($sTarget,$sEvent,$sHandler) + { + $this->xml .= $this->_cmdXML(array("n"=>"ah","t"=>$sTarget,"p"=>$sEvent),$sHandler); + } + + /** + * Adds a remove handler command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addRemoveHandler("contentDiv", "onclick", "content_click");</kbd> + * + * @param string contains the id of an HTML element + * @param string the event you wish to remove ("onclick", "onmouseover", + * etc.) + * @param string the name of a Javascript handler function that you want to + * remove + */ + function addRemoveHandler($sTarget,$sEvent,$sHandler) + { + $this->xml .= $this->_cmdXML(array("n"=>"rh","t"=>$sTarget,"p"=>$sEvent),$sHandler); + } + + /** + * Adds an include script command message to the XML response. + * + * <i>Usage:</i> <kbd>$objResponse->addIncludeScript("functions.js");</kbd> + * + * @param string URL of the Javascript file to include + */ + function addIncludeScript($sFileName) + { + $this->xml .= $this->_cmdXML(array("n"=>"in"),$sFileName); + } + + /** + * Returns the XML to be returned from your function to the xajax processor + * on your page. Since xajax 0.2, you can also return an xajaxResponse + * object from your function directly, and xajax will automatically request + * the XML using this method call. + * + * <i>Usage:</i> <kbd>return $objResponse->getXML();</kbd> + * + * @return string response XML data + */ + function getXML() + { + $sXML = "<?xml version=\"1.0\""; + if ($this->sEncoding && strlen(trim($this->sEncoding)) > 0) + $sXML .= " encoding=\"".$this->sEncoding."\""; + $sXML .= " ?"."><xjx>" . $this->xml . "</xjx>"; + + return $sXML; + } + + /** + * Adds the commands of the provided response XML output to this response + * object + * + * <i>Usage:</i> + * <code>$r1 = $objResponse1->getXML(); + * $objResponse2->loadXML($r1); + * return $objResponse2->getXML();</code> + * + * @param string the response XML (returned from a getXML() method) to add + * to the end of this response object + */ + function loadXML($mXML) + { + if (is_a($mXML, "xajaxResponse")) { + $mXML = $mXML->getXML(); + } + $sNewXML = ""; + $iStartPos = strpos($mXML, "<xjx>") + 5; + $sNewXML = substr($mXML, $iStartPos); + $iEndPos = strpos($sNewXML, "</xjx>"); + $sNewXML = substr($sNewXML, 0, $iEndPos); + $this->xml .= $sNewXML; + } + + /** + * Generates XML from command data + * + * @access private + * @param array associative array of attributes + * @param string data + * @return string XML command + */ + function _cmdXML($aAttributes, $sData) + { + if ($this->bOutputEntities) { + if (function_exists('mb_convert_encoding')) { + $sData = call_user_func_array('mb_convert_encoding', array(&$sData, 'HTML-ENTITIES', $this->sEncoding)); + } + else { + trigger_error("The xajax XML response output could not be converted to HTML entities because the mb_convert_encoding function is not available", E_USER_NOTICE); + } + } + $xml = "<cmd"; + foreach($aAttributes as $sAttribute => $sValue) + $xml .= " $sAttribute=\"$sValue\""; + if ($sData !== null && !stristr($sData,'<![CDATA[')) + $xml .= "><![CDATA[$sData]]></cmd>"; + else if ($sData !== null) + $xml .= ">$sData</cmd>"; + else + $xml .= "></cmd>"; + + return $xml; + } + + /** + * Recursively serializes a data structure in XML so it can be sent to + * the client. It could be thought of as the opposite of + * {@link xajax::_parseObjXml()}. + * + * @access private + * @param mixed data structure to serialize to XML + * @return string serialized XML + */ + function _buildObjXml($var) { + if (gettype($var) == "object") $var = get_object_vars($var); + if (!is_array($var)) { + return "<![CDATA[$var]]>"; + } + else { + $data = "<xjxobj>"; + foreach ($var as $key => $value) { + $data .= "<e>"; + $data .= "<k>" . htmlspecialchars($key) . "</k>"; + $data .= "<v>" . $this->_buildObjXml($value) . "</v>"; + $data .= "</e>"; + } + $data .= "</xjxobj>"; + return $data; + } + } + +}// end class xajaxResponse +?> diff --git a/modules/xajax/xajax_js/xajax.js b/modules/xajax/xajax_js/xajax.js new file mode 100644 index 00000000..0dca8f52 --- /dev/null +++ b/modules/xajax/xajax_js/xajax.js @@ -0,0 +1,172 @@ +/* xajax Javascript library :: version 0.2.4 */ +Array.prototype.containsValue=function(valueToCheck){for(var i=0;i<this.length;i++){if(this[i]==valueToCheck)return true;} +return false;} +function Xajax(){this.DebugMessage=function(text){if(text.length > 1000)text=text.substr(0,1000)+"...\n[long response]\n...";try{if(this.debugWindow==undefined||this.debugWindow.closed==true){this.debugWindow=window.open('about:blank','xajax-debug','width=800,height=600,scrollbars=1,resizable,status');this.debugWindow.document.write('<html><head><title>Xajax debug output</title></head><body><h2>Xajax debug output</h2><div id="debugTag"></div></body></html>');} +text=text.replace(/&/g,"&") +text=text.replace(/</g,"<") +text=text.replace(/>/g,">") +debugTag=this.debugWindow.document.getElementById('debugTag');debugTag.innerHTML=('<b>'+(new Date()).toString()+'</b>: '+text+'<hr/>')+debugTag.innerHTML;}catch(e){alert("Xajax Debug:\n "+text);} +};this.workId='xajaxWork'+new Date().getTime();this.depth=0;this.responseErrorsForAlert=["400","401","402","403","404","500","501","502","503"];this.getRequestObject=function(){if(xajaxDebug)this.DebugMessage("Initializing Request Object..");var req=null;if(typeof XMLHttpRequest!="undefined") +req=new XMLHttpRequest();if(!req&&typeof ActiveXObject!="undefined"){try{req=new ActiveXObject("Msxml2.XMLHTTP");} +catch(e){try{req=new ActiveXObject("Microsoft.XMLHTTP");} +catch(e2){try{req=new ActiveXObject("Msxml2.XMLHTTP.4.0");} +catch(e3){req=null;} +} +} +} +if(!req&&window.createRequest) +req=window.createRequest();if(!req)this.DebugMessage("Request Object Instantiation failed.");return req;} +this.$=function(sId){if(!sId){return null;} +var returnObj=document.getElementById(sId);if(!returnObj&&document.all){returnObj=document.all[sId];} +if(xajaxDebug&&!returnObj&&sId!=this.workId){this.DebugMessage("Element with the id \""+sId+"\" not found.");} +return returnObj;} +this.include=function(sFileName){var objHead=document.getElementsByTagName('head');var objScript=document.createElement('script');objScript.type='text/javascript';objScript.src=sFileName;objHead[0].appendChild(objScript);} +this.stripOnPrefix=function(sEventName){sEventName=sEventName.toLowerCase();if(sEventName.indexOf('on')==0){sEventName=sEventName.replace(/on/,'');} +return sEventName;} +this.addOnPrefix=function(sEventName){sEventName=sEventName.toLowerCase();if(sEventName.indexOf('on')!=0){sEventName='on'+sEventName;} +return sEventName;} +this.addHandler=function(sElementId,sEvent,sFunctionName){if(window.addEventListener){sEvent=this.stripOnPrefix(sEvent);eval("this.$('"+sElementId+"').addEventListener('"+sEvent+"',"+sFunctionName+",false);");} +else{sAltEvent=this.addOnPrefix(sEvent);eval("this.$('"+sElementId+"').attachEvent('"+sAltEvent+"',"+sFunctionName+",false);");} +} +this.removeHandler=function(sElementId,sEvent,sFunctionName){if(window.addEventListener){sEvent=this.stripOnPrefix(sEvent);eval("this.$('"+sElementId+"').removeEventListener('"+sEvent+"',"+sFunctionName+",false);");} +else{sAltEvent=this.addOnPrefix(sEvent);eval("this.$('"+sElementId+"').detachEvent('"+sAltEvent+"',"+sFunctionName+",false);");} +} +this.create=function(sParentId,sTag,sId){var objParent=this.$(sParentId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);if(objParent) +objParent.appendChild(objElement);} +this.insert=function(sBeforeId,sTag,sId){var objSibling=this.$(sBeforeId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);objSibling.parentNode.insertBefore(objElement,objSibling);} +this.insertAfter=function(sAfterId,sTag,sId){var objSibling=this.$(sAfterId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);objSibling.parentNode.insertBefore(objElement,objSibling.nextSibling);} +this.getInput=function(sType,sName,sId){var Obj;if(!window.addEventListener){Obj=document.createElement('<input type="'+sType+'" id="'+sId+'" name="'+sName+'">');} +else{Obj=document.createElement('input');Obj.setAttribute('type',sType);Obj.setAttribute('name',sName);Obj.setAttribute('id',sId);} +return Obj;} +this.createInput=function(sParentId,sType,sName,sId){var objParent=this.$(sParentId);var objElement=this.getInput(sType,sName,sId);if(objParent&&objElement) +objParent.appendChild(objElement);} +this.insertInput=function(sBeforeId,sType,sName,sId){var objSibling=this.$(sBeforeId);var objElement=this.getInput(sType,sName,sId);if(objElement&&objSibling&&objSibling.parentNode) +objSibling.parentNode.insertBefore(objElement,objSibling);} +this.insertInputAfter=function(sAfterId,sType,sName,sId){var objSibling=this.$(sAfterId);var objElement=this.getInput(sType,sName,sId);if(objElement&&objSibling&&objSibling.parentNode){objSibling.parentNode.insertBefore(objElement,objSibling.nextSibling);} +} +this.remove=function(sId){objElement=this.$(sId);if(objElement&&objElement.parentNode&&objElement.parentNode.removeChild){objElement.parentNode.removeChild(objElement);} +} +this.replace=function(sId,sAttribute,sSearch,sReplace){var bFunction=false;if(sAttribute=="innerHTML") +sSearch=this.getBrowserHTML(sSearch);eval("var txt=this.$('"+sId+"')."+sAttribute);if(typeof txt=="function"){txt=txt.toString();bFunction=true;} +if(txt.indexOf(sSearch)>-1){var newTxt='';while(txt.indexOf(sSearch)>-1){x=txt.indexOf(sSearch)+sSearch.length+1;newTxt+=txt.substr(0,x).replace(sSearch,sReplace);txt=txt.substr(x,txt.length-x);} +newTxt+=txt;if(bFunction){eval('this.$("'+sId+'").'+sAttribute+'=newTxt;');} +else if(this.willChange(sId,sAttribute,newTxt)){eval('this.$("'+sId+'").'+sAttribute+'=newTxt;');} +} +} +this.getFormValues=function(frm){var objForm;var submitDisabledElements=false;if(arguments.length > 1&&arguments[1]==true) +submitDisabledElements=true;var prefix="";if(arguments.length > 2) +prefix=arguments[2];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].name) +continue;if(formElements[i].name.substring(0,prefix.length)!=prefix) +continue;if(formElements[i].type&&(formElements[i].type=='radio'||formElements[i].type=='checkbox')&&formElements[i].checked==false) +continue;if(formElements[i].disabled&&formElements[i].disabled==true&&submitDisabledElements==false) +continue;var name=formElements[i].name;if(name){if(sXml!='<xjxquery><q>') +sXml+='&';if(formElements[i].type=='select-multiple'){for(var j=0;j < formElements[i].length;j++){if(formElements[i].options[j].selected==true) +sXml+=name+"="+encodeURIComponent(formElements[i].options[j].value)+"&";} +} +else{sXml+=name+"="+encodeURIComponent(formElements[i].value);} +} +} +} +sXml+="</q></xjxquery>";return sXml;} +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"&&this.depth <=50){this.depth++;value=this.objectToXML(value);this.depth--;} +sXml+="<e><k>"+key+"</k><v>"+value+"</v></e>";} +catch(e){if(xajaxDebug)this.DebugMessage(e.name+": "+e.message);} +} +sXml+="</xjxobj>";return sXml;} +this._nodeToObject=function(node){if(node.nodeName=='#cdata-section'){var data="";for(var j=0;j<node.parentNode.childNodes.length;j++){data+=node.parentNode.childNodes[j].data;} +return data;} +else if(node.nodeName=='xjxobj'){var data=new Array();for(var j=0;j<node.childNodes.length;j++){var child=node.childNodes[j];var key;var value;if(child.nodeName=='e'){for(var k=0;k<child.childNodes.length;k++){if(child.childNodes[k].nodeName=='k'){key=child.childNodes[k].firstChild.data;} +else if(child.childNodes[k].nodeName=='v'){value=this._nodeToObject(child.childNodes[k].firstChild);} +} +if(key!=null&&value!=null){data[key]=value;key=value=null;} +} +} +return data;} +} +this.loadingFunction=function(){};this.doneLoadingFunction=function(){};var loadingTimeout;this.call=function(sFunction,aArgs,sRequestType){var i,r,postData;if(document.body&&xajaxWaitCursor) +document.body.style.cursor='wait';if(xajaxStatusMessages==true)window.status='Sending Request...';clearTimeout(loadingTimeout);loadingTimeout=setTimeout("xajax.loadingFunction();",400);if(xajaxDebug)this.DebugMessage("Starting xajax...");if(sRequestType==null){var xajaxRequestType=xajaxDefinedPost;} +else{var xajaxRequestType=sRequestType;} +var uri=xajaxRequestUri;var value;switch(xajaxRequestType){case xajaxDefinedGet:{var uriGet=uri.indexOf("?")==-1?"?xajax="+encodeURIComponent(sFunction):"&xajax="+encodeURIComponent(sFunction);if(aArgs){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 xajaxDefinedPost:{postData="xajax="+encodeURIComponent(sFunction);postData+="&xajaxr="+new Date().getTime();if(aArgs){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();if(!r)return false;r.open(xajaxRequestType==xajaxDefinedGet?"GET":"POST",uri,true);if(xajaxRequestType==xajaxDefinedPost){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){if(xajaxDebug)xajax.DebugMessage("Received:\n"+r.responseText);if(r.responseXML&&r.responseXML.documentElement) +xajax.processResponse(r.responseXML);else{var errorString="Error: the XML response that was returned from the server is invalid.";errorString+="\nReceived:\n"+r.responseText;trimmedResponseText=r.responseText.replace(/^\s+/g,"");trimmedResponseText=trimmedResponseText.replace(/\s+$/g,"");if(trimmedResponseText!=r.responseText) +errorString+="\nYou have whitespace in your response.";alert(errorString);document.body.style.cursor='default';if(xajaxStatusMessages==true)window.status='Invalid XML response error';} +} +else{if(xajax.responseErrorsForAlert.containsValue(r.status)){var errorString="Error: the server returned the following HTTP status: "+r.status;errorString+="\nReceived:\n"+r.responseText;alert(errorString);} +document.body.style.cursor='default';if(xajaxStatusMessages==true)window.status='Invalid XML response error';} +delete r;r=null;} +if(xajaxDebug)this.DebugMessage("Calling "+sFunction+" uri="+uri+" (post:"+postData+")");r.send(postData);if(xajaxStatusMessages==true)window.status='Waiting for data...';delete r;return true;} +this.getBrowserHTML=function(html){tmpXajax=this.$(this.workId);if(!tmpXajax){tmpXajax=document.createElement("div");tmpXajax.setAttribute('id',this.workId);tmpXajax.style.display="none";tmpXajax.style.visibility="hidden";document.body.appendChild(tmpXajax);} +tmpXajax.innerHTML=html;var browserHTML=tmpXajax.innerHTML;tmpXajax.innerHTML='';return browserHTML;} +this.willChange=function(element,attribute,newData){if(!document.body){return true;} +if(attribute=="innerHTML"){newData=this.getBrowserHTML(newData);} +elementObject=this.$(element);if(elementObject){var oldData;eval("oldData=this.$('"+element+"')."+attribute);if(newData!==oldData) +return true;} +return false;} +this.viewSource=function(){return "<html>"+document.getElementsByTagName("HTML")[0].innerHTML+"</html>";} +this.processResponse=function(xml){clearTimeout(loadingTimeout);this.doneLoadingFunction();if(xajaxStatusMessages==true)window.status='Processing...';var tmpXajax=null;xml=xml.documentElement;if(xml==null) +return;var skipCommands=0;for(var i=0;i<xml.childNodes.length;i++){if(skipCommands > 0){skipCommands--;continue;} +if(xml.childNodes[i].nodeName=="cmd"){var cmd;var id;var property;var data;var search;var type;var before;var objElement=null;for(var j=0;j<xml.childNodes[i].attributes.length;j++){if(xml.childNodes[i].attributes[j].name=="n"){cmd=xml.childNodes[i].attributes[j].value;} +else if(xml.childNodes[i].attributes[j].name=="t"){id=xml.childNodes[i].attributes[j].value;} +else if(xml.childNodes[i].attributes[j].name=="p"){property=xml.childNodes[i].attributes[j].value;} +else if(xml.childNodes[i].attributes[j].name=="c"){type=xml.childNodes[i].attributes[j].value;} +} +if(xml.childNodes[i].childNodes.length > 1&&xml.childNodes[i].firstChild.nodeName=="#cdata-section"){data="";for(var j=0;j<xml.childNodes[i].childNodes.length;j++){data+=xml.childNodes[i].childNodes[j].data;} +} +else if(xml.childNodes[i].firstChild&&xml.childNodes[i].firstChild.nodeName=='xjxobj'){data=this._nodeToObject(xml.childNodes[i].firstChild);objElement="XJX_SKIP";} +else if(xml.childNodes[i].childNodes.length > 1){for(var j=0;j<xml.childNodes[i].childNodes.length;j++){if(xml.childNodes[i].childNodes[j].childNodes.length > 1&&xml.childNodes[i].childNodes[j].firstChild.nodeName=="#cdata-section"){var internalData="";for(var k=0;k<xml.childNodes[i].childNodes[j].childNodes.length;k++){internalData+=xml.childNodes[i].childNodes[j].childNodes[k].nodeValue;} +}else{var internalData=xml.childNodes[i].childNodes[j].firstChild.nodeValue;} +if(xml.childNodes[i].childNodes[j].nodeName=="s"){search=internalData;} +if(xml.childNodes[i].childNodes[j].nodeName=="r"){data=internalData;} +} +} +else if(xml.childNodes[i].firstChild) +data=xml.childNodes[i].firstChild.nodeValue;else +data="";if(objElement!="XJX_SKIP")objElement=this.$(id);var cmdFullname;try{if(cmd=="cc"){cmdFullname="addConfirmCommands";var confirmResult=confirm(data);if(!confirmResult){skipCommands=id;} +} +if(cmd=="al"){cmdFullname="addAlert";alert(data);} +else if(cmd=="js"){cmdFullname="addScript/addRedirect";eval(data);} +else if(cmd=="jc"){cmdFullname="addScriptCall";var scr=id+'(';if(data[0]!=null){scr+='data[0]';for(var l=1;l<data.length;l++){scr+=',data['+l+']';} +} +scr+=');';eval(scr);} +else if(cmd=="in"){cmdFullname="addIncludeScript";this.include(data);} +else if(cmd=="as"){cmdFullname="addAssign/addClear";if(this.willChange(id,property,data)){eval("objElement."+property+"=data;");} +} +else if(cmd=="ap"){cmdFullname="addAppend";eval("objElement."+property+"+=data;");} +else if(cmd=="pp"){cmdFullname="addPrepend";eval("objElement."+property+"=data+objElement."+property);} +else if(cmd=="rp"){cmdFullname="addReplace";this.replace(id,property,search,data) +} +else if(cmd=="rm"){cmdFullname="addRemove";this.remove(id);} +else if(cmd=="ce"){cmdFullname="addCreate";this.create(id,data,property);} +else if(cmd=="ie"){cmdFullname="addInsert";this.insert(id,data,property);} +else if(cmd=="ia"){cmdFullname="addInsertAfter";this.insertAfter(id,data,property);} +else if(cmd=="ci"){cmdFullname="addCreateInput";this.createInput(id,type,data,property);} +else if(cmd=="ii"){cmdFullname="addInsertInput";this.insertInput(id,type,data,property);} +else if(cmd=="iia"){cmdFullname="addInsertInputAfter";this.insertInputAfter(id,type,data,property);} +else if(cmd=="ev"){cmdFullname="addEvent";property=this.addOnPrefix(property);eval("this.$('"+id+"')."+property+"= function(){"+data+";}");} +else if(cmd=="ah"){cmdFullname="addHandler";this.addHandler(id,property,data);} +else if(cmd=="rh"){cmdFullname="addRemoveHandler";this.removeHandler(id,property,data);} +} +catch(e){if(xajaxDebug) +alert("While trying to '"+cmdFullname+"' (command number "+i+"), the following error occured:\n" ++e.name+": "+e.message+"\n" ++(id&&!objElement?"Object with id='"+id+"' wasn't found.\n":""));} +delete objElement;delete cmd;delete cmdFullname;delete id;delete property;delete search;delete data;delete type;delete before;delete internalData;delete j;delete k;} +} +delete xml;delete i;document.body.style.cursor='default';if(xajaxStatusMessages==true)window.status='Done';} +} +var xajax=new Xajax();xajaxLoaded=true;
\ No newline at end of file diff --git a/modules/xajax/xajax_js/xajax_uncompressed.js b/modules/xajax/xajax_js/xajax_uncompressed.js new file mode 100644 index 00000000..df51ccde --- /dev/null +++ b/modules/xajax/xajax_js/xajax_uncompressed.js @@ -0,0 +1,795 @@ +/* xajax Javascript library :: version 0.2.4 */ + +Array.prototype.containsValue = function(valueToCheck) +{ + for (var i=0;i<this.length;i++) { + if (this[i] == valueToCheck) return true; + } + return false; +} + +function Xajax() +{ + this.DebugMessage = function(text) + { + if (text.length > 1000) text = text.substr(0,1000)+"...\n[long response]\n..."; + try { + if (this.debugWindow == undefined || this.debugWindow.closed == true) { + this.debugWindow = window.open('about:blank', 'xajax-debug', 'width=800,height=600,scrollbars=1,resizable,status'); + this.debugWindow.document.write('<html><head><title>Xajax debug output</title></head><body><h2>Xajax debug output</h2><div id="debugTag"></div></body></html>'); + } + text = text.replace(/&/g, "&") + text = text.replace(/</g, "<") + text = text.replace(/>/g, ">") + debugTag = this.debugWindow.document.getElementById('debugTag'); + debugTag.innerHTML = ('<b>'+(new Date()).toString()+'</b>: ' + text + '<hr/>') + debugTag.innerHTML; + } catch (e) { + alert("Xajax Debug:\n " + text); + } + }; + + this.workId = 'xajaxWork'+ new Date().getTime(); + this.depth = 0; + this.responseErrorsForAlert = ["400","401","402","403","404","500","501","502","503"]; + + //Get the XMLHttpRequest Object + this.getRequestObject = function() + { + if (xajaxDebug) this.DebugMessage("Initializing Request Object.."); + var req = null; + if (typeof XMLHttpRequest != "undefined") + req = new XMLHttpRequest(); + if (!req && typeof ActiveXObject != "undefined") + { + try + { + req=new ActiveXObject("Msxml2.XMLHTTP"); + } + catch (e) + { + try + { + req=new ActiveXObject("Microsoft.XMLHTTP"); + } + catch (e2) + { + try { + req=new ActiveXObject("Msxml2.XMLHTTP.4.0"); + } + catch (e3) + { + req=null; + } + } + } + } + if(!req && window.createRequest) + req = window.createRequest(); + + if (!req) this.DebugMessage("Request Object Instantiation failed."); + + return req; + } + + // xajax.$() is shorthand for document.getElementById() + this.$ = function(sId) + { + if (!sId) { + return null; + } + var returnObj = document.getElementById(sId); + if (!returnObj && document.all) { + returnObj = document.all[sId]; + } + if (xajaxDebug && !returnObj && sId != this.workId) { + this.DebugMessage("Element with the id \"" + sId + "\" not found."); + } + return returnObj; + } + + // xajax.include(sFileName) dynamically includes an external javascript file + this.include = function(sFileName) + { + var objHead = document.getElementsByTagName('head'); + var objScript = document.createElement('script'); + objScript.type = 'text/javascript'; + objScript.src = sFileName; + objHead[0].appendChild(objScript); + } + + this.stripOnPrefix = function(sEventName) + { + sEventName = sEventName.toLowerCase(); + if (sEventName.indexOf('on') == 0) + { + sEventName = sEventName.replace(/on/,''); + } + + return sEventName; + } + + this.addOnPrefix = function(sEventName) + { + sEventName = sEventName.toLowerCase(); + if (sEventName.indexOf('on') != 0) + { + sEventName = 'on' + sEventName; + } + + return sEventName; + } + + // xajax.addHandler adds an event handler to an element + this.addHandler = function(sElementId, sEvent, sFunctionName) + { + if (window.addEventListener) + { + sEvent = this.stripOnPrefix(sEvent); + eval("this.$('"+sElementId+"').addEventListener('"+sEvent+"',"+sFunctionName+",false);"); + } + else + { + sAltEvent = this.addOnPrefix(sEvent); + eval("this.$('"+sElementId+"').attachEvent('"+sAltEvent+"',"+sFunctionName+",false);"); + } + } + + // xajax.removeHandler removes an event handler from an element + this.removeHandler = function(sElementId, sEvent, sFunctionName) + { + if (window.addEventListener) + { + sEvent = this.stripOnPrefix(sEvent); + eval("this.$('"+sElementId+"').removeEventListener('"+sEvent+"',"+sFunctionName+",false);"); + } + else + { + sAltEvent = this.addOnPrefix(sEvent); + eval("this.$('"+sElementId+"').detachEvent('"+sAltEvent+"',"+sFunctionName+",false);"); + } + } + + // xajax.create creates a new child node under a parent + this.create = function(sParentId, sTag, sId) + { + var objParent = this.$(sParentId); + objElement = document.createElement(sTag); + objElement.setAttribute('id',sId); + if (objParent) + objParent.appendChild(objElement); + } + + // xajax.insert inserts a new node before another node + this.insert = function(sBeforeId, sTag, sId) + { + var objSibling = this.$(sBeforeId); + objElement = document.createElement(sTag); + objElement.setAttribute('id',sId); + objSibling.parentNode.insertBefore(objElement, objSibling); + } + + // xajax.insertAfter inserts a new node after another node + this.insertAfter = function(sAfterId, sTag, sId) + { + var objSibling = this.$(sAfterId); + objElement = document.createElement(sTag); + objElement.setAttribute('id',sId); + objSibling.parentNode.insertBefore(objElement, objSibling.nextSibling); + } + + this.getInput = function(sType, sName, sId) + { + var Obj; + if (!window.addEventListener) + { + Obj = document.createElement('<input type="'+sType+'" id="'+sId+'" name="'+sName+'">'); + } + else + { + Obj = document.createElement('input'); + Obj.setAttribute('type',sType); + Obj.setAttribute('name',sName); + Obj.setAttribute('id',sId); + } + return Obj; + } + + // xajax.createInput creates a new input node under a parent + this.createInput = function(sParentId, sType, sName, sId) + { + var objParent = this.$(sParentId); + var objElement = this.getInput(sType, sName, sId); + if (objParent && objElement) + objParent.appendChild(objElement); + } + + // xajax.insertInput creates a new input node before another node + this.insertInput = function(sBeforeId, sType, sName, sId) + { + var objSibling = this.$(sBeforeId); + var objElement = this.getInput(sType, sName, sId); + if (objElement && objSibling && objSibling.parentNode) + objSibling.parentNode.insertBefore(objElement, objSibling); + } + + // xajax.insertInputAfter creates a new input node after another node + this.insertInputAfter = function(sAfterId, sType, sName, sId) + { + var objSibling = this.$(sAfterId); + var objElement = this.getInput(sType, sName, sId); + if (objElement && objSibling && objSibling.parentNode) { + objSibling.parentNode.insertBefore(objElement, objSibling.nextSibling); + } + } + + // xajax.remove deletes an element + this.remove = function(sId) + { + objElement = this.$(sId); + if (objElement && objElement.parentNode && objElement.parentNode.removeChild) + { + objElement.parentNode.removeChild(objElement); + } + } + + //xajax.replace searches for text in an attribute of an element and replaces it + //with a different text + this.replace = function(sId,sAttribute,sSearch,sReplace) + { + var bFunction = false; + + if (sAttribute == "innerHTML") + sSearch = this.getBrowserHTML(sSearch); + + eval("var txt=this.$('"+sId+"')."+sAttribute); + if (typeof txt == "function") + { + txt = txt.toString(); + bFunction = true; + } + if (txt.indexOf(sSearch)>-1) + { + var newTxt = ''; + while (txt.indexOf(sSearch) > -1) + { + x = txt.indexOf(sSearch)+sSearch.length+1; + newTxt += txt.substr(0,x).replace(sSearch,sReplace); + txt = txt.substr(x,txt.length-x); + } + newTxt += txt; + if (bFunction) + { + eval('this.$("'+sId+'").'+sAttribute+'=newTxt;'); + } + else if (this.willChange(sId,sAttribute,newTxt)) + { + eval('this.$("'+sId+'").'+sAttribute+'=newTxt;'); + } + } + } + + // xajax.getFormValues() builds a query string XML message from the elements of a form object + // * The first argument is the id of the form + // * The second argument (optional) can be set to true if you want to submit disabled elements + // * The third argument (optional) allows you to specify a string prefix that a form element + // name must contain if you want that element to be submitted + this.getFormValues = function(frm) + { + var objForm; + var submitDisabledElements = false; + if (arguments.length > 1 && arguments[1] == true) + submitDisabledElements = true; + var prefix=""; + if(arguments.length > 2) + prefix = arguments[2]; + + 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].name) + continue; + if (formElements[i].name.substring(0, prefix.length) != prefix) + continue; + if (formElements[i].type && (formElements[i].type == 'radio' || formElements[i].type == 'checkbox') && formElements[i].checked == false) + continue; + if (formElements[i].disabled && formElements[i].disabled == true && submitDisabledElements == false) + continue; + var name = formElements[i].name; + if (name) + { + if (sXml != '<xjxquery><q>') + sXml += '&'; + if(formElements[i].type=='select-multiple') + { + for (var j = 0; j < formElements[i].length; j++) + { + if (formElements[i].options[j].selected == true) + sXml += name+"="+encodeURIComponent(formElements[i].options[j].value)+"&"; + } + } + else + { + 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" && this.depth <= 50) + { + this.depth++; + value = this.objectToXML(value); + this.depth--; + } + + sXml += "<e><k>"+key+"</k><v>"+value+"</v></e>"; + + } + catch(e) + { + if (xajaxDebug) this.DebugMessage(e.name+": "+e.message); + } + } + sXml += "</xjxobj>"; + + return sXml; + } + + // unserializes data structure from xajaxResponse::_buildObjXml() + this._nodeToObject = function(node) { + // parentNode here is weird, have to tune + if (node.nodeName == '#cdata-section') { + var data = ""; + for (var j=0; j<node.parentNode.childNodes.length; j++) { + data += node.parentNode.childNodes[j].data; + } + return data; + } + else if (node.nodeName == 'xjxobj') { + var data = new Array(); + for (var j=0; j<node.childNodes.length; j++) { + var child = node.childNodes[j]; + var key; + var value; + if (child.nodeName == 'e') { + for (var k=0; k<child.childNodes.length; k++) { + if (child.childNodes[k].nodeName == 'k') { + key = child.childNodes[k].firstChild.data; + } + else if (child.childNodes[k].nodeName == 'v') { + value = this._nodeToObject(child.childNodes[k].firstChild); + } + } + if (key != null && value != null) { + data[key] = value; + key = value = null; + } + } + } + return data; + } + } + + this.loadingFunction = function(){}; + this.doneLoadingFunction = function(){}; + var loadingTimeout; + + // Sends a XMLHttpRequest to call the specified PHP function on the server + // * sRequestType is optional -- defaults to POST + this.call = function(sFunction, aArgs, sRequestType) + { + var i,r,postData; + if (document.body && xajaxWaitCursor) + document.body.style.cursor = 'wait'; + if (xajaxStatusMessages == true) window.status = 'Sending Request...'; + clearTimeout(loadingTimeout); + loadingTimeout = setTimeout("xajax.loadingFunction();",400); + if (xajaxDebug) this.DebugMessage("Starting xajax..."); + if (sRequestType == null) { + var xajaxRequestType = xajaxDefinedPost; + } + else { + var xajaxRequestType = sRequestType; + } + var uri = xajaxRequestUri; + var value; + switch(xajaxRequestType) + { + case xajaxDefinedGet:{ + var uriGet = uri.indexOf("?")==-1?"?xajax="+encodeURIComponent(sFunction):"&xajax="+encodeURIComponent(sFunction); + if (aArgs) { + 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 xajaxDefinedPost:{ + postData = "xajax="+encodeURIComponent(sFunction); + postData += "&xajaxr="+new Date().getTime(); + if (aArgs) { + 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(); + if (!r) return false; + r.open(xajaxRequestType==xajaxDefinedGet?"GET":"POST", uri, true); + if (xajaxRequestType == xajaxDefinedPost) + { + 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) + { + if (xajaxDebug) xajax.DebugMessage("Received:\n" + r.responseText); + if (r.responseXML && r.responseXML.documentElement) + xajax.processResponse(r.responseXML); + else { + var errorString = "Error: the XML response that was returned from the server is invalid."; + errorString += "\nReceived:\n" + r.responseText; + trimmedResponseText = r.responseText.replace( /^\s+/g, "" );// strip leading space
+ trimmedResponseText = trimmedResponseText.replace( /\s+$/g, "" );// strip trailing + if (trimmedResponseText != r.responseText) + errorString += "\nYou have whitespace in your response."; + alert(errorString); + document.body.style.cursor = 'default'; + if (xajaxStatusMessages == true) window.status = 'Invalid XML response error'; + } + } + else { + if (xajax.responseErrorsForAlert.containsValue(r.status)) { + var errorString = "Error: the server returned the following HTTP status: " + r.status; + errorString += "\nReceived:\n" + r.responseText; + alert(errorString); + } + document.body.style.cursor = 'default'; + if (xajaxStatusMessages == true) window.status = 'Invalid XML response error'; + } + + delete r; + r = null; + } + if (xajaxDebug) this.DebugMessage("Calling "+sFunction +" uri="+uri+" (post:"+ postData +")"); + r.send(postData); + if (xajaxStatusMessages == true) window.status = 'Waiting for data...'; + delete r; + return true; + } + + //Gets the text as it would be if it were being retrieved from + //the innerHTML property in the current browser + this.getBrowserHTML = function(html) + { + tmpXajax = this.$(this.workId); + if (!tmpXajax) + { + tmpXajax = document.createElement("div"); + tmpXajax.setAttribute('id',this.workId); + tmpXajax.style.display = "none"; + tmpXajax.style.visibility = "hidden"; + document.body.appendChild(tmpXajax); + } + tmpXajax.innerHTML = html; + var browserHTML = tmpXajax.innerHTML; + tmpXajax.innerHTML = ''; + + return browserHTML; + } + + // Tests if the new Data is the same as the extant data + this.willChange = function(element, attribute, newData) + { + if (!document.body) + { + return true; + } + if (attribute == "innerHTML") + { + newData = this.getBrowserHTML(newData); + } + elementObject = this.$(element); + if (elementObject) { + var oldData; + eval("oldData=this.$('"+element+"')."+attribute); + if (newData !== oldData) + return true; + } + + return false; + } + + //Returns the source code of the page after it's been modified by xajax + this.viewSource = function() + { + return "<html>"+document.getElementsByTagName("HTML")[0].innerHTML+"</html>"; + } + + //Process XML xajaxResponses returned from the request + this.processResponse = function(xml) + { + clearTimeout(loadingTimeout); + this.doneLoadingFunction(); + if (xajaxStatusMessages == true) window.status = 'Processing...'; + var tmpXajax = null; + xml = xml.documentElement; + if (xml == null) + return; + + var skipCommands = 0; + for (var i=0; i<xml.childNodes.length; i++) + { + if (skipCommands > 0) { + skipCommands--; + continue; + } + if (xml.childNodes[i].nodeName == "cmd") + { + var cmd; + var id; + var property; + var data; + var search; + var type; + var before; + var objElement = null; + + for (var j=0; j<xml.childNodes[i].attributes.length; j++) + { + if (xml.childNodes[i].attributes[j].name == "n") + { + cmd = xml.childNodes[i].attributes[j].value; + } + else if (xml.childNodes[i].attributes[j].name == "t") + { + id = xml.childNodes[i].attributes[j].value; + } + else if (xml.childNodes[i].attributes[j].name == "p") + { + property = xml.childNodes[i].attributes[j].value; + } + else if (xml.childNodes[i].attributes[j].name == "c") + { + type = xml.childNodes[i].attributes[j].value; + } + } + if (xml.childNodes[i].childNodes.length > 1 && xml.childNodes[i].firstChild.nodeName == "#cdata-section") + { + data = ""; + for (var j=0; j<xml.childNodes[i].childNodes.length; j++) + { + data += xml.childNodes[i].childNodes[j].data; + } + } + else if (xml.childNodes[i].firstChild && xml.childNodes[i].firstChild.nodeName == 'xjxobj') { + data = this._nodeToObject(xml.childNodes[i].firstChild); + objElement = "XJX_SKIP"; + } + else if (xml.childNodes[i].childNodes.length > 1) + { + for (var j=0; j<xml.childNodes[i].childNodes.length; j++) + { + if (xml.childNodes[i].childNodes[j].childNodes.length > 1 && xml.childNodes[i].childNodes[j].firstChild.nodeName == "#cdata-section") + { + var internalData = ""; + for (var k=0; k<xml.childNodes[i].childNodes[j].childNodes.length;k++) + { + internalData+=xml.childNodes[i].childNodes[j].childNodes[k].nodeValue; + } + } else { + var internalData = xml.childNodes[i].childNodes[j].firstChild.nodeValue; + } + + if (xml.childNodes[i].childNodes[j].nodeName == "s") + { + search = internalData; + } + if (xml.childNodes[i].childNodes[j].nodeName == "r") + { + data = internalData; + } + } + } + else if (xml.childNodes[i].firstChild) + data = xml.childNodes[i].firstChild.nodeValue; + else + data = ""; + + if (objElement != "XJX_SKIP") objElement = this.$(id); + var cmdFullname; + try + { + if (cmd=="cc") { + cmdFullname = "addConfirmCommands"; + var confirmResult = confirm(data); + if (!confirmResult) { + skipCommands = id; + } + } + if (cmd=="al") + { + cmdFullname = "addAlert"; + alert(data); + } + else if (cmd=="js") + { + cmdFullname = "addScript/addRedirect"; + eval(data); + } + else if (cmd=="jc") + { + cmdFullname = "addScriptCall"; + var scr = id + '('; + if (data[0] != null) { + scr += 'data[0]'; + for (var l=1; l<data.length; l++) { + scr += ',data['+l+']'; + } + } + scr += ');'; + eval(scr); + } + else if (cmd=="in") + { + cmdFullname = "addIncludeScript"; + this.include(data); + } + else if (cmd=="as") + { + cmdFullname = "addAssign/addClear"; + if (this.willChange(id,property,data)) + { + eval("objElement."+property+"=data;"); + } + } + else if (cmd=="ap") + { + cmdFullname = "addAppend"; + eval("objElement."+property+"+=data;"); + } + else if (cmd=="pp") + { + cmdFullname = "addPrepend"; + eval("objElement."+property+"=data+objElement."+property); + } + else if (cmd=="rp") + { + cmdFullname = "addReplace"; + this.replace(id,property,search,data) + } + else if (cmd=="rm") + { + cmdFullname = "addRemove"; + this.remove(id); + } + else if (cmd=="ce") + { + cmdFullname = "addCreate"; + this.create(id,data,property); + } + else if (cmd=="ie") + { + cmdFullname = "addInsert"; + this.insert(id,data,property); + } + else if (cmd=="ia") + { + cmdFullname = "addInsertAfter"; + this.insertAfter(id,data,property); + } + else if (cmd=="ci") + { + cmdFullname = "addCreateInput"; + this.createInput(id,type,data,property); + } + else if (cmd=="ii") + { + cmdFullname = "addInsertInput"; + this.insertInput(id,type,data,property); + } + else if (cmd=="iia") + { + cmdFullname = "addInsertInputAfter"; + this.insertInputAfter(id,type,data,property); + } + else if (cmd=="ev") + { + cmdFullname = "addEvent"; + property = this.addOnPrefix(property); + eval("this.$('"+id+"')."+property+"= function(){"+data+";}"); + } + else if (cmd=="ah") + { + cmdFullname = "addHandler"; + this.addHandler(id, property, data); + } + else if (cmd=="rh") + { + cmdFullname = "addRemoveHandler"; + this.removeHandler(id, property, data); + } + } + catch(e) + { + if (xajaxDebug) + alert("While trying to '"+cmdFullname+"' (command number "+i+"), the following error occured:\n" + + e.name+": "+e.message+"\n" + + (id&&!objElement?"Object with id='"+id+"' wasn't found.\n":"")); + } + delete objElement; + delete cmd; + delete cmdFullname; + delete id; + delete property; + delete search; + delete data; + delete type; + delete before; + delete internalData; + delete j; + delete k; + } + } + delete xml; + delete i; + document.body.style.cursor = 'default'; + if (xajaxStatusMessages == true) window.status = 'Done'; + } +} + +var xajax = new Xajax(); +xajaxLoaded = true; |